From 44de676b2195f282fab288498f1a4a2e56a18922 Mon Sep 17 00:00:00 2001
From: AkiraFukushima
Date: Thu, 11 Feb 2021 14:28:49 +0900
Subject: [PATCH] Fill Role names in kops-controller-config instead of instance
profile names when it is specified
The role names are checked in node bootstrap.
If profile names are provided, bootstrap will fail.
Because profile name and role name do not always mactch in AWS IAM
---
pkg/testutils/BUILD.bazel | 1 +
pkg/testutils/integrationtestharness.go | 12 +++++++++++
upup/pkg/fi/cloudup/apply_cluster.go | 1 +
upup/pkg/fi/cloudup/awsup/aws_cloud.go | 15 +++++++++++++
.../cloudup/bootstrapchannelbuilder_test.go | 1 +
upup/pkg/fi/cloudup/template_functions.go | 21 +++++++++++++++++--
6 files changed, 49 insertions(+), 2 deletions(-)
diff --git a/pkg/testutils/BUILD.bazel b/pkg/testutils/BUILD.bazel
index c639e91e1c70b..71ae0307ca37c 100644
--- a/pkg/testutils/BUILD.bazel
+++ b/pkg/testutils/BUILD.bazel
@@ -37,6 +37,7 @@ go_library(
"//vendor/github.com/aws/aws-sdk-go/aws:go_default_library",
"//vendor/github.com/aws/aws-sdk-go/service/ec2:go_default_library",
"//vendor/github.com/aws/aws-sdk-go/service/elbv2:go_default_library",
+ "//vendor/github.com/aws/aws-sdk-go/service/iam:go_default_library",
"//vendor/github.com/aws/aws-sdk-go/service/route53:go_default_library",
"//vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/flavors:go_default_library",
"//vendor/github.com/gophercloud/gophercloud/openstack/dns/v2/zones:go_default_library",
diff --git a/pkg/testutils/integrationtestharness.go b/pkg/testutils/integrationtestharness.go
index 07825d67b99a4..9362bb260a941 100644
--- a/pkg/testutils/integrationtestharness.go
+++ b/pkg/testutils/integrationtestharness.go
@@ -26,6 +26,7 @@ import (
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/aws/aws-sdk-go/service/elbv2"
+ "github.com/aws/aws-sdk-go/service/iam"
"github.com/aws/aws-sdk-go/service/route53"
"github.com/gophercloud/gophercloud/openstack/compute/v2/flavors"
"github.com/gophercloud/gophercloud/openstack/dns/v2/zones"
@@ -256,6 +257,17 @@ func (h *IntegrationTestHarness) SetupMockAWS() *awsup.MockAWSCloud {
Name: aws.String("my-external-tg-3"),
})
+ mockIAM.CreateRole(&iam.CreateRoleInput{
+ RoleName: aws.String("kops-custom-node-role"),
+ })
+ mockIAM.CreateInstanceProfile(&iam.CreateInstanceProfileInput{
+ InstanceProfileName: aws.String("kops-custom-node-role"),
+ })
+ mockIAM.AddRoleToInstanceProfile(&iam.AddRoleToInstanceProfileInput{
+ InstanceProfileName: aws.String("kops-custom-node-role"),
+ RoleName: aws.String("kops-custom-node-role"),
+ })
+
return cloud
}
diff --git a/upup/pkg/fi/cloudup/apply_cluster.go b/upup/pkg/fi/cloudup/apply_cluster.go
index 373647801b8db..b40452edbd879 100644
--- a/upup/pkg/fi/cloudup/apply_cluster.go
+++ b/upup/pkg/fi/cloudup/apply_cluster.go
@@ -496,6 +496,7 @@ func (c *ApplyClusterCmd) Run(ctx context.Context) error {
tf := &TemplateFunctions{
KopsModelContext: *modelContext,
+ cloud: cloud,
}
{
diff --git a/upup/pkg/fi/cloudup/awsup/aws_cloud.go b/upup/pkg/fi/cloudup/awsup/aws_cloud.go
index 4294f3d1fc7c1..a39d2e5eb1d97 100644
--- a/upup/pkg/fi/cloudup/awsup/aws_cloud.go
+++ b/upup/pkg/fi/cloudup/awsup/aws_cloud.go
@@ -1751,3 +1751,18 @@ func (c *awsCloudImplementation) AccountInfo() (string, string, error) {
}
return arn.AccountID, arn.Partition, nil
}
+
+// GetRolesInInstanceProfile return role names which are associated with the instance profile specified by profileName.
+func GetRolesInInstanceProfile(c AWSCloud, profileName string) ([]string, error) {
+ output, err := c.IAM().GetInstanceProfile(&iam.GetInstanceProfileInput{
+ InstanceProfileName: aws.String(profileName),
+ })
+ if err != nil {
+ return nil, err
+ }
+ var roleNames []string
+ for _, role := range output.InstanceProfile.Roles {
+ roleNames = append(roleNames, *role.RoleName)
+ }
+ return roleNames, nil
+}
diff --git a/upup/pkg/fi/cloudup/bootstrapchannelbuilder_test.go b/upup/pkg/fi/cloudup/bootstrapchannelbuilder_test.go
index 406df0bbe0991..26111fc1a776c 100644
--- a/upup/pkg/fi/cloudup/bootstrapchannelbuilder_test.go
+++ b/upup/pkg/fi/cloudup/bootstrapchannelbuilder_test.go
@@ -154,6 +154,7 @@ func runChannelBuilderTest(t *testing.T, key string, addonManifests []string) {
tf := &TemplateFunctions{
KopsModelContext: kopsModel,
+ cloud: cloud,
}
tf.AddTo(templates.TemplateFunctions, secretStore)
diff --git a/upup/pkg/fi/cloudup/template_functions.go b/upup/pkg/fi/cloudup/template_functions.go
index c4affd4d9d487..9cd460c7225ee 100644
--- a/upup/pkg/fi/cloudup/template_functions.go
+++ b/upup/pkg/fi/cloudup/template_functions.go
@@ -59,6 +59,8 @@ import (
// TemplateFunctions provides a collection of methods used throughout the templates
type TemplateFunctions struct {
model.KopsModelContext
+
+ cloud fi.Cloud
}
// AddTo defines the available functions we can use in our YAML models.
@@ -445,9 +447,24 @@ func (tf *TemplateFunctions) KopsControllerConfig() (string, error) {
if ig.Spec.Role == kops.InstanceGroupRoleNode {
profile, err := tf.LinkToIAMInstanceProfile(ig)
if err != nil {
- return "", fmt.Errorf("getting role for ig %s: %v", ig.Name, err)
+ return "", fmt.Errorf("getting profile for ig %s: %v", ig.Name, err)
+ }
+ // The IAM Instance Profile has not been created at this point if it is not specified.
+ // Because the IAM Instance Profile and the IAM Role are created in IAMModelBuilder tasks.
+ // Therefore, the IAM Role associated with IAM Instance Profile is acquired only when it is not specified.
+ if ig.Spec.IAM != nil && ig.Spec.IAM.Profile != nil {
+ c := tf.cloud.(awsup.AWSCloud)
+ roles, err := awsup.GetRolesInInstanceProfile(c, *profile.Name)
+ if err != nil {
+ return "", fmt.Errorf("getting role from profile %s: %v", *profile.Name, err)
+ }
+ nodesRoles.Insert(roles...)
+ } else {
+ // When the IAM Instance Profile is not specified, IAM Instance Profile is created by kOps.
+ // In this case, the IAM Instance Profile name and IAM Role name are same.
+ // So there is no problem even if IAM Instance Profile name is inserted as role name in nodesRoles.
+ nodesRoles.Insert(*profile.Name)
}
- nodesRoles.Insert(*profile.Name)
}
}
config.Server.Provider.AWS = &awsup.AWSVerifierOptions{