/
bucket.go
138 lines (122 loc) · 4.3 KB
/
bucket.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
package opts
import (
"context"
"fmt"
"io"
"net/url"
"time"
v1 "github.com/jenkins-x/jx-api/pkg/apis/jenkins.io/v1"
"github.com/jenkins-x/jx/v2/pkg/cloud/gke"
"github.com/jenkins-x/jx-logging/pkg/log"
"github.com/jenkins-x/jx/v2/pkg/cloud/buckets"
"github.com/jenkins-x/jx/v2/pkg/kube"
"github.com/jenkins-x/jx/v2/pkg/kube/cluster"
"github.com/jenkins-x/jx/v2/pkg/util"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"gocloud.dev/blob"
)
// CreateBucketValues contains the values to create a Bucket on cloud storage
type CreateBucketValues struct {
Bucket string
BucketKind string
// GKE specific values
GKEProjectID string
GKEZone string
}
// AddCreateBucketFlags adds the CLI arguments to be able to specify to create a new bucket along with any cloud specific parameters
func (cb *CreateBucketValues) AddCreateBucketFlags(cmd *cobra.Command) {
cmd.Flags().StringVarP(&cb.Bucket, "bucket", "", "", "Specify the name of the bucket to use")
cmd.Flags().StringVarP(&cb.BucketKind, "bucket-kind", "", "", "The kind of bucket to use like 'gs, s3, azure' etc")
cmd.Flags().StringVarP(&cb.GKEProjectID, "gke-project-id", "", "", "Google Project ID to use for a new bucket")
cmd.Flags().StringVarP(&cb.GKEZone, "gke-zone", "", "", "The GKE zone (e.g. us-central1-a) where the new bucket will be created")
}
// IsEmpty returns true if there is no bucket name specified
func (cb *CreateBucketValues) IsEmpty() bool {
return cb.Bucket == ""
}
// CreateBucket creates a new bucket using the create bucket values and team settings returning the newly created bucket URL
func (o *CommonOptions) CreateBucket(cb *CreateBucketValues, settings *v1.TeamSettings) (string, error) {
bucketURL, err := buckets.CreateBucketURL(cb.Bucket, cb.BucketKind, settings)
if err != nil {
return bucketURL, errors.Wrapf(err, "failed to create the bucket URL for %s", cb.Bucket)
}
ctx, _ := context.WithTimeout(context.Background(), time.Second*20)
bucket, err := blob.Open(ctx, bucketURL)
if err != nil {
return bucketURL, errors.Wrapf(err, "failed to open the bucket for %s", bucketURL)
}
// lets check if the bucket exists
iter := bucket.List(nil)
obj, err := iter.Next(ctx)
if err != nil {
if err == io.EOF {
log.Logger().Infof("bucket %s is empty", bucketURL)
} else {
log.Logger().Infof("The bucket %s does not exist yet so lets create it...", util.ColorInfo(bucketURL))
err = o.CreateBucketFromURL(bucketURL, bucket, cb)
if err != nil {
return bucketURL, errors.Wrapf(err, "failed to create the bucket for %s", bucketURL)
}
}
} else {
log.Logger().Infof("Found item in bucket %s for %s", bucketURL, obj.Key)
}
return bucketURL, nil
}
// CreateBucketFromURL creates a bucket if it does not already exist
func (o *CommonOptions) CreateBucketFromURL(bucketURL string, bucket *blob.Bucket, cb *CreateBucketValues) error {
u, err := url.Parse(bucketURL)
if err != nil {
return err
}
switch u.Scheme {
case "gs":
return o.createGcsBucket(u, bucket, cb)
default:
return fmt.Errorf("Cannot create a bucket for provider %s", bucketURL)
}
}
func (o *CommonOptions) createGcsBucket(u *url.URL, bucket *blob.Bucket, cb *CreateBucketValues) error {
var err error
if cb.GKEProjectID == "" {
if kubeClient, ns, err := o.KubeClientAndDevNamespace(); err == nil {
if data, err := kube.ReadInstallValues(kubeClient, ns); err == nil && data != nil {
cb.GKEProjectID = data[kube.ProjectID]
if cb.GKEZone == "" {
cb.GKEZone = data[kube.Zone]
}
}
}
}
if cb.GKEProjectID == "" {
cb.GKEProjectID, err = o.GetGoogleProjectID("")
if err != nil {
return err
}
}
err = o.RunCommandVerbose(
"gcloud", "config", "set", "project", cb.GKEProjectID)
if err != nil {
return err
}
if cb.GKEZone == "" {
defaultZone := ""
if cluster, err := cluster.Name(o.Kube()); err == nil && cluster != "" {
if clusterZone, err := o.GCloud().ClusterZone(cluster); err == nil {
defaultZone = clusterZone
}
}
cb.GKEZone, err = o.GetGoogleZoneWithDefault(cb.GKEProjectID, defaultZone)
if err != nil {
return err
}
}
bucketName := u.Host
region := gke.GetRegionFromZone(cb.GKEZone)
err = o.GCloud().CreateBucket(cb.GKEProjectID, bucketName, region)
if err != nil {
return errors.Wrapf(err, "creating bucket %s in project %s and region %s", bucketName, cb.GKEProjectID, region)
}
return nil
}