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

     1  package requirements
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"path/filepath"
     7  	"strings"
     8  
     9  	"github.com/olli-ai/jx/v2/pkg/cmd/helper"
    10  	"github.com/olli-ai/jx/v2/pkg/config"
    11  	"github.com/olli-ai/jx/v2/pkg/gits"
    12  
    13  	"github.com/jenkins-x/jx-logging/pkg/log"
    14  	"github.com/pkg/errors"
    15  	"github.com/spf13/cobra"
    16  
    17  	"github.com/olli-ai/jx/v2/pkg/cmd/opts"
    18  	"github.com/olli-ai/jx/v2/pkg/cmd/templates"
    19  	"github.com/olli-ai/jx/v2/pkg/util"
    20  )
    21  
    22  // RequirementsOptions the CLI options for this command
    23  type RequirementsOptions struct {
    24  	*opts.CommonOptions
    25  
    26  	Dir string
    27  
    28  	Requirements  config.RequirementsConfig
    29  	SecretStorage string
    30  	Webhook       string
    31  	Flags         RequirementBools
    32  }
    33  
    34  // RequirementBools for the boolean flags we only update if specified on the CLI
    35  type RequirementBools struct {
    36  	AutoUpgrade, EnvironmentGitPublic, GitOps, Kaniko, Terraform bool
    37  	VaultRecreateBucket, VaultDisableURLDiscover                 bool
    38  }
    39  
    40  var (
    41  	requirementsLong = templates.LongDesc(`
    42  		Edits the local 'jx-requirements.yml file for 'jx boot'
    43  `)
    44  
    45  	requirementsExample = templates.Examples(`
    46  		# edits the local 'jx-requirements.yml' file used for 'jx boot'
    47  		jx edit requirements --domain foo.com --tls --provider eks
    48  `)
    49  )
    50  
    51  // NewCmdEditRequirements creates the new command
    52  func NewCmdEditRequirements(commonOpts *opts.CommonOptions) *cobra.Command {
    53  	options := &RequirementsOptions{
    54  		CommonOptions: commonOpts,
    55  	}
    56  	cmd := &cobra.Command{
    57  		Use:     "requirements",
    58  		Short:   "Edits the local 'jx-requirements.yml file for 'jx boot'",
    59  		Long:    requirementsLong,
    60  		Example: requirementsExample,
    61  		Aliases: []string{"req", "require", "requirement"},
    62  		Run: func(cmd *cobra.Command, args []string) {
    63  			options.Cmd = cmd
    64  			options.Args = args
    65  			err := options.Run()
    66  			helper.CheckErr(err)
    67  		},
    68  		RunE: func(cmd *cobra.Command, args []string) error {
    69  			options.Cmd = cmd
    70  			options.Args = args
    71  			return options.Run()
    72  		},
    73  	}
    74  	cmd.Flags().StringVarP(&options.Dir, "dir", "", ".", "the directory to search for the 'jx-requirements.yml' file")
    75  
    76  	// bools
    77  	cmd.Flags().BoolVarP(&options.Flags.AutoUpgrade, "autoupgrade", "", false, "enables or disables auto upgrades")
    78  	cmd.Flags().BoolVarP(&options.Flags.EnvironmentGitPublic, "env-git-public", "", false, "enables or disables whether the environment repositories should be public")
    79  	cmd.Flags().BoolVarP(&options.Flags.GitOps, "gitops", "g", false, "enables or disables the use of gitops")
    80  	cmd.Flags().BoolVarP(&options.Flags.Kaniko, "kaniko", "", false, "enables or disables the use of kaniko")
    81  	cmd.Flags().BoolVarP(&options.Flags.Terraform, "terraform", "", false, "enables or disables the use of terraform")
    82  	cmd.Flags().BoolVarP(&options.Flags.VaultRecreateBucket, "vault-recreate-bucket", "", false, "enables or disables whether to rereate the secret bucket on boot")
    83  	cmd.Flags().BoolVarP(&options.Flags.VaultDisableURLDiscover, "vault-disable-url-discover", "", false, "override the default lookup of the Vault URL, could be incluster service or external ingress")
    84  
    85  	// requirements
    86  	cmd.Flags().StringVarP(&options.Requirements.BootConfigURL, "boot-config-url", "", "", "specify the boot configuration git URL")
    87  	cmd.Flags().StringVarP(&options.SecretStorage, "secret", "s", "", fmt.Sprintf("configures the kind of secret storage. Values: %s", strings.Join(config.SecretStorageTypeValues, ", ")))
    88  	cmd.Flags().StringVarP(&options.Webhook, "webhook", "w", "", fmt.Sprintf("configures the kind of webhook. Values %s", strings.Join(config.WebhookTypeValues, ", ")))
    89  
    90  	// auto upgrade
    91  	cmd.Flags().StringVarP(&options.Requirements.AutoUpdate.Schedule, "autoupdate-schedule", "", "", "the cron schedule for auto upgrading your cluster")
    92  
    93  	// cluster
    94  	cmd.Flags().StringVarP(&options.Requirements.Cluster.ClusterName, "cluster", "c", "", "configures the cluster name")
    95  	cmd.Flags().StringVarP(&options.Requirements.Cluster.Namespace, "namespace", "n", "", "configures the namespace to use")
    96  	cmd.Flags().StringVarP(&options.Requirements.Cluster.Provider, "provider", "p", "", "configures the kubernetes provider")
    97  	cmd.Flags().StringVarP(&options.Requirements.Cluster.ProjectID, "project", "", "", "configures the Google Project ID")
    98  	cmd.Flags().StringVarP(&options.Requirements.Cluster.Registry, "registry", "", "", "configures the host name of the container registry")
    99  	cmd.Flags().StringVarP(&options.Requirements.Cluster.Region, "region", "r", "", "configures the cloud region")
   100  	cmd.Flags().StringVarP(&options.Requirements.Cluster.Zone, "zone", "z", "", "configures the cloud zone")
   101  
   102  	cmd.Flags().StringVarP(&options.Requirements.Cluster.ExternalDNSSAName, "extdns-sa", "", "", "configures the External DNS service account name")
   103  	cmd.Flags().StringVarP(&options.Requirements.Cluster.KanikoSAName, "kaniko-sa", "", "", "configures the Kaniko service account name")
   104  	cmd.Flags().StringVarP(&options.Requirements.Cluster.HelmMajorVersion, "helm-version", "", "", "configures the Helm major version. e.g. 3 to try helm 3")
   105  
   106  	// git
   107  	cmd.Flags().StringVarP(&options.Requirements.Cluster.GitKind, "git-kind", "", "", fmt.Sprintf("the kind of git repository to use. Possible values: %s", strings.Join(gits.KindGits, ", ")))
   108  	cmd.Flags().StringVarP(&options.Requirements.Cluster.GitName, "git-name", "", "", "the name of the git repository")
   109  	cmd.Flags().StringVarP(&options.Requirements.Cluster.GitServer, "git-server", "", "", "the git server host such as https://github.com or https://gitlab.com")
   110  	cmd.Flags().StringVarP(&options.Requirements.Cluster.EnvironmentGitOwner, "env-git-owner", "", "", "the git owner (organisation or user) used to own the git repositories for the environments")
   111  
   112  	// ingress
   113  	cmd.Flags().StringVarP(&options.Requirements.Ingress.Domain, "domain", "d", "", "configures the domain name")
   114  	cmd.Flags().StringVarP(&options.Requirements.Ingress.TLS.Email, "tls-email", "", "", "the TLS email address to enable TLS on the domain")
   115  
   116  	// storage
   117  	cmd.Flags().StringVarP(&options.Requirements.Storage.Logs.URL, "bucket-logs", "", "", "the bucket URL to store logs")
   118  	cmd.Flags().StringVarP(&options.Requirements.Storage.Backup.URL, "bucket-backups", "", "", "the bucket URL to store backups")
   119  	cmd.Flags().StringVarP(&options.Requirements.Storage.Repository.URL, "bucket-repo", "", "", "the bucket URL to store repository artifacts")
   120  	cmd.Flags().StringVarP(&options.Requirements.Storage.Reports.URL, "bucket-reports", "", "", "the bucket URL to store reports. If not specified default to te logs bucket")
   121  
   122  	// vault
   123  	cmd.Flags().StringVarP(&options.Requirements.Vault.Name, "vault-name", "", "", "specify the vault name")
   124  	cmd.Flags().StringVarP(&options.Requirements.Vault.Bucket, "vault-bucket", "", "", "specify the vault bucket")
   125  	cmd.Flags().StringVarP(&options.Requirements.Vault.Keyring, "vault-keyring", "", "", "specify the vault key ring")
   126  	cmd.Flags().StringVarP(&options.Requirements.Vault.Key, "vault-key", "", "", "specify the vault key")
   127  	cmd.Flags().StringVarP(&options.Requirements.Vault.ServiceAccount, "vault-sa", "", "", "specify the vault Service Account name")
   128  
   129  	// velero
   130  	cmd.Flags().StringVarP(&options.Requirements.Velero.ServiceAccount, "velero-sa", "", "", "specify the Velero Service Account name")
   131  	cmd.Flags().StringVarP(&options.Requirements.Velero.Namespace, "velero-ns", "", "", "specify the Velero Namespace")
   132  
   133  	// version stream
   134  	cmd.Flags().StringVarP(&options.Requirements.VersionStream.URL, "version-stream-url", "", "", "specify the Version Stream git URL")
   135  	cmd.Flags().StringVarP(&options.Requirements.VersionStream.Ref, "version-stream-ref", "", "", "specify the Version Stream git reference (branch, tag, sha)")
   136  	return cmd
   137  }
   138  
   139  // Run runs the command
   140  func (o *RequirementsOptions) Run() error {
   141  	requirements, fileName, err := config.LoadRequirementsConfig(o.Dir, config.DefaultFailOnValidationError)
   142  	if err != nil {
   143  		return err
   144  	}
   145  	if fileName == "" {
   146  		fileName = filepath.Join(o.Dir, config.RequirementsConfigFileName)
   147  	}
   148  	o.Requirements = *requirements
   149  
   150  	// lets re-parse the CLI arguments to re-populate the loaded requirements
   151  	err = o.Cmd.Flags().Parse(os.Args)
   152  	if err != nil {
   153  		return errors.Wrap(err, "failed to reparse arguments")
   154  	}
   155  
   156  	err = o.applyDefaults()
   157  	if err != nil {
   158  		return err
   159  	}
   160  
   161  	err = o.Requirements.SaveConfig(fileName)
   162  	if err != nil {
   163  		return errors.Wrapf(err, "failed to save %s", fileName)
   164  	}
   165  
   166  	log.Logger().Infof("saved file: %s", util.ColorInfo(fileName))
   167  	return nil
   168  }
   169  
   170  func (o *RequirementsOptions) applyDefaults() error {
   171  	r := &o.Requirements
   172  
   173  	gitKind := r.Cluster.GitKind
   174  	if gitKind != "" && util.StringArrayIndex(gits.KindGits, gitKind) < 0 {
   175  		return util.InvalidOption("git-kind", gitKind, gits.KindGits)
   176  	}
   177  
   178  	// override boolean flags if specified
   179  	if o.FlagChanged("autoupgrade") {
   180  		r.AutoUpdate.Enabled = o.Flags.AutoUpgrade
   181  	}
   182  	if o.FlagChanged("env-git-public") {
   183  		r.Cluster.EnvironmentGitPublic = o.Flags.EnvironmentGitPublic
   184  	}
   185  	if o.FlagChanged("gitops") {
   186  		r.GitOps = o.Flags.GitOps
   187  	}
   188  	if o.FlagChanged("kaniko") {
   189  		r.Kaniko = o.Flags.Kaniko
   190  	}
   191  	if o.FlagChanged("terraform") {
   192  		r.Terraform = o.Flags.Terraform
   193  	}
   194  	if o.FlagChanged("vault-disable-url-discover") {
   195  		r.Vault.DisableURLDiscovery = o.Flags.VaultDisableURLDiscover
   196  	}
   197  	if o.FlagChanged("vault-recreate-bucket") {
   198  		r.Vault.RecreateBucket = o.Flags.VaultRecreateBucket
   199  	}
   200  
   201  	// custom string types...
   202  	if o.SecretStorage != "" {
   203  		switch o.SecretStorage {
   204  		case "local":
   205  			r.SecretStorage = config.SecretStorageTypeLocal
   206  		case "vault":
   207  			r.SecretStorage = config.SecretStorageTypeVault
   208  		default:
   209  			return util.InvalidOption("secret", o.SecretStorage, config.SecretStorageTypeValues)
   210  		}
   211  	}
   212  	if o.Webhook != "" {
   213  		switch o.Webhook {
   214  		case "jenkins":
   215  			r.Webhook = config.WebhookTypeJenkins
   216  		case "lighthouse":
   217  			r.Webhook = config.WebhookTypeLighthouse
   218  		case "prow":
   219  			r.Webhook = config.WebhookTypeProw
   220  		default:
   221  			return util.InvalidOption("webhook", o.Webhook, config.WebhookTypeValues)
   222  		}
   223  	}
   224  
   225  	// default flags if associated values
   226  	if r.AutoUpdate.Schedule != "" {
   227  		r.AutoUpdate.Enabled = true
   228  	}
   229  	if r.Ingress.TLS.Email != "" {
   230  		r.Ingress.TLS.Enabled = true
   231  	}
   232  
   233  	// enable storage if we specify a URL
   234  	storage := &r.Storage
   235  	if storage.Logs.URL != "" && storage.Reports.URL == "" {
   236  		storage.Reports.URL = storage.Logs.URL
   237  	}
   238  	o.defaultStorage(&storage.Backup)
   239  	o.defaultStorage(&storage.Logs)
   240  	o.defaultStorage(&storage.Reports)
   241  	o.defaultStorage(&storage.Repository)
   242  	return nil
   243  }
   244  
   245  func (o *RequirementsOptions) defaultStorage(storage *config.StorageEntryConfig) {
   246  	if storage.URL != "" {
   247  		storage.Enabled = true
   248  	}
   249  }