Repository: PrefectHQ/prefect

Issue:
Users of ECR and the Fargate Agent unable to use AWS Docker auth
## Description

Continuing to work on the branch @joshmeek did in https://github.com/PrefectHQ/prefect/pull/2877 (same diagnostics as https://github.com/PrefectHQ/prefect/issues/2875), I came across an invalidation error for not providing Fargate Agent with a `repositoryCredentials` (with a `credentialsParameter`).

```
Missing required parameter in containerDefinitions[0].repositoryCredentials: "credentialsParameter" 
```


## Expected Behavior

Despite [what the boto3 docs say](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/ecs.html#ECS.Client.register_task_definition), I believe this shouldn't be a required field to run. One can see it's not required in [the main API](https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_ContainerDefinition.html) (also [here](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ecs-taskdefinition-containerdefinitions.html#cfn-ecs-taskdefinition-containerdefinition-repositorycredentials)).

Because users of ECR should not use credentials like these, auth is handled automatically as long as the task execution role is allowed to use the ECR repo. Amazon covers this in a warning here: https://docs.aws.amazon.com/AmazonECS/latest/developerguide/private-auth.html (`If your task definition references an image stored in Amazon ECR, this topic does not apply`). The auth I mention is covered [here](https://docs.aws.amazon.com/AmazonECR/latest/userguide/ECR_on_ECS.html).

I tested just altering your `fargate/agent.py` to remove all settings of `repositoryCredentials`, dropping the below lines:

* https://github.com/PrefectHQ/prefect/blob/master/src/prefect/agent/fargate/agent.py#L343
* https://github.com/PrefectHQ/prefect/blob/master/src/prefect/agent/fargate/agent.py#L642-L644

And the error went away, proceeding to do the boto call [without errors].



Discussion:
Thanks for the bug report @n-batalha I'll update the container defs to fix this behavior!

Resolving patch:
diff --git a/src/prefect/agent/fargate/agent.py b/src/prefect/agent/fargate/agent.py
--- a/src/prefect/agent/fargate/agent.py
+++ b/src/prefect/agent/fargate/agent.py
@@ -610,9 +610,6 @@ def _create_task_definition(
                         "value": "prefect.engine.cloud.CloudTaskRunner",
                     },
                 ],
-                "secrets": [],
-                "mountPoints": [],
-                "logConfiguration": {},
                 "essential": True,
             }
         ]
@@ -641,18 +638,26 @@ def _create_task_definition(
         container_definitions[0]["environment"].extend(  # type: ignore
             container_definitions_environment
         )
-        container_definitions[0]["secrets"] = container_definitions_kwargs.get(
-            "secrets", []
-        )
-        container_definitions[0]["mountPoints"] = container_definitions_kwargs.get(
-            "mountPoints", []
-        )
-        container_definitions[0]["logConfiguration"] = container_definitions_kwargs.get(
-            "logConfiguration", {}
-        )
-        container_definitions[0][
-            "repositoryCredentials"
-        ] = container_definitions_kwargs.get("repositoryCredentials", {})
+
+        # Set container definition values if provided
+        if container_definitions_kwargs.get("secrets"):
+            container_definitions[0]["secrets"] = container_definitions_kwargs.get(
+                "secrets", []
+            )
+
+        if container_definitions_kwargs.get("mountPoints"):
+            container_definitions[0]["mountPoints"] = container_definitions_kwargs.get(
+                "mountPoints", []
+            )
+        if container_definitions_kwargs.get("logConfiguration"):
+            container_definitions[0][
+                "logConfiguration"
+            ] = container_definitions_kwargs.get("logConfiguration", {})
+
+        if container_definitions_kwargs.get("repositoryCredentials"):
+            container_definitions[0][
+                "repositoryCredentials"
+            ] = container_definitions_kwargs.get("repositoryCredentials", {})
 
         # Register task definition
         self.logger.debug(
@@ -739,9 +744,6 @@ def validate_configuration(self) -> None:
                 "image": "busybox",
                 "command": ["/bin/sh", "-c", "echo 'I am alive!'"],
                 "environment": [],
-                "secrets": [],
-                "mountPoints": [],
-                "logConfiguration": {},
                 "essential": True,
             }
         ]
@@ -757,15 +759,27 @@ def validate_configuration(self) -> None:
         container_definitions[0]["environment"].extend(  # type: ignore
             container_definitions_environment
         )
