Skip to content

Commit

Permalink
config docs generation
Browse files Browse the repository at this point in the history
  • Loading branch information
jaymccon committed Oct 31, 2019
1 parent c807b43 commit 74ec178
Show file tree
Hide file tree
Showing 4 changed files with 310 additions and 32 deletions.
78 changes: 78 additions & 0 deletions generate_config_docs.py
@@ -0,0 +1,78 @@
# flake8: noqa
import json

if __name__ == "__main__":

schema = json.load(open("./taskcat/cfg/config_schema.json", "r"))

def resolve_ref(props):
if "$ref" in props:
ref = props["$ref"].split("/")[-1]
del props["$ref"]
props.update(schema["definitions"][ref])
return props

for k, v in schema["properties"].items():
item_str = f"* `{k}` "
v = resolve_ref(v)
item_str += f"*type:* `{v['type']}` "
if "description" in v:
item_str += f'{v["description"]}'
print(item_str)
if "properties" in v:
for ik, iv in v["properties"].items():
item_str = f" * `{ik}` "
iv = resolve_ref(iv)
item_str += f"*type:* `{iv['type']}` "
if "description" in iv:
item_str += f'{iv["description"]}'
print(item_str)
if iv["type"] == "object":
if "properties" in iv:
for iik, iiv in iv["properties"].items():
item_str = f" * `{iik}` "
iiv = resolve_ref(iiv)
item_str += f"*type:* `{iiv['type']}` "
if "description" in iiv:
item_str += f'{iiv["description"]}'
elif "additionalProperties" in iv:
name = ik[:-1] if ik.endswith("s") else ik
item_str = f" * `<{name.upper()}_NAME>` "
props = resolve_ref(iv["additionalProperties"])
item_str += f"*type:* `{iv['type']}` "
if "description" in props:
item_str += f'{props["description"]}'
print(item_str)
elif "additionalProperties" in v:
name = k[:-1] if k.endswith("s") else k
item_str = f" * `<{name.upper()}_NAME>` "
props = resolve_ref(v["additionalProperties"])
item_str += f"*type:* `{v['type']}` "
if "description" in props:
item_str += f'{props["description"]}'
if "properties" in props:
for ik, iv in props["properties"].items():
item_str = f" * `{ik}` "
iv = resolve_ref(iv)
item_str += f"*type:* `{iv['type']}` "
if "description" in iv:
item_str += f'{iv["description"]}'
print(item_str)
if iv["type"] == "object":
if "properties" in iv:
for iik, iiv in iv["properties"].items():
item_str = f" * `{iik}` "
iiv = resolve_ref(iiv)
item_str += f"*type:* `{iiv['type']}` "
if "description" in iiv:
item_str += f'{iiv["description"]}'
elif "additionalProperties" in iv:
name = ik[:-1] if ik.endswith("s") else ik
item_str = f" * `<{name.upper()}_NAME>` "
iprops = resolve_ref(iv["additionalProperties"])
item_str += f"*type:* `{iv['type']}` "
if "description" in iprops:
item_str += f'{iprops["description"]}'
print(item_str)
else:
print(v)
160 changes: 132 additions & 28 deletions taskcat/_dataclasses.py
Expand Up @@ -15,6 +15,57 @@

LOG = logging.getLogger(__name__)

# property descriptions

