github.com/olli-ai/jx/v2@v2.0.400-0.20210921045218-14731b4dd448/pkg/cmd/create/create_variable.go (about)

     1  package create
     2  
     3  import (
     4  	"fmt"
     5  	"path/filepath"
     6  
     7  	"github.com/olli-ai/jx/v2/pkg/cmd/create/options"
     8  
     9  	"github.com/olli-ai/jx/v2/pkg/cmd/helper"
    10  
    11  	"github.com/jenkins-x/jx-logging/pkg/log"
    12  	"github.com/olli-ai/jx/v2/pkg/cmd/opts"
    13  	"github.com/olli-ai/jx/v2/pkg/cmd/templates"
    14  	"github.com/olli-ai/jx/v2/pkg/config"
    15  	"github.com/olli-ai/jx/v2/pkg/jenkinsfile"
    16  	"github.com/olli-ai/jx/v2/pkg/jenkinsfile/gitresolver"
    17  	"github.com/olli-ai/jx/v2/pkg/kube"
    18  	"github.com/olli-ai/jx/v2/pkg/util"
    19  	"github.com/pkg/errors"
    20  	"github.com/spf13/cobra"
    21  )
    22  
    23  var (
    24  	createVariableLong = templates.LongDesc(`
    25  		Creates an environment variable in the Jenkins X Pipeline
    26  `)
    27  
    28  	createVariableExample = templates.Examples(`
    29  		# Create a new environment variable with a name and value
    30  		jx create var -n CHEESE -v Edam
    31  
    32  		# Create a new environment variable with a name and ask the user for the value
    33  		jx create var -n CHEESE 
    34  
    35  		# Overrides an environment variable from the build pack
    36  		jx create var 
    37  	`)
    38  )
    39  
    40  // CreateVariableOptions the options for the create spring command
    41  type CreateVariableOptions struct {
    42  	options.CreateOptions
    43  
    44  	Dir   string
    45  	Name  string
    46  	Value string
    47  }
    48  
    49  // NewCmdCreateVariable creates a command object for the "create" command
    50  func NewCmdCreateVariable(commonOpts *opts.CommonOptions) *cobra.Command {
    51  	options := &CreateVariableOptions{
    52  		CreateOptions: options.CreateOptions{
    53  			CommonOptions: commonOpts,
    54  		},
    55  	}
    56  
    57  	cmd := &cobra.Command{
    58  		Use:     "variable",
    59  		Short:   "Creates an environment variable in the Jenkins X Pipeline",
    60  		Aliases: []string{"var", "envvar"},
    61  		Long:    createVariableLong,
    62  		Example: createVariableExample,
    63  		Run: func(cmd *cobra.Command, args []string) {
    64  			options.Cmd = cmd
    65  			options.Args = args
    66  			err := options.Run()
    67  			helper.CheckErr(err)
    68  		},
    69  	}
    70  
    71  	cmd.Flags().StringVarP(&options.Name, "name", "n", "", "The name of the environment variable to set")
    72  	cmd.Flags().StringVarP(&options.Value, "value", "v", "", "The value of the environment variable to set")
    73  	cmd.Flags().StringVarP(&options.Dir, "dir", "d", "", "The root project directory. Defaults to the current dir")
    74  	return cmd
    75  }
    76  
    77  // Run implements the command
    78  func (o *CreateVariableOptions) Run() error {
    79  	dir := o.Dir
    80  	var err error
    81  	if dir == "" {
    82  		dir, _, err := o.Git().FindGitConfigDir(o.Dir)
    83  		if err != nil {
    84  			return err
    85  		}
    86  		if dir == "" {
    87  			dir = "."
    88  		}
    89  	}
    90  	projectConfig, fileName, err := config.LoadProjectConfig(dir)
    91  	if err != nil {
    92  		return err
    93  	}
    94  	enrichedProjectConfig, _, err := config.LoadProjectConfig(dir)
    95  	if err != nil {
    96  		return err
    97  	}
    98  
    99  	name := o.Name
   100  	value := o.Value
   101  	if o.BatchMode {
   102  		if name == "" {
   103  			return util.MissingOption("name")
   104  		}
   105  		if value == "" {
   106  			return util.MissingOption("value")
   107  		}
   108  	}
   109  
   110  	defaultValues, err := o.loadEnvVars(enrichedProjectConfig)
   111  	if err != nil {
   112  		return err
   113  	}
   114  	keys := util.SortedMapKeys(defaultValues)
   115  
   116  	if name == "" {
   117  		message := "environment variable name: "
   118  		help := "the name of the environment variable which is usually upper case without spaces or dashes"
   119  		if len(keys) == 0 {
   120  			name, err = util.PickValue(message, "", true, help, o.GetIOFileHandles())
   121  		} else {
   122  			name, err = util.PickName(keys, message, help, o.GetIOFileHandles())
   123  		}
   124  		if err != nil {
   125  			return err
   126  		}
   127  		if name == "" {
   128  			return util.MissingOption("name")
   129  		}
   130  	}
   131  	if value == "" {
   132  		message := "environment variable value: "
   133  		value, err = util.PickValue(message, defaultValues[name], true, "", o.GetIOFileHandles())
   134  		if err != nil {
   135  			return err
   136  		}
   137  		if name == "" {
   138  			return util.MissingOption("name")
   139  		}
   140  	}
   141  
   142  	if projectConfig.PipelineConfig == nil {
   143  		projectConfig.PipelineConfig = &jenkinsfile.PipelineConfig{}
   144  	}
   145  	projectConfig.PipelineConfig.Env = kube.SetEnvVar(projectConfig.PipelineConfig.Env, name, value)
   146  
   147  	err = projectConfig.SaveConfig(fileName)
   148  	if err != nil {
   149  		return err
   150  	}
   151  	log.Logger().Infof("Updated Jenkins X Pipeline file: %s", util.ColorInfo(fileName))
   152  	return nil
   153  
   154  }
   155  
   156  func (o *CreateVariableOptions) loadEnvVars(projectConfig *config.ProjectConfig) (map[string]string, error) {
   157  	answer := map[string]string{}
   158  
   159  	teamSettings, err := o.TeamSettings()
   160  	if err != nil {
   161  		return answer, err
   162  	}
   163  
   164  	packsDir, err := gitresolver.InitBuildPack(o.Git(), teamSettings.BuildPackURL, teamSettings.BuildPackRef)
   165  	if err != nil {
   166  		return answer, err
   167  	}
   168  
   169  	resolver, err := gitresolver.CreateResolver(packsDir, o.Git())
   170  	if err != nil {
   171  		return answer, err
   172  	}
   173  
   174  	name := projectConfig.BuildPack
   175  	if name == "" {
   176  		name, err = o.DiscoverBuildPack(o.Dir, projectConfig, name)
   177  		if err != nil {
   178  			return answer, err
   179  		}
   180  	}
   181  	if projectConfig.PipelineConfig == nil {
   182  		projectConfig.PipelineConfig = &jenkinsfile.PipelineConfig{}
   183  	}
   184  	pipelineConfig := projectConfig.PipelineConfig
   185  	if name != "none" {
   186  		packDir := filepath.Join(packsDir, name)
   187  		pipelineFile := filepath.Join(packDir, jenkinsfile.PipelineConfigFileName)
   188  		exists, err := util.FileExists(pipelineFile)
   189  		if err != nil {
   190  			return answer, errors.Wrapf(err, "failed to find build pack pipeline YAML: %s", pipelineFile)
   191  		}
   192  		if !exists {
   193  			return answer, fmt.Errorf("no build pack for %s exists at directory %s", name, packDir)
   194  		}
   195  		buildPackPipelineConfig, err := jenkinsfile.LoadPipelineConfig(pipelineFile, resolver, true, false)
   196  		if err != nil {
   197  			return answer, errors.Wrapf(err, "failed to load build pack pipeline YAML: %s", pipelineFile)
   198  		}
   199  		err = pipelineConfig.ExtendPipeline(buildPackPipelineConfig, false)
   200  		if err != nil {
   201  			return answer, errors.Wrapf(err, "failed to override PipelineConfig using configuration in file %s", pipelineFile)
   202  		}
   203  	}
   204  
   205  	kubeClient, ns, err := o.KubeClientAndDevNamespace()
   206  	if err != nil {
   207  		return answer, err
   208  	}
   209  
   210  	answer = pipelineConfig.GetAllEnvVars()
   211  
   212  	podTemplates, err := kube.LoadPodTemplates(kubeClient, ns)
   213  	if err != nil {
   214  		return answer, err
   215  	}
   216  	containerName := pipelineConfig.Agent.GetImage()
   217  	if containerName != "" && podTemplates != nil && podTemplates[containerName] != nil {
   218  		podTemplate := podTemplates[containerName]
   219  		if len(podTemplate.Spec.Containers) > 0 {
   220  			container := podTemplate.Spec.Containers[0]
   221  			for _, env := range container.Env {
   222  				if env.Value != "" || answer[env.Name] == "" {
   223  					answer[env.Name] = env.Value
   224  				}
   225  			}
   226  		}
   227  	}
   228  	return answer, nil
   229  }