Sign inSign up

lucasbasquerotto/ctl

By lucasbasquerotto

•Updated about 4 years ago

Image
0

198

lucasbasquerotto/ctl repository overview

⁠(Under Construction) Controller Layer

This repository corresponds to the controller layer and is used to deploy projects. This is the top layer and is responsible to manage and deploy projects. After setting up this layer, you can start deploying projects, according to the projects defined in the main environment repository⁠.

The deployment of a specific project is done by the cloud layer, which uses the variables⁠ generated in the preparation step⁠ of this layer (controller).

A default implementation of the cloud layer is located at http://github.com/lucasbasquerotto/cloud⁠.

⁠Demo

Before start using this layer, it's easier to see it in action. Below is a simple demo used to deploy a project. The demo uses pre-defined variables generated by the controller layer⁠ so that this layer is not needed to execute, and then execute the cloud layer⁠ directly to deploy a project.

To execute the demo you will need a container engine (like docker or podman).

  1. Create an empty directory somewhere in your filesystem, let's say, /var/demo.

  2. Create 2 directories in it: env and data (the names could be different, just remember to use these directories when mapping volumes to the container).

  3. Create a demo.yml file inside env with the data needed to deploy the project:

# Enter the data here (see the demo examples)
  1. Deploy the project:
docker run -it --rm -v /var/demo/env:/env -v /var/demo/data:/lrd local/demo

The above commands in a shell script:

mkdir -p /var/demo/env /var/demo/data

cat <<'SHELL' > /var/demo/env/demo.yml
# Enter the data here (see the demo examples)
SHELL

docker run -it --rm -v /var/demo/env:/env -v /var/demo/data:/lrd local/demo

That's it. The project was deployed.

šŸš€ You can see examples of project deployment demos here⁠.

The demos are great for what they are meant to be: demos, prototypes. They shouldn't be used for development (bad DX if you need real time changes without having to push and pull newer versions of repositories, furthermore you are unable to clone repositories in specific locations defined by you in the project folder). They also shouldn't be used in production environments due to bad security (the vault value used for decryption is 123456, and changes to the project environment repository⁠ may be lost if you forget to push them).

⁠Root Directory

The root folder is the base directory in which the projects managed by the controller are defined. It's the parent of the controller repository (ctl) and contains:

  • The secrets directory: has the vault files to decrypt the ssh files to clone the projects environment repositories⁠).

  • The projects directory: has the project files, secrets and repositories.

  • The users directory: has the users home directories (when use_subuser⁠ is true).

  • The data directory: used mainly in local development environments to contain project deployment data (like logs, databases and uploaded files).

The following instructions assume that they are being run from the <root> folder, which will contain the data generated from all projects.

⁠Setup

The machine that will deploy the projects should have the following tools:

To be able to deploy the projects, the controller will need to know which projects to deploy. That information is declared in the main environment repository⁠. You can manually clone the repository with git at the folder ctl/env-main (or point a symlink located at ctl/env-main to another location on you machine) or run the following command that will do that for you:

./ctl/run setup

The above command will ask you to enter the repository which willl be cloned (git clone <git_env_main_repository>). An alternative is to enter the repository directly like the following:

./ctl/run setup <git_env_main_repository>

If you have a symlink at ctl/env-main pointing to an empty directory, the git repository will be cloned at that target repository.

To make things more practical, you can create a repository to become the root folder of your environment and then make an instruction that runs the entire setup step in a more straightforward way, with just a simple command like ./setup.

This repository⁠ does that, and you can fork it and change only the env.sh file, defining in it the controller repository and branch, your main environment repository, and optionally the location of this repository relatively to the root directory (a symlink will be created at ctl/env-main).

⁠Main Environment Repository

The main environment repository will be a hub containing information about the projects to deploy. It will be located at ctl/env-main and must have the following files:

  • Main Environment Options File: env.sh

File that will be sourced during launch⁠ to know which container engine should run the projects and also which container image it will run. It also has other useful options⁠ and examples⁠ explained below.

  • Main Environment Vars File: vars.yml

File that contains the specifications for all projects. It will be used during launch⁠ to deploy the project specified in the launch command. See its structure⁠ and the example⁠ below.

⁠Main Environment Options

