Skip to content

Commit

Permalink
Adds simple Exists implementation to machine actuator (openshift#67)
Browse files Browse the repository at this point in the history
* Adds simple Exists implementation to machine actuator

Remove the machine actuator test for now.

Trying to test it will be possible, but it will be a *ton* of work and
right now it's not worth the effort.

Exports the ec2 service's EC2 field.

Signed-off-by: Chuck Ha <chuck@heptio.com>

* Update deps

Signed-off-by: Chuck Ha <chuck@heptio.com>
  • Loading branch information
chuckha authored and k8s-ci-robot committed Sep 20, 2018
1 parent 8c827ef commit d3df0ea
Show file tree
Hide file tree
Showing 10 changed files with 138 additions and 137 deletions.
25 changes: 22 additions & 3 deletions cloud/aws/actuators/machine/actuator.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

package machine

// should not need to import the ec2 sdk here
import (
"fmt"

Expand Down Expand Up @@ -145,10 +146,28 @@ func (a *Actuator) Update(cluster *clusterv1.Cluster, machine *clusterv1.Machine
return fmt.Errorf("TODO: Not yet implemented")
}

// Exists test for the existance of a machine and is invoked by the Machine Controller
// Exists test for the existence of a machine and is invoked by the Machine Controller
func (a *Actuator) Exists(cluster *clusterv1.Cluster, machine *clusterv1.Machine) (bool, error) {
glog.Infof("Checking if machine %v for cluster %v exists.", machine.Name, cluster.Name)
return false, fmt.Errorf("TODO: Not yet implemented")
glog.Info("Checking if machine %v for cluster %v exists.", machine.Name, cluster.Name)
status, err := a.machineProviderStatus(machine)
if err != nil {
return false, err
}

instance, err := a.ec2.InstanceIfExists(status.InstanceID)
if err != nil {
return false, err
}
if instance == nil {
return false, nil
}
// TODO update status here
switch instance.State {
case ec2svc.InstanceStateRunning, ec2svc.InstanceStatePending:
return true, nil
default:
return false, nil
}
}

func (a *Actuator) machineProviderConfig(providerConfig clusterv1.ProviderConfig) (*v1alpha1.AWSMachineProviderConfig, error) {
Expand Down
109 changes: 0 additions & 109 deletions cloud/aws/actuators/machine/actuator_test.go

This file was deleted.

6 changes: 3 additions & 3 deletions cloud/aws/services/ec2/gateways.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,12 @@ func (s *Service) reconcileInternetGateways(in *v1alpha1.Network) error {
}

func (s *Service) createInternetGateway(vpc *v1alpha1.VPC) (*ec2.InternetGateway, error) {
ig, err := s.ec2.CreateInternetGateway(&ec2.CreateInternetGatewayInput{})
ig, err := s.EC2.CreateInternetGateway(&ec2.CreateInternetGatewayInput{})
if err != nil {
return nil, errors.Wrap(err, "failed to create internet gateway")
}

_, err = s.ec2.AttachInternetGateway(&ec2.AttachInternetGatewayInput{
_, err = s.EC2.AttachInternetGateway(&ec2.AttachInternetGatewayInput{
InternetGatewayId: ig.InternetGateway.InternetGatewayId,
VpcId: aws.String(vpc.ID),
})
Expand All @@ -55,7 +55,7 @@ func (s *Service) createInternetGateway(vpc *v1alpha1.VPC) (*ec2.InternetGateway
}

func (s *Service) describeVpcInternetGateways(vpc *v1alpha1.VPC) ([]*ec2.InternetGateway, error) {
out, err := s.ec2.DescribeInternetGateways(&ec2.DescribeInternetGatewaysInput{
out, err := s.EC2.DescribeInternetGateways(&ec2.DescribeInternetGatewaysInput{
Filters: []*ec2.Filter{
{
Name: aws.String("attachment.vpc-id"),
Expand Down
21 changes: 16 additions & 5 deletions cloud/aws/services/ec2/instances.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
package ec2

import (
"fmt"

"github.com/aws/aws-sdk-go/service/ec2"
"github.com/pkg/errors"
clusterv1 "sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha1"
Expand All @@ -25,6 +27,12 @@ const (

// InstanceStateTerminated indicates the instance has been terminated
InstanceStateTerminated = ec2.InstanceStateNameTerminated

// InstanceStateRunning indicates the instance is running
InstanceStateRunning = ec2.InstanceStateNameRunning

// InstanceStatePending indicates the instance is pending
InstanceStatePending = ec2.InstanceStateNamePending
)

// Instance is an internal representation of an AWS instance.
Expand All @@ -41,10 +49,13 @@ func (s *Service) InstanceIfExists(instanceID *string) (*Instance, error) {
input := &ec2.DescribeInstancesInput{
InstanceIds: []*string{instanceID},
}
out, err := s.EC2.DescribeInstances(input)

out, err := s.ec2.DescribeInstances(input)
if err != nil {
return nil, errors.Wrapf(err, "failed to describe instances")
switch {
case IsNotFound(err):
return nil, nil
case err != nil:
return nil, fmt.Errorf("failed to describe instances: %v", err)
}

if len(out.Reservations) > 0 && len(out.Reservations[0].Instances) > 0 {
Expand All @@ -61,7 +72,7 @@ func (s *Service) InstanceIfExists(instanceID *string) (*Instance, error) {
func (s *Service) CreateInstance(machine *clusterv1.Machine) (*Instance, error) {
input := &ec2.RunInstancesInput{}

reservation, err := s.ec2.RunInstances(input)
reservation, err := s.EC2.RunInstances(input)
if err != nil {
return nil, errors.Wrapf(err, "failed to run instances")
}
Expand All @@ -85,7 +96,7 @@ func (s *Service) TerminateInstance(instanceID *string) error {
},
}

_, err := s.ec2.TerminateInstances(input)
_, err := s.EC2.TerminateInstances(input)
if err != nil {
return err
}
Expand Down
82 changes: 81 additions & 1 deletion cloud/aws/services/ec2/instances_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,11 @@ import (
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/golang/mock/gomock"
"github.com/pkg/errors"
"k8s.io/apimachinery/pkg/runtime"

ec2svc "sigs.k8s.io/cluster-api-provider-aws/cloud/aws/services/ec2"
"sigs.k8s.io/cluster-api-provider-aws/cloud/aws/services/ec2/mock_ec2iface"
clusterv1 "sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha1"
)

func TestInstanceIfExists(t *testing.T) {
Expand All @@ -42,7 +45,7 @@ func TestInstanceIfExists(t *testing.T) {
DescribeInstances(gomock.Eq(&ec2.DescribeInstancesInput{
InstanceIds: []*string{aws.String("hello")},
})).
Return(&ec2.DescribeInstancesOutput{}, nil)
Return(nil, ec2svc.NewNotFound(errors.New("not found")))
},
check: func(instance *ec2svc.Instance, err error) {
if err != nil {
Expand Down Expand Up @@ -92,6 +95,20 @@ func TestInstanceIfExists(t *testing.T) {
}
},
},
{
name: "error describing instances",
instanceID: "one",
expect: func(m *mock_ec2iface.MockEC2API) {
m.EXPECT().
DescribeInstances(&ec2.DescribeInstancesInput{InstanceIds: []*string{aws.String("one")}}).
Return(nil, errors.New("some unknown error"))
},
check: func(i *ec2svc.Instance, err error) {
if err == nil {
t.Fatalf("expected an error but got none.")
}
},
},
}

for _, tc := range testCases {
Expand Down Expand Up @@ -161,3 +178,66 @@ func TestTerminateInstance(t *testing.T) {
})
}
}

func TestCreateInstance(t *testing.T) {
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()

testcases := []struct {
name string
machine clusterv1.Machine
expect func(m *mock_ec2iface.MockEC2API)
check func(instance *ec2svc.Instance, err error)
}{
{
name: "simple",
machine: clusterv1.Machine{
Spec: clusterv1.MachineSpec{
ProviderConfig: clusterv1.ProviderConfig{
Value: &runtime.RawExtension{
Raw: []byte(`apiVersion: "cluster.k8s.io/v1alpha1"
kind: Machine
metadata:
generateName: aws-controlplane-
labels:
set: controlplane
spec:
versions:
kubelet: v1.11.2
controlPlane: v1.11.2`),
},
},
},
},
expect: func(m *mock_ec2iface.MockEC2API) {
m.EXPECT().
RunInstances(&ec2.RunInstancesInput{}).
Return(&ec2.Reservation{
Instances: []*ec2.Instance{
&ec2.Instance{
State: &ec2.InstanceState{
Name: aws.String(ec2.InstanceStateNamePending),
},
InstanceId: aws.String("two"),
},
},
}, nil)
},
check: func(instance *ec2svc.Instance, err error) {
if err != nil {
t.Fatalf("did not expect error: %v", err)
}
},
},
}

for _, tc := range testcases {
t.Run(tc.name, func(t *testing.T) {
ec2Mock := mock_ec2iface.NewMockEC2API(mockCtrl)
tc.expect(ec2Mock)
s := ec2svc.NewService(ec2Mock)
instance, err := s.CreateInstance(&tc.machine)
tc.check(instance, err)
})
}
}
6 changes: 3 additions & 3 deletions cloud/aws/services/ec2/routetables.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ func (s *Service) reconcileRouteTables(in *v1alpha1.Network) error {
}

func (s *Service) describeVpcRouteTables(vpcID string) ([]*ec2.RouteTable, error) {
out, err := s.ec2.DescribeRouteTables(&ec2.DescribeRouteTablesInput{
out, err := s.EC2.DescribeRouteTables(&ec2.DescribeRouteTablesInput{
Filters: []*ec2.Filter{
{
Name: aws.String("vpc-id"),
Expand All @@ -43,7 +43,7 @@ func (s *Service) describeVpcRouteTables(vpcID string) ([]*ec2.RouteTable, error
}

func (s *Service) createRouteTable(rt *v1alpha1.RouteTable, vpc *v1alpha1.VPC) (*v1alpha1.RouteTable, error) {
out, err := s.ec2.CreateRouteTable(&ec2.CreateRouteTableInput{
out, err := s.EC2.CreateRouteTable(&ec2.CreateRouteTableInput{
VpcId: aws.String(vpc.ID),
})

Expand All @@ -57,7 +57,7 @@ func (s *Service) createRouteTable(rt *v1alpha1.RouteTable, vpc *v1alpha1.VPC) (
}

func (s *Service) associateRouteTable(rt *v1alpha1.RouteTable, subnetID string) error {
_, err := s.ec2.AssociateRouteTable(&ec2.AssociateRouteTableInput{
_, err := s.EC2.AssociateRouteTable(&ec2.AssociateRouteTableInput{
RouteTableId: aws.String(rt.ID),
SubnetId: aws.String(subnetID),
})
Expand Down
4 changes: 2 additions & 2 deletions cloud/aws/services/ec2/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,12 @@ import (
// The interfaces are broken down like this to group functions together.
// One alternative is to have a large list of functions from the ec2 client.
type Service struct {
ec2 ec2iface.EC2API
EC2 ec2iface.EC2API
}

// NewService returns a new service given the ec2 api client.
func NewService(i ec2iface.EC2API) *Service {
return &Service{
ec2: i,
EC2: i,
}
}
Loading

0 comments on commit d3df0ea

Please sign in to comment.