From 0900c57510103492a0e600048f29a59eb4413649 Mon Sep 17 00:00:00 2001
From: mjsterckx <msterckx@amazon.com>
Date: Wed, 7 Sep 2022 22:36:19 +0000
Subject: [PATCH] ecs-resource-agent: added field for existing profile

Added field for existing IAM profile to the CRD and code to check
if the field contains a value: if so, retrieves the ARN of the
submitted profile instead of the default one.
---
 .../bin/ecs-resource-agent/ecs_provider.rs    | 27 ++++++++++++++-----
 bottlerocket/testsys/src/run_aws_ecs.rs       |  6 +++++
 bottlerocket/types/src/agent_config.rs        |  4 +++
 3 files changed, 31 insertions(+), 6 deletions(-)

diff --git a/bottlerocket/agents/src/bin/ecs-resource-agent/ecs_provider.rs b/bottlerocket/agents/src/bin/ecs-resource-agent/ecs_provider.rs
index 5d433244..21f1a8e8 100644
--- a/bottlerocket/agents/src/bin/ecs-resource-agent/ecs_provider.rs
+++ b/bottlerocket/agents/src/bin/ecs-resource-agent/ecs_provider.rs
@@ -110,8 +110,20 @@ impl Create for EcsCreator {
             .await
             .context(Resources::Clear, "The cluster could not be created.")?;
 
-        info!("Creating instance profile");
-        let iam_arn = create_iam_instance_profile(&iam_client).await?;
+        let iam_arn = match spec.configuration.iam_instance_profile_name {
+            Some(iam_instance_profile_name) => {
+                instance_profile_arn(&iam_client, &iam_instance_profile_name)
+                    .await
+                    .context(
+                        Resources::Clear,
+                        "The iam instance profile name was not found.",
+                    )?
+            }
+            None => {
+                info!("Creating instance profile");
+                create_iam_instance_profile(&iam_client).await?
+            }
+        };
 
         info!("Getting cluster information");
         let created_cluster = created_cluster(
@@ -142,7 +154,7 @@ async fn create_iam_instance_profile(iam_client: &aws_sdk_iam::Client) -> Provid
         .send()
         .await;
     if exists(get_instance_profile_result) {
-        instance_profile_arn(iam_client).await
+        instance_profile_arn(iam_client, IAM_INSTANCE_PROFILE_NAME).await
     } else {
         iam_client
             .create_role()
@@ -184,7 +196,7 @@ async fn create_iam_instance_profile(iam_client: &aws_sdk_iam::Client) -> Provid
                 Resources::Remaining,
                 "Unable to add role to instance profile",
             )?;
-        instance_profile_arn(iam_client).await
+        instance_profile_arn(iam_client, IAM_INSTANCE_PROFILE_NAME).await
     }
 }
 
@@ -200,10 +212,13 @@ fn exists(result: Result<GetInstanceProfileOutput, SdkError<GetInstanceProfileEr
     true
 }
 
-async fn instance_profile_arn(iam_client: &aws_sdk_iam::Client) -> ProviderResult<String> {
+async fn instance_profile_arn(
+    iam_client: &aws_sdk_iam::Client,
+    iam_instance_profile_name: &str,
+) -> ProviderResult<String> {
     iam_client
         .get_instance_profile()
-        .instance_profile_name(IAM_INSTANCE_PROFILE_NAME)
+        .instance_profile_name(iam_instance_profile_name)
         .send()
         .await
         .context(Resources::Remaining, "Unable to get instance profile.")?
diff --git a/bottlerocket/testsys/src/run_aws_ecs.rs b/bottlerocket/testsys/src/run_aws_ecs.rs
index c1c324ab..7e2da17d 100644
--- a/bottlerocket/testsys/src/run_aws_ecs.rs
+++ b/bottlerocket/testsys/src/run_aws_ecs.rs
@@ -146,6 +146,11 @@ pub(crate) struct RunAwsEcs {
     /// The arn for the role that should be assumed by the agents.
     #[structopt(long)]
     assume_role: Option<String>,
+
+    /// The IAM instance profile name for the EC2 instances in the ECS cluster. If no value is
+    /// provided, then the ECS test agent will attempt to create an IAM instance profile.
+    #[structopt(long)]
+    iam_instance_profile_name: Option<String>,
 }
 
 impl RunAwsEcs {
@@ -326,6 +331,7 @@ impl RunAwsEcs {
                             region: Some(self.region.clone()),
                             vpc: self.vpc.clone(),
                             assume_role: self.assume_role.clone(),
+                            iam_instance_profile_name: self.iam_instance_profile_name.clone(),
                         }
                         .into_map()
                         .context(error::ConfigMapSnafu)?,
diff --git a/bottlerocket/types/src/agent_config.rs b/bottlerocket/types/src/agent_config.rs
index c75dcd02..b6fb1cf8 100644
--- a/bottlerocket/types/src/agent_config.rs
+++ b/bottlerocket/types/src/agent_config.rs
@@ -212,6 +212,10 @@ pub struct EcsClusterConfig {
 
     /// The role that should be assumed when creating the ecs cluster.
     pub assume_role: Option<String>,
+
+    /// The IAM instance profile name for the EC2 instances in the ECS cluster. If no value is
+    /// provided, then the ECS test agent will attempt to create an IAM instance profile.
+    pub iam_instance_profile_name: Option<String>,
 }
 
 impl Configuration for EcsClusterConfig {}