Repository: cloud-custodian/cloud-custodian

Issue:
Tagging CloudFormation - Error: Parameters must have value
Initially the stack is created with an input parameter.

**c7n policy**
```
policies:
  - name: add-cfn-tag
    resource: cfn
    filters:
      - "tag:testcfn": present
    actions:
      - type: tag
        value: abc
        key: BusinessUnit
```
**Error**
An error occurred (ValidationError) when calling the UpdateStack operation: Parameters: [input_param] must have values


Discussion:

Resolving patch:
diff --git a/c7n/resources/cfn.py b/c7n/resources/cfn.py
--- a/c7n/resources/cfn.py
+++ b/c7n/resources/cfn.py
@@ -145,9 +145,14 @@ def process_resource_set(self, stacks, tags):
             self.manager.session_factory).client('cloudformation')
 
         def _tag_stacks(s):
+            params = []
+            for p in s.get('Parameters', []):
+                params.append({'ParameterKey': p['ParameterKey'],
+                               'UsePreviousValue': True})
             client.update_stack(
                 StackName=s['StackName'],
                 UsePreviousTemplate=True,
+                Parameters=params,
                 Tags=tags)
 
         with self.executor_factory(max_workers=2) as w:


Test patch:
diff --git a/tests/data/placebo/test_cfn_add_tag_w_params/cloudformation.DescribeStacks_1.json b/tests/data/placebo/test_cfn_add_tag_w_params/cloudformation.DescribeStacks_1.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_cfn_add_tag_w_params/cloudformation.DescribeStacks_1.json
@@ -0,0 +1,63 @@
+{
+    "status_code": 200,
+    "data": {
+        "Stacks": [
+            {
+                "StackId": "arn:aws:cloudformation:us-east-1:644160558196:stack/mosdef2/387d82a0-23f5-11e9-98e5-128a65397f5a",
+                "StackName": "mosdef2",
+                "Description": "A sample template",
+                "Parameters": [
+                    {
+                        "ParameterKey": "UserName",
+                        "ParameterValue": "m1.small"
+                    }
+                ],
+                "CreationTime": {
+                    "__class__": "datetime",
+                    "year": 2019,
+                    "month": 1,
+                    "day": 29,
+                    "hour": 18,
+                    "minute": 39,
+                    "second": 44,
+                    "microsecond": 569000
+                },
+                "LastUpdatedTime": {
+                    "__class__": "datetime",
+                    "year": 2019,
+                    "month": 1,
+                    "day": 29,
+                    "hour": 18,
+                    "minute": 48,
+                    "second": 41,
+                    "microsecond": 771000
+                },
+                "RollbackConfiguration": {},
+                "StackStatus": "UPDATE_COMPLETE",
+                "DisableRollback": false,
+                "NotificationARNs": [],
+                "Tags": [
+                    {
+                        "Key": "Author",
+                        "Value": "Kapil"
+                    }
+                ],
+                "DriftInformation": {
+                    "StackDriftStatus": "NOT_CHECKED"
+                }
+            }
+        ],
+        "ResponseMetadata": {
+            "RequestId": "e9940725-23f6-11e9-a2ce-4597e04b9a84",
+            "HTTPStatusCode": 200,
+            "HTTPHeaders": {
+                "x-amzn-requestid": "e9940725-23f6-11e9-a2ce-4597e04b9a84",
+                "content-type": "text/xml",
+                "content-length": "16472",
+                "vary": "Accept-Encoding",
+                "date": "Tue, 29 Jan 2019 18:51:39 GMT"
+            },
+            "RetryAttempts": 0
+        }
+    }
+}
diff --git a/tests/data/placebo/test_cfn_add_tag_w_params/cloudformation.DescribeStacks_2.json b/tests/data/placebo/test_cfn_add_tag_w_params/cloudformation.DescribeStacks_2.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_cfn_add_tag_w_params/cloudformation.DescribeStacks_2.json
@@ -0,0 +1,64 @@
+{
+    "status_code": 200,
+    "data": {
+        "Stacks": [
+            {
+                "StackId": "arn:aws:cloudformation:us-east-1:644160558196:stack/mosdef2/387d82a0-23f5-11e9-98e5-128a65397f5a",
+                "StackName": "mosdef2",
+                "Description": "A sample template",
+                "Parameters": [
+                    {
+                        "ParameterKey": "UserName",
+                        "ParameterValue": "m1.small"
+                    }
+                ],
+                "CreationTime": {
+                    "__class__": "datetime",
+                    "year": 2019,
+                    "month": 1,
+                    "day": 29,
+                    "hour": 18,
+                    "minute": 39,
+                    "second": 44,
+                    "microsecond": 569000
+                },
+                "LastUpdatedTime": {
+                    "__class__": "datetime",
+                    "year": 2019,
+                    "month": 1,
+                    "day": 29,
+                    "hour": 18,
+                    "minute": 51,
+                    "second": 40,
+                    "microsecond": 115000
+                },
+                "RollbackConfiguration": {},
+                "StackStatus": "UPDATE_IN_PROGRESS",
+                "StackStatusReason": "User Initiated",
+                "DisableRollback": false,
+                "NotificationARNs": [],
+                "Tags": [
+                    {
+                        "Key": "Env",
+                        "Value": "Dev"
+                    }
+                ],
+                "EnableTerminationProtection": false,
+                "DriftInformation": {
+                    "StackDriftStatus": "NOT_CHECKED"
+                }
+            }
+        ],
+        "ResponseMetadata": {
+            "RequestId": "e9c5291a-23f6-11e9-8a67-cbe15c822cf9",
+            "HTTPStatusCode": 200,
+            "HTTPHeaders": {
+                "x-amzn-requestid": "e9c5291a-23f6-11e9-8a67-cbe15c822cf9",
+                "content-type": "text/xml",
+                "content-length": "1400",
+                "date": "Tue, 29 Jan 2019 18:51:39 GMT"
+            },
+            "RetryAttempts": 0
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_cfn_add_tag_w_params/cloudformation.UpdateStack_1.json b/tests/data/placebo/test_cfn_add_tag_w_params/cloudformation.UpdateStack_1.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_cfn_add_tag_w_params/cloudformation.UpdateStack_1.json
@@ -0,0 +1,17 @@
+{
+    "status_code": 200,
+    "data": {
+        "StackId": "arn:aws:cloudformation:us-east-1:644160558196:stack/mosdef2/387d82a0-23f5-11e9-98e5-128a65397f5a",
+        "ResponseMetadata": {
+            "RequestId": "e9a62eec-23f6-11e9-9333-3feb7299e7ae",
+            "HTTPStatusCode": 200,
+            "HTTPHeaders": {
+                "x-amzn-requestid": "e9a62eec-23f6-11e9-9333-3feb7299e7ae",
+                "content-type": "text/xml",
+                "content-length": "377",
+                "date": "Tue, 29 Jan 2019 18:51:39 GMT"
+            },
+            "RetryAttempts": 0
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/test_cfn.py b/tests/test_cfn.py
--- a/tests/test_cfn.py
+++ b/tests/test_cfn.py
@@ -66,6 +66,26 @@ def test_disable_protection(self):
         )
         self.assertEqual(stacks[0].get("EnableTerminationProtection"), False)
 
+    def test_cfn_add_tag_with_params(self):
+        session_factory = self.replay_flight_data("test_cfn_add_tag_w_params")
+        p = self.load_policy(
+            {
+                "name": "cfn-add-tag",
+                "resource": "cfn",
+                "filters": [{"StackName": "mosdef2"}],
+                "actions": [
+                    {"type": "tag", "tags": {'Env': 'Dev'}}
+                ],
+            },
+            session_factory=session_factory,
+        )
+        resources = p.run()
+        self.assertEqual(len(resources), 1)
+        client = session_factory(region="us-east-1").client("cloudformation")
+        tags = {t['Key']: t['Value'] for t in client.describe_stacks(
+            StackName=resources[0]["StackName"])["Stacks"][0]["Tags"]}
+        self.assertEqual(tags, {'Env': 'Dev'})
+
     def test_cfn_add_tag(self):
         session_factory = self.replay_flight_data("test_cfn_add_tag")
         p = self.load_policy(