cmd/utils/flags.go (131 lines of code) (raw):

// Copyright (c) Microsoft Corporation. // Licensed under the MIT License. package utils import ( "errors" "fmt" "strings" "github.com/spf13/cobra" "github.com/Azure/kubectl-aks/cmd/utils/config" ) const ( NodeKey = "node" SubscriptionIDKey = "subscription" ResourceGroupKey = "resource-group" ClusterNameKey = "cluster-name" NodeResourceGroupKey = "node-resource-group" VMSSKey = "vmss" VMSSInstanceIDKey = "instance-id" ResourceIDKey = "id" ) // We need package level variables to ensure that the viper flag binding works correctly. // See: https://github.com/spf13/viper/issues/375#issuecomment-578552586 var ( node string subscriptionID string nodeResourceGroup string vmss string vmssInstanceID string resourceID string ) // CommonFlags contains CLI flags common for all subcommands type CommonFlags struct { Verbose bool } func AddCommonFlags(command *cobra.Command, flags *CommonFlags) { command.PersistentFlags().BoolVarP( &flags.Verbose, "verbose", "v", false, "Verbose output.", ) } // AddNodeFlags adds node flags and binds them to config/environment variables // Every command that allows user to specify the node name has three options: // (1) Provide the kubernetes node name // (2) Provide the VMMS instance information (--subscription, --node-resource-group, --vmss and --instance-id) // (3) Provide Resource ID (/subscriptions/mySubID/resourceGroups/myRG/providers/myProvider/virtualMachineScaleSets/myVMSS/virtualMachines/myInsID) func AddNodeFlags(command *cobra.Command) { addNodeFlags(command, false) } // AddNodeFlagsOnly adds node flags without binding config/environment variables func AddNodeFlagsOnly(command *cobra.Command) { addNodeFlags(command, true) } func addNodeFlags(command *cobra.Command, useFlagsOnly bool) { command.PersistentFlags().StringVarP( &node, NodeKey, "", "", "Kubernetes node name.", ) command.PersistentFlags().StringVarP( &subscriptionID, SubscriptionIDKey, "", "", "Subscription ID.", ) command.PersistentFlags().StringVarP( &nodeResourceGroup, NodeResourceGroupKey, "", "", "Node resource group name.", ) command.PersistentFlags().StringVarP( &vmss, VMSSKey, "", "", "Virtual machine scale set name.", ) command.PersistentFlags().StringVarP( &vmssInstanceID, VMSSInstanceIDKey, "", "", "VM scale set instance ID.", ) command.PersistentFlags().StringVarP( &resourceID, ResourceIDKey, "", "", `Resource ID containing all information of the VMSS instance using format: e.g. /subscriptions/mySubID/resourceGroups/myRG/providers/myProvider/virtualMachineScaleSets/myVMSS/virtualMachines/myInsID. Notice it is not case sensitive.`, ) command.PersistentPreRunE = func(cmd *cobra.Command, args []string) error { // If node or resource ID is set, we don't need to read the config file // nor the environment variables because the CLI flags have precedence. if !useFlagsOnly && node == "" && resourceID == "" { config := config.New() if cc, ok := config.CurrentConfig(); ok { config = cc } // bind environment variables config.AutomaticEnv() config.SetEnvPrefix("kubectl_aks") config.SetEnvKeyReplacer(strings.NewReplacer(".", "_")) // bind CLI flags if err := config.BindPFlags(cmd.PersistentFlags()); err != nil { return fmt.Errorf("binding flags: %w", err) } // set the values with precedence: // (1) CLI flag // (2) environment variable // (3) config file node = config.GetString(NodeKey) subscriptionID = config.GetString(SubscriptionIDKey) nodeResourceGroup = config.GetString(NodeResourceGroupKey) vmss = config.GetString(VMSSKey) vmssInstanceID = config.GetString(VMSSInstanceIDKey) resourceID = config.GetString(ResourceIDKey) } // validate the parameters var nodeSet, vmssInfoSet, resourceIDSet bool if node != "" { nodeSet = true } if subscriptionID != "" && nodeResourceGroup != "" && vmss != "" && vmssInstanceID != "" { vmssInfoSet = true } if resourceID != "" { resourceIDSet = true } if !nodeSet && !vmssInfoSet && !resourceIDSet { if subscriptionID != "" || nodeResourceGroup != "" || vmss != "" || vmssInstanceID != "" { return errors.New("specify complete VMMS instance information ('subscription', 'node-resource-group', 'vmss' and 'instance-id')") } return errors.New("specify either 'node' or 'id' or VMMS instance information ('subscription', 'node-resource-group', 'vmss' and 'instance-id')") } else if nodeSet { if vmssInfoSet { return errors.New("specify either 'node' or VMMS instance information ('subscription', 'node-resource-group', 'vmss' and 'instance-id')") } if resourceIDSet { return errors.New("specify either 'node' or 'id'") } } else if vmssInfoSet { if resourceIDSet { return errors.New("specify either VMMS instance information ('subscription', 'node-resource-group', 'vmss' and 'instance-id') or 'id'") } } return nil } }