Merge pull request #79335 from rosti/kubeadm-nuke-normalizer

kubeadm: Stop using //pkg/util/normalizer
This commit is contained in:
Kubernetes Prow Robot 2019-06-24 08:02:11 -07:00 committed by GitHub
commit ddc4ed0365
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 239 additions and 62 deletions

View File

@ -83,7 +83,6 @@
"k8s.io/kubernetes/pkg/util/ipvs",
"k8s.io/kubernetes/pkg/util/metrics",
"k8s.io/kubernetes/pkg/util/node",
"k8s.io/kubernetes/pkg/util/normalizer",
"k8s.io/kubernetes/pkg/util/parsers",
"k8s.io/kubernetes/pkg/util/procfs",
"k8s.io/kubernetes/pkg/util/sysctl",

View File

@ -31,7 +31,6 @@ go_library(
"//cmd/kubeadm/app/util/apiclient:go_default_library",
"//cmd/kubeadm/app/util/config:go_default_library",
"//cmd/kubeadm/app/util/kubeconfig:go_default_library",
"//pkg/util/normalizer:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/duration:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/version:go_default_library",
"//vendor/github.com/lithammer/dedent:go_default_library",

View File

@ -38,11 +38,10 @@ import (
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config"
kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig"
"k8s.io/kubernetes/pkg/util/normalizer"
)
var (
genericCertRenewLongDesc = normalizer.LongDesc(`
genericCertRenewLongDesc = cmdutil.LongDesc(`
Renew the %s.
Renewals run unconditionally, regardless of certificate expiration date; extra attributes such as SANs will
@ -55,12 +54,12 @@ var (
eventually re-distribute the renewed certificate in case the file is used elsewhere.
`)
allLongDesc = normalizer.LongDesc(`
allLongDesc = cmdutil.LongDesc(`
Renew all known certificates necessary to run the control plane. Renewals are run unconditionally, regardless
of expiration date. Renewals can also be run individually for more control.
`)
expirationLongDesc = normalizer.LongDesc(`
expirationLongDesc = cmdutil.LongDesc(`
Checks expiration for the certificates in the local PKI managed by kubeadm.
`)

View File

@ -28,19 +28,18 @@ import (
kubeconfigphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/kubeconfig"
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config"
"k8s.io/kubernetes/pkg/util/normalizer"
)
var (
kubeconfigLongDesc = normalizer.LongDesc(`
kubeconfigLongDesc = cmdutil.LongDesc(`
Kubeconfig file utilities.
` + cmdutil.AlphaDisclaimer)
userKubeconfigLongDesc = normalizer.LongDesc(`
userKubeconfigLongDesc = cmdutil.LongDesc(`
Output a kubeconfig file for an additional user.
` + cmdutil.AlphaDisclaimer)
userKubeconfigExample = normalizer.Examples(`
userKubeconfigExample = cmdutil.Examples(`
# Output a kubeconfig file for an additional user named foo
kubeadm alpha kubeconfig user --client-name=foo
`)

View File

@ -29,18 +29,17 @@ import (
"k8s.io/kubernetes/cmd/kubeadm/app/preflight"
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig"
"k8s.io/kubernetes/pkg/util/normalizer"
utilsexec "k8s.io/utils/exec"
)
var (
kubeletConfigDownloadLongDesc = normalizer.LongDesc(`
kubeletConfigDownloadLongDesc = cmdutil.LongDesc(`
Download the kubelet configuration from a ConfigMap of the form "kubelet-config-1.X" in the cluster,
where X is the minor version of the kubelet. Either kubeadm autodetects the kubelet version by exec-ing
"kubelet --version" or respects the --kubelet-version parameter.
` + cmdutil.AlphaDisclaimer)
kubeletConfigDownloadExample = normalizer.Examples(fmt.Sprintf(`
kubeletConfigDownloadExample = cmdutil.Examples(fmt.Sprintf(`
# Download the kubelet configuration from the ConfigMap in the cluster. Autodetect the kubelet version.
kubeadm alpha phase kubelet config download
@ -48,7 +47,7 @@ var (
kubeadm alpha phase kubelet config download --kubelet-version %s
`, constants.CurrentKubernetesVersion))
kubeletConfigEnableDynamicLongDesc = normalizer.LongDesc(`
kubeletConfigEnableDynamicLongDesc = cmdutil.LongDesc(`
Enable or update dynamic kubelet configuration for a Node, against the kubelet-config-1.X ConfigMap in the cluster,
where X is the minor version of the desired kubelet version.
@ -57,7 +56,7 @@ var (
` + cmdutil.AlphaDisclaimer)
kubeletConfigEnableDynamicExample = normalizer.Examples(fmt.Sprintf(`
kubeletConfigEnableDynamicExample = cmdutil.Examples(fmt.Sprintf(`
# Enable dynamic kubelet configuration for a Node.
kubeadm alpha phase kubelet enable-dynamic-config --node-name node-1 --kubelet-version %s

View File

@ -20,7 +20,9 @@ import (
"bufio"
"fmt"
"io"
"os"
"strings"
"time"
"github.com/pkg/errors"
"github.com/spf13/cobra"
@ -38,21 +40,17 @@ import (
"k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient"
configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config"
kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig"
"k8s.io/kubernetes/pkg/util/normalizer"
"os"
"time"
)
var (
selfhostingLongDesc = normalizer.LongDesc(`
selfhostingLongDesc = cmdutil.LongDesc(`
Convert static Pod files for control plane components into self-hosted DaemonSets configured via the Kubernetes API.
See the documentation for self-hosting limitations.
` + cmdutil.AlphaDisclaimer)
selfhostingExample = normalizer.Examples(`
selfhostingExample = cmdutil.Examples(`
# Convert a static Pod-hosted control plane into a self-hosted one.
kubeadm alpha phase self-hosting convert-from-staticpods

View File

@ -45,7 +45,6 @@ go_library(
"//cmd/kubeadm/app/util/apiclient:go_default_library",
"//cmd/kubeadm/app/util/dryrun:go_default_library",
"//cmd/kubeadm/app/util/pkiutil:go_default_library",
"//pkg/util/normalizer:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
"//staging/src/k8s.io/client-go/kubernetes:go_default_library",

View File

@ -26,16 +26,15 @@ import (
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
dnsaddon "k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/dns"
proxyaddon "k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/proxy"
"k8s.io/kubernetes/pkg/util/normalizer"
)
var (
coreDNSAddonLongDesc = normalizer.LongDesc(`
coreDNSAddonLongDesc = cmdutil.LongDesc(`
Install the CoreDNS addon components via the API server.
Please note that although the DNS server is deployed, it will not be scheduled until CNI is installed.
`)
kubeProxyAddonLongDesc = normalizer.LongDesc(`
kubeProxyAddonLongDesc = cmdutil.LongDesc(`
Install the kube-proxy addon components via the API server.
`)
)

View File

@ -23,13 +23,13 @@ import (
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/options"
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow"
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
clusterinfophase "k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/clusterinfo"
nodebootstraptokenphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/node"
"k8s.io/kubernetes/pkg/util/normalizer"
)
var (
bootstrapTokenLongDesc = normalizer.LongDesc(`
bootstrapTokenLongDesc = cmdutil.LongDesc(`
Bootstrap tokens are used for establishing bidirectional trust between a node joining
the cluster and a the control-plane node.
@ -37,7 +37,7 @@ var (
and then creates an initial token.
`)
bootstrapTokenExamples = normalizer.Examples(`
bootstrapTokenExamples = cmdutil.Examples(`
# Make all the bootstrap token configurations and create an initial token, functionally
# equivalent to what generated by kubeadm init.
kubeadm init phase bootstrap-token

View File

@ -32,17 +32,16 @@ import (
certsphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/certs"
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
"k8s.io/kubernetes/cmd/kubeadm/app/util/pkiutil"
"k8s.io/kubernetes/pkg/util/normalizer"
)
var (
saKeyLongDesc = fmt.Sprintf(normalizer.LongDesc(`
saKeyLongDesc = fmt.Sprintf(cmdutil.LongDesc(`
Generate the private key for signing service account tokens along with its public key, and save them into
%s and %s files.
If both files already exist, kubeadm skips the generation step and existing files will be used.
`+cmdutil.AlphaDisclaimer), kubeadmconstants.ServiceAccountPrivateKeyName, kubeadmconstants.ServiceAccountPublicKeyName)
genericLongDesc = normalizer.LongDesc(`
genericLongDesc = cmdutil.LongDesc(`
Generate the %[1]s, and save them into %[2]s.cert and %[2]s.key files.%[3]s
If both files already exist, kubeadm skips the generation step and existing files will be used.

View File

@ -26,11 +26,10 @@ import (
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
"k8s.io/kubernetes/cmd/kubeadm/app/phases/controlplane"
"k8s.io/kubernetes/pkg/util/normalizer"
)
var (
controlPlaneExample = normalizer.Examples(`
controlPlaneExample = cmdutil.Examples(`
# Generates all static Pod manifest files for control plane components,
# functionally equivalent to what is generated by kubeadm init.
kubeadm init phase control-plane all

View File

@ -26,11 +26,10 @@ import (
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow"
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
etcdphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/etcd"
"k8s.io/kubernetes/pkg/util/normalizer"
)
var (
etcdLocalExample = normalizer.Examples(`
etcdLocalExample = cmdutil.Examples(`
# Generates the static Pod manifest file for etcd, functionally
# equivalent to what is generated by kubeadm init.
kubeadm init phase etcd local

View File

@ -25,7 +25,6 @@ import (
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
kubeconfigphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/kubeconfig"
"k8s.io/kubernetes/pkg/util/normalizer"
)
var (
@ -42,7 +41,7 @@ var (
kubeadmconstants.KubeletKubeConfigFileName: {
name: "kubelet",
short: "Generate a kubeconfig file for the kubelet to use *only* for cluster bootstrapping purposes",
long: normalizer.LongDesc(`
long: cmdutil.LongDesc(`
Generate the kubeconfig file for the kubelet to use and save it to %s file.
Please note that this should *only* be used for cluster bootstrapping purposes. After your control plane is up,

View File

@ -21,12 +21,12 @@ import (
"k8s.io/klog"
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/options"
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow"
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
kubeletphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/kubelet"
"k8s.io/kubernetes/pkg/util/normalizer"
)
var (
kubeletStartPhaseExample = normalizer.Examples(`
kubeletStartPhaseExample = cmdutil.Examples(`
# Writes a dynamic environment file with kubelet flags from a InitConfiguration file.
kubeadm init phase kubelet-start --config config.yaml
`)

View File

@ -20,12 +20,12 @@ import (
"github.com/pkg/errors"
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/options"
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow"
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
markcontrolplanephase "k8s.io/kubernetes/cmd/kubeadm/app/phases/markcontrolplane"
"k8s.io/kubernetes/pkg/util/normalizer"
)
var (
markControlPlaneExample = normalizer.Examples(`
markControlPlaneExample = cmdutil.Examples(`
# Applies control-plane label and taint to the current node, functionally equivalent to what executed by kubeadm init.
kubeadm init phase mark-control-plane --config config.yml

View File

@ -22,13 +22,13 @@ import (
"github.com/pkg/errors"
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/options"
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow"
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
"k8s.io/kubernetes/cmd/kubeadm/app/preflight"
"k8s.io/kubernetes/pkg/util/normalizer"
utilsexec "k8s.io/utils/exec"
)
var (
preflightExample = normalizer.Examples(`
preflightExample = cmdutil.Examples(`
# Run pre-flight checks for kubeadm init using a config file.
kubeadm init phase preflight --config kubeadm-config.yml
`)

View File

@ -31,28 +31,27 @@ import (
kubeletphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/kubelet"
patchnodephase "k8s.io/kubernetes/cmd/kubeadm/app/phases/patchnode"
"k8s.io/kubernetes/cmd/kubeadm/app/phases/uploadconfig"
"k8s.io/kubernetes/pkg/util/normalizer"
)
var (
uploadKubeadmConfigLongDesc = fmt.Sprintf(normalizer.LongDesc(`
uploadKubeadmConfigLongDesc = fmt.Sprintf(cmdutil.LongDesc(`
Upload the kubeadm ClusterConfiguration to a ConfigMap called %s in the %s namespace.
This enables correct configuration of system components and a seamless user experience when upgrading.
Alternatively, you can use kubeadm config.
`), kubeadmconstants.KubeadmConfigConfigMap, metav1.NamespaceSystem)
uploadKubeadmConfigExample = normalizer.Examples(`
uploadKubeadmConfigExample = cmdutil.Examples(`
# upload the configuration of your cluster
kubeadm init phase upload-config --config=myConfig.yaml
`)
uploadKubeletConfigLongDesc = normalizer.LongDesc(`
uploadKubeletConfigLongDesc = cmdutil.LongDesc(`
Upload kubelet configuration extracted from the kubeadm InitConfiguration object to a ConfigMap
of the form kubelet-config-1.X in the cluster, where X is the minor version of the current (API Server) Kubernetes version.
`)
uploadKubeletConfigExample = normalizer.Examples(`
uploadKubeletConfigExample = cmdutil.Examples(`
# Upload the kubelet configuration from the kubeadm Config file to a ConfigMap in the cluster.
kubeadm init phase upload-config kubelet --config kubeadm.yaml
`)

View File

@ -16,6 +16,7 @@ go_library(
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
"//cmd/kubeadm/app/cmd/options:go_default_library",
"//cmd/kubeadm/app/cmd/phases/workflow:go_default_library",
"//cmd/kubeadm/app/cmd/util:go_default_library",
"//cmd/kubeadm/app/constants:go_default_library",
"//cmd/kubeadm/app/phases/certs:go_default_library",
"//cmd/kubeadm/app/phases/controlplane:go_default_library",
@ -29,7 +30,6 @@ go_library(
"//cmd/kubeadm/app/preflight:go_default_library",
"//cmd/kubeadm/app/util/apiclient:go_default_library",
"//cmd/kubeadm/app/util/kubeconfig:go_default_library",
"//pkg/util/normalizer:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/version:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library",

View File

@ -24,14 +24,14 @@ import (
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/options"
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow"
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
etcdphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/etcd"
markcontrolplanephase "k8s.io/kubernetes/cmd/kubeadm/app/phases/markcontrolplane"
uploadconfigphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/uploadconfig"
"k8s.io/kubernetes/pkg/util/normalizer"
)
var controlPlaneJoinExample = normalizer.Examples(`
var controlPlaneJoinExample = cmdutil.Examples(`
# Joins a machine as a control plane instance
kubeadm join phase control-plane-join all
`)

View File

@ -26,16 +26,16 @@ import (
"k8s.io/klog"
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/options"
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow"
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
certsphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/certs"
"k8s.io/kubernetes/cmd/kubeadm/app/phases/controlplane"
"k8s.io/kubernetes/cmd/kubeadm/app/phases/copycerts"
kubeconfigphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/kubeconfig"
kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig"
"k8s.io/kubernetes/pkg/util/normalizer"
)
var controlPlanePrepareExample = normalizer.Examples(`
var controlPlanePrepareExample = cmdutil.Examples(`
# Prepares the machine for serving a control plane
kubeadm join phase control-plane-prepare all
`)

View File

@ -27,14 +27,14 @@ import (
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/options"
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow"
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
"k8s.io/kubernetes/cmd/kubeadm/app/phases/certs"
"k8s.io/kubernetes/cmd/kubeadm/app/preflight"
"k8s.io/kubernetes/pkg/util/normalizer"
utilsexec "k8s.io/utils/exec"
)
var (
preflightExample = normalizer.Examples(`
preflightExample = cmdutil.Examples(`
# Run join pre-flight checks using a config file.
kubeadm join phase preflight --config kubeadm-config.yml
`)

View File

@ -13,12 +13,12 @@ go_library(
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
"//cmd/kubeadm/app/cmd/options:go_default_library",
"//cmd/kubeadm/app/cmd/phases/workflow:go_default_library",
"//cmd/kubeadm/app/cmd/util:go_default_library",
"//cmd/kubeadm/app/constants:go_default_library",
"//cmd/kubeadm/app/phases/kubelet:go_default_library",
"//cmd/kubeadm/app/phases/upgrade:go_default_library",
"//cmd/kubeadm/app/util/apiclient:go_default_library",
"//cmd/kubeadm/app/util/dryrun:go_default_library",
"//pkg/util/normalizer:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/version:go_default_library",
"//staging/src/k8s.io/client-go/kubernetes:go_default_library",
"//vendor/github.com/pkg/errors:go_default_library",

View File

@ -26,15 +26,15 @@ import (
"k8s.io/apimachinery/pkg/util/version"
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/options"
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow"
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
kubeletphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/kubelet"
"k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade"
dryrunutil "k8s.io/kubernetes/cmd/kubeadm/app/util/dryrun"
"k8s.io/kubernetes/pkg/util/normalizer"
)
var (
kubeletConfigLongDesc = normalizer.LongDesc(`
kubeletConfigLongDesc = cmdutil.LongDesc(`
Download the kubelet configuration from a ConfigMap of the form "kubelet-config-1.X" in the cluster,
where X is the minor version of the kubelet. kubeadm uses the KuberneteVersion field in the kubeadm-config
ConfigMap to determine what the _desired_ kubelet version is, but the user can override this by using the

View File

@ -14,7 +14,6 @@ go_library(
"//cmd/kubeadm/app/constants:go_default_library",
"//cmd/kubeadm/app/util/kubeconfig:go_default_library",
"//cmd/kubeadm/app/util/pubkeypin:go_default_library",
"//pkg/util/normalizer:go_default_library",
"//staging/src/k8s.io/client-go/tools/clientcmd:go_default_library",
"//staging/src/k8s.io/client-go/util/cert:go_default_library",
"//vendor/github.com/pkg/errors:go_default_library",
@ -26,7 +25,10 @@ go_library(
go_test(
name = "go_default_test",
srcs = ["cmdutil_test.go"],
srcs = [
"cmdutil_test.go",
"documentation_test.go",
],
embed = [":go_default_library"],
)

View File

@ -17,7 +17,7 @@ limitations under the License.
package util
import (
"k8s.io/kubernetes/pkg/util/normalizer"
"strings"
)
var (
@ -27,7 +27,79 @@ var (
`
// MacroCommandLongDescription provide a standard description for "macro" commands
MacroCommandLongDescription = normalizer.LongDesc(`
MacroCommandLongDescription = LongDesc(`
This command is not meant to be run on its own. See list of available subcommands.
`)
)
// LongDesc is designed to help with producing better long command line descriptions in code.
// Its behavior is somewhat inspired by the same function of kubectl, which uses Markdown for the input message.
// This one is not Markdown compliant, but it covers the needs of kubeadm. In particular:
// - Beginning and trailing space characters (including empty lines), are stripped from the output.
// - Consecutive non-empty lines of text are joined with spaces to form paragraphs.
// - Paragraphs are blocks of text divided by one or more empty lines or lines consisting only of "space" characters.
// - Paragraphs are spaced by precisely one empty line in the output.
// - A line break can be forced by adding a couple of empty spaces at the end of a text line.
// - All indentation is removed. The resulting output is not indented.
func LongDesc(s string) string {
// Strip beginning and trailing space characters (including empty lines) and split the lines into a slice
lines := strings.Split(strings.TrimSpace(s), "\n")
output := []string{}
paragraph := []string{}
for _, line := range lines {
// Remove indentation and trailing spaces from the current line
trimmedLine := strings.TrimSpace(line)
if trimmedLine == "" {
if len(paragraph) > 0 {
// If the line is empty and the current paragraph is not, we have reached a paragraph end.
// (if the paragraph and the line are empty, then this is non-first empty line in between paragraphs and needs to be ignored)
// In that case we join all of the paragraph lines with a single space,
// add a trailing newline character (to ensure an empty line after the paragraph),
// append the paragraph text to the output and clear everything in the current paragraph slice.
output = append(output, strings.Join(paragraph, " ")+"\n")
paragraph = []string{}
}
} else {
// Non-empty text line, append it to the current paragraph
paragraph = append(paragraph, trimmedLine)
if strings.HasSuffix(line, " ") {
// If the original line has a suffix of couple of spaces, then we add a line break.
// This is achieved by flushing out the current paragraph and starting a new one.
// No trailing space is added to the flushed paragraph,
// so that no empty line is placed between the old and the new paragraphs (a simple line break)
output = append(output, strings.Join(paragraph, " "))
paragraph = []string{}
}
}
}
// The last paragraph is always unflushed, so flush it.
// We don't add a trailing newline character, so that we won't have to strip the output.
output = append(output, strings.Join(paragraph, " "))
// Join all the paragraphs together with new lines in between them.
return strings.Join(output, "\n")
}
// Examples is designed to help with producing examples for command line usage.
// Its behavior is mimicking a similar kubectl function in the following ways:
// - Beginning and trailing space characters (including empty lines), are stripped from the output.
// - All lines of text are stripped of beginning and trailing spaces (thus loosing indentation) and are then double-space indented.
func Examples(s string) string {
trimmedText := strings.TrimSpace(s)
if trimmedText == "" {
return ""
}
const indent = ` `
inLines := strings.Split(trimmedText, "\n")
outLines := make([]string, 0, len(inLines))
for _, line := range inLines {
outLines = append(outLines, indent+strings.TrimSpace(line))
}
return strings.Join(outLines, "\n")
}

View File

@ -0,0 +1,117 @@
/*
Copyright 2019 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package util
import (
"testing"
)
func TestLongDesc(t *testing.T) {
tests := []struct {
desc string
in string
out string
}{
{
desc: "Empty input produces empty output",
in: "",
out: "",
},
{
desc: "Single line text is preserved as is",
in: "Some text",
out: "Some text",
},
{
desc: "Consecutive new lines are combined into a single paragraph",
in: "Line1\nLine2",
out: "Line1 Line2",
},
{
desc: "Leading and trailing spaces are stripped (single line)",
in: "\t \nThe text line \n \t",
out: "The text line",
},
{
desc: "Leading and trailing spaces are stripped (multi line)",
in: "\t \nLine1\nLine2 \n \t",
out: "Line1 Line2",
},
{
desc: "Multiple paragraphs are separated by a single empty line",
in: "Paragraph1\n\nParagraph2\n\n\nParagraph3",
out: "Paragraph1\n\nParagraph2\n\nParagraph3",
},
{
desc: "Indentation is not preserved",
in: "\tParagraph1Line1\n\tParagraph1Line2\n\n Paragraph2Line1\n Paragraph2Line2",
out: "Paragraph1Line1 Paragraph1Line2\n\nParagraph2Line1 Paragraph2Line2",
},
{
desc: "Double spaced line breaks",
in: "Line1 \nLine2",
out: "Line1\nLine2",
},
{
desc: "Double spaced line breaks don't preserve indentation",
in: "\tLine1 \n\tLine2",
out: "Line1\nLine2",
},
}
for _, test := range tests {
t.Run(test.desc, func(t *testing.T) {
got := LongDesc(test.in)
if got != test.out {
t.Errorf("expected(%d):\n%s\n=====\ngot(%d):\n%s\n", len(test.out), test.out, len(got), got)
}
})
}
}
func TestExamples(t *testing.T) {
tests := []struct {
desc string
in string
out string
}{
{
desc: "Empty input produces empty output",
in: "",
out: "",
},
{
desc: "Text is indented with a couple of spaces",
in: "\tLine1\n\tLine2",
out: " Line1\n Line2",
},
{
desc: "Text is stripped of leading and trailing spaces",
in: "\t\n\tLine1\t \n\tLine2\t \n\t\n\n",
out: " Line1\n Line2",
},
}
for _, test := range tests {
t.Run(test.desc, func(t *testing.T) {
got := Examples(test.in)
if got != test.out {
t.Errorf("expected(%d):\n%s\n=====\ngot(%d):\n%s\n", len(test.out), test.out, len(got), got)
}
})
}
}