OptionDefaultDescription
containerThe container repository (and tag) that will run the Controller Preparation Step⁠.
container_typedockerThe container engine CLI used when running the container. The command to run the container is the value of this option. The commands accepted by the CLI are assumed to be compatible with the ones from the docker CLI.
rootfalseWhen true, runs the container in the Controller Preparation Step⁠ as root (with sudo).
use_subuserfalseWhen true, runs the container in the Controller Preparation Step⁠, as well as the container to run the steps in the next layer, with the username <subuser_prefix><project_name> (the user will be created if it doesn't exists already, and the home directory will be users/<username>).
subuser_prefixThe prefix used to create the user that will run the containers. The username will be <subuser_prefix><project_name>. For example, if subuser_prefix is project- and project_name is my-demo, the username will be project-my-demo. When use_subuser is true, this option is required and cannot be empty.

⁠Main Environment Options File - Examples

An example of the file for a development environment is as follows:

export container=lucasbasquerotto/ansible:0.0.2
export container_type=podman

Another example:

export container=lucasbasquerotto/ansible:0.0.2
export root=true

The above example will use docker as the container engine (container_type).

An example of the file for a production environment is as follows:

export container=lucasbasquerotto/ansible:0.0.2
export container_type=podman
export use_subuser=true
export subuser_prefix=project-

⁠Main Environment Vars

OptionDefaultDescription
devfalseWhen true, defines that the project will run in a development environment. If the value is false, the project can't be launched with the --dev⁠ option.
init{}Define a dictionary in which the value of each key is an object of the type specified in the Init⁠ section.
repo{}Define a dictionary in which the value of each key is an object of the type specified in the Repo⁠ section.
repo_vault{}Define a dictionary in which the value of each key is an object of the type specified in the Repo Vault⁠ section.
env_params{}Define a dictionary in which the value of each key is an object of the type specified in the Env Params⁠ section.
path_params{}Define a dictionary in which the value of each key is an object of the type specified in the Path Params⁠ section.
TODO
⁠Main Env Vars - Init

This object contains data about the container in which the step after the Controller Preparation Step⁠ will run.

OptionDefaultDescription
containerThe container repository (and tag) that will run the steps after the Controller Preparation Step⁠.
container_typedockerThe container engine CLI used when running the container. The command to run the container is the value of this option. The commands accepted by the CLI are assumed to be compatible with the ones from the docker CLI.
rootfalseWhen true, runs the container as root (with sudo).
run_file/usr/local/bin/runThe executable file to run inside the container after the Controller Preparation Step⁠ ends. See details.⁠
⁠Main Env Vars - Repo

This object contains data about the project environment repository⁠.

OptionDefaultDescription
srcThe repository source (URL).
versionmasterThe repository branch or tag.
ssh_file(Optional) The location (relative to the main environment repository⁠) of the ssh file needed to clone the repository. The file can be in an encrypted with ansible-vault⁠ (the key to decrypt the file should be in the Main Vault File⁠).
⁠Main Env Vars - Repo Vault

This object contains the location to the project vault file⁠.

OptionDefaultDescription
fileThe project vault file (relative to the project environment repository⁠).
forcefalseWill ask for the vault passphrase whenever the vault value should be used. This option is only considered if file is empty.
⁠Main Env Vars - Env Params

This object contains project specific variables. It's expected that the next layer is able to handle this option, merging the options defined here with the options defined in the project environment file⁠. Specifying options here can be convenient to deploy multiple similar projects without having to create a different project environment file⁠ for each case, achieving a more DRY approach. To make staging and production environments more predictable, it's advisable to not use this option for such projects.

There are no pre-established properties for this option (they are project specific).

Using the cloud layer defined at http://github.com/lucasbasquerotto/cloud⁠, the variables defined in this option will be accessible through the params object in the project environment file⁠.

⁠Main Env Vars - Path Params

This object could be considered a special case of the Env Params⁠ section. It contains paths to repositories, to be mapped to different locations than they would be otherwise. The paths are relative to the root repository.

Repositories mapped this way will be cloned the first time (when the directory is empty) and ignored from then on, allowing the deployment of projects along with real-time changes to the deployment code, if the code is inside one of the mapped repositories.

Mapped repositories can be shared accross different projects as long as the mapped locations are the same.

Using the cloud layer defined at http://github.com/lucasbasquerotto/cloud⁠, this option will be ignored when not running in a development environment (dev: false⁠). In this case, it accepts the following options:

OptionDefaultDescription
path_envPath in which the project environment repository⁠ will be cloned.
path_env_basePath in which the environment base repository, defined in the env option inside project environment file⁠, will be cloned.
path_map_repos{}Dictionary with objects in the form [repo]: string, in which repositories defined in the project environment file⁠ are mapped to the specified paths.

⁠Main Environment Vars File - Example

dev: true

init:
  default:
    container: "lucasbasquerotto/cloud:1.3.6"
    root: true
  other:
    container: "lucasbasquerotto/cloud:1.3.6"
    container_type: "podman"
  other2:
    container: "lucasbasquerotto/cloud"
    container_type: "podman"
    root: true

repo:
  default:
    src: "ssh://[email protected]/lucasbasquerotto/project-env-demo.git"
    version: "master"
    ssh_file: "ssh/repo.encrypted.key"
  other:
    src: "ssh://[email protected]/lucasbasquerotto/other-project-env-demo.git"
    version: "master"
    ssh_file: "ssh/repo.encrypted.key"

repo_vault:
  default:
    file: "vault/main"
  other:
    force: true

env_params:
  local:
    pod_custom_dir_sync: true
    named_volumes: true
  custom:
    name: "my-custom-project"

path_params:
  default:
    path_env: "repos/env"
    path_env_base: "repos/env-base"
    path_map_repos:
      env_base: "repos/env-base"
      cloud: "repos/cloud"
      ext_cloud: "repos/ext-cloud"
      pod: "repos/pod"
      ext_pod: "repos/ext-pod"
      app: "repos/app"

# TODO

⁠Controller Preparation Step

This step is the first and only step executed in the controller layer to launch the project (deployment). The main environment repository⁠ must be present at ctl/env-main so that this step can be run.

This step generates the Controller Output Vars⁠, as well as the project ssh key file⁠ and the project vault file⁠ to be used by the next layer⁠.

⁠Main Vault File

The main vault file for a project is located at secrets/projects/<project_name>/vault and contains the value to decrypt:

  1. The project ssh key file⁠ to clone the project environment repository⁠.

  2. The project vault file⁠ to decrypt the contents of the project environment file⁠.

⁠Project SSH Key File

The SSH file used to clone the project environment repository⁠. This file is optional and isn't needed for public repositories, but it's very important that this ssh file is specified if the aforementioned repository has secrets in it (and the repository should be private).

⁠Project Vault File

The vault file used to decrypt the project environment file⁠ in the project environment repository⁠. This file is optional, but recommended to be used if the environment file has secrets in it. It's also recommended to make the repository private. The encryption should be done with ansible-vault⁠.

⁠Launch

The launch command deploys a project. It is executed like ctl/launch ... (or alternatively ctl/run launch ..., or even ctl/run l ...) and is responsible to run the Controller Preparation Step⁠ and call the command to run the subsequent steps (in the next layers). Below you can see the options⁠ that can be used with it as well as examples⁠ of running this step.

⁠Launch options

Below are the options that can be used to launch⁠ a project:

OptionDescription
-c
--clear
Clears the project directory and ends the execution (may be used to clear the directory when the mapping to the project repositories (during development) changes (with the path_params property), which could cause issues with symlinks). If the project was deployed with the --dev option, it should be cleared with this option too, like ./ctl/launch -dc <project_name>.
-d
--dev
Runs the project in a development environment. It allows to map paths to repositories to share the repository across multiple projects and avoid cleaning live changes made to the repository that were still not commited (will not update the repository to the version specified, which allows to develop and test changes without the need to push those changes).
-e
--enter
Enters the container that runs the preparation step in the controller layer, instead of executing it. The command that would be executed can be seen by running (inside the container) cat tmp/cmd. This command doesn't work with the --inside option.
-f
--force
Force the execution even if the commit of the project environment repository⁠ is the same as the last time it was executed.
-i
--inside
Considers that the current environment is already inside an environment that has the necessary stuff to run the project, without the need to run it inside a container (the environment may already be a container). See Running Inside a Container⁠ and Running Without Containers⁠ for more information.
-n
--next
The deployment will use parameters passed after the project name to be used by the next steps. How those parameters will be used depends on what the next step expects them to be.

Using the cloud layer defined at http://github.com/lucasbasquerotto/cloud⁠, this will expect the parameters specified here⁠.
-p
--prepare
Only runs the preparation step and expects that the subsequent layers accept this option so as to run only the preparation step in that layer, and forwards the option to subsequent layers, if needed.

This has a particular feature that allows to pass arguments to each step that will handle it (as long as subsequent layers handle it). For example, passing the args -vv after the project name would generally be used only by the last step (Cloud Context Main Step⁠), but in this case it will be used as args to run the Controller Preparation Step⁠ and no args to subsequent steps.

You can pass -- to indicate the end of the arguments for a given step, so the following args -a -b -- -c -- -d will pass the args -a -b to the Controller Preparation Step⁠, and -c -- -d to the next step. You can use --skip to skip a given step (you shouldn't pass -- in this case). For example, --skip -c -- -d will skip the Controller Preparation Step⁠ and pass -c -- -d to the next step.

Using the cloud layer defined at http://github.com/lucasbasquerotto/cloud⁠, this will run the steps Controller Preparation Step⁠, Cloud Preparation Step⁠ and Cloud Context Preparation Step⁠, but won't run the Cloud Context Main Step⁠. You will have 3 steps in this case, so if you run ctl/run launch <project_name> -- --skip -vv, the Controller Preparation Step⁠ will run without args, the Cloud Preparation Step⁠ will be skipped and the Cloud Context Preparation Step⁠ will run in verbose mode⁠
-P
--no-prompt
By default, the launch expects an unencrypted vault file⁠ at secrets/projects/<project_name>/vault. This vault file is used to decrypt values in the main environment repository for a specific project, like the ssh key for the project environment repository, or the vault to be used for the next steps (to decrypt values in the project environment repository). If this file is not present, there is a prompt asking to enter the vault passphrase. This option runs the Controller Preparation Step⁠ without the vault file if the file is not present (it's expected that the file was created beforehand, or that the main environment file for this project doesn't use encrypted values to be decrypted using a vault file, otherwise an error will be thrown).
-s
--fast
Skips the Controller Preparation Step⁠ and may skip preparation steps in subsequent layers (if those layers use this option and forwards it to the next layer).

Using the cloud layer defined at http://github.com/lucasbasquerotto/cloud⁠, this will skip the Controller Preparation Step⁠, Cloud Preparation Step⁠ and Cloud Context Preparation Step⁠, running only the Cloud Context Main Step⁠ for each context.
-V
--no-vault
By default, the launch expects an unencrypted vault file⁠ at secrets/projects/<project_name>/vault. This vault file is used to decrypt values in the main environment repository for a specific project, like the ssh key for the project environment repository, or the vault to be used for the next steps (to decrypt values in the project environment repository). This option runs the Controller Preparation Step⁠ without the vault file (it's expected that the main environment file for this project doesn't use encrypted values to be decrypted using a vault file, otherwise an error will be thrown).
--ctlRuns only the Controller Preparation Step⁠ and generates the Controller Output Vars⁠. Usiful to generate the variables that will be used in a demo that doesn't need the controller layer, like the official demo⁠.
--debugRuns in verbose mode and forwards this option to the subsequent step.
--migrationRuns with the project migration parameter set as the value specified in this parameter. This value overrides the migration value specified for the project in the vars.yml file in the Main Environment Repository⁠ (when both are specified). This parameter is useful to make sure that an automated process deploy the project only if this value is the same as the one specified for the environment. This is also useful to make sure that a migration that must run manually doesn't run automatically (the automatic process would fail in the preparation step, because the migration value is different from the one specified in the environment file, then you can run manually specifying this parameter explicitly when launching the project).
-w
--new-pass
Clears the project secrets directory (the directory that stores the passphrase used to decrypt the project variables at the main environment repository, which is asked right after deploying the project for the first time). It can be useful

Tag summary

Content type

Image

Digest

sha256:b6210ac4d…

Size

247.8 MB

Last updated

about 4 years ago

docker pull lucasbasquerotto/ctl:20220727