-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
cli: Introduce an upgrade command #2564
Merged
Merged
Changes from 10 commits
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
c4383da
cli: Introduce an upgrade command
olix0r 292f1da
const up issuer file names
olix0r e813001
fixup doc
olix0r 83ad264
fixup lint
olix0r b72b057
fixup error message
olix0r f394fae
Only expose flags when they can be used
olix0r 4095c7d
remove stupid printlns
olix0r e23d85c
fixup kube client constructor
olix0r 85447ac
fixup per review
olix0r 7068101
flagSet reorg
olix0r eead6d9
clarify recordableFlagSet
olix0r 374562e
bump ci
olix0r File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -208,25 +208,51 @@ func newCmdInstall() *cobra.Command { | |
Short: "Output Kubernetes configs to install Linkerd", | ||
Long: "Output Kubernetes configs to install Linkerd.", | ||
RunE: func(cmd *cobra.Command, args []string) error { | ||
options.recordFlags(flags) | ||
if !options.ignoreCluster { | ||
exitIfClusterExists() | ||
} | ||
|
||
values, configs, err := options.validateAndBuild() | ||
values, configs, err := options.validateAndBuild(flags) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
return values.render(os.Stdout, configs) | ||
}, | ||
} | ||
|
||
cmd.PersistentFlags().AddFlagSet(flags) | ||
|
||
// Issuer flags are currently only supported on the initial install. | ||
cmd.PersistentFlags().AddFlagSet(options.issuerFlagSet(pflag.ExitOnError)) | ||
// Some flags are not available during upgrade, etc. | ||
cmd.PersistentFlags().AddFlagSet(options.flagSet(pflag.ExitOnError)) | ||
|
||
return cmd | ||
} | ||
|
||
func (options *installOptions) flagSet(e pflag.ErrorHandling) *pflag.FlagSet { | ||
func (options *installOptions) validateAndBuild(flags *pflag.FlagSet) (*installValues, *pb.All, error) { | ||
if err := options.validate(); err != nil { | ||
return nil, nil, err | ||
} | ||
options.recordFlags(flags) | ||
|
||
identityValues, err := options.identityOptions.validateAndBuild() | ||
if err != nil { | ||
return nil, nil, err | ||
} | ||
|
||
configs := options.configs(identityValues.toIdentityContext()) | ||
|
||
values, err := options.buildValuesWithoutIdentity(configs) | ||
if err != nil { | ||
return nil, nil, err | ||
} | ||
values.Identity = identityValues | ||
|
||
return values, configs, nil | ||
} | ||
|
||
// flagSet returns flags usable during install or upgrade. | ||
func (options *installOptions) baseFlagSet(e pflag.ErrorHandling) *pflag.FlagSet { | ||
flags := pflag.NewFlagSet("install", e) | ||
|
||
flags.AddFlagSet(options.proxyConfigOptions.flagSet(e)) | ||
|
@@ -259,12 +285,17 @@ func (options *installOptions) flagSet(e pflag.ErrorHandling) *pflag.FlagSet { | |
&options.identityOptions.issuanceLifetime, "identity-issuance-lifetime", options.identityOptions.issuanceLifetime, | ||
"The amount of time for which the Identity issuer should certify identity", | ||
) | ||
flags.DurationVar( | ||
&options.identityOptions.clockSkewAllowance, "identity-clock-skew-allowance", options.identityOptions.clockSkewAllowance, | ||
"The amount of time to allow for clock skew within a Linkerd cluster", | ||
) | ||
|
||
return flags | ||
} | ||
|
||
func (options *installOptions) issuerFlagSet(e pflag.ErrorHandling) *pflag.FlagSet { | ||
flags := pflag.NewFlagSet("issuer", e) | ||
// installOnlyFlagSet includes flags that are only accessible at install-time and not at upgrade-time. | ||
func (options *installOptions) flagSet(e pflag.ErrorHandling) *pflag.FlagSet { | ||
flags := options.baseFlagSet(e) | ||
|
||
flags.StringVar( | ||
&options.identityOptions.trustDomain, "identity-trust-domain", options.identityOptions.trustDomain, | ||
|
@@ -282,13 +313,10 @@ func (options *installOptions) issuerFlagSet(e pflag.ErrorHandling) *pflag.FlagS | |
&options.identityOptions.keyPEMFile, "identity-issuer-key-file", options.identityOptions.keyPEMFile, | ||
"A path to a PEM-encoded file containing the Linkerd Identity issuer private key (generated by default)", | ||
) | ||
flags.DurationVar( | ||
&options.identityOptions.clockSkewAllowance, "identity-clock-skew-allowance", options.identityOptions.clockSkewAllowance, | ||
"The amount of time to allow for clock skew within a Linkerd cluster", | ||
) | ||
flags.DurationVar( | ||
&options.identityOptions.issuanceLifetime, "identity-issuance-lifetime", options.identityOptions.issuanceLifetime, | ||
"The amount of time for which the Identity issuer should certify identity", | ||
|
||
flags.BoolVar( | ||
&options.ignoreCluster, "ignore-cluster", options.ignoreCluster, | ||
"Ignore the current Kubernetes cluster when checking for existing cluster configuration (default false)", | ||
) | ||
|
||
return flags | ||
|
@@ -331,26 +359,6 @@ func (options *installOptions) validate() error { | |
return errors.New("--proxy-log-level must not be empty") | ||
} | ||
|
||
if !options.ignoreCluster { | ||
exists, err := linkerdConfigAlreadyExistsInCluster() | ||
if err != nil { | ||
fmt.Fprintln(os.Stderr, "Unable to connect to a Kubernetes cluster to check for configuration. If this expected, use the --ignore-cluster flag.") | ||
os.Exit(1) | ||
} | ||
if exists { | ||
fmt.Fprintln(os.Stderr, "You are already running a control plane. If you would like to ignore its configuration, use the --ignore-cluster flag.") | ||
os.Exit(1) | ||
} | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func (options *installOptions) validateAndBuild() (*installValues, *pb.All, error) { | ||
if err := options.validate(); err != nil { | ||
return nil, nil, err | ||
} | ||
|
||
if options.highAvailability { | ||
if options.controllerReplicas == defaultControllerReplicas { | ||
options.controllerReplicas = defaultHAControllerReplicas | ||
|
@@ -366,16 +374,14 @@ func (options *installOptions) validateAndBuild() (*installValues, *pb.All, erro | |
} | ||
|
||
options.identityOptions.replicas = options.controllerReplicas | ||
identityValues, err := options.identityOptions.validateAndBuild() | ||
if err != nil { | ||
return nil, nil, err | ||
} | ||
|
||
configs := options.configs(identityValues.toIdentityContext()) | ||
return nil | ||
} | ||
|
||
func (options *installOptions) buildValuesWithoutIdentity(configs *pb.All) (*installValues, error) { | ||
globalJSON, proxyJSON, installJSON, err := config.ToJSON(configs) | ||
if err != nil { | ||
return nil, nil, err | ||
return nil, err | ||
} | ||
|
||
values := &installValues{ | ||
|
@@ -410,8 +416,6 @@ func (options *installOptions) validateAndBuild() (*installValues, *pb.All, erro | |
Proxy: proxyJSON, | ||
Install: installJSON, | ||
}, | ||
|
||
Identity: identityValues, | ||
} | ||
|
||
if options.highAvailability { | ||
|
@@ -438,7 +442,7 @@ func (options *installOptions) validateAndBuild() (*installValues, *pb.All, erro | |
} | ||
} | ||
|
||
return values, configs, nil | ||
return values, nil | ||
} | ||
|
||
func toPromLogLevel(level string) string { | ||
|
@@ -622,42 +626,48 @@ func (options *installOptions) proxyConfig() *pb.Proxy { | |
} | ||
} | ||
|
||
// linkerdConfigAlreadyExistsInCluster checks the kubernetes API to determine | ||
// whether a config exists. | ||
// exitIfClusterExists checks the kubernetes API to determine | ||
// whether a config exists and exits if it does exist or if an error is | ||
// encountered. | ||
// | ||
// This bypasses the public API so that public API errors cannot cause us to | ||
// misdiagnose a controller error to indicate that no control plane exists. | ||
// | ||
// If we cannot determine whether the configuration exists, an error is returned. | ||
func linkerdConfigAlreadyExistsInCluster() (bool, error) { | ||
api, err := k8s.NewAPI(kubeconfigPath, kubeContext) | ||
func exitIfClusterExists() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Other than the error handling, this looks very similar to the func exitIfClusterExists() {
- kubeConfig, err := k8s.GetConfig(kubeconfigPath, kubeContext)
+ k, err := newK8s()
if err != nil {
fmt.Fprintln(os.Stderr, "Unable to build a Kubernetes client to check for configuration. If this expected, use the --ignore-cluster flag.")
fmt.Fprintf(os.Stderr, "Error: %s\n", err)
os.Exit(1)
}
- k, err := kubernetes.NewForConfig(kubeConfig)
+ _, err = fetchConfigs(k)
if err != nil {
- fmt.Fprintln(os.Stderr, "Unable to build a Kubernetes client to check for configuration. If this expected, use the --ignore-cluster flag.")
- fmt.Fprintf(os.Stderr, "Error: %s\n", err)
- os.Exit(1)
- }
-
- c := k.CoreV1().ConfigMaps(controlPlaneNamespace)
- if _, err = c.Get(k8s.ConfigConfigMapName, metav1.GetOptions{}); err != nil {
if kerrors.IsNotFound(err) {
return
} |
||
kubeConfig, err := k8s.GetConfig(kubeconfigPath, kubeContext) | ||
if err != nil { | ||
return false, err | ||
fmt.Fprintln(os.Stderr, "Unable to build a Kubernetes client to check for configuration. If this expected, use the --ignore-cluster flag.") | ||
fmt.Fprintf(os.Stderr, "Error: %s\n", err) | ||
os.Exit(1) | ||
} | ||
|
||
k, err := kubernetes.NewForConfig(api.Config) | ||
k, err := kubernetes.NewForConfig(kubeConfig) | ||
if err != nil { | ||
return false, err | ||
fmt.Fprintln(os.Stderr, "Unable to build a Kubernetes client to check for configuration. If this expected, use the --ignore-cluster flag.") | ||
olix0r marked this conversation as resolved.
Show resolved
Hide resolved
|
||
fmt.Fprintf(os.Stderr, "Error: %s\n", err) | ||
os.Exit(1) | ||
} | ||
|
||
c := k.CoreV1().ConfigMaps(controlPlaneNamespace) | ||
if _, err = c.Get(k8s.ConfigConfigMapName, metav1.GetOptions{}); err != nil { | ||
if kerrors.IsNotFound(err) { | ||
return false, nil | ||
return | ||
} | ||
|
||
return false, err | ||
fmt.Fprintln(os.Stderr, "Unable to build a Kubernetes client to check for configuration. If this expected, use the --ignore-cluster flag.") | ||
fmt.Fprintf(os.Stderr, "Error: %s\n", err) | ||
os.Exit(1) | ||
} | ||
|
||
return true, nil | ||
fmt.Fprintln(os.Stderr, "Linkerd has already been installed on your cluster in the linkerd namespace. Please run upgrade if you'd like to update this installation. Otherwise, use the --ignore-cluster flag.") | ||
os.Exit(1) | ||
} | ||
|
||
func (idopts *installIdentityOptions) validate() error { | ||
if idopts == nil { | ||
return nil | ||
} | ||
|
||
if idopts.trustDomain == "" { | ||
if idopts.trustDomain != "" { | ||
if errs := validation.IsDNS1123Subdomain(idopts.trustDomain); len(errs) > 0 { | ||
return fmt.Errorf("invalid trust domain '%s': %s", idopts.trustDomain, errs[0]) | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i think this is redundant with line 204:
flags := options.flagSet(pflag.ExitOnError)
?