Skip to content

Commit edea2ad

Browse files
vinceprik8s-ci-robot
authored andcommitted
Add bastion host (openshift#155)
Signed-off-by: Vince Prignano <[email protected]>
1 parent 70a1098 commit edea2ad

File tree

10 files changed

+377
-67
lines changed

10 files changed

+377
-67
lines changed

cloud/aws/actuators/cluster/actuator.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,10 @@ func (a *Actuator) Reconcile(cluster *clusterv1.Cluster) (reterr error) {
9696
return errors.Errorf("unable to reconcile network: %v", err)
9797
}
9898

99+
if err := svc.ReconcileBastion(cluster.Name, status); err != nil {
100+
return errors.Errorf("unable to reconcile network: %v", err)
101+
}
102+
99103
return nil
100104
}
101105

cloud/aws/actuators/cluster/actuator_test.go

Lines changed: 72 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"github.com/aws/aws-sdk-go/service/ec2/ec2iface"
2222
"github.com/golang/mock/gomock"
2323
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
24+
"k8s.io/apimachinery/pkg/runtime"
2425
providerconfig "sigs.k8s.io/cluster-api-provider-aws/cloud/aws/providerconfig/v1alpha1"
2526
clusterv1 "sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha1"
2627
clientv1 "sigs.k8s.io/cluster-api/pkg/client/clientset_generated/clientset/typed/cluster/v1alpha1"
@@ -251,7 +252,7 @@ func TestReconcile(t *testing.T) {
251252
Return(&ec2.DescribeSecurityGroupsOutput{
252253
SecurityGroups: []*ec2.SecurityGroup{
253254
&ec2.SecurityGroup{
254-
GroupId: aws.String("sg-cp1"),
255+
GroupId: aws.String("sg-bastion1"),
255256
GroupName: aws.String("test-bastion"),
256257
IpPermissions: []*ec2.IpPermission{
257258
&ec2.IpPermission{
@@ -275,9 +276,9 @@ func TestReconcile(t *testing.T) {
275276
FromPort: aws.Int64(22),
276277
ToPort: aws.Int64(22),
277278
IpProtocol: aws.String("tcp"),
278-
IpRanges: []*ec2.IpRange{
279-
&ec2.IpRange{
280-
CidrIp: aws.String("0.0.0.0/0"),
279+
UserIdGroupPairs: []*ec2.UserIdGroupPair{
280+
&ec2.UserIdGroupPair{
281+
GroupId: aws.String("sg-bastion1"),
281282
Description: aws.String("SSH"),
282283
},
283284
},
@@ -325,9 +326,9 @@ func TestReconcile(t *testing.T) {
325326
FromPort: aws.Int64(22),
326327
ToPort: aws.Int64(22),
327328
IpProtocol: aws.String("tcp"),
328-
IpRanges: []*ec2.IpRange{
329-
&ec2.IpRange{
330-
CidrIp: aws.String("0.0.0.0/0"),
329+
UserIdGroupPairs: []*ec2.UserIdGroupPair{
330+
&ec2.UserIdGroupPair{
331+
GroupId: aws.String("sg-bastion1"),
331332
Description: aws.String("SSH"),
332333
},
333334
},
@@ -358,6 +359,63 @@ func TestReconcile(t *testing.T) {
358359
},
359360
},
360361
}, nil),
362+
363+
// Reconcile bastion.
364+
me.EXPECT().
365+
DescribeInstances(gomock.Eq(&ec2.DescribeInstancesInput{
366+
Filters: []*ec2.Filter{
367+
&ec2.Filter{
368+
Name: aws.String("tag:sigs.k8s.io/cluster-api-provider-aws/role"),
369+
Values: []*string{aws.String("bastion")},
370+
},
371+
&ec2.Filter{
372+
Name: aws.String("tag-key"),
373+
Values: []*string{aws.String("kubernetes.io/cluster/test")},
374+
},
375+
},
376+
})).
377+
Return(&ec2.DescribeInstancesOutput{}, nil),
378+
me.EXPECT().
379+
RunInstances(gomock.AssignableToTypeOf(&ec2.RunInstancesInput{})).
380+
DoAndReturn(func(input *ec2.RunInstancesInput) (*ec2.Reservation, error) {
381+
if len(input.TagSpecifications) == 0 {
382+
t.Fatalf("expected tags to be applied on bootstrap, got none")
383+
}
384+
385+
if input.TagSpecifications[0].ResourceType == nil || *input.TagSpecifications[0].ResourceType != ec2.ResourceTypeInstance {
386+
t.Fatalf("expected tag specification to be instance, got %v", input.TagSpecifications[0].ResourceType)
387+
}
388+
389+
if len(input.TagSpecifications[0].Tags) < 2 {
390+
t.Fatalf("was expecting at least 2 tags for bastion host got: %v", input.TagSpecifications[0].Tags)
391+
}
392+
393+
for _, key := range []string{"sigs.k8s.io/cluster-api-provider-aws/role", "kubernetes.io/cluster/test"} {
394+
found := false
395+
for _, x := range input.TagSpecifications[0].Tags {
396+
if *x.Key == key {
397+
found = true
398+
break
399+
}
400+
}
401+
402+
if !found {
403+
t.Fatalf("couldn't find tag for bastion host: %s", key)
404+
}
405+
}
406+
407+
return &ec2.Reservation{
408+
Instances: []*ec2.Instance{
409+
&ec2.Instance{
410+
State: &ec2.InstanceState{Code: aws.Int64(0), Name: aws.String("pending")},
411+
InstanceId: aws.String("bastion-1"),
412+
InstanceType: input.InstanceType,
413+
ImageId: input.ImageId,
414+
SubnetId: input.SubnetId,
415+
},
416+
},
417+
}, nil
418+
}),
361419
)
362420

363421
c, err := providerconfig.NewCodec()
@@ -377,6 +435,13 @@ func TestReconcile(t *testing.T) {
377435

378436
cluster := &clusterv1.Cluster{
379437
ObjectMeta: metav1.ObjectMeta{Name: "test", ClusterName: "test"},
438+
Spec: clusterv1.ClusterSpec{
439+
ProviderConfig: clusterv1.ProviderConfig{
440+
Value: &runtime.RawExtension{
441+
Raw: []byte(`{"kind":"AWSClusterProviderConfig","apiVersion":"awsproviderconfig/v1alpha1","region":"us-east-1"}`),
442+
},
443+
},
444+
},
380445
}
381446

382447
if err := a.Reconcile(cluster); err != nil {

cloud/aws/actuators/cluster/interfaces.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ type EC2Getter interface {
2727

2828
type ec2SvcIface interface {
2929
ReconcileNetwork(string, *providerconfigv1.Network) error
30+
ReconcileBastion(string, *providerconfigv1.AWSClusterProviderStatus) error
3031
}
3132

3233
type codec interface {

cloud/aws/providerconfig/v1alpha1/types.go

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -161,8 +161,9 @@ type AWSMachineProviderCondition struct {
161161
type AWSClusterProviderStatus struct {
162162
metav1.TypeMeta `json:",inline"`
163163

164-
Region string `json:"region"`
165-
Network Network `json:"network"`
164+
Region string `json:"region"`
165+
Network Network `json:"network"`
166+
Bastion Instance `json:"bastion"`
166167
}
167168

168169
// Network encapsulates AWS networking resources.
@@ -341,6 +342,13 @@ type Instance struct {
341342
// The name of the SSH key pair.
342343
KeyName *string `json:"keyName"`
343344

345+
// SecurityGroupIDs are one or more security group IDs this instance belongs to.
346+
SecurityGroupIDs []string `json:"securityGroupIds"`
347+
348+
// UserData is the raw data script passed to the instance which is run upon bootstrap.
349+
// This field must not be base64 encoded and should only be used when running a new instance.
350+
UserData *string `json:"userData"`
351+
344352
// The ARN of the IAM instance profile associated with the instance, if applicable.
345353
IAMProfile *AWSResourceReference `json:"iamProfile"`
346354

@@ -356,9 +364,6 @@ type Instance struct {
356364
// Indicates whether the instance is optimized for Amazon EBS I/O.
357365
EBSOptimized *bool `json:"ebsOptimized"`
358366

359-
// UserData defines the Base64-encoded user data to make available to the instance.
360-
UserData *string
361-
362-
// SecurityGroupIDs are one or more security group IDs this instance belongs to.
363-
SecurityGroupIDs []*string
367+
// The tags associated with the instance.
368+
Tags map[string]string `json:"tag"`
364369
}

cloud/aws/providerconfig/v1alpha1/zz_generated.deepcopy.go

Lines changed: 47 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cloud/aws/services/ec2/ami.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,3 +54,40 @@ func (s *Service) defaultAMILookup(region string) string {
5454
return "unknown region"
5555
}
5656
}
57+
58+
func (s *Service) defaultBastionAMILookup(region string) string {
59+
switch region {
60+
case "ap-northeast-1":
61+
return "ami-d39a02b5"
62+
case "ap-northeast-2":
63+
return "ami-67973709"
64+
case "ap-south-1":
65+
return "ami-5d055232"
66+
case "ap-southeast-1":
67+
return "ami-325d2e4e"
68+
case "ap-southeast-2":
69+
return "ami-37df2255"
70+
case "ca-central-1":
71+
return "ami-f0870294"
72+
case "eu-central-1":
73+
return "ami-af79ebc0"
74+
case "eu-west-1":
75+
return "ami-4d46d534"
76+
case "eu-west-2":
77+
return "ami-d7aab2b3"
78+
case "eu-west-3":
79+
return "ami-5e0eb923"
80+
case "sa-east-1":
81+
return "ami-1157157d"
82+
case "us-east-1":
83+
return "ami-41e0b93b"
84+
case "us-east-2":
85+
return "ami-2581aa40"
86+
case "us-west-1":
87+
return "ami-79aeae19"
88+
case "us-west-2":
89+
return "ami-1ee65166"
90+
default:
91+
return "unknown region"
92+
}
93+
}

0 commit comments

Comments
 (0)