From 072fec86e7c15dc016ba014698f178690c5dd32b Mon Sep 17 00:00:00 2001 From: tenyo Date: Tue, 26 Apr 2022 10:35:46 -0400 Subject: [PATCH] Support for creating/deleting volumes (#24) * add support for creating volumes * add support for deleting volumes * fixup * update modules --- api/handlers.go | 8 +- api/handlers_instances.go | 2 +- api/handlers_volumes.go | 95 +++++++++++++++++ api/orchestration_volumes.go | 50 +++++++++ api/policy.go | 50 +++++++++ api/routes.go | 4 +- api/types.go | 10 ++ ec2/volumes.go | 41 ++++++++ ec2/volumes_test.go | 195 +++++++++++++++++++++++++++++++++++ go.mod | 12 +-- go.sum | 26 ++--- 11 files changed, 466 insertions(+), 27 deletions(-) create mode 100644 api/orchestration_volumes.go create mode 100644 ec2/volumes_test.go diff --git a/api/handlers.go b/api/handlers.go index 4978f5f..608db70 100644 --- a/api/handlers.go +++ b/api/handlers.go @@ -50,8 +50,14 @@ func NotImplemented(w http.ResponseWriter, r *http.Request) { w.Write([]byte("Not Implemented")) } -// handleResponseOk handles the standard response +// handleResponseOk handles the standard success response +// returns 200 or 204 (if no response content) func handleResponseOk(w http.ResponseWriter, response interface{}) { + if response == nil { + w.WriteHeader(http.StatusNoContent) + return + } + j, err := json.Marshal(response) if err != nil { log.Errorf("cannot marshal response (%v) into JSON: %s", response, err) diff --git a/api/handlers_instances.go b/api/handlers_instances.go index b0b8496..7bfadc5 100644 --- a/api/handlers_instances.go +++ b/api/handlers_instances.go @@ -106,7 +106,7 @@ func (s *server) InstanceDeleteHandler(w http.ResponseWriter, r *http.Request) { return } - handleResponseOk(w, "OK") + handleResponseOk(w, nil) } func (s *server) InstanceListHandler(w http.ResponseWriter, r *http.Request) { diff --git a/api/handlers_volumes.go b/api/handlers_volumes.go index 0f0a03f..fd515e5 100644 --- a/api/handlers_volumes.go +++ b/api/handlers_volumes.go @@ -1,6 +1,7 @@ package api import ( + "encoding/json" "fmt" "net/http" "strconv" @@ -11,6 +12,100 @@ import ( "github.com/gorilla/mux" ) +func (s *server) VolumeCreateHandler(w http.ResponseWriter, r *http.Request) { + w = LogWriter{w} + vars := mux.Vars(r) + account := s.mapAccountNumber(vars["account"]) + + req := Ec2VolumeCreateRequest{} + if err := json.NewDecoder(r.Body).Decode(&req); err != nil { + msg := fmt.Sprintf("cannot decode body into create volume input: %s", err) + handleError(w, apierror.New(apierror.ErrBadRequest, msg, err)) + return + } + + if req.AZ == nil { + handleError(w, apierror.New(apierror.ErrBadRequest, "missing required field: az", nil)) + return + } + + if req.Size == nil && req.SnapshotId == nil { + handleError(w, apierror.New(apierror.ErrBadRequest, "at least one of these must be specified: size, snapshot_id", nil)) + return + } + + if aws.Int64Value(req.Size) < 1 || aws.Int64Value(req.Size) > 16384 { + handleError(w, apierror.New(apierror.ErrBadRequest, "volume size must be between 1 and 16384", nil)) + return + } + + if req.Type == nil { + req.Type = aws.String("gp3") + } + + if req.Encrypted == nil { + req.Encrypted = aws.Bool(false) + } + + policy, err := volumeCreatePolicy() + if err != nil { + handleError(w, err) + return + } + + orch, err := s.newEc2Orchestrator(r.Context(), &sessionParams{ + role: fmt.Sprintf("arn:aws:iam::%s:role/%s", account, s.session.RoleName), + inlinePolicy: policy, + policyArns: []string{ + "arn:aws:iam::aws:policy/AmazonEC2ReadOnlyAccess", + }, + }) + if err != nil { + handleError(w, err) + return + } + + out, err := orch.createVolume(r.Context(), &req) + if err != nil { + handleError(w, err) + return + } + + handleResponseOk(w, out) +} + +func (s *server) VolumeDeleteHandler(w http.ResponseWriter, r *http.Request) { + w = LogWriter{w} + vars := mux.Vars(r) + account := s.mapAccountNumber(vars["account"]) + id := vars["id"] + + policy, err := volumeDeletePolicy(id) + if err != nil { + handleError(w, apierror.New(apierror.ErrInternalError, "failed to generate policy", err)) + return + } + + orch, err := s.newEc2Orchestrator(r.Context(), &sessionParams{ + role: fmt.Sprintf("arn:aws:iam::%s:role/%s", account, s.session.RoleName), + inlinePolicy: policy, + policyArns: []string{ + "arn:aws:iam::aws:policy/AmazonEC2ReadOnlyAccess", + }, + }) + if err != nil { + handleError(w, err) + return + } + + if err := orch.deleteVolume(r.Context(), id); err != nil { + handleError(w, err) + return + } + + handleResponseOk(w, nil) +} + func (s *server) VolumeListHandler(w http.ResponseWriter, r *http.Request) { w = LogWriter{w} vars := mux.Vars(r) diff --git a/api/orchestration_volumes.go b/api/orchestration_volumes.go new file mode 100644 index 0000000..3b3e6cf --- /dev/null +++ b/api/orchestration_volumes.go @@ -0,0 +1,50 @@ +package api + +import ( + "context" + + "github.com/YaleSpinup/apierror" + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/awsutil" + "github.com/aws/aws-sdk-go/service/ec2" + log "github.com/sirupsen/logrus" +) + +func (o *ec2Orchestrator) createVolume(ctx context.Context, req *Ec2VolumeCreateRequest) (string, error) { + if req == nil { + return "", apierror.New(apierror.ErrBadRequest, "invalid input", nil) + } + + log.Debugf("got request to create volume: %s", awsutil.Prettify(req)) + + input := &ec2.CreateVolumeInput{ + AvailabilityZone: req.AZ, + Encrypted: req.Encrypted, + Iops: req.Iops, + KmsKeyId: req.KmsKeyId, + Size: req.Size, + SnapshotId: req.SnapshotId, + VolumeType: req.Type, + } + + out, err := o.ec2Client.CreateVolume(ctx, input) + if err != nil { + return "", err + } + + return aws.StringValue(out.VolumeId), nil +} + +func (o *ec2Orchestrator) deleteVolume(ctx context.Context, id string) error { + if id == "" { + return apierror.New(apierror.ErrBadRequest, "invalid input", nil) + } + + log.Debugf("got request to delete volume %s", id) + + if err := o.ec2Client.DeleteVolume(ctx, id); err != nil { + return err + } + + return nil +} diff --git a/api/policy.go b/api/policy.go index 173c196..0210930 100644 --- a/api/policy.go +++ b/api/policy.go @@ -172,6 +172,8 @@ func sgUpdatePolicy(id string) (string, error) { } func tagCreatePolicy() (string, error) { + log.Debugf("generating tag crete policy document") + policy := iam.PolicyDocument{ Version: "2012-10-17", Statement: []iam.StatementEntry{ @@ -192,3 +194,51 @@ func tagCreatePolicy() (string, error) { return string(j), nil } + +func volumeCreatePolicy() (string, error) { + log.Debugf("generating volume crete policy document") + + policy := iam.PolicyDocument{ + Version: "2012-10-17", + Statement: []iam.StatementEntry{ + { + Effect: "Allow", + Action: []string{ + "ec2:CreateVolume", + }, + Resource: []string{"*"}, + }, + }, + } + + j, err := json.Marshal(policy) + if err != nil { + return "", err + } + + return string(j), nil +} + +func volumeDeletePolicy(id string) (string, error) { + log.Debugf("generating volume delete policy document") + + policy := iam.PolicyDocument{ + Version: "2012-10-17", + Statement: []iam.StatementEntry{ + { + Effect: "Allow", + Action: []string{ + "ec2:DeleteVolume", + }, + Resource: []string{"*"}, + }, + }, + } + + j, err := json.Marshal(policy) + if err != nil { + return "", err + } + + return string(j), nil +} diff --git a/api/routes.go b/api/routes.go index 04ecd99..74abe5b 100644 --- a/api/routes.go +++ b/api/routes.go @@ -60,7 +60,7 @@ func (s *server) routes() { api.HandleFunc("/{account}/instances", s.InstanceCreateHandler).Methods(http.MethodPost) api.HandleFunc("/{account}/instances/{id}/volumes", s.ProxyRequestHandler).Methods(http.MethodPost) api.HandleFunc("/{account}/sgs", s.SecurityGroupCreateHandler).Methods(http.MethodPost) - api.HandleFunc("/{account}/volumes", s.ProxyRequestHandler).Methods(http.MethodPost) + api.HandleFunc("/{account}/volumes", s.VolumeCreateHandler).Methods(http.MethodPost) api.HandleFunc("/{account}/snapshots", s.ProxyRequestHandler).Methods(http.MethodPost) api.HandleFunc("/{account}/images", s.ProxyRequestHandler).Methods(http.MethodPost) @@ -80,7 +80,7 @@ func (s *server) routes() { api.HandleFunc("/{account}/instances/{id}/volumes/{vid}", s.ProxyRequestHandler).Methods(http.MethodDelete) api.HandleFunc("/{account}/instanceprofiles/{name}", s.ProxyRequestHandler).Methods(http.MethodDelete) api.HandleFunc("/{account}/sgs/{id}", s.SecurityGroupDeleteHandler).Methods(http.MethodDelete) - api.HandleFunc("/{account}/volumes/{id}", s.ProxyRequestHandler).Methods(http.MethodDelete) + api.HandleFunc("/{account}/volumes/{id}", s.VolumeDeleteHandler).Methods(http.MethodDelete) api.HandleFunc("/{account}/snapshots/{id}", s.ProxyRequestHandler).Methods(http.MethodDelete) api.HandleFunc("/{account}/images/{id}", s.ProxyRequestHandler).Methods(http.MethodDelete) } diff --git a/api/types.go b/api/types.go index 742d414..3eabf4c 100644 --- a/api/types.go +++ b/api/types.go @@ -49,6 +49,16 @@ type Ec2BlockDevice struct { Ebs *Ec2EbsVolume `json:"ebs"` } +type Ec2VolumeCreateRequest struct { + Type *string `json:"type"` + Size *int64 `json:"size"` + Iops *int64 `json:"iops"` + AZ *string `json:"az"` + SnapshotId *string `json:"snapshot_id"` + KmsKeyId *string `json:"kms_key_id"` + Encrypted *bool `json:"encrypted"` +} + type Ec2EbsVolume struct { Encrypted *bool `json:"encrypted"` VolumeSize *int64 `json:"volume_size"` diff --git a/ec2/volumes.go b/ec2/volumes.go index 20ef97c..a458a05 100644 --- a/ec2/volumes.go +++ b/ec2/volumes.go @@ -10,6 +10,47 @@ import ( log "github.com/sirupsen/logrus" ) +// CreateVolume creates a new volume and returns the volume details +func (e *Ec2) CreateVolume(ctx context.Context, input *ec2.CreateVolumeInput) (*ec2.Volume, error) { + if input == nil { + return nil, apierror.New(apierror.ErrBadRequest, "invalid input", nil) + } + + log.Infof("creating volume of type %s, size %d", aws.StringValue(input.VolumeType), aws.Int64Value(input.Size)) + + out, err := e.Service.CreateVolumeWithContext(ctx, input) + if err != nil { + return nil, common.ErrCode("failed to create volume", err) + } + + log.Debugf("got output creating volume: %+v", out) + + if out == nil { + return nil, apierror.New(apierror.ErrInternalError, "Unexpected volume output", nil) + } + + return out, nil +} + +func (e *Ec2) DeleteVolume(ctx context.Context, id string) error { + if id == "" { + return apierror.New(apierror.ErrBadRequest, "invalid input", nil) + } + + log.Infof("deleting volume %s", id) + + out, err := e.Service.DeleteVolumeWithContext(ctx, &ec2.DeleteVolumeInput{ + VolumeId: aws.String(id), + }) + if err != nil { + return common.ErrCode("failed to delete volume", err) + } + + log.Debugf("got output deleting volume: %+v", out) + + return nil +} + func (e *Ec2) ListVolumes(ctx context.Context, org string, per int64, next *string) ([]map[string]*string, *string, error) { log.Infof("listing volumes") diff --git a/ec2/volumes_test.go b/ec2/volumes_test.go new file mode 100644 index 0000000..250ef8e --- /dev/null +++ b/ec2/volumes_test.go @@ -0,0 +1,195 @@ +package ec2 + +import ( + "context" + "reflect" + "testing" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/awserr" + "github.com/aws/aws-sdk-go/aws/request" + "github.com/aws/aws-sdk-go/aws/session" + "github.com/aws/aws-sdk-go/service/ec2" + "github.com/aws/aws-sdk-go/service/ec2/ec2iface" +) + +func (m mockEC2Client) CreateVolumeWithContext(ctx context.Context, input *ec2.CreateVolumeInput, opts ...request.Option) (*ec2.Volume, error) { + if m.err != nil { + return nil, m.err + } + + // return nil Volume (unexpected) + if aws.StringValue(input.VolumeType) == "weird" { + return nil, nil + } + + return &ec2.Volume{ + VolumeId: aws.String("vol-0123456789abcdef0"), + }, nil +} + +func (m mockEC2Client) DeleteVolumeWithContext(ctx context.Context, input *ec2.DeleteVolumeInput, opts ...request.Option) (*ec2.DeleteVolumeOutput, error) { + if m.err != nil { + return nil, m.err + } + + return &ec2.DeleteVolumeOutput{}, nil +} + +func TestEc2_CreateVolume(t *testing.T) { + type fields struct { + session *session.Session + Service ec2iface.EC2API + DefaultKMSKeyId string + DefaultSgs []string + DefaultSubnets []string + org string + } + type args struct { + ctx context.Context + input *ec2.CreateVolumeInput + } + + tests := []struct { + name string + fields fields + args args + want *ec2.Volume + wantErr bool + }{ + { + name: "nil input", + fields: fields{ + Service: newmockEC2Client(t, nil), + }, + args: args{ctx: context.TODO()}, + wantErr: true, + }, + { + name: "unexpected output", + fields: fields{ + Service: newmockEC2Client(t, nil), + }, + args: args{ + ctx: context.TODO(), + input: &ec2.CreateVolumeInput{ + AvailabilityZone: aws.String("us-east-1"), + VolumeType: aws.String("weird"), + }, + }, + wantErr: true, + }, + { + name: "good input", + fields: fields{ + Service: newmockEC2Client(t, nil), + }, + args: args{ + ctx: context.TODO(), + input: &ec2.CreateVolumeInput{ + AvailabilityZone: aws.String("us-east-1"), + VolumeType: aws.String("gp3"), + }, + }, + want: &ec2.Volume{ + VolumeId: aws.String("vol-0123456789abcdef0"), + }, + }, + { + name: "aws err", + fields: fields{ + Service: newmockEC2Client(t, awserr.New("BadRequest", "boom", nil)), + }, + args: args{ctx: context.TODO()}, + wantErr: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + e := &Ec2{ + session: tt.fields.session, + Service: tt.fields.Service, + DefaultKMSKeyId: tt.fields.DefaultKMSKeyId, + DefaultSgs: tt.fields.DefaultSgs, + DefaultSubnets: tt.fields.DefaultSubnets, + org: tt.fields.org, + } + got, err := e.CreateVolume(tt.args.ctx, tt.args.input) + if (err != nil) != tt.wantErr { + t.Errorf("Ec2.CreateVolume() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("Ec2.CreateVolume() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestEc2_DeleteVolume(t *testing.T) { + type fields struct { + session *session.Session + Service ec2iface.EC2API + DefaultKMSKeyId string + DefaultSgs []string + DefaultSubnets []string + org string + } + type args struct { + ctx context.Context + input string + } + + tests := []struct { + name string + fields fields + args args + wantErr bool + }{ + { + name: "nil input", + fields: fields{ + Service: newmockEC2Client(t, nil), + }, + args: args{ctx: context.TODO()}, + wantErr: true, + }, + { + name: "good input", + fields: fields{ + Service: newmockEC2Client(t, nil), + }, + args: args{ + ctx: context.TODO(), + input: "vol-0123456789abcdef0", + }, + }, + { + name: "aws err", + fields: fields{ + Service: newmockEC2Client(t, awserr.New("BadRequest", "boom", nil)), + }, + args: args{ctx: context.TODO()}, + wantErr: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + e := &Ec2{ + session: tt.fields.session, + Service: tt.fields.Service, + DefaultKMSKeyId: tt.fields.DefaultKMSKeyId, + DefaultSgs: tt.fields.DefaultSgs, + DefaultSubnets: tt.fields.DefaultSubnets, + org: tt.fields.org, + } + err := e.DeleteVolume(tt.args.ctx, tt.args.input) + if (err != nil) != tt.wantErr { + t.Errorf("Ec2.DeleteVolume() error = %v, wantErr %v", err, tt.wantErr) + return + } + }) + } +} diff --git a/go.mod b/go.mod index 27e660a..1af592e 100644 --- a/go.mod +++ b/go.mod @@ -5,8 +5,8 @@ go 1.18 require ( github.com/YaleSpinup/apierror v0.1.0 github.com/YaleSpinup/aws-go v0.2.0 - github.com/aws/amazon-ec2-instance-selector/v2 v2.1.0 - github.com/aws/aws-sdk-go v1.43.30 + github.com/aws/amazon-ec2-instance-selector/v2 v2.3.0 + github.com/aws/aws-sdk-go v1.44.0 github.com/google/uuid v1.3.0 github.com/gorilla/handlers v1.5.1 github.com/gorilla/mux v1.8.0 @@ -14,7 +14,7 @@ require ( github.com/pkg/errors v0.9.1 github.com/prometheus/client_golang v1.12.1 github.com/sirupsen/logrus v1.8.1 - golang.org/x/crypto v0.0.0-20220321153916-2c7772ba3064 + golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4 ) require ( @@ -22,18 +22,16 @@ require ( github.com/blang/semver/v4 v4.0.0 // indirect github.com/cespare/xxhash/v2 v2.1.2 // indirect github.com/felixge/httpsnoop v1.0.2 // indirect - github.com/ghodss/yaml v1.0.0 // indirect github.com/golang/protobuf v1.5.2 // indirect github.com/imdario/mergo v0.3.12 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/prometheus/client_model v0.2.0 // indirect - github.com/prometheus/common v0.33.0 // indirect + github.com/prometheus/common v0.34.0 // indirect github.com/prometheus/procfs v0.7.3 // indirect go.uber.org/atomic v1.9.0 // indirect go.uber.org/multierr v1.8.0 // indirect - golang.org/x/sys v0.0.0-20220330033206-e17cdc41300f // indirect + golang.org/x/sys v0.0.0-20220422013727-9388b58f7150 // indirect google.golang.org/protobuf v1.28.0 // indirect - gopkg.in/yaml.v2 v2.4.0 // indirect ) diff --git a/go.sum b/go.sum index 728fd89..08b2889 100644 --- a/go.sum +++ b/go.sum @@ -42,10 +42,10 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuy github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= -github.com/aws/amazon-ec2-instance-selector/v2 v2.1.0 h1:c+t2xa2kG6amf022jIUyh7fOx8qi97SxfmqbOotGHX4= -github.com/aws/amazon-ec2-instance-selector/v2 v2.1.0/go.mod h1:YDeSLaJknr4/GTVHh09hEOip/zkCKLZueKHW8iWQXik= -github.com/aws/aws-sdk-go v1.43.30 h1:Q3lgrX/tz/MkEiPVVQnOQThBAK2QC2SCTCKTD1mwGFA= -github.com/aws/aws-sdk-go v1.43.30/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo= +github.com/aws/amazon-ec2-instance-selector/v2 v2.3.0 h1:EcP2xXjzr7+I58EjmrRfZnVGVe32mgAijCIS6LB/1qM= +github.com/aws/amazon-ec2-instance-selector/v2 v2.3.0/go.mod h1:/KFJVMLvjzGl+KsAzEkrZ09wCYlbYAdXmPGxLvlwAr0= +github.com/aws/aws-sdk-go v1.44.0 h1:jwtHuNqfnJxL4DKHBUVUmQlfueQqBW7oXP6yebZR/R0= +github.com/aws/aws-sdk-go v1.44.0/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -71,8 +71,6 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7 github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/felixge/httpsnoop v1.0.2 h1:+nS9g82KMXccJ/wp0zyRW9ZBHFETmMGtkk+2CTTrW4o= github.com/felixge/httpsnoop v1.0.2/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= -github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= @@ -147,7 +145,6 @@ github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= @@ -168,10 +165,8 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= -github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= @@ -207,8 +202,8 @@ github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y8 github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -github.com/prometheus/common v0.33.0 h1:rHgav/0a6+uYgGdNt3jwz8FNSesO/Hsang3O0T9A5SE= -github.com/prometheus/common v0.33.0/go.mod h1:gB3sOl7P0TvJabZpLY5uQMpUqRCPPCyRLCZYc7JZTNE= +github.com/prometheus/common v0.34.0 h1:RBmGO9d/FVjqHT0yUGQwBJhkwKV+wPCn7KGpvfab0uE= +github.com/prometheus/common v0.34.0/go.mod h1:gB3sOl7P0TvJabZpLY5uQMpUqRCPPCyRLCZYc7JZTNE= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= @@ -247,8 +242,8 @@ golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20220321153916-2c7772ba3064 h1:S25/rfnfsMVgORT4/J61MJ7rdyseOZOyvLIrZEZ7s6s= -golang.org/x/crypto v0.0.0-20220321153916-2c7772ba3064/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4 h1:kUhD7nTDoI3fVd9G4ORWrbV5NY0liEs/Jg2pv5f+bBA= +golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -365,8 +360,8 @@ golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220330033206-e17cdc41300f h1:rlezHXNlxYWvBCzNses9Dlc7nGFaNMJeqLolcmQSSZY= -golang.org/x/sys v0.0.0-20220330033206-e17cdc41300f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220422013727-9388b58f7150 h1:xHms4gcpe1YE7A3yIllJXP16CMAGuqwO2lX1mTyyRRc= +golang.org/x/sys v0.0.0-20220422013727-9388b58f7150/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -504,7 +499,6 @@ google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqw gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=