# Deploy Lock This is a tool to lock a cluster or service, in order to prevent people from deploying changes during test automation or restarting pods during an infrastructure incident. ## Features - in-memory data store, mostly for testing - DynamoDB data store - lock paths and recursive checking - infer lock data from CI variables ## Contents - [Deploy Lock](#deploy-lock) - [Features](#features) - [Contents](#contents) - [Concepts](#concepts) - [Lock Path](#lock-path) - [Lock Data](#lock-data) - [Usage](#usage) - [Command-line Interface](#command-line-interface) - [Basic Options](#basic-options) - [Lock Data Options](#lock-data-options) - [Storage Backend Options](#storage-backend-options) - [Admission Controller Options](#admission-controller-options) - [REST API](#rest-api) - [Endpoints](#endpoints) ## Concepts ![readme banner top](docs/banner-top.png) ### Lock Path Briefly describe paths. [More details here.](./docs/concepts.md#deploy-path) ### Lock Data Each lock must contain the following fields: ```typescript interface Lock { type: 'automation' | 'deploy' | 'freeze' | 'incident' | 'maintenance'; path: string; author: string; links: Map; // often duplicates of path, but useful for cross-project locks source: string; // Timestamps, calculated from --duration and --until created_at: number; updated_at: number; expires_at: number; // CI fields, optional ci?: { project: string; ref: string; commit: string; pipeline: string; job: string; } } ``` If `$CI` is not set, the `ci` sub-struct will not be present. ## Usage ### Command-line Interface ```shell > deploy-lock check apps/staging/a/auth-app # is equivalent to > deploy-lock check apps && deploy-lock check apps/staging && deploy-lock check apps/staging/a && deploy-lock check apps/staging/a/auth-app > deploy-lock check apps/staging/a/auth-app --recursive=false # only checks the leaf node > deploy-lock list > deploy-lock list apps/staging # list all locks within the apps/staging path > deploy-lock lock apps/staging --type automation --duration 60m > deploy-lock lock apps/staging/a/auth-app --type deploy --duration 5m > deploy-lock lock apps/staging --until 2022-12-31T12:00 # local TZ, unless Z specified > deploy-lock prune # prune all expired locks > deploy-lock prune apps/staging # prune expired locks within the path > deploy-lock prune apps/staging --now future-date # prune locks that will expire by --now > deploy-lock unlock apps/staging --type automation # unlock type must match lock type ``` #### Basic Options - command - one of `check`, `list`, `lock`, `prune`, `unlock` - `` - positional, required - string - lock path - always lowercase (forced in code) - `/^[-a-z\/]+$/` - `--now` - number, optional - defaults to current epoch time - `--recursive` - boolean - recursively check locks - defaults to true for `check` - defaults to false for `lock`, `unlock` - `--type` - string, enum - type of lock - one of `automation`, `deploy`, `freeze`, `incident`, or `maintenance` #### Lock Data Options - `--allow` - array, strings - check types to allow while this lock is active - this does not allow creating other locks at the same path, it only changes whether the check returns allowed - `--author` - string - defaults to `$GITLAB_USER_EMAIL` if `$GITLAB_CI` is set - defaults to `$USER` otherwise - `--duration` - string - duration of lock, relative to now - may be given in epoch seconds (`\d+`), as an ISO-8601 date, or a human interval (`30m`) - mutually exclusive with `--until` - `--link` - array, strings - `--source` - string - each component: - first - defaults to `$CLUSTER_NAME` if set - defaults to `path.split.0` otherwise - second - defaults to `$DEPLOY_ENV` if set - defaults to `path.split.1` otherwise - third - defaults to `$DEPLOY_TARGET` if set - defaults to `path.split.2` otherwise - fourth - defaults to `--ci-project` if set - defaults to `$CI_PROJECT_PATH` if set - defaults to `path.split.3` otherwise - fifth - defaults to `--ci-ref` if set - defaults to `$CI_COMMIT_REF_SLUG` if set - defaults to `path.split.4` otherwise - `--until` - string, timestamp - duration of lock, absolute - may be given in epoch seconds (`\d+`) or as an ISO-8601 date (intervals are not allowed) - mutually exclusive with `--duration` - `--ci-project` - optional string - project path - defaults to `$CI_PROJECT_PATH` if set - defaults to `path.split.3` otherwise - `--ci-ref` - optional string - branch or tag - defaults to `$CI_COMMIT_REF_SLUG` if set - defaults to `path.split.4` otherwise - `--ci-commit` - optional string - SHA of ref - defaults to `$CI_COMMIT_SHA` if set - `--ci-pipeline` - optional string - pipeline ID - defaults to `$CI_PIPELINE_ID` if set - `--ci-job` - optional string - job ID - defaults to `$CI_JOB_ID` if set #### Storage Backend Options - `--storage` - string - one of `dynamodb`, `memory` - `--region` - string, optional - DynamoDB region name - `--table` - string - DynamoDB table name - `--endpoint` - string, optional - DynamoDB endpoint - set to `http://localhost:8000` for testing with DynamoDB local - `--fake` - string, optional - a fake lock that should be added to the in-memory data store - the in-memory data store always starts empty, this is the only way to have an existing lock #### Admission Controller Options - `--admission-base` - string - base path for admission controller requests - usually the path to the cluster within the deploy path, like `aws/staging/us-east-1/apps/a` - `--admission-path` - array, strings - path keys to use when checking admission controller requests - must be fields within the `AdmissionReview` kind - usually something like `[namespace, name]` or `[namespace, requestResource.group, requestResource.resource, name]` ### REST API #### Endpoints - `/admission POST` - Kubernetes admission controller webhook - `/locks GET` - equivalent to `deploy-lock list` - `/locks POST` - equivalent to `deploy-lock lock` - path taken from request body - `/locks DELETE` - equivalent to `deploy-lock prune` - `/locks/:path GET` - equivalent to `deploy-lock check` - `/locks/:path PUT` - equivalent to `deploy-lock lock` - path taken from URL path - `/locks/:path DELETE` - equivalent to `deploy-lock unlock` - `/ok` - health check ![readme bottom banner](docs/banner-bottom.png)