diff --git a/README.md b/README.md index aeccb26..284045e 100644 --- a/README.md +++ b/README.md @@ -74,6 +74,8 @@ classDiagram DevopsBuild <|-- ProvsK3sBuild DevopsBuild <|-- C4kBuild + link DevopsBuild "./doc/DevopsBuild.md" + ``` Principles we follow are: @@ -81,7 +83,7 @@ Principles we follow are: * Seperate build artefacts from version controlled code * Domain Driven Design - in order to stay sustainable -# Setup +## Installation Ensure that yout python3 version is at least Python 3.10 @@ -91,7 +93,13 @@ pip3 install -r requirements.txt export PATH=$PATH:~/.local/bin ``` -# Example Build +## Reference + +* [DevopsBuild](./doc/DevopsBuild.md) + + + +## Example Build lets assume the following project structure @@ -105,7 +113,7 @@ my-project | | -> ... ``` -``` +```python from pybuilder.core import task, init from ddadevops import * @@ -113,22 +121,36 @@ name = 'my-project' MODULE = 'my-module' PROJECT_ROOT_PATH = '..' -class MyBuild(DevopsTerraformBuild): - pass - @init def initialize(project): - project.build_depends_on('ddadevops>=0.5.0') - account_name = 'my-aws-account-name' - account_id = 'my-aws-account-id' - stage = 'my stage i.e. dev|test|prod' - additional_vars = {'var_to_use_insied_terraform': '...'} - additional_var_files = ['variable-' + account_name + '-' + stage + '.tfvars'] - config = create_devops_terraform_build_config(stage, PROJECT_ROOT_PATH, - MODULE, additional_vars, - additional_tfvar_files=additional_var_files) - build = MyBuild(project, config) + project.build_depends_on("ddadevops>=4.0.0-dev") + + config = { + "credentials_mapping": [ + { + "gopass_path": environ.get("DIGITALOCEAN_TOKEN_KEY_PATH", None), + "name": "do_api_key", + }, + { + "gopass_path": environ.get("HETZNER_API_KEY_PATH", None), + "name": "hetzner_api_key", + }, + ], + "name": name, + "module": MODULE, + "stage": environ["STAGE"], + "project_root_path": PROJECT_ROOT_PATH, + "build_types": ["TERRAFORM"], + "mixin_types": [], + "tf_provider_types": ["DIGITALOCEAN", "HETZNER"], + "tf_use_workspace": False, + "tf_terraform_semantic_version": "1.4.2", + "do_as_backend": True, + "do_bucket": "your-bucket", + } + + build = DevopsTerraformBuild(project, config) build.initialize_build_dir() @@ -141,137 +163,16 @@ def plan(project): @task def apply(project): build = get_devops_build(project) - build.apply() - -@task -def destroy(project): - build = get_devops_build(project) - build.destroy() - -@task -def tf_import(project): - build = get_devops_build(project) - build.tf_import('aws_resource.choosen_name', 'the_aws_id') -``` - -## Feature aws-backend - -Will use a file `backend.dev.live.properties` where dev is the [account-name], live is the [stage]. - -the backend.dev.live.properties file content: -``` -key = ".." -region = "the aws region" -profile = "the profile used for aws" -bucket = "the s3 bucket name" -kms_key_id = "the aws key id" -``` - -the build.py file content: -``` -class MyBuild(AwsBackendPropertiesMixin, DevopsTerraformBuild): - pass - - -@init -def initialize(project): - project.build_depends_on('ddadevops>=1.0') - account_name = 'my-aws-account-name' - account_id = 'my-aws-account-id' - stage = 'my stage i.e. dev|test|prod' - additional_vars = {} - config = create_devops_terraform_build_config(stage, PROJECT_ROOT_PATH, - MODULE, additional_vars) - config = add_aws_backend_properties_mixin_config(config, account_name) - build = MyBuild(project, config) - build.initialize_build_dir() -``` - -## Feature aws-mfa-assume-role - -In order to use aws assume role in combination with the mfa-tool (`pip install mfa`): - -the build.py file content: -``` -class MyBuild(class MyBuild(AwsMfaMixin, DevopsTerraformBuild): - pass - - -@init -def initialize(project): - project.build_depends_on('ddadevops>=1.0') - account_name = 'my-aws-account-name' - account_id = 'my-aws-account-id' - stage = 'my stage i.e. dev|test|prod' - additional_vars = {} - config = create_devops_terraform_build_config(stage, PROJECT_ROOT_PATH, - MODULE, additional_vars) - config = add_aws_backend_properties_mixin_config(config, account_name) - config = add_aws_mfa_mixin_config(config, account_id, 'eu-central-1', - mfa_role='my_developer_role', - mfa_account_prefix='company-', - mfa_login_account_suffix='users_are_defined_here') - build = MyBuild(project, config) - build.initialize_build_dir() - -@task -def access(project): - build = get_devops_build(project) - build.get_mfa_session() -``` - -## Feature DdaImageBuild - -The docker build supports image building, tagging, testing and login to dockerhost. -For bash based builds we support often used script-parts as predefined functions [see install_functions.sh](src/main/resources/docker/image/resources/install_functions.sh). + build.apply(True) -A full working example: [doc/example/50_docker_module](doc/example/50_docker_module) - -## Feature AwsRdsPgMixin - -The AwsRdsPgMixin provides -* execute_pg_rds_sql - function will optionally resolve dns-c-names for trusted ssl-handshakes -* alter_db_user_password -* add_new_user -* deactivate_user - -the build.py file content: -``` -class MyBuild(..., AwsRdsPgMixin): - pass - - -@init -def initialize(project): - project.build_depends_on('ddadevops>=1.0') - - ... - config = add_aws_rds_pg_mixin_config(config, - stage + "-db.bcsimport.kauf." + account_name + ".breuni.de", - "kauf_bcsimport", - rds_resolve_dns=True,) - build = MyBuild(project, config) - build.initialize_build_dir() @task -def rotate_credentials_in(project): +def destroy(project): build = get_devops_build(project) - build.alter_db_user_password('/postgres/support') - build.alter_db_user_password('/postgres/superuser') - build.add_new_user('/postgres/superuser', '/postgres/app', 'pg_group_role') + build.destroy(True) - -@task -def rotate_credentials_out(project): - build = get_devops_build(project) - build.deactivate_user('/postgres/superuser', 'old_user_name') ``` -# Releasing and updating -## Publish snapshot - -1. every push will be published as dev-dependency - ## Release ``` @@ -285,7 +186,7 @@ git push pip3 install --upgrade --user ddadevops ``` -# License +## License -Copyright © 2021 meissa GmbH +Copyright © 2023 meissa GmbH Licensed under the [Apache License, Version 2.0](LICENSE) (the "License") diff --git a/doc/DevopsBuild.md b/doc/DevopsBuild.md new file mode 100644 index 0000000..16e63d2 --- /dev/null +++ b/doc/DevopsBuild.md @@ -0,0 +1,61 @@ +# DevopsBuild + +DevopsBuild stellt die build Grundlagen zur Verfügung. + +```mermaid +classDiagram + class DevopsBuild { + name() - thename of build + build_path() - the build dir in target + initialize_build_dir() - copy current directory & additional files to target + } + +``` + +## Input + +| name | description | default | +| ----------------- | -------------------------------------------------------------------------------------------------- | ------- | +| name | dedicated name of the build | module | +| module | module name - may result in a hierarchy like name/module | | +| stage | sth. like test, int, acc or prod | | +| project_root_path | relative path to projects root. Is used to locate the target dir | | +| build_dir_name | name of dir, build is executed in | target | +| build_types | list of special builds used. Valid values are ["IMAGE", "C4K", "K3S", "TERRAFORM"] | [] | +| mixin_types | mixins are orthoganl to builds and represent additional capabilities. Valid Values are ["RELEASE"] | [] | + + +## Example Usage + + +```python +from subprocess import run +from pybuilder.core import task, init +from ddadevops import * + +name = 'my-project' +MODULE = 'my-module' +PROJECT_ROOT_PATH = '..' + +@init +def initialize(project): + project.build_depends_on("ddadevops>=4.0.0") + + config = { + "name": name, + "module": MODULE, + "stage": environ["STAGE"], + "project_root_path": PROJECT_ROOT_PATH, + "build_types": [], + "mixin_types": [], + } + + build = DevopsTerraformBuild(project, config) + build.initialize_build_dir() + + +@task +def list_build_dir(project): + build = get_devops_build(project) + run(f"ls -la {build.build_path()}") +``` \ No newline at end of file