Skip to content

Commit 0d06e8b

Browse files
Revise CLI wizard to support access mode and git provider (#646)
* add git provider and access mode seletcion to cli wizard * bump * add doc to git tokens and try to determine access mode based on provided flags * fix
1 parent 64ee1a3 commit 0d06e8b

File tree

6 files changed

+168
-52
lines changed

6 files changed

+168
-52
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
VERSION=v0.1.9
1+
VERSION=v0.1.10
22

33
OUT_DIR=dist
44
YEAR?=$(shell date +"%Y")

cmd/commands/common.go

Lines changed: 80 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ import (
3030
"github.com/codefresh-io/cli-v2/pkg/config"
3131
cfgit "github.com/codefresh-io/cli-v2/pkg/git"
3232
"github.com/codefresh-io/cli-v2/pkg/log"
33+
"github.com/codefresh-io/cli-v2/pkg/reporter"
34+
"github.com/codefresh-io/cli-v2/pkg/runtime"
3335
"github.com/codefresh-io/cli-v2/pkg/store"
3436
"github.com/codefresh-io/cli-v2/pkg/util"
3537

@@ -323,7 +325,7 @@ func ensureGitUserToken(ctx context.Context, opts *RuntimeInstallOptions) error
323325

324326
func getGitTokenFromUserInput(cmd *cobra.Command) error {
325327
gitTokenPrompt := promptui.Prompt{
326-
Label: "Runtime git api token",
328+
Label: fmt.Sprintf("Runtime git token: (required scopes should be as described in: %s )", store.Get().GitTokensLink),
327329
Mask: '*',
328330
}
329331
gitTokenInput, err := gitTokenPrompt.Run()
@@ -396,6 +398,55 @@ func ensureKubeContextName(context, kubeconfig *pflag.Flag) (string, error) {
396398
return contextName, nil
397399
}
398400

401+
func ensureAccessMode(ctx context.Context, opts *RuntimeInstallOptions) error {
402+
var err error
403+
404+
if opts.AccessMode == "" {
405+
if opts.IngressClass != "" || opts.IngressHost != "" {
406+
opts.AccessMode = platmodel.AccessModeIngress
407+
} else if opts.TunnelSubdomain != "" {
408+
opts.AccessMode = platmodel.AccessModeTunnel
409+
} else {
410+
if store.Get().Silent {
411+
// Tunnel mode if the default
412+
opts.AccessMode = platmodel.AccessModeTunnel
413+
} else {
414+
err = getAccessModeFromUserSelect(&opts.AccessMode)
415+
if err != nil {
416+
return err
417+
}
418+
}
419+
}
420+
}
421+
422+
if opts.AccessMode == platmodel.AccessModeTunnel {
423+
handleCliStep(reporter.InstallStepPreCheckEnsureIngressClass, "-skipped (ingressless)-", nil, true, false)
424+
handleCliStep(reporter.InstallStepPreCheckEnsureIngressHost, "-skipped (ingressless)-", nil, true, false)
425+
opts.featuresToInstall = append(opts.featuresToInstall, runtime.InstallFeatureIngressless)
426+
accountId, err := cfConfig.GetCurrentContext().GetAccountId(ctx)
427+
if err != nil {
428+
return fmt.Errorf("failed creating ingressHost for tunnel: %w", err)
429+
}
430+
431+
opts.TunnelSubdomain = fmt.Sprintf("%s-%s", accountId, opts.RuntimeName)
432+
opts.IngressHost = fmt.Sprintf("https://%s.%s", opts.TunnelSubdomain, opts.TunnelDomain)
433+
} else {
434+
err := ensureRoutingControllerSupported(ctx, opts)
435+
handleCliStep(reporter.InstallStepPreCheckEnsureIngressClass, "Getting ingress class", err, true, false)
436+
if err != nil {
437+
return err
438+
}
439+
440+
err = getIngressHost(ctx, opts)
441+
handleCliStep(reporter.InstallStepPreCheckEnsureIngressHost, "Getting ingressHost", err, true, false)
442+
if err != nil {
443+
return err
444+
}
445+
}
446+
447+
return nil
448+
}
449+
399450
func getKubeContextName(context, kubeconfig *pflag.Flag) (string, error) {
400451
kubeconfigPath := kubeconfig.Value.String()
401452

@@ -453,6 +504,34 @@ func getKubeContextNameFromUserSelect(kubeconfig string) (string, error) {
453504
return contexts[index].Name, nil
454505
}
455506

507+
func getAccessModeFromUserSelect(accessMode *platmodel.AccessMode) (error) {
508+
templates := &promptui.SelectTemplates{
509+
Selected: "{{ .Name | yellow }}",
510+
}
511+
512+
labelStr := fmt.Sprintf("%vSelect access mode%v", CYAN, COLOR_RESET)
513+
514+
prompt := promptui.Select{
515+
Label: labelStr,
516+
Items: []string{"Codefresh Tunnel Based", "Ingress Based"},
517+
Templates: templates,
518+
}
519+
520+
index, _, err := prompt.Run()
521+
if err != nil {
522+
return err
523+
}
524+
525+
switch index {
526+
case 0:
527+
*accessMode = platmodel.AccessModeTunnel
528+
case 1:
529+
*accessMode = platmodel.AccessModeIngress
530+
}
531+
532+
return nil
533+
}
534+
456535
func validateIngressHost(ingressHost string) error {
457536
isValid, err := isValidIngressHost(ingressHost)
458537
if err != nil {

cmd/commands/runtime_install.go

Lines changed: 37 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ type (
109109
IpsAllowList string
110110
SkipIngress bool
111111
BypassIngressClassCheck bool
112+
DownloadRuntimeDef *runtime.Runtime
112113

113114
versionStr string
114115
kubeContext string
@@ -195,9 +196,11 @@ func NewRuntimeInstallCommand() *cobra.Command {
195196

196197
createAnalyticsReporter(ctx, reporter.InstallFlow, installationOpts.DisableTelemetry)
197198

198-
installationOpts.AccessMode = platmodel.AccessMode(strings.ToUpper(accessMode))
199-
if !installationOpts.AccessMode.IsValid() {
200-
return fmt.Errorf("invalid access-mode %s, must be one of: ingress|tunnel", accessMode)
199+
if (accessMode != "") {
200+
installationOpts.AccessMode = platmodel.AccessMode(strings.ToUpper(accessMode))
201+
if !installationOpts.AccessMode.IsValid() {
202+
return fmt.Errorf("invalid access-mode %s, must be one of: ingress|tunnel", accessMode)
203+
}
201204
}
202205

203206
err := runtimeInstallCommandPreRunHandler(cmd, installationOpts)
@@ -262,7 +265,7 @@ func NewRuntimeInstallCommand() *cobra.Command {
262265
cmd.Flags().StringToStringVar(&installationOpts.InternalIngressAnnotation, "internal-ingress-annotation", nil, "Add annotations to the internal ingress")
263266
cmd.Flags().StringToStringVar(&installationOpts.ExternalIngressAnnotation, "external-ingress-annotation", nil, "Add annotations to the external ingress")
264267
cmd.Flags().StringVar(&installationOpts.runtimeDef, "runtime-def", "", "Install runtime from a specific manifest")
265-
cmd.Flags().StringVar(&accessMode, "access-mode", string(platmodel.AccessModeIngress), "The access mode to the cluster, one of: ingress|tunnel")
268+
cmd.Flags().StringVar(&accessMode, "access-mode", "", "The access mode to the cluster, one of: ingress|tunnel")
266269
cmd.Flags().StringVar(&installationOpts.TunnelRegisterHost, "tunnel-register-host", "register-tunnels.cf-cd.com", "The host name for registering a new tunnel")
267270
cmd.Flags().StringVar(&installationOpts.TunnelDomain, "tunnel-domain", "tunnels.cf-cd.com", "The base domain for the tunnels")
268271
cmd.Flags().StringVar(&installationOpts.IpsAllowList, "ips-allow-list", "", "lists the rules to configure which IP addresses (IPv4/IPv6) and subnet masks can access your client (e.g \"192.168.0.0/16, FE80:CD00:0000:0CDE:1257::/64\")")
@@ -301,6 +304,32 @@ func runtimeInstallCommandPreRunHandler(cmd *cobra.Command, opts *RuntimeInstall
301304

302305
err = validateVersionIfExists(opts.versionStr)
303306
handleCliStep(reporter.InstallStepPreCheckValidateRuntimeVersion, "Validating runtime version", err, true, false)
307+
308+
if opts.runtimeDef == "" {
309+
opts.runtimeDef = runtime.GetRuntimeDefURL(opts.versionStr)
310+
}
311+
312+
runtimeDef := getRuntimeDef(opts.runtimeDef, opts.versionStr)
313+
rt, err := runtime.Download(runtimeDef, opts.RuntimeName, opts.featuresToInstall)
314+
handleCliStep(reporter.InstallStepRunPreCheckDownloadRuntimeDefinition, "Downloading runtime definition", err, true, true)
315+
if err != nil {
316+
return fmt.Errorf("failed to download runtime definition: %w", err)
317+
}
318+
319+
if rt.Spec.DefVersion != nil {
320+
if rt.Spec.DefVersion.GreaterThan(store.Get().MaxDefVersion) {
321+
err = fmt.Errorf("your cli version is out of date. please upgrade to the latest version before installing")
322+
} else if rt.Spec.DefVersion.LessThan(store.Get().MaxDefVersion) {
323+
val := store.Get().DefVersionToLastCLIVersion[rt.Spec.DefVersion.String()]
324+
err = fmt.Errorf("to install this version, please downgrade your cli to version %s", val)
325+
}
326+
} else {
327+
err = runtime.CheckRuntimeVersionCompatible(rt.Spec.RequiredCLIVersion)
328+
}
329+
if err != nil {
330+
return err
331+
}
332+
304333
if opts.RuntimeName == "" {
305334
if !store.Get().Silent {
306335
opts.RuntimeName, err = getRuntimeNameFromUserInput()
@@ -325,29 +354,8 @@ func runtimeInstallCommandPreRunHandler(cmd *cobra.Command, opts *RuntimeInstall
325354
return err
326355
}
327356

328-
if opts.AccessMode == platmodel.AccessModeTunnel {
329-
handleCliStep(reporter.InstallStepPreCheckEnsureIngressClass, "-skipped (ingressless)-", err, true, false)
330-
handleCliStep(reporter.InstallStepPreCheckEnsureIngressHost, "-skipped (ingressless)-", err, true, false)
331-
opts.featuresToInstall = append(opts.featuresToInstall, runtime.InstallFeatureIngressless)
332-
accountId, err := cfConfig.GetCurrentContext().GetAccountId(ctx)
333-
if err != nil {
334-
return fmt.Errorf("failed creating ingressHost for tunnel: %w", err)
335-
}
336-
337-
opts.TunnelSubdomain = fmt.Sprintf("%s-%s", accountId, opts.RuntimeName)
338-
opts.IngressHost = fmt.Sprintf("https://%s.%s", opts.TunnelSubdomain, opts.TunnelDomain)
339-
} else {
340-
err = ensureRoutingControllerSupported(ctx, opts)
341-
handleCliStep(reporter.InstallStepPreCheckEnsureIngressClass, "Getting ingress class", err, true, false)
342-
if err != nil {
343-
return err
344-
}
345-
346-
err = getIngressHost(ctx, opts)
347-
handleCliStep(reporter.InstallStepPreCheckEnsureIngressHost, "Getting ingressHost", err, true, false)
348-
if err != nil {
349-
return err
350-
}
357+
if err = ensureAccessMode(ctx, opts); err != nil {
358+
return err
351359
}
352360

353361
if err = ensureGitData(cmd, opts); err != nil {
@@ -384,12 +392,9 @@ func runtimeInstallCommandPreRunHandler(cmd *cobra.Command, opts *RuntimeInstall
384392
log.G(ctx).Infof("using repo '%s' as shared config repo for this account", sharedConfigRepo)
385393
}
386394

387-
if opts.runtimeDef == "" {
388-
opts.runtimeDef = runtime.GetRuntimeDefURL(opts.versionStr)
389-
}
390-
391395
opts.Insecure = true // installs argo-cd in insecure mode, we need this so that the eventsource can talk to the argocd-server with http
392396
opts.CommonConfig = &runtime.CommonConfig{CodefreshBaseURL: cfConfig.GetCurrentContext().URL}
397+
opts.DownloadRuntimeDef = rt
393398

394399
return nil
395400
}
@@ -1140,23 +1145,7 @@ func preInstallationChecks(ctx context.Context, opts *RuntimeInstallOptions) (*r
11401145
return nil, err
11411146
}
11421147

1143-
runtimeDef := getRuntimeDef(opts.runtimeDef, opts.versionStr)
1144-
rt, err := runtime.Download(runtimeDef, opts.RuntimeName, opts.featuresToInstall)
1145-
handleCliStep(reporter.InstallStepRunPreCheckDownloadRuntimeDefinition, "Downloading runtime definition", err, true, true)
1146-
if err != nil {
1147-
return nil, fmt.Errorf("failed to download runtime definition: %w", err)
1148-
}
1149-
1150-
if rt.Spec.DefVersion != nil {
1151-
if rt.Spec.DefVersion.GreaterThan(store.Get().MaxDefVersion) {
1152-
err = fmt.Errorf("your cli version is out of date. please upgrade to the latest version before installing")
1153-
} else if rt.Spec.DefVersion.LessThan(store.Get().MaxDefVersion) {
1154-
val := store.Get().DefVersionToLastCLIVersion[rt.Spec.DefVersion.String()]
1155-
err = fmt.Errorf("to install this version, please downgrade your cli to version %s", val)
1156-
}
1157-
} else {
1158-
err = runtime.CheckRuntimeVersionCompatible(rt.Spec.RequiredCLIVersion)
1159-
}
1148+
rt := opts.DownloadRuntimeDef
11601149

11611150
handleCliStep(reporter.InstallStepRunPreCheckEnsureCliVersion, "Checking CLI version", err, true, false)
11621151
if err != nil {

docs/releases/release_notes.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ cf version
2323

2424
```bash
2525
# download and extract the binary
26-
curl -L --output - https://github.com/codefresh-io/cli-v2/releases/download/v0.1.9/cf-linux-amd64.tar.gz | tar zx
26+
curl -L --output - https://github.com/codefresh-io/cli-v2/releases/download/v0.1.10/cf-linux-amd64.tar.gz | tar zx
2727

2828
# move the binary to your $PATH
2929
mv ./cf-linux-amd64 /usr/local/bin/cf
@@ -36,7 +36,7 @@ cf version
3636

3737
```bash
3838
# download and extract the binary
39-
curl -L --output - https://github.com/codefresh-io/cli-v2/releases/download/v0.1.9/cf-darwin-amd64.tar.gz | tar zx
39+
curl -L --output - https://github.com/codefresh-io/cli-v2/releases/download/v0.1.10/cf-darwin-amd64.tar.gz | tar zx
4040

4141
# move the binary to your $PATH
4242
mv ./cf-darwin-amd64 /usr/local/bin/cf

pkg/git/provider.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,17 @@ import (
2121
"strings"
2222

2323
apgit "github.com/argoproj-labs/argocd-autopilot/pkg/git"
24+
"github.com/codefresh-io/cli-v2/pkg/store"
25+
"github.com/manifoldco/promptui"
2426
)
2527

2628
//go:generate mockgen -destination=./mocks/roundTripper.go -package=mocks net/http RoundTripper
2729

30+
var (
31+
CYAN = "\033[36m"
32+
COLOR_RESET = "\033[0m"
33+
)
34+
2835
type (
2936
ProviderType string
3037

@@ -77,5 +84,44 @@ func GetProvider(providerType ProviderType, baseURL, certFile string) (Provider,
7784
return NewBitbucketProvider(baseURL, client)
7885
}
7986

87+
if !store.Get().Silent {
88+
provider := getGitProviderFromUserSelect(baseURL, client)
89+
if provider != nil {
90+
return provider, nil
91+
}
92+
}
93+
8094
return nil, fmt.Errorf("failed getting provider for clone url %s", baseURL)
8195
}
96+
97+
func getGitProviderFromUserSelect(baseURL string, client *http.Client) (Provider) {
98+
var providers = map[string]func(string, *http.Client) (Provider, error){
99+
"Bitbucket": NewBitbucketServerProvider,
100+
"Github": NewGithubProvider,
101+
"Gitlab": NewGitlabProvider,
102+
}
103+
104+
templates := &promptui.SelectTemplates{
105+
Selected: "{{ .Name | yellow }}",
106+
}
107+
108+
labelStr := fmt.Sprintf("%vSelect git provider%v", CYAN, COLOR_RESET)
109+
110+
prompt := promptui.Select{
111+
Label: labelStr,
112+
Items: []string{"Github", "Gitlab", "Bitbucket"},
113+
Templates: templates,
114+
}
115+
116+
_, label, err := prompt.Run()
117+
if err != nil {
118+
return nil
119+
}
120+
121+
if fn, ok := providers[label]; ok {
122+
provider, _ := fn(baseURL, client)
123+
return provider
124+
}
125+
126+
return nil
127+
}

pkg/store/store.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ type Store struct {
131131
AnalysisRunResourceName string
132132
WorkflowResourceName string
133133
RequirementsLink string
134+
GitTokensLink string
134135
DownloadCliLink string
135136
RolloutReporterName string
136137
RolloutResourceName string
@@ -249,6 +250,7 @@ func init() {
249250
s.RolloutReporterName = "rollout-reporter"
250251
s.RolloutReporterServiceAccount = "rollout-reporter-sa"
251252
s.RequirementsLink = "https://codefresh.io/csdp-docs/docs/runtime/requirements/"
253+
s.GitTokensLink = "https://codefresh.io/csdp-docs/docs/reference/git-tokens/"
252254
s.DownloadCliLink = "https://codefresh.io/csdp-docs/docs/clients/csdp-cli/"
253255
s.DefaultNamespace = "default"
254256
s.NetworkTesterName = "cf-network-tester"

0 commit comments

Comments
 (0)