diff --git a/cmd/update.go b/cmd/update.go index bb5ebf758..7d10f6cbd 100644 --- a/cmd/update.go +++ b/cmd/update.go @@ -33,7 +33,7 @@ func init() { cmdUpdate.Flags().BoolVar(&updateOpts.prettyPrint, "pretty-print", false, "Pretty print the resulting CloudFormation") cmdUpdate.Flags().BoolVar(&updateOpts.skipWait, "skip-wait", false, "Don't wait the resources finish") cmdUpdate.Flags().BoolVar(&updateOpts.force, "force", false, "Don't ask for confirmation") - cmdUpdate.Flags().StringSliceVar(&updateOpts.targets, "targets", root.AllOperationTargetsAsStringSlice(), "Update nothing but specified sub-stacks. Defaults to `etcd,controller,worker`") + cmdUpdate.Flags().StringSliceVar(&updateOpts.targets, "targets", root.AllOperationTargetsAsStringSlice(), "Update nothing but specified sub-stacks. Specify `all` or any combination of `etcd`, `control-plane`, and node pool names. Defaults to `all`") } func runCmdUpdate(cmd *cobra.Command, args []string) error { @@ -49,11 +49,13 @@ func runCmdUpdate(cmd *cobra.Command, args []string) error { return fmt.Errorf("Failed to read cluster config: %v", err) } - if _, err := cluster.ValidateStack(); err != nil { + targets := root.OperationTargetsFromStringSlice(updateOpts.targets) + + if _, err := cluster.ValidateStack(targets); err != nil { return err } - report, err := cluster.Update(root.OperationTargetsFromStringSlice(updateOpts.targets)) + report, err := cluster.Update(targets) if err != nil { return fmt.Errorf("Error updating cluster: %v", err) } diff --git a/cmd/validate.go b/cmd/validate.go index 1c3ea949b..713880c12 100644 --- a/cmd/validate.go +++ b/cmd/validate.go @@ -21,6 +21,7 @@ var ( awsDebug bool skipWait bool s3URI string + targets []string }{} ) @@ -32,6 +33,11 @@ func init() { false, "Log debug information from aws-sdk-go library", ) + cmdValidate.Flags().StringSliceVar( + &validateOpts.targets, + "targets", + root.AllOperationTargetsAsStringSlice(), + "Validate nothing but specified sub-stacks. Specify `all` or any combination of `etcd`, `control-plane`, and node pool names. Defaults to `all`") } func runCmdValidate(cmd *cobra.Command, args []string) error { @@ -43,7 +49,10 @@ func runCmdValidate(cmd *cobra.Command, args []string) error { } fmt.Printf("Validating UserData and stack template...\n") - report, err := cluster.ValidateStack() + + targets := root.OperationTargetsFromStringSlice(validateOpts.targets) + + report, err := cluster.ValidateStack(targets) if report != "" { fmt.Fprintf(os.Stderr, "Validation Report: %s\n", report) } diff --git a/core/controlplane/cluster/cluster.go b/core/controlplane/cluster/cluster.go index 55ed13adc..ee539a52e 100644 --- a/core/controlplane/cluster/cluster.go +++ b/core/controlplane/cluster/cluster.go @@ -13,9 +13,9 @@ import ( "github.com/kubernetes-incubator/kube-aws/cfnstack" "github.com/kubernetes-incubator/kube-aws/core/controlplane/config" "github.com/kubernetes-incubator/kube-aws/model" + "github.com/kubernetes-incubator/kube-aws/naming" "github.com/kubernetes-incubator/kube-aws/plugin/clusterextension" "github.com/kubernetes-incubator/kube-aws/plugin/pluginmodel" - "github.com/kubernetes-incubator/kube-aws/naming" ) // VERSION set by build script diff --git a/core/controlplane/config/config.go b/core/controlplane/config/config.go index 7e1ce4ee1..fb3ef3eeb 100644 --- a/core/controlplane/config/config.go +++ b/core/controlplane/config/config.go @@ -17,11 +17,11 @@ import ( "github.com/kubernetes-incubator/kube-aws/gzipcompressor" "github.com/kubernetes-incubator/kube-aws/model" "github.com/kubernetes-incubator/kube-aws/model/derived" + "github.com/kubernetes-incubator/kube-aws/naming" "github.com/kubernetes-incubator/kube-aws/netutil" "github.com/kubernetes-incubator/kube-aws/node" "github.com/kubernetes-incubator/kube-aws/plugin/pluginmodel" "gopkg.in/yaml.v2" - "github.com/kubernetes-incubator/kube-aws/naming" ) const ( @@ -962,7 +962,7 @@ func (c Cluster) StackConfig(stackName string, opts StackTemplateOptions, extra var err error stackConfig := StackConfig{ - StackName: stackName, + StackName: stackName, ExtraCfnResources: map[string]interface{}{}, } diff --git a/core/etcd/cluster/cluster.go b/core/etcd/cluster/cluster.go index 2782a9ac3..6c5c486a3 100644 --- a/core/etcd/cluster/cluster.go +++ b/core/etcd/cluster/cluster.go @@ -10,9 +10,9 @@ import ( "github.com/kubernetes-incubator/kube-aws/cfnstack" "github.com/kubernetes-incubator/kube-aws/core/controlplane/config" "github.com/kubernetes-incubator/kube-aws/model" + "github.com/kubernetes-incubator/kube-aws/naming" "github.com/kubernetes-incubator/kube-aws/plugin/clusterextension" "github.com/kubernetes-incubator/kube-aws/plugin/pluginmodel" - "github.com/kubernetes-incubator/kube-aws/naming" ) // VERSION set by build script diff --git a/core/network/cluster/cluster.go b/core/network/cluster/cluster.go index 08a88bc1f..01ba4f258 100644 --- a/core/network/cluster/cluster.go +++ b/core/network/cluster/cluster.go @@ -10,8 +10,8 @@ import ( "github.com/kubernetes-incubator/kube-aws/cfnstack" "github.com/kubernetes-incubator/kube-aws/core/controlplane/config" "github.com/kubernetes-incubator/kube-aws/model" - "github.com/kubernetes-incubator/kube-aws/plugin/pluginmodel" "github.com/kubernetes-incubator/kube-aws/naming" + "github.com/kubernetes-incubator/kube-aws/plugin/pluginmodel" ) // VERSION set by build script diff --git a/core/root/cluster.go b/core/root/cluster.go index 147abf0f8..b48b3000e 100644 --- a/core/root/cluster.go +++ b/core/root/cluster.go @@ -111,7 +111,7 @@ type Cluster interface { EstimateCost() ([]string, error) Info() (*Info, error) Update(OperationTargets) (string, error) - ValidateStack() (string, error) + ValidateStack(...OperationTargets) (string, error) ValidateTemplates() error ControlPlane() *controlplane.Cluster NodePools() []*nodepool.Cluster @@ -238,10 +238,28 @@ func (c clusterImpl) NodePools() []*nodepool.Cluster { return c.nodePools } +func (c clusterImpl) allOperationTargets() OperationTargets { + names := []string{} + for _, np := range c.nodePools { + names = append(names, np.NodePoolName) + } + return AllOperationTargetsWith(names) +} + +func (c clusterImpl) operationTargetsFromUserInput(opts []OperationTargets) OperationTargets { + var targets OperationTargets + if len(opts) > 0 && !opts[0].IsAll() { + targets = OperationTargetsFromStringSlice(opts[0]) + } else { + targets = c.allOperationTargets() + } + return targets +} + func (c clusterImpl) Create() error { cfSvc := cloudformation.New(c.session) - assets, err := c.generateAssets(AllOperationTargets()) + assets, err := c.generateAssets(c.allOperationTargets()) if err != nil { return err } @@ -305,13 +323,11 @@ func (c clusterImpl) generateAssets(targets OperationTargets) (cfnstack.Assets, } var wAssets cfnstack.Assets - if targets.IncludeWorker() { - wAssets = cfnstack.EmptyAssets() - for _, np := range c.nodePools { + wAssets = cfnstack.EmptyAssets() + for _, np := range c.nodePools { + if targets.IncludeWorker(np.NodePoolName) { wAssets = wAssets.Merge(np.Assets()) } - } else { - wAssets = cfnstack.EmptyAssets() } nestedStacksAssets := netAssets.Merge(cpAssets).Merge(etcdAssets).Merge(wAssets) @@ -324,30 +340,39 @@ func (c clusterImpl) generateAssets(targets OperationTargets) (cfnstack.Assets, var stackTemplate string // Do not update the root stack but update either controlplane or worker stack(s) only when specified so - if targets.IncludeAll() { + includeAll := targets.IncludeNetwork() && targets.IncludeEtcd() && targets.IncludeControlPlane() + for _, np := range c.nodePools { + includeAll = includeAll && targets.IncludeWorker(np.NodePoolName) + } + if includeAll { renderedTemplate, err := c.renderTemplateAsString() if err != nil { return nil, fmt.Errorf("failed to render template : %v", err) } stackTemplate = renderedTemplate } else { - target := targets[0] + for _, target := range targets { + fmt.Printf("updating template url of %s\n", target) - rootStackTemplate, err := c.getCurrentRootStackTemplate() - if err != nil { - return nil, fmt.Errorf("failed to render template : %v", err) - } + rootStackTemplate, err := c.getCurrentRootStackTemplate() + if err != nil { + return nil, fmt.Errorf("failed to render template : %v", err) + } - a, err := nestedStacksAssets.FindAssetByStackAndFileName(target, REMOTE_STACK_TEMPLATE_FILENAME) + a, err := nestedStacksAssets.FindAssetByStackAndFileName(target, REMOTE_STACK_TEMPLATE_FILENAME) + if err != nil { + return nil, fmt.Errorf("failed to find assets for stack %s: %v", target, err) + } - nestedStackTemplateURL, err := a.URL() - if err != nil { - return nil, fmt.Errorf("failed to locate %s stack template url: %v", target, err) - } + nestedStackTemplateURL, err := a.URL() + if err != nil { + return nil, fmt.Errorf("failed to locate %s stack template url: %v", target, err) + } - stackTemplate, err = c.setNestedStackTemplateURL(rootStackTemplate, target, nestedStackTemplateURL) - if err != nil { - return nil, fmt.Errorf("failed to update stack template: %v", err) + stackTemplate, err = c.setNestedStackTemplateURL(rootStackTemplate, target, nestedStackTemplateURL) + if err != nil { + return nil, fmt.Errorf("failed to update stack template: %v", err) + } } } rootStackAssetsBuilder.Add(REMOTE_STACK_TEMPLATE_FILENAME, stackTemplate) @@ -392,7 +417,7 @@ func (c clusterImpl) extractRootStackTemplateURL(assets cfnstack.Assets) (string } func (c clusterImpl) Assets() (cfnstack.Assets, error) { - return c.generateAssets(AllOperationTargets()) + return c.generateAssets(c.allOperationTargets()) } func (c clusterImpl) templatePath() string { @@ -501,10 +526,12 @@ func (c clusterImpl) ValidateTemplates() error { } // ValidateStack validates all the CloudFormation stack templates already uploaded to S3 -func (c clusterImpl) ValidateStack() (string, error) { +func (c clusterImpl) ValidateStack(opts ...OperationTargets) (string, error) { reports := []string{} - assets, err := c.generateAssets(AllOperationTargets()) + targets := c.operationTargetsFromUserInput(opts) + + assets, err := c.generateAssets(targets) if err != nil { return "", err } diff --git a/core/root/operation_targets.go b/core/root/operation_targets.go index a7cbe0d22..31221a2f1 100644 --- a/core/root/operation_targets.go +++ b/core/root/operation_targets.go @@ -4,36 +4,38 @@ import "strings" // TODO: Add etcd const ( - OperationTargetWorker = "worker" OperationTargetControlPlane = "control-plane" OperationTargetEtcd = "etcd" OperationTargetNetwork = "network" + OperationTargetAll = "all" ) var OperationTargetNames = []string{ OperationTargetControlPlane, OperationTargetEtcd, - OperationTargetWorker, OperationTargetNetwork, } type OperationTargets []string func AllOperationTargetsAsStringSlice() []string { - return OperationTargetNames + return []string{"all"} } -func AllOperationTargets() OperationTargets { - return OperationTargets(OperationTargetNames) +func AllOperationTargetsWith(nodePoolNames []string) OperationTargets { + ts := []string{} + ts = append(ts, OperationTargetNames...) + ts = append(ts, nodePoolNames...) + return OperationTargets(ts) } func OperationTargetsFromStringSlice(targets []string) OperationTargets { return OperationTargets(targets) } -func (ts OperationTargets) IncludeWorker() bool { +func (ts OperationTargets) IncludeWorker(nodePoolName string) bool { for _, t := range ts { - if t == OperationTargetWorker { + if t == nodePoolName { return true } } @@ -67,18 +69,13 @@ func (ts OperationTargets) IncludeEtcd() bool { return false } -func (ts OperationTargets) IncludeAll() bool { - w := false - c := false - e := false - n := false +func (ts OperationTargets) IsAll() bool { for _, t := range ts { - w = w || t == OperationTargetWorker - c = c || t == OperationTargetControlPlane - e = e || t == OperationTargetEtcd - n = n || t == OperationTargetNetwork + if t == OperationTargetAll { + return true + } } - return w && c && e && n + return false } func (ts OperationTargets) String() string { diff --git a/core/root/template_params.go b/core/root/template_params.go index f4350ebb5..c3439c6eb 100644 --- a/core/root/template_params.go +++ b/core/root/template_params.go @@ -4,9 +4,9 @@ import ( "fmt" controlplane "github.com/kubernetes-incubator/kube-aws/core/controlplane/cluster" - network "github.com/kubernetes-incubator/kube-aws/core/network/cluster" - etcd "github.com/kubernetes-incubator/kube-aws/core/etcd/cluster" config "github.com/kubernetes-incubator/kube-aws/core/controlplane/config" + etcd "github.com/kubernetes-incubator/kube-aws/core/etcd/cluster" + network "github.com/kubernetes-incubator/kube-aws/core/network/cluster" nodepool "github.com/kubernetes-incubator/kube-aws/core/nodepool/cluster" )