Skip to content

Architecture

An architecture overview to help with developing new plugins.

High level

A overview diagram of Codify

At a high level the codify loads plugins from the registry which contains resources. Resources do 2 main functions, they get the current status of the system and they apply changes.

Refresh

Plugins are required to implement the async refresh(parameters: Partial<T>): Promise<Partial<T> | null> method of the plugin library. Within this method, plugins are expected to pull the current config of the system based on the desired parameters of the user that are passed in. The refresh method returns a config of the current status of the system, that is to say if the returned config were to be applied no changes would result. Codify will then calculate a change set that is needed to turn the current config generated by refresh() to the desired config supplied by the user.

Plan

A collection of change sets across multiple resources is called a plan. A plan consists of change sets which are in turn composed by one resource operation and a list of parameter operations. A resource operation can be one of: create, destroy, re-create, modify or no-op. This controls tells the resource to create, destroy, re-create or modify the resource. The resource level operation is calculated using a couple of factors:

  1. Does the current config exist? If null is returned by the refresh then the create operation is returned.
  2. Based on resource parameters. If the resource exists then Codify will use the parameter operations to determine the resource operation. By default, any parameter changes will cause the resource to be re-created. However, resources can explicitly enable parameter level modifications in their configs.
  3. If the desired and current config matches perfectly, then no-op or no operation is returned

Parameter operations can be one of add, modify, remove, or no-op. A parameter change is add if it exists in the desired config but not the current. modify is returned when the parameter exists in both but the value has changed. remove is returned when a parameter exists in current but not desired. no-op is returned if the parameter stays the same between the desired and current configs.

Apply

Applies make the changes in the plan on the user’s operating system. The operations undertaken by an apply is entirely described by a plan. Plugins are required to implement:

  • async applyCreate(plan: CreatePlan<TerraformConfig>): Promise<void>
  • async applyDestroy(plan:DestroyPlan<AliasConfig>): Promise<void>
  • Optionally: applyModify(pc: ParameterChange<AliasConfig>, plan: ModifyPlan<AliasConfig>): Promise<void>

In applyCreate a resource is expected to install packages on the operating system. In applyDestroy the resource is expected to uninstall packages. Optionally resources to override applyModify to apply parameter level changes like for example in the aws-profile resource, modify was overridden to allow the modification of the awsAccessKeyId and awsAccessKeySecret without re-creating a profile.

Example: aws-cli resource

Let’s go over an example to make the overall architecture more clear.

Refresh

In the refresh method of the aws-cli resource. The resource will check if aws cli is already installed on the system. If it’s not then return null, if it is then it returns an empty config {} because the aws-cli resource has no parameters.

Plan

Codify will use this information to generate a change set and a plan. Based on if the current config is null or not Codify will determine if the resource operation is apply or no-op.

Apply

During the Apply, Codify will choose to either call applyCreate or not call anything at all depends on the plan. If applyCreate is called, the aws-cli resource will install aws-cli on the system using the method recommended by AWS. For arm based macs, this means installing aws-cli using homebrew.