/
approve.go
129 lines (109 loc) · 3.86 KB
/
approve.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
package approve
import (
"context"
"errors"
"fmt"
"connectrpc.com/connect"
"github.com/spf13/cobra"
"github.com/akuity/kargo/internal/cli/client"
"github.com/akuity/kargo/internal/cli/config"
"github.com/akuity/kargo/internal/cli/option"
"github.com/akuity/kargo/internal/cli/templates"
v1alpha1 "github.com/akuity/kargo/pkg/api/service/v1alpha1"
)
type approvalOptions struct {
Config config.CLIConfig
ClientOptions client.Options
Project string
FreightName string
FreightAlias string
Stage string
}
func NewCommand(cfg config.CLIConfig) *cobra.Command {
cmdOpts := &approvalOptions{
Config: cfg,
}
cmd := &cobra.Command{
Use: "approve [--project=project] (--freight=freight | --freight-alias=alias) --stage=stage",
Short: "Manually approve a piece of freight for promotion to a stage",
Args: option.NoArgs,
Example: templates.Example(`
# Approve a piece of freight specified by name for the QA stage
kargo approve --project=my-project --freight=abc1234 --stage=qa
# Approve a piece of freight specified by alias for the QA stage
kargo approve --project=my-project --freight-alias=wonky-wombat --stage=qa
# Approve a piece of freight specified by name for the QA stage in the default project
kargo config set-project my-project
kargo approve --freight=abc1234 --stage=qa
# Approve a piece of freight specified by alias for the QA stage in the default project
kargo config set-project my-project
kargo approve --freight-alias=wonky-wombat --stage=qa
`),
RunE: func(cmd *cobra.Command, _ []string) error {
if err := cmdOpts.validate(); err != nil {
return err
}
return cmdOpts.run(cmd.Context())
},
}
// Register the option flags on the command.
cmdOpts.addFlags(cmd)
return cmd
}
// addFlags adds the flags for the approval options to the provided command.
func (o *approvalOptions) addFlags(cmd *cobra.Command) {
o.ClientOptions.AddFlags(cmd.PersistentFlags())
option.Project(
cmd.Flags(), &o.Project, o.Config.Project,
"The project the freight belongs to. If not set, the default project will be used.",
)
option.Freight(cmd.Flags(), &o.FreightName, "The name of the freight to approve.")
option.FreightAlias(cmd.Flags(), &o.FreightAlias, "The alias of the freight to approve.")
option.Stage(cmd.Flags(), &o.Stage, "The stage for which to approve the freight.")
if err := cmd.MarkFlagRequired(option.StageFlag); err != nil {
panic(fmt.Errorf("could not mark %s flag as required: %w", option.StageFlag, err))
}
cmd.MarkFlagsOneRequired(option.FreightFlag, option.FreightAliasFlag)
cmd.MarkFlagsMutuallyExclusive(option.FreightFlag, option.FreightAliasFlag)
}
// validate performs validation of the options. If the options are invalid, an
// error is returned.
func (o *approvalOptions) validate() error {
var errs []error
// While the flags are marked as required, a user could still provide an empty
// string. This is a check to ensure that the flags are not empty.
if o.Project == "" {
errs = append(errs, fmt.Errorf("%s is required", option.ProjectFlag))
}
if o.FreightName == "" && o.FreightAlias == "" {
errs = append(
errs,
fmt.Errorf("either %s or %s is required", option.FreightFlag, option.FreightAliasFlag),
)
}
if o.Stage == "" {
errs = append(errs, fmt.Errorf("%s is required", option.StageFlag))
}
return errors.Join(errs...)
}
// run performs the approval of a freight based on the options.
func (o *approvalOptions) run(ctx context.Context) error {
kargoSvcCli, err := client.GetClientFromConfig(ctx, o.Config, o.ClientOptions)
if err != nil {
return fmt.Errorf("get client from config: %w", err)
}
if _, err = kargoSvcCli.ApproveFreight(
ctx,
connect.NewRequest(
&v1alpha1.ApproveFreightRequest{
Project: o.Project,
Name: o.FreightName,
Alias: o.FreightAlias,
Stage: o.Stage,
},
),
); err != nil {
return fmt.Errorf("approve freight: %w", err)
}
return nil
}