-
Notifications
You must be signed in to change notification settings - Fork 111
/
gcpconfigservice.go
152 lines (129 loc) · 5.47 KB
/
gcpconfigservice.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
package gcpcloudstorageservice
import (
"context"
"encoding/json"
"fmt"
"google.golang.org/api/iterator"
"google.golang.org/api/option"
"cloud.google.com/go/storage"
"github.com/chef/automate/components/automate-cli/pkg/verifyserver/constants"
"github.com/chef/automate/components/automate-cli/pkg/verifyserver/models"
"github.com/chef/automate/lib/logger"
"github.com/google/uuid"
"github.com/pkg/errors"
)
type GCPCloudStorageConfig interface {
GetGCPConnection(ctx context.Context, req *models.GCPCloudStorageConfigRequest) *models.Checks
GetBucketAccess(ctx context.Context, req *models.GCPCloudStorageConfigRequest) *models.Checks
}
type GCPConfigService struct {
Logger logger.Logger
Req *models.GCPCloudStorageConfigRequest
GCPUtils GCPUtils
}
func NewGCPCloudStorageConfig(logger logger.Logger) GCPCloudStorageConfig {
return &GCPConfigService{
Logger: logger,
GCPUtils: NewGCPUtils(logger),
}
}
func (ss *GCPConfigService) GetGCPConnection(ctx context.Context, req *models.GCPCloudStorageConfigRequest) *models.Checks {
ss.Req = req
client, err := ss.GCPUtils.NewSessionWithOptions(ctx, ss.Req.GcpServiceAccount)
if err != nil {
ss.Logger.Errorf("error while creating a client: %v", err)
return ss.Response(constants.GCP_CONNECTION_TITLE, "", errors.Wrap(err, constants.GCP_CONNECTION_ERROR_MSG).Error(), constants.GCP_CONNECTION_RESOLUTION_MSG, false)
}
defer client.Close()
bucket := client.Bucket(ss.Req.BucketName)
err = ss.GCPUtils.BucketAttributes(ctx, bucket)
if err != nil {
return ss.Response(constants.GCP_CONNECTION_TITLE, "", errors.Wrap(err, constants.GCP_BUCKET_NOT_FOUND).Error(), constants.GCP_CONNECTION_RESOLUTION_GENERAL_MSG, false)
}
return ss.Response(constants.GCP_CONNECTION_TITLE, constants.GCP_CONNECTION_SUCCESS_MSG, "", "", true)
}
func (ss *GCPConfigService) GetBucketAccess(ctx context.Context, req *models.GCPCloudStorageConfigRequest) *models.Checks {
ss.Req = req
client, err := ss.GCPUtils.NewSessionWithOptions(ctx, ss.Req.GcpServiceAccount)
if err != nil {
ss.Logger.Errorf("error while creating a client: %v", err)
return ss.Response(constants.GCP_CONNECTION_TITLE, "", errors.Wrap(err, constants.GCP_CONNECTION_ERROR_MSG).Error(), constants.GCP_CONNECTION_RESOLUTION_MSG, false)
}
// Upload data in GCP bucket
uniqueID := uuid.New().String()
fileName := constants.GCP_CHECK_FILE_PREFIX + uniqueID + ".txt"
bucket := client.Bucket(ss.Req.BucketName)
obj := bucket.Object(fileName)
if err := ss.GCPUtils.NewUploader(ctx, obj); err != nil {
ss.Logger.Errorf("Error uploading the objects")
return ss.Response(constants.GCP_CONNECTION_TITLE, "", errors.Wrap(err, constants.GCP_BUCKET_UPLOAD_ERROR_MSG).Error(), constants.GCP_BUCKET_UPLOAD_RESOLUTION_MSG, false)
}
// read/list data in GCP bucket
query := &storage.Query{Prefix: constants.GCP_CHECK_FILE_PREFIX}
if err := ss.GCPUtils.ListObjects(ctx, bucket, query); err != nil {
ss.Logger.Errorf("Error listing the objects")
return ss.Response(constants.GCP_CONNECTION_TITLE, "", errors.Wrap(err, constants.GCP_BUCKET_LIST_ERROR_MSG).Error(), constants.GCP_BUCKET_LIST_RESOLUTION_MSG, false)
}
// Delete data in GCP bucket
if err := ss.GCPUtils.DeleteObject(ctx, obj); err != nil {
ss.Logger.Errorf("Error deleting the objects")
return ss.Response(constants.GCP_CONNECTION_TITLE, "", errors.Wrap(err, constants.GCP_BUCKET_DELETE_ERROR_MSG).Error(), constants.GCP_BUCKET_DELETE_RESOLUTION_MSG, false)
}
return ss.Response(constants.GCP_BUCKET_ACCESS_TITLE, constants.GCP_CONNECTION_SUCCESS_MSG, "", "", true)
}
func (ss *GCPConfigService) Response(Title, SuccessMsg, ErrorMsg, ResolutionMsg string, Passed bool) *models.Checks {
return &models.Checks{
Title: Title,
Passed: Passed,
SuccessMsg: SuccessMsg,
ErrorMsg: ErrorMsg,
ResolutionMsg: ResolutionMsg,
}
}
type GCPUtils interface {
NewSessionWithOptions(ctx context.Context, gsa *models.GcpServiceAccount) (*storage.Client, error)
DeleteObject(ctx context.Context, obj *storage.ObjectHandle) error
ListObjects(ctx context.Context, bucket *storage.BucketHandle, query *storage.Query) error
NewUploader(ctx context.Context, obj *storage.ObjectHandle) error
BucketAttributes(ctx context.Context, bucket *storage.BucketHandle) error
}
func NewGCPUtils(logger logger.Logger) *GCPUtilsImpl {
return &GCPUtilsImpl{
Logger: logger,
}
}
type GCPUtilsImpl struct {
Logger logger.Logger
}
func (au *GCPUtilsImpl) NewSessionWithOptions(ctx context.Context, gsa *models.GcpServiceAccount) (*storage.Client, error) {
bx, _ := json.Marshal(gsa)
return storage.NewClient(ctx, option.WithCredentialsJSON(bx))
}
func (au *GCPUtilsImpl) NewUploader(ctx context.Context, uploadObject *storage.ObjectHandle) error {
wc := uploadObject.NewWriter(ctx)
_, err := fmt.Fprintf(wc, "test message")
if err != nil {
return err
}
return wc.Close()
}
func (au *GCPUtilsImpl) DeleteObject(ctx context.Context, obj *storage.ObjectHandle) error {
return obj.Delete(ctx)
}
func (au *GCPUtilsImpl) ListObjects(ctx context.Context, bucket *storage.BucketHandle, query *storage.Query) error {
it := bucket.Objects(ctx, query)
for attrs, err := it.Next(); err != iterator.Done; attrs, err = it.Next() {
if err != nil {
au.Logger.Errorf("Error listing the objects")
return err
}
au.Logger.Debug("Objects in the bucket", attrs.Name)
}
return nil
}
func (au *GCPUtilsImpl) BucketAttributes(ctx context.Context, bucket *storage.BucketHandle) error {
if _, err := bucket.Attrs(ctx); err != nil {
return err
}
return nil
}