From cafa29bdcd47271d0a52ad81be48f2dc9ebf5e8d Mon Sep 17 00:00:00 2001 From: Vince Prignano Date: Sun, 18 Nov 2018 18:54:25 -0800 Subject: [PATCH] Add converters package, use awserrors pkg for all errors Signed-off-by: Vince Prignano --- pkg/cloud/aws/actuators/machine/BUILD.bazel | 2 +- pkg/cloud/aws/actuators/machine/actuator.go | 5 +- pkg/cloud/aws/converters/BUILD.bazel | 16 +++ pkg/cloud/aws/converters/instance.go | 49 ++++++++ pkg/cloud/aws/converters/tags.go | 37 ++++++ pkg/cloud/aws/services/awserrors/errors.go | 106 ++++++++++++++++ pkg/cloud/aws/services/ec2/BUILD | 4 +- pkg/cloud/aws/services/ec2/bastion.go | 10 +- pkg/cloud/aws/services/ec2/eips.go | 5 +- pkg/cloud/aws/services/ec2/errors.go | 125 ------------------- pkg/cloud/aws/services/ec2/filters.go | 13 ++ pkg/cloud/aws/services/ec2/gateways.go | 7 +- pkg/cloud/aws/services/ec2/instances.go | 52 ++------ pkg/cloud/aws/services/ec2/instances_test.go | 3 +- pkg/cloud/aws/services/ec2/securitygroups.go | 5 +- pkg/cloud/aws/services/ec2/vpc.go | 10 +- 16 files changed, 261 insertions(+), 188 deletions(-) create mode 100644 pkg/cloud/aws/converters/BUILD.bazel create mode 100644 pkg/cloud/aws/converters/instance.go create mode 100644 pkg/cloud/aws/converters/tags.go delete mode 100644 pkg/cloud/aws/services/ec2/errors.go diff --git a/pkg/cloud/aws/actuators/machine/BUILD.bazel b/pkg/cloud/aws/actuators/machine/BUILD.bazel index 67978ebe88..78e7c6ab83 100644 --- a/pkg/cloud/aws/actuators/machine/BUILD.bazel +++ b/pkg/cloud/aws/actuators/machine/BUILD.bazel @@ -13,7 +13,7 @@ go_library( deps = [ "//pkg/apis/awsprovider/v1alpha1:go_default_library", "//pkg/cloud/aws/services:go_default_library", - "//pkg/cloud/aws/services/ec2:go_default_library", + "//pkg/cloud/aws/services/awserrors:go_default_library", "//pkg/deployer:go_default_library", "//pkg/tokens:go_default_library", "//vendor/github.com/aws/aws-sdk-go/aws:go_default_library", diff --git a/pkg/cloud/aws/actuators/machine/actuator.go b/pkg/cloud/aws/actuators/machine/actuator.go index 7d0f3bce0a..5557c0ce0c 100644 --- a/pkg/cloud/aws/actuators/machine/actuator.go +++ b/pkg/cloud/aws/actuators/machine/actuator.go @@ -27,7 +27,7 @@ import ( "sigs.k8s.io/cluster-api-provider-aws/pkg/apis/awsprovider/v1alpha1" "sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/aws/services" service "sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/aws/services" - ec2svc "sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/aws/services/ec2" + "sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/aws/services/awserrors" "sigs.k8s.io/cluster-api-provider-aws/pkg/deployer" "sigs.k8s.io/cluster-api-provider-aws/pkg/tokens" clusterv1 "sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha1" @@ -145,8 +145,7 @@ func (a *Actuator) Create(cluster *clusterv1.Cluster, machine *clusterv1.Machine i, err := a.ec2(clusterConfig).CreateOrGetMachine(machine, status, config, clusterStatus, clusterConfig, cluster, bootstrapToken) if err != nil { - - if ec2svc.IsFailedDependency(errors.Cause(err)) { + if awserrors.IsFailedDependency(errors.Cause(err)) { klog.Errorf("network not ready to launch instances yet: %s", err) return &controllerError.RequeueAfterError{ RequeueAfter: time.Minute, diff --git a/pkg/cloud/aws/converters/BUILD.bazel b/pkg/cloud/aws/converters/BUILD.bazel new file mode 100644 index 0000000000..f71d6d8881 --- /dev/null +++ b/pkg/cloud/aws/converters/BUILD.bazel @@ -0,0 +1,16 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = [ + "instance.go", + "tags.go", + ], + importpath = "sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/aws/converters", + visibility = ["//visibility:public"], + deps = [ + "//pkg/apis/awsprovider/v1alpha1:go_default_library", + "//vendor/github.com/aws/aws-sdk-go/aws:go_default_library", + "//vendor/github.com/aws/aws-sdk-go/service/ec2:go_default_library", + ], +) diff --git a/pkg/cloud/aws/converters/instance.go b/pkg/cloud/aws/converters/instance.go new file mode 100644 index 0000000000..211ba96e3a --- /dev/null +++ b/pkg/cloud/aws/converters/instance.go @@ -0,0 +1,49 @@ +// Copyright © 2018 The Kubernetes Authors. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package converters + +import ( + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/ec2" + "sigs.k8s.io/cluster-api-provider-aws/pkg/apis/awsprovider/v1alpha1" +) + +func SDKToInstance(v *ec2.Instance) *v1alpha1.Instance { + i := &v1alpha1.Instance{ + ID: aws.StringValue(v.InstanceId), + State: v1alpha1.InstanceState(*v.State.Name), + Type: aws.StringValue(v.InstanceType), + SubnetID: aws.StringValue(v.SubnetId), + ImageID: aws.StringValue(v.ImageId), + KeyName: v.KeyName, + PrivateIP: v.PrivateIpAddress, + PublicIP: v.PublicIpAddress, + ENASupport: v.EnaSupport, + EBSOptimized: v.EbsOptimized, + } + + for _, sg := range v.SecurityGroups { + i.SecurityGroupIDs = append(i.SecurityGroupIDs, *sg.GroupId) + } + + // TODO: Handle returned IAM instance profile, since we are currently + // using a string representing the name, but the InstanceProfile returned + // from the sdk only returns ARN and ID. + + if len(v.Tags) > 0 { + i.Tags = TagsToMap(v.Tags) + } + + return i +} diff --git a/pkg/cloud/aws/converters/tags.go b/pkg/cloud/aws/converters/tags.go new file mode 100644 index 0000000000..1de2efd588 --- /dev/null +++ b/pkg/cloud/aws/converters/tags.go @@ -0,0 +1,37 @@ +package converters + +import ( + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/ec2" +) + +// TagsToMap converts a []*ec2.Tag into a map[string]string. +func TagsToMap(src []*ec2.Tag) map[string]string { + // Create an array of exactly the length we require to hopefully avoid some + // allocations while looping. + tags := make(map[string]string) + + for _, t := range src { + tags[*t.Key] = *t.Value + } + + return tags +} + +// MapToTags converts a map[string]string to a []*ec2.Tag +func MapToTags(src map[string]string) []*ec2.Tag { + // Create an array of exactly the length we require to hopefully avoid some + // allocations while looping. + tags := make([]*ec2.Tag, 0, len(src)) + + for k, v := range src { + tag := &ec2.Tag{ + Key: aws.String(k), + Value: aws.String(v), + } + + tags = append(tags, tag) + } + + return tags +} diff --git a/pkg/cloud/aws/services/awserrors/errors.go b/pkg/cloud/aws/services/awserrors/errors.go index 933b2b78e5..8bc90eb791 100644 --- a/pkg/cloud/aws/services/awserrors/errors.go +++ b/pkg/cloud/aws/services/awserrors/errors.go @@ -14,9 +14,20 @@ package awserrors import ( + "net/http" + "github.com/aws/aws-sdk-go/aws/awserr" ) +const ( + AuthFailure = "AuthFailure" + InUseIPAddress = "InvalidIPAddress.InUse" + GroupNotFound = "InvalidGroup.NotFound" + PermissionNotFound = "InvalidPermission.NotFound" +) + +var _ error = &EC2Error{} + // Code returns the AWS error code as a string func Code(err error) (string, bool) { if awserr, ok := err.(awserr.Error); ok { @@ -32,3 +43,98 @@ func Message(err error) string { } return "" } + +// EC2Error is an error exposed to users of this library. +type EC2Error struct { //nolint + err error + + Code int +} + +// Error implements the Error interface. +func (e *EC2Error) Error() string { + return e.err.Error() +} + +// NewNotFound returns a new error which indicates that the resource of the kind and the name was not found. +func NewNotFound(err error) error { + return &EC2Error{ + err: err, + Code: http.StatusNotFound, + } +} + +// NewConflict returns a new error which indicates that the request cannot be processed due to a conflict. +func NewConflict(err error) error { + return &EC2Error{ + err: err, + Code: http.StatusConflict, + } +} + +// NewFailedDependency returns a new error which indicates that a dependency failure status +func NewFailedDependency(err error) error { + return &EC2Error{ + err: err, + Code: http.StatusFailedDependency, + } +} + +// IsFailedDependency checks if the error is pf http.StatusFailedDependency +func IsFailedDependency(err error) bool { + if ReasonForError(err) == http.StatusFailedDependency { + return true + } + return false +} + +// IsNotFound returns true if the error was created by NewNotFound. +func IsNotFound(err error) bool { + if ReasonForError(err) == http.StatusNotFound { + return true + } + return IsInvalidNotFoundError(err) +} + +// IsConflict returns true if the error was created by NewConflict. +func IsConflict(err error) bool { + return ReasonForError(err) == http.StatusConflict +} + +// IsSDKError returns true if the error is of type awserr.Error. +func IsSDKError(err error) (ok bool) { + _, ok = err.(awserr.Error) + return +} + +// IsInvalidNotFoundError tests for common aws not found errors +func IsInvalidNotFoundError(err error) bool { + if code, ok := Code(err); ok { + switch code { + case "InvalidVpcID.NotFound": + return true + } + } + return false +} + +// ReasonForError returns the HTTP status for a particular error. +func ReasonForError(err error) int { + switch t := err.(type) { + case *EC2Error: + return t.Code + } + return -1 +} + +func IsIgnorableSecurityGroupError(err error) error { + if code, ok := Code(err); ok { + switch code { + case GroupNotFound, PermissionNotFound: + return nil + default: + return err + } + } + return nil +} diff --git a/pkg/cloud/aws/services/ec2/BUILD b/pkg/cloud/aws/services/ec2/BUILD index 18e157f24b..39068527ec 100644 --- a/pkg/cloud/aws/services/ec2/BUILD +++ b/pkg/cloud/aws/services/ec2/BUILD @@ -8,7 +8,6 @@ go_library( "bastion.go", "console.go", "eips.go", - "errors.go", "filters.go", "gateways.go", "instances.go", @@ -25,11 +24,11 @@ go_library( visibility = ["//visibility:public"], deps = [ "//pkg/apis/awsprovider/v1alpha1:go_default_library", + "//pkg/cloud/aws/converters:go_default_library", "//pkg/cloud/aws/services/awserrors:go_default_library", "//pkg/cloud/aws/services/userdata:go_default_library", "//pkg/cloud/aws/services/wait:go_default_library", "//vendor/github.com/aws/aws-sdk-go/aws:go_default_library", - "//vendor/github.com/aws/aws-sdk-go/aws/awserr:go_default_library", "//vendor/github.com/aws/aws-sdk-go/service/ec2:go_default_library", "//vendor/github.com/aws/aws-sdk-go/service/ec2/ec2iface:go_default_library", "//vendor/github.com/pkg/errors:go_default_library", @@ -51,6 +50,7 @@ go_test( embed = [":go_default_library"], deps = [ "//pkg/apis/awsprovider/v1alpha1:go_default_library", + "//pkg/cloud/aws/services/awserrors:go_default_library", "//pkg/cloud/aws/services/ec2/mock_ec2iface:go_default_library", "//vendor/github.com/aws/aws-sdk-go/aws:go_default_library", "//vendor/github.com/aws/aws-sdk-go/service/ec2:go_default_library", diff --git a/pkg/cloud/aws/services/ec2/bastion.go b/pkg/cloud/aws/services/ec2/bastion.go index af0b43c09e..b436abcb67 100644 --- a/pkg/cloud/aws/services/ec2/bastion.go +++ b/pkg/cloud/aws/services/ec2/bastion.go @@ -22,6 +22,8 @@ import ( "github.com/pkg/errors" "k8s.io/klog" "sigs.k8s.io/cluster-api-provider-aws/pkg/apis/awsprovider/v1alpha1" + "sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/aws/converters" + "sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/aws/services/awserrors" "sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/aws/services/userdata" ) @@ -49,7 +51,7 @@ func (s *Service) ReconcileBastion(clusterName, keyName string, status *v1alpha1 // Describe bastion instance, if any. instance, err := s.describeBastionInstance(clusterName, status) - if IsNotFound(err) { + if awserrors.IsNotFound(err) { instance, err = s.runInstance(spec) if err != nil { return err @@ -73,7 +75,7 @@ func (s *Service) ReconcileBastion(clusterName, keyName string, status *v1alpha1 func (s *Service) DeleteBastion(clusterName string, status *v1alpha1.AWSClusterProviderStatus) error { instance, err := s.describeBastionInstance(clusterName, status) if err != nil { - if IsNotFound(err) { + if awserrors.IsNotFound(err) { klog.V(2).Info("bastion instance does not exist") return nil } @@ -107,12 +109,12 @@ func (s *Service) describeBastionInstance(clusterName string, status *v1alpha1.A for _, res := range out.Reservations { for _, instance := range res.Instances { if aws.StringValue(instance.State.Name) != ec2.InstanceStateNameTerminated { - return fromSDKTypeToInstance(instance), nil + return converters.SDKToInstance(instance), nil } } } - return nil, NewNotFound(errors.New("bastion host not found")) + return nil, awserrors.NewNotFound(errors.New("bastion host not found")) } func (s *Service) getDefaultBastion(clusterName string, region string, network v1alpha1.Network, keyName string) *v1alpha1.Instance { diff --git a/pkg/cloud/aws/services/ec2/eips.go b/pkg/cloud/aws/services/ec2/eips.go index 53dfa3aba0..b712a7e9b3 100644 --- a/pkg/cloud/aws/services/ec2/eips.go +++ b/pkg/cloud/aws/services/ec2/eips.go @@ -20,6 +20,7 @@ import ( "github.com/aws/aws-sdk-go/service/ec2" "github.com/pkg/errors" "k8s.io/klog" + "sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/aws/services/awserrors" "sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/aws/services/wait" ) @@ -93,8 +94,8 @@ func (s *Service) releaseAddresses(clusterName string) error { } retryableErrors := []string{ - errorAuthFailure, - errorInUseIPAddress, + awserrors.AuthFailure, + awserrors.InUseIPAddress, } err := wait.WaitForWithRetryable(wait.NewBackoff(), delete, retryableErrors) diff --git a/pkg/cloud/aws/services/ec2/errors.go b/pkg/cloud/aws/services/ec2/errors.go deleted file mode 100644 index e7912a3e40..0000000000 --- a/pkg/cloud/aws/services/ec2/errors.go +++ /dev/null @@ -1,125 +0,0 @@ -// Copyright © 2018 The Kubernetes Authors. -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package ec2 - -import ( - "net/http" - - "github.com/aws/aws-sdk-go/aws/awserr" - "sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/aws/services/awserrors" -) - -const ( - errorAuthFailure = "AuthFailure" - errorInUseIPAddress = "InvalidIPAddress.InUse" - errorGroupNotFound = "InvalidGroup.NotFound" - errorPermissionNotFound = "InvalidPermission.NotFound" -) - -var _ error = &EC2Error{} - -// EC2Error is an error exposed to users of this library. -type EC2Error struct { //nolint - err error - - Code int -} - -// Error implements the Error interface. -func (e *EC2Error) Error() string { - return e.err.Error() -} - -// NewNotFound returns a new error which indicates that the resource of the kind and the name was not found. -func NewNotFound(err error) error { - return &EC2Error{ - err: err, - Code: http.StatusNotFound, - } -} - -// NewConflict returns a new error which indicates that the request cannot be processed due to a conflict. -func NewConflict(err error) error { - return &EC2Error{ - err: err, - Code: http.StatusConflict, - } -} - -// NewFailedDependency returns a new error which indicates that a dependency failure status -func NewFailedDependency(err error) error { - return &EC2Error{ - err: err, - Code: http.StatusFailedDependency, - } -} - -// IsFailedDependency checks if the error is pf http.StatusFailedDependency -func IsFailedDependency(err error) bool { - if ReasonForError(err) == http.StatusFailedDependency { - return true - } - return false -} - -// IsNotFound returns true if the error was created by NewNotFound. -func IsNotFound(err error) bool { - if ReasonForError(err) == http.StatusNotFound { - return true - } - return IsInvalidNotFoundError(err) -} - -// IsConflict returns true if the error was created by NewConflict. -func IsConflict(err error) bool { - return ReasonForError(err) == http.StatusConflict -} - -// IsSDKError returns true if the error is of type awserr.Error. -func IsSDKError(err error) (ok bool) { - _, ok = err.(awserr.Error) - return -} - -// IsInvalidNotFoundError tests for common aws not found errors -func IsInvalidNotFoundError(err error) bool { - if code, ok := awserrors.Code(err); ok { - switch code { - case "InvalidVpcID.NotFound": - return true - } - } - return false -} - -// ReasonForError returns the HTTP status for a particular error. -func ReasonForError(err error) int { - switch t := err.(type) { - case *EC2Error: - return t.Code - } - return -1 -} - -func isIgnorableSecurityGroupError(err error) error { - if code, ok := awserrors.Code(err); ok { - switch code { - case errorGroupNotFound, errorPermissionNotFound: - return nil - default: - return err - } - } - return nil -} diff --git a/pkg/cloud/aws/services/ec2/filters.go b/pkg/cloud/aws/services/ec2/filters.go index 9c48c355b0..dd87094620 100644 --- a/pkg/cloud/aws/services/ec2/filters.go +++ b/pkg/cloud/aws/services/ec2/filters.go @@ -1,3 +1,16 @@ +// Copyright © 2018 The Kubernetes Authors. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package ec2 import ( diff --git a/pkg/cloud/aws/services/ec2/gateways.go b/pkg/cloud/aws/services/ec2/gateways.go index 8700ee76b1..2bba03b42f 100644 --- a/pkg/cloud/aws/services/ec2/gateways.go +++ b/pkg/cloud/aws/services/ec2/gateways.go @@ -21,13 +21,14 @@ import ( "github.com/pkg/errors" "k8s.io/klog" "sigs.k8s.io/cluster-api-provider-aws/pkg/apis/awsprovider/v1alpha1" + "sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/aws/services/awserrors" ) func (s *Service) reconcileInternetGateways(clusterName string, in *v1alpha1.Network) error { klog.V(2).Infof("Reconciling internet gateways") igs, err := s.describeVpcInternetGateways(clusterName, &in.VPC) - if IsNotFound(err) { + if awserrors.IsNotFound(err) { ig, err := s.createInternetGateway(clusterName, &in.VPC) if err != nil { return nil @@ -43,7 +44,7 @@ func (s *Service) reconcileInternetGateways(clusterName string, in *v1alpha1.Net func (s *Service) deleteInternetGateways(clusterName string, in *v1alpha1.Network) error { igs, err := s.describeVpcInternetGateways(clusterName, &in.VPC) - if IsNotFound(err) { + if awserrors.IsNotFound(err) { return nil } else if err != nil { return err @@ -112,7 +113,7 @@ func (s *Service) describeVpcInternetGateways(clusterName string, vpc *v1alpha1. } if len(out.InternetGateways) == 0 { - return nil, NewNotFound(errors.Errorf("no nat gateways found in vpc %q", vpc.ID)) + return nil, awserrors.NewNotFound(errors.Errorf("no nat gateways found in vpc %q", vpc.ID)) } return out.InternetGateways, nil diff --git a/pkg/cloud/aws/services/ec2/instances.go b/pkg/cloud/aws/services/ec2/instances.go index e234358743..05fa9c47cc 100644 --- a/pkg/cloud/aws/services/ec2/instances.go +++ b/pkg/cloud/aws/services/ec2/instances.go @@ -16,11 +16,14 @@ package ec2 import ( "encoding/base64" + "sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/aws/converters" + "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/ec2" "github.com/pkg/errors" "k8s.io/klog" "sigs.k8s.io/cluster-api-provider-aws/pkg/apis/awsprovider/v1alpha1" + "sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/aws/services/awserrors" "sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/aws/services/userdata" clusterv1 "sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha1" ) @@ -39,7 +42,7 @@ func (s *Service) InstanceByTags(machine *clusterv1.Machine, cluster *clusterv1. out, err := s.EC2.DescribeInstances(input) switch { - case IsNotFound(err): + case awserrors.IsNotFound(err): return nil, nil case err != nil: return nil, errors.Wrap(err, "failed to describe instances by tags") @@ -50,7 +53,7 @@ func (s *Service) InstanceByTags(machine *clusterv1.Machine, cluster *clusterv1. // match for _, res := range out.Reservations { for _, inst := range res.Instances { - return fromSDKTypeToInstance(inst), nil + return converters.SDKToInstance(inst), nil } } @@ -68,14 +71,14 @@ func (s *Service) InstanceIfExists(instanceID *string) (*v1alpha1.Instance, erro out, err := s.EC2.DescribeInstances(input) switch { - case IsNotFound(err): + case awserrors.IsNotFound(err): return nil, nil case err != nil: return nil, errors.Wrapf(err, "failed to describe instance: %q", *instanceID) } if len(out.Reservations) > 0 && len(out.Reservations[0].Instances) > 0 { - return fromSDKTypeToInstance(out.Reservations[0].Instances[0]), nil + return converters.SDKToInstance(out.Reservations[0].Instances[0]), nil } return nil, nil @@ -110,7 +113,7 @@ func (s *Service) CreateInstance(machine *clusterv1.Machine, config *v1alpha1.AW } else { sns := clusterStatus.Network.Subnets.FilterPrivate() if len(sns) == 0 { - return nil, NewFailedDependency( + return nil, awserrors.NewFailedDependency( errors.Errorf("failed to run machine %q, no subnets available", machine.Name), ) } @@ -121,7 +124,7 @@ func (s *Service) CreateInstance(machine *clusterv1.Machine, config *v1alpha1.AW if machine.ObjectMeta.Labels["set"] == "controlplane" { if clusterStatus.Network.SecurityGroups[v1alpha1.SecurityGroupControlPlane] == nil { - return nil, NewFailedDependency( + return nil, awserrors.NewFailedDependency( errors.New("failed to run controlplane, security group not available"), ) } @@ -224,7 +227,7 @@ func (s *Service) CreateOrGetMachine(machine *clusterv1.Machine, status *v1alpha klog.V(2).Infof("Looking up machine %q by id %q", machine.Name, *status.InstanceID) instance, err := s.InstanceIfExists(status.InstanceID) - if err != nil && !IsNotFound(err) { + if err != nil && !awserrors.IsNotFound(err) { return nil, errors.Wrapf(err, "failed to look up machine %q by id %q", machine.Name, *status.InstanceID) } else if err == nil && instance != nil { return instance, nil @@ -233,7 +236,7 @@ func (s *Service) CreateOrGetMachine(machine *clusterv1.Machine, status *v1alpha klog.V(2).Infof("Looking up machine %q by tags", machine.Name) instance, err := s.InstanceByTags(machine, cluster) - if err != nil && !IsNotFound(err) { + if err != nil && !awserrors.IsNotFound(err) { return nil, errors.Wrapf(err, "failed to query machine %q instance by tags", machine.Name) } else if err == nil && instance != nil { return instance, nil @@ -291,7 +294,7 @@ func (s *Service) runInstance(i *v1alpha1.Instance) (*v1alpha1.Instance, error) s.EC2.WaitUntilInstanceRunning(&ec2.DescribeInstancesInput{InstanceIds: []*string{out.Instances[0].InstanceId}}) - return fromSDKTypeToInstance(out.Instances[0]), nil + return converters.SDKToInstance(out.Instances[0]), nil } // UpdateInstanceSecurityGroups modifies the security groups of the given @@ -358,34 +361,3 @@ func (s *Service) UpdateResourceTags(resourceID *string, create map[string]strin return nil } - -// fromSDKTypeToInstance takes a ec2.Instance and returns our v1.alpha1.Instance -// type. EC2 types are wrapped or converted to our own types here. -func fromSDKTypeToInstance(v *ec2.Instance) *v1alpha1.Instance { - i := &v1alpha1.Instance{ - ID: aws.StringValue(v.InstanceId), - State: v1alpha1.InstanceState(*v.State.Name), - Type: aws.StringValue(v.InstanceType), - SubnetID: aws.StringValue(v.SubnetId), - ImageID: aws.StringValue(v.ImageId), - KeyName: v.KeyName, - PrivateIP: v.PrivateIpAddress, - PublicIP: v.PublicIpAddress, - ENASupport: v.EnaSupport, - EBSOptimized: v.EbsOptimized, - } - - for _, sg := range v.SecurityGroups { - i.SecurityGroupIDs = append(i.SecurityGroupIDs, *sg.GroupId) - } - - // TODO: Handle returned IAM instance profile, since we are currently - // using a string representing the name, but the InstanceProfile returned - // from the sdk only returns ARN and ID. - - if len(v.Tags) > 0 { - i.Tags = tagsToMap(v.Tags) - } - - return i -} diff --git a/pkg/cloud/aws/services/ec2/instances_test.go b/pkg/cloud/aws/services/ec2/instances_test.go index eb91b228b5..39090000fb 100644 --- a/pkg/cloud/aws/services/ec2/instances_test.go +++ b/pkg/cloud/aws/services/ec2/instances_test.go @@ -24,6 +24,7 @@ import ( clusterv1 "sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha1" "sigs.k8s.io/cluster-api-provider-aws/pkg/apis/awsprovider/v1alpha1" + "sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/aws/services/awserrors" ec2svc "sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/aws/services/ec2" "sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/aws/services/ec2/mock_ec2iface" ) @@ -52,7 +53,7 @@ func TestInstanceIfExists(t *testing.T) { }, }, })). - Return(nil, ec2svc.NewNotFound(errors.New("not found"))) + Return(nil, awserrors.NewNotFound(errors.New("not found"))) }, check: func(instance *v1alpha1.Instance, err error) { if err != nil { diff --git a/pkg/cloud/aws/services/ec2/securitygroups.go b/pkg/cloud/aws/services/ec2/securitygroups.go index 307d0f255f..6b4e9e96f6 100644 --- a/pkg/cloud/aws/services/ec2/securitygroups.go +++ b/pkg/cloud/aws/services/ec2/securitygroups.go @@ -21,6 +21,7 @@ import ( "github.com/pkg/errors" "k8s.io/klog" "sigs.k8s.io/cluster-api-provider-aws/pkg/apis/awsprovider/v1alpha1" + "sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/aws/services/awserrors" ) func (s *Service) reconcileSecurityGroups(clusterName string, network *v1alpha1.Network) error { @@ -98,7 +99,7 @@ func (s *Service) deleteSecurityGroups(clusterName string, network *v1alpha1.Net for _, sg := range network.SecurityGroups { current := sg.IngressRules - if err := s.revokeSecurityGroupIngressRules(sg.ID, current); isIgnorableSecurityGroupError(err) != nil { + if err := s.revokeSecurityGroupIngressRules(sg.ID, current); awserrors.IsIgnorableSecurityGroupError(err) != nil { return err } @@ -110,7 +111,7 @@ func (s *Service) deleteSecurityGroups(clusterName string, network *v1alpha1.Net GroupId: aws.String(sg.ID), } - if _, err := s.EC2.DeleteSecurityGroup(input); isIgnorableSecurityGroupError(err) != nil { + if _, err := s.EC2.DeleteSecurityGroup(input); awserrors.IsIgnorableSecurityGroupError(err) != nil { return errors.Wrapf(err, "failed to delete security group %q", sg.ID) } diff --git a/pkg/cloud/aws/services/ec2/vpc.go b/pkg/cloud/aws/services/ec2/vpc.go index 6eb445f550..d79c409670 100644 --- a/pkg/cloud/aws/services/ec2/vpc.go +++ b/pkg/cloud/aws/services/ec2/vpc.go @@ -32,7 +32,7 @@ func (s *Service) reconcileVPC(clusterName string, in *v1alpha1.VPC) error { klog.V(2).Infof("Reconciling VPC") vpc, err := s.describeVPC(clusterName, in.ID) - if IsNotFound(err) { + if awserrors.IsNotFound(err) { // Create a new vpc. vpc, err = s.createVPC(clusterName, in) if err != nil { @@ -115,7 +115,7 @@ func (s *Service) describeVPC(clusterName string, id string) (*v1alpha1.VPC, err out, err := s.EC2.DescribeVpcs(input) if err != nil { - if IsNotFound(err) { + if awserrors.IsNotFound(err) { return nil, err } @@ -123,15 +123,15 @@ func (s *Service) describeVPC(clusterName string, id string) (*v1alpha1.VPC, err } if len(out.Vpcs) == 0 { - return nil, NewNotFound(errors.Errorf("could not find vpc %q", id)) + return nil, awserrors.NewNotFound(errors.Errorf("could not find vpc %q", id)) } else if len(out.Vpcs) > 1 { - return nil, NewConflict(errors.Errorf("found more than one vpc with supplied filters. Please clean up extra VPCs: %s", out.GoString())) + return nil, awserrors.NewConflict(errors.Errorf("found more than one vpc with supplied filters. Please clean up extra VPCs: %s", out.GoString())) } switch *out.Vpcs[0].State { case ec2.VpcStateAvailable, ec2.VpcStatePending: default: - return nil, NewNotFound(errors.Errorf("could not find available or pending vpc")) + return nil, awserrors.NewNotFound(errors.Errorf("could not find available or pending vpc")) } return &v1alpha1.VPC{