-
Notifications
You must be signed in to change notification settings - Fork 153
/
init.go
174 lines (143 loc) · 4.56 KB
/
init.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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
package main
import (
"context"
"fmt"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"github.com/hypnoglow/helm-s3/internal/awss3"
"github.com/hypnoglow/helm-s3/internal/awsutil"
"github.com/hypnoglow/helm-s3/internal/helmutil"
)
const initDesc = `This command initializes an empty repository on AWS S3.
'helm s3 init' takes one argument:
- URI - URI of the repository.
`
const initExample = ` helm s3 init s3://awesome-bucket/charts - inits chart repository in 'awesome-bucket' bucket under 'charts' path.`
func newInitCommand(opts *options) *cobra.Command {
act := &initAction{
printer: nil,
acl: "",
uri: "",
force: false,
ignoreIfExists: false,
}
cmd := &cobra.Command{
Use: "init URI",
Short: "Initialize empty repository on AWS S3.",
Long: initDesc,
Example: initExample,
Args: wrapPositionalArgsBadUsage(cobra.ExactArgs(1)),
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
// No completions for the URI argument.
return nil, cobra.ShellCompDirectiveNoFileComp
},
RunE: func(cmd *cobra.Command, args []string) error {
act.printer = cmd
act.acl = opts.acl
act.uri = args[0]
return act.run(cmd.Context())
},
}
flags := cmd.Flags()
flags.BoolVar(&act.force, "force", act.force, "Replace the index file if it already exists.")
flags.BoolVar(&act.ignoreIfExists, "ignore-if-exists", act.ignoreIfExists, "If the index file already exists, exit normally and do not trigger an error.")
return cmd
}
type initAction struct {
printer printer
// global flags
acl string
// args
uri string
// flags
force bool
ignoreIfExists bool
}
func (act *initAction) run(ctx context.Context) error {
if act.force && act.ignoreIfExists {
act.printer.PrintErrf(
"The --force and --ignore-if-exists flags are mutually exclusive and cannot be specified together.\n",
)
return newSilentError()
}
repoEntry, ok, err := helmutil.LookupRepoEntryByURL(act.uri)
if err != nil {
return fmt.Errorf("lookup repo entry by url: %v", err)
}
if ok {
if act.ignoreIfExists {
return act.ignoreIfExistsError(repoEntry.Name())
}
if !act.force {
return act.alreadyExistsError(repoEntry.Name())
}
// fallthrough on --force
}
r, err := helmutil.NewIndex().Reader()
if err != nil {
return errors.WithMessage(err, "get index reader")
}
sess, err := awsutil.Session(awsutil.DynamicBucketRegion(act.uri))
if err != nil {
return err
}
storage := awss3.New(sess)
exists, err := storage.IndexExists(ctx, act.uri)
if err != nil {
return fmt.Errorf("check if index exists in the storage: %v", err)
}
if exists {
if act.ignoreIfExists {
return act.ignoreIfExistsInStorageError()
}
if !act.force {
return act.alreadyExistsInStorageError()
}
// fallthrough on --force
}
if err := storage.PutIndex(ctx, act.uri, act.acl, r); err != nil {
return errors.WithMessage(err, "upload index to s3")
}
// TODO:
// do we need to automatically do `helm repo add <name> <uri>`,
// like we are doing `helm repo update` when we push a chart
// with this plugin?
act.printer.Printf("Initialized empty repository at %s\n", act.uri)
return nil
}
func (act *initAction) ignoreIfExistsError(name string) error {
act.printer.Printf(
"The repository with the provided URI already exists under name %q, ignore init operation.\n",
name,
)
return nil
}
func (act *initAction) ignoreIfExistsInStorageError() error {
act.printer.Printf(
"The index file already exists under the provided URI, ignore init operation.\n",
)
return nil
}
func (act *initAction) alreadyExistsError(name string) error {
act.printer.PrintErrf(
"The repository with the provided URI already exists under name %[1]q, the index file and cannot be overwritten without an explicit intent.\n\n"+
"If you want to replace existing index file, use --force flag:\n\n"+
" helm s3 init --force %[2]s\n\n"+
"If you want to ignore this error, use --ignore-if-exists flag:\n\n"+
" helm s3 init --ignore-if-exists %[2]s\n\n",
name,
act.uri,
)
return newSilentError()
}
func (act *initAction) alreadyExistsInStorageError() error {
act.printer.PrintErrf(
"The index file already exists under the provided URI and cannot be overwritten without an explicit intent.\n\n"+
"If you want to replace existing index file, use --force flag:\n\n"+
" helm s3 init --force %[1]s\n\n"+
"If you want to ignore this error, use --ignore-if-exists flag:\n\n"+
" helm s3 init --ignore-if-exists %[1]s\n\n",
act.uri,
)
return newSilentError()
}