-        container_definitions[0]["secrets"] = flow_container_definitions_kwargs.get(
-            "secrets", []
-        )
-        container_definitions[0]["mountPoints"] = flow_container_definitions_kwargs.get(
-            "mountPoints", []
-        )
-        container_definitions[0][
-            "logConfiguration"
-        ] = flow_container_definitions_kwargs.get("logConfiguration", {})
+
+        # Assign user-provided container definition options
+        if flow_container_definitions_kwargs.get("secrets"):
+            container_definitions[0]["secrets"] = flow_container_definitions_kwargs.get(
+                "secrets", []
+            )
+
+        if flow_container_definitions_kwargs.get("mountPoints"):
+            container_definitions[0][
+                "mountPoints"
+            ] = flow_container_definitions_kwargs.get("mountPoints", [])
+
+        if flow_container_definitions_kwargs.get("logConfiguration"):
+            container_definitions[0][
+                "logConfiguration"
+            ] = flow_container_definitions_kwargs.get("logConfiguration", {})
+
+        if flow_container_definitions_kwargs.get("repositoryCredentials"):
+            container_definitions[0][
+                "repositoryCredentials"
+            ] = flow_container_definitions_kwargs.get("repositoryCredentials", {})
 
         # Register task definition
         flow_task_definition_kwargs = copy.deepcopy(self.task_definition_kwargs)


Test patch:
diff --git a/tests/agent/test_fargate_agent.py b/tests/agent/test_fargate_agent.py
--- a/tests/agent/test_fargate_agent.py
+++ b/tests/agent/test_fargate_agent.py
@@ -1165,10 +1165,6 @@ def test_deploy_flows_includes_agent_labels_in_environment(
                 },
             ],
             "essential": True,
-            "secrets": [],
-            "mountPoints": [],
-            "logConfiguration": {},
-            "repositoryCredentials": {},
         }
     ]
     assert boto3_client.register_task_definition.call_args[1][
@@ -1179,70 +1175,6 @@ def test_deploy_flows_includes_agent_labels_in_environment(
     assert boto3_client.register_task_definition.call_args[1]["memory"] == "2"
 
 
-def test_deploy_flow_register_task_definition_no_repo_credentials(
-    monkeypatch, runner_token, cloud_api
-):
-    boto3_client = MagicMock()
-
-    boto3_client.describe_task_definition.side_effect = ClientError({}, None)
-    boto3_client.run_task.return_value = {"tasks": [{"taskArn": "test"}]}
-    boto3_client.register_task_definition.return_value = {}
-
-    monkeypatch.setattr("boto3.client", MagicMock(return_value=boto3_client))
-
-    with set_temporary_config({"logging.log_to_cloud": True}):
-        agent = FargateAgent()
-
-    agent.deploy_flow(
-        flow_run=GraphQLResult(
-            {
-                "flow": GraphQLResult(
-                    {
-                        "storage": Docker(
-                            registry_url="test", image_name="name", image_tag="tag"
-                        ).serialize(),
-                        "environment": LocalEnvironment().serialize(),
-                        "id": "id",
-                    }
-                ),
-                "id": "id",
-            }
-        )
-    )
-
-    assert boto3_client.describe_task_definition.called
-    assert boto3_client.register_task_definition.called
-    assert boto3_client.register_task_definition.call_args[1][
-        "containerDefinitions"
-    ] == [
-        {
-            "name": "flow",
-            "image": "test/name:tag",
-            "command": ["/bin/sh", "-c", "prefect execute cloud-flow"],
-            "environment": [
-                {"name": "PREFECT__CLOUD__API", "value": "https://api.prefect.io"},
-                {"name": "PREFECT__CLOUD__AGENT__LABELS", "value": "[]"},
-                {"name": "PREFECT__CLOUD__USE_LOCAL_SECRETS", "value": "false"},
-                {"name": "PREFECT__LOGGING__LOG_TO_CLOUD", "value": "true"},
-                {"name": "PREFECT__LOGGING__LEVEL", "value": "DEBUG"},
-                {
-                    "name": "PREFECT__ENGINE__FLOW_RUNNER__DEFAULT_CLASS",
-                    "value": "prefect.engine.cloud.CloudFlowRunner",
-                },
-                {
-                    "name": "PREFECT__ENGINE__TASK_RUNNER__DEFAULT_CLASS",
-                    "value": "prefect.engine.cloud.CloudTaskRunner",
-                },
-            ],
-            "essential": True,
-            "secrets": [],
-            "mountPoints": [],
-            "logConfiguration": {},
-            "repositoryCredentials": {},
-        }
-    ]
-
-
 def test_deploy_flows_require_docker_storage(monkeypatch, runner_token):
     boto3_client = MagicMock()
 
@@ -1331,10 +1263,6 @@ def test_deploy_flows_enable_task_revisions_no_tags(
                     },
                 ],
                 "essential": True,
-                "secrets": [],
-                "mountPoints": [],
-                "logConfiguration": {},
-                "repositoryCredentials": {},
             }
         ],
         family="name",
@@ -1712,10 +1640,6 @@ def test_deploy_flows_enable_task_revisions_with_external_kwargs(
                     },
                 ],
                 "essential": True,
-                "secrets": [],
-                "mountPoints": [],
-                "logConfiguration": {},
-                "repositoryCredentials": {},
             }
         ],
         cpu="256",