Skip to content

Commit

Permalink
docs: Initial CDK docs
Browse files Browse the repository at this point in the history
  • Loading branch information
techman83 committed Apr 13, 2024
1 parent 7f7d839 commit d512b51
Show file tree
Hide file tree
Showing 3 changed files with 357 additions and 0 deletions.
354 changes: 354 additions & 0 deletions docs/cdk.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,354 @@
CDK
===
Continuing on from the generalised overview found in the :ref:`concepts`, Cally at
its core, was built to abstract and generate valid Terraform json, via the CDK for
Terraform.

-------------
CallyResource
-------------
This is used as a wrapper, to provide a convenient and pythonic interface to CDK
for Terraform resources. Though you can use constructs, I'd prefer to not work
around the nuances of very typescript feeling python, and just lean on the benfits
of the CDK for Terraform. Which is an extremely robust and reliable Terraform JSON
generator.

.. code-block:: python
class RandomPet(CallyResource):
provider = 'random'
resource = 'random_pet'
defaults = MappingProxyType({'prefix': 'foo')
This class when instantiated will generate a random pet name, prefixed by ``foo``.
defaults are copied via deepcopy, so complex structures can be defined here. If the
service provides a value, the default is ignored.
----------
CallyStack
----------
This is what will be instantiated during tf print/write commands, you have the freedom
to construct your stack, any way you see fit. Leaning on all the functionality availble
within python, without needing to be concerned about how to construct things in a 'CDK
for Terraform' way. Cally takes care of backend + provider configuration, leaving you to
focus entirely on service design.
A stack can be as minimal as adding a single resource, or as complex as building a full
service, including VMs, Load Balancers, Dashboards, secrets management, IAM, etc.
.. code-block:: python
class PetRandom(CallyStack):
def __init__(self, service: CallyStackService) -> None:
super().__init__(service)
self.add_resource(Pet('beagle'))
----------------
Example Use Case
----------------
This shows an example of building an IDP, that is able to generate Versioned Buckets
from very minimal configuration.
Project layout
.. code-block:: shell
├── cally
│ └── idp
│ ├── defaults.py
│ ├── __init__.py
│ ├── py.typed
│ ├── resources
│ │ ├── __init__.py
│ │ └── storage.py
│ └── stacks
│ ├── gcp.py
│ ├── __init__.py
├── cally.yaml
└── pyproject.toml
defaults
--------
Defaults are where you set the things you'd like to be provided to all services, like
backend. Further details can be found in the :ref:`config-top-defaults` documentation.
.. code-block:: python
:caption: defaults.py
DEFAULTS = {
'backend': {
'config': {
'bucket': 'my-state-files',
},
'path': '{environment}/{name}',
'path_key': 'prefix',
'type': 'GcsBackend',
},
'providers': {
'google': {
'region': 'australia-southeast1',
'default_labels': {'deployment_tool': 'cally'},
}
},
}
resources
---------
The intention is within your idp.resources, you'd build out a collection of the
resources your stacks will pull in. With any relevant defaults. For example, if
I were building out a storage stack, I would define all my resources and defaults
like this example:
.. note::
It is expected that the class name match the CDK for Terraform class name,
so that cally is able to resolve and instantiate the correct class when it
is time to 'synth' the stack.
.. code-block:: python
:caption: resources/storage.py
from types import MappingProxyType
class StorageBucket(CallyResource):
provider = 'google'
resource = 'storage_bucket'
class StorageBucketLifecycleRule(CallyResource):
provider = 'google'
resource = 'storage_bucket'
class StorageBucketLifecycleRuleCondition(CallyResource):
provider = 'google'
resource = 'storage_bucket'
class StorageBucketLifecycleRuleAction(CallyResource):
provider = 'google'
resource = 'storage_bucket'
class StorageBucketVersioning(CallyResource):
provider = 'google'
resource = 'storage_bucket'
defaults = MappingProxyType({'enabled': True})
Whilst it is not strictly necessary to define attribute resources, you lose the
strict type checking you get by using them. So when a stack is synthed, you can
get an output that fails to be processed correctly by Terraform, due to things
like a string where an int is expected.
stacks
------
.. code-block:: python
:caption: stacks/gcp.py
from cally.cdk import CallyStack
from cally.cli.config.types import CallyStackService
from ..resources import storage
class VersionedBucket(CallyStack):
def __init__(self, service: CallyStackService) -> None:
super().__init__(service)
lifecycle_rule = storage.StorageBucketLifecycleRule(
condition=storage.StorageBucketLifecycleRuleCondition(
days_since_noncurrent_time=service.get_stack_var('object_age', 30),
with_state='ARCHIVED',
),
action=storage.StorageBucketLifecycleRuleAction(
type='Delete',
),
)
self.bucket = storage.StorageBucket(
f'{self.name}-bucket',
name=service.get_stack_var('bucket_name', self.name),
location=service.get_stack_var('location', 'AUSTRALIA-SOUTHEAST1'),
lifecycle_rule=[lifecycle_rule],
versioning=storage.StorageBucketVersioning(),
)
self.add_resource(self.bucket)
cally.yaml
----------
Now that you have resources + a stack, you can create a config file that to generate
buckets with versioning automatically enabled.
.. code-block:: yaml
:caption: cally.yaml
defaults:
providers:
google:
project: my-default-project
dev:
defaults:
providers:
google:
project: my-dev-project
services:
versioned-defaults:
stack_type: VersionedBucket
versioned-customised:
providers:
google:
project: another-buckety-project
region: australia-southeast2
backend:
config:
bucket: alternative-state-bucket
stack_type: VersionedBucket
stack_vars:
bucket_name: my-bucket-name
object_age: 7
location: australia-southeast2
Results
-------
The resulting outputs from those service examples can be seen below
.. code-block:: json
:caption: ➜ example git:(main) ✗ cally tf print --environment dev --service versioned-defaults
{
"//": {
"metadata": {
"backend": "gcs",
"stackName": "versioned-defaults",
"version": "0.20.5"
},
"outputs": {
}
},
"provider": {
"google": [
{
"default_labels": {
"deployment_tool": "cally"
},
"project": "my-dev-project",
"region": "australia-southeast1"
}
]
},
"resource": {
"google_storage_bucket": {
"versioned-defaults-bucket": {
"//": {
"metadata": {
"path": "versioned-defaults/versioned-defaults-bucket",
"uniqueId": "versioned-defaults-bucket"
}
},
"lifecycle_rule": [
{
"action": {
"type": "Delete"
},
"condition": {
"days_since_noncurrent_time": 30,
"with_state": "ARCHIVED"
}
}
],
"location": "AUSTRALIA-SOUTHEAST1",
"name": "versioned-defaults",
"provider": "google",
"versioning": {
"enabled": true
}
}
}
},
"terraform": {
"backend": {
"gcs": {
"bucket": "my-state-files",
"prefix": "dev/versioned-defaults"
}
},
"required_providers": {
"google": {
"source": "hashicorp/google",
"version": "5.23.0"
}
}
}
}
.. code-block:: json
:caption: ➜ example git:(main) ✗ cally tf print --environment dev --service versioned-customised
{
"//": {
"metadata": {
"backend": "gcs",
"stackName": "versioned-customised",
"version": "0.20.5"
},
"outputs": {
}
},
"provider": {
"google": [
{
"default_labels": {
"deployment_tool": "cally"
},
"project": "another-buckety-project",
"region": "australia-southeast2"
}
]
},
"resource": {
"google_storage_bucket": {
"versioned-customised-bucket": {
"//": {
"metadata": {
"path": "versioned-customised/versioned-customised-bucket",
"uniqueId": "versioned-customised-bucket"
}
},
"lifecycle_rule": [
{
"action": {
"type": "Delete"
},
"condition": {
"days_since_noncurrent_time": 7,
"with_state": "ARCHIVED"
}
}
],
"location": "australia-southeast2",
"name": "my-bucket-name",
"provider": "google",
"versioning": {
"enabled": true
}
}
}
},
"terraform": {
"backend": {
"gcs": {
"bucket": "alternative-state-bucket",
"prefix": "dev/versioned-customised"
}
},
"required_providers": {
"google": {
"source": "hashicorp/google",
"version": "5.23.0"
}
}
}
}
2 changes: 2 additions & 0 deletions docs/concepts.rst
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
.. _concepts:

========
Concepts
========
Expand Down
1 change: 1 addition & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ usage patterns.
concepts
configuration
cli
cdk

API Reference
-------------
Expand Down

0 comments on commit d512b51

Please sign in to comment.