METADATA = {
"project__name": {
"description": "Project name, used as s3 key prefix when " "uploading objects"
},
"auth": {"description": "AWS authentication section"},
"project__owner": {
"description": "email address for project owner (not used at present)"
},
"regions": {"description": "List of AWS regions"},
"az_ids": {
"description": "List of Availablilty Zones ID's to exclude when generating "
"availability zones"
},
"package_lambda": {
"description": "Package Lambda functions into zips before uploading to s3, "
"set to false to disable"
},
"lambda_zip_path": {
"description": "Path relative to the project root to place Lambda zip "
"files, default is 'lambda_functions/zips'"
},
"lambda_source_path": {
"description": "Path relative to the project root containing Lambda zip "
"files, default is 'lambda_functions/source'"
},
"s3_bucket": {
"description": "Name of S3 bucket to upload project to, if left out "
"a bucket will be auto-generated"
},
"parameters": {
"description": "Parameter key-values to pass to CloudFormation, "
"parameters provided in global config take precedence"
},
"build_submodules": {
"description": "Build Lambda zips recursively for submodules, "
"set to false to disable"
},
"template": {
"description": "path to template file relative to the project "
"config file path"
},
"tags": {"description": "Tags to apply to CloudFormation template"},
"enable_sig_v2": {
"description": "Enable (deprecated) sigv2 access to auto-generated buckets"
},
"s3_object_acl": {
"description": "ACL for uploaded s3 objects, defaults to 'private'"
},
}

# types

Expand All @@ -36,7 +87,12 @@
class ParameterKeyField(FieldEncoder):
@property
def json_schema(self):
return {"type": "string", "pattern": r"[a-zA-Z0-9]*^$"}
return {
"type": "string",
"pattern": r"[a-zA-Z0-9]*^$",
"Description": "CloudFormation parameter name, can contain letters and "
"numbers only",
}


JsonSchemaMixin.register_field_encoders({ParameterKey: ParameterKeyField()})
Expand All @@ -49,6 +105,7 @@ def json_schema(self):
"type": "string",
"pattern": r"^(ap|eu|us|sa|ca|cn|af|me|us-gov)-(central|south|north|east|"
r"west|southeast|southwest|northeast|northwest)-[0-9]$",
"description": "AWS Region name eg.: 'us-east-1'",
}


Expand All @@ -58,7 +115,11 @@ def json_schema(self):
class AlNumDashField(FieldEncoder):
@property
def json_schema(self):
return {"type": "string", "pattern": r"^[a-z0-9-]*$"}
return {
"type": "string",
"pattern": r"^[a-z0-9-]*$",
"description": "accepts lower case letters, numbers and -",
}


JsonSchemaMixin.register_field_encoders({AlNumDash: AlNumDashField()})
Expand All @@ -71,6 +132,7 @@ def json_schema(self):
"type": "string",
"pattern": r"^(ap|eu|us|sa|ca|cn|af|me)(n|s|e|w|c|ne|se|nw|sw)[0-9]-az[0-9]"
r"$",
"description": "Availability Zone ID, eg.: 'use1-az1'",
}


Expand Down Expand Up @@ -247,41 +309,81 @@ class TestObj:

@dataclass
class GeneralConfig(JsonSchemaMixin, allow_additional_props=False):
parameters: Optional[Dict[ParameterKey, ParameterValue]] = field(default=None)
tags: Optional[Dict[TagKey, TagValue]] = field(default=None)
auth: Optional[Dict[Region, str]] = field(default=None)
s3_bucket: Optional[str] = field(default=None)
"""General configuration settings."""

parameters: Optional[Dict[ParameterKey, ParameterValue]] = field(
default=None, metadata=METADATA["parameters"]
)
tags: Optional[Dict[TagKey, TagValue]] = field(
default=None, metadata=METADATA["tags"]
)
auth: Optional[Dict[Region, str]] = field(default=None, metadata=METADATA["auth"])
s3_bucket: Optional[str] = field(default=None, metadata=METADATA["s3_bucket"])


@dataclass
class TestConfig(JsonSchemaMixin, allow_additional_props=False):
template: Optional[str] = field(default=None)
parameters: Optional[Dict[ParameterKey, ParameterValue]] = field(default=None)
regions: Optional[List[Region]] = field(default=None)
tags: Optional[Dict[TagKey, TagValue]] = field(default=None)
auth: Optional[Dict[Region, str]] = field(default=None)
s3_bucket: Optional[S3BucketName] = field(default=None)
az_blacklist: Optional[List[AzId]] = field(default=None)
"""Test specific configuration section."""

template: Optional[str] = field(default=None, metadata=METADATA["template"])
parameters: Optional[Dict[ParameterKey, ParameterValue]] = field(
default=None, metadata=METADATA["parameters"]
)
regions: Optional[List[Region]] = field(default=None, metadata=METADATA["regions"])
tags: Optional[Dict[TagKey, TagValue]] = field(
default=None, metadata=METADATA["tags"]
)
auth: Optional[Dict[Region, str]] = field(default=None, metadata=METADATA["auth"])
s3_bucket: Optional[S3BucketName] = field(
default=None, metadata=METADATA["s3_bucket"]
)
az_blacklist: Optional[List[AzId]] = field(
default=None, metadata=METADATA["az_ids"]
)


# pylint: disable=too-many-instance-attributes
@dataclass
class ProjectConfig(JsonSchemaMixin, allow_additional_props=False):
name: Optional[ProjectName] = field(default=None)
auth: Optional[Dict[Region, str]] = field(default=None)
owner: Optional[str] = field(default=None)
regions: Optional[List[Region]] = field(default=None)
az_blacklist: Optional[List[AzId]] = field(default=None)
package_lambda: Optional[bool] = field(default=None)
lambda_zip_path: Optional[str] = field(default=None)
lambda_source_path: Optional[str] = field(default=None)
s3_bucket: Optional[S3BucketName] = field(default=None)
parameters: Optional[Dict[ParameterKey, ParameterValue]] = field(default=None)
build_submodules: Optional[bool] = field(default=None)
template: Optional[str] = field(default=None)
tags: Optional[Dict[TagKey, TagValue]] = field(default=None)
s3_enable_sig_v2: Optional[bool] = field(default=None)
s3_object_acl: Optional[str] = field(default=None)
"""Project specific configuration section"""

name: Optional[ProjectName] = field(
default=None, metadata=METADATA["project__name"]
)
auth: Optional[Dict[Region, str]] = field(default=None, metadata=METADATA["auth"])
owner: Optional[str] = field(default=None, metadata=METADATA["project__owner"])
regions: Optional[List[Region]] = field(default=None, metadata=METADATA["regions"])
az_blacklist: Optional[List[AzId]] = field(
default=None, metadata=METADATA["az_ids"]
)
package_lambda: Optional[bool] = field(
default=None, metadata=METADATA["package_lambda"]
)
lambda_zip_path: Optional[str] = field(
default=None, metadata=METADATA["lambda_zip_path"]
)
lambda_source_path: Optional[str] = field(
default=None, metadata=METADATA["lambda_source_path"]
)
s3_bucket: Optional[S3BucketName] = field(
default=None, metadata=METADATA["s3_bucket"]
)
parameters: Optional[Dict[ParameterKey, ParameterValue]] = field(
default=None, metadata=METADATA["parameters"]
)
build_submodules: Optional[bool] = field(
default=None, metadata=METADATA["build_submodules"]
)
template: Optional[str] = field(default=None, metadata=METADATA["template"])
tags: Optional[Dict[TagKey, TagValue]] = field(
default=None, metadata=METADATA["tags"]
)
s3_enable_sig_v2: Optional[bool] = field(
default=None, metadata=METADATA["enable_sig_v2"]
)
s3_object_acl: Optional[str] = field(
default=None, metadata=METADATA["s3_object_acl"]
)


PROPAGATE_KEYS = ["tags", "parameters", "auth"]
Expand All @@ -292,6 +394,8 @@ class ProjectConfig(JsonSchemaMixin, allow_additional_props=False):
# pylint: disable=no-member
@dataclass
class BaseConfig(JsonSchemaMixin, allow_additional_props=False):
"""Taskcat configuration file"""

general: GeneralConfig = field(default_factory=GeneralConfig)
project: ProjectConfig = field(default_factory=ProjectConfig)
tests: Dict[TestName, TestConfig] = field(default_factory=dict)
Expand Down

0 comments on commit 74ec178

Please sign in to comment.