Repository: cloud-custodian/cloud-custodian

Issue:
aws - custom log/output directories with --region all
**Describe the bug**

--region all unconditionally suffixes a region, even though it may already be present in a custom output/format string. it should detect output region usage and avoid the suffix.




Discussion:

Resolving patch:
diff --git a/c7n/resources/aws.py b/c7n/resources/aws.py
--- a/c7n/resources/aws.py
+++ b/c7n/resources/aws.py
@@ -639,7 +639,7 @@ def initialize_policies(self, policy_collection, options):
         """Return a set of policies targetted to the given regions.
 
         Supports symbolic regions like 'all'. This will automatically
-        filter out policies if their being targetted to a region that
+        filter out policies if they are being targetted to a region that
         does not support the service. Global services will target a
         single region (us-east-1 if only all specified, else first
         region in the list).
@@ -705,6 +705,8 @@ def initialize_policies(self, policy_collection, options):
 
 
 def join_output(output_dir, suffix):
+    if '{region}' in output_dir:
+        return output_dir.rstrip('/')
     if output_dir.endswith('://'):
         return output_dir + suffix
     return output_dir.rstrip('/') + '/%s' % suffix


Test patch:
diff --git a/tests/test_policy.py b/tests/test_policy.py
--- a/tests/test_policy.py
+++ b/tests/test_policy.py
@@ -478,7 +478,8 @@ def test_policy_region_expand_global(self):
             config=Config.empty(regions=["us-east-1", "us-west-2"]),
         )
 
-        collection = AWS().initialize_policies(original, Config.empty(regions=["all"]))
+        collection = AWS().initialize_policies(
+            original, Config.empty(regions=["all"], output_dir="/test/output/"))
         self.assertEqual(len(collection.resource_types), 2)
         s3_regions = [p.options.region for p in collection if p.resource_type == "s3"]
         self.assertTrue("us-east-1" in s3_regions)
@@ -486,13 +487,23 @@ def test_policy_region_expand_global(self):
         iam = [p for p in collection if p.resource_type == "iam-user"]
         self.assertEqual(len(iam), 1)
         self.assertEqual(iam[0].options.region, "us-east-1")
+        self.assertEqual(iam[0].options.output_dir, "/test/output/us-east-1")
+
+        # Don't append region when it's already in the path.
+        collection = AWS().initialize_policies(
+            original, Config.empty(regions=["all"], output_dir="/test/{region}/output/"))
+        self.assertEqual(len(collection.resource_types), 2)
+        iam = [p for p in collection if p.resource_type == "iam-user"]
+        self.assertEqual(iam[0].options.region, "us-east-1")
+        self.assertEqual(iam[0].options.output_dir, "/test/{region}/output")
 
         collection = AWS().initialize_policies(
-            original, Config.empty(regions=["eu-west-1", "eu-west-2"])
+            original, Config.empty(regions=["eu-west-1", "eu-west-2"], output_dir="/test/output/")
         )
         iam = [p for p in collection if p.resource_type == "iam-user"]
         self.assertEqual(len(iam), 1)
         self.assertEqual(iam[0].options.region, "eu-west-1")
+        self.assertEqual(iam[0].options.output_dir, "/test/output/eu-west-1")
         self.assertEqual(len(collection), 3)