105 lines
4.6 KiB
Markdown
105 lines
4.6 KiB
Markdown
# Developing
|
|
|
|
## Contents
|
|
|
|
- [Developing](#developing)
|
|
- [Contents](#contents)
|
|
- [Building](#building)
|
|
- [Testing](#testing)
|
|
- [Messaging](#messaging)
|
|
- [Friendly Types](#friendly-types)
|
|
- [TODOs](#todos)
|
|
- [Features](#features)
|
|
- [Questions](#questions)
|
|
|
|
## Building
|
|
|
|
1. Clone with `git clone git@github.com:ssube/deploy-lock.git`
|
|
2. Switch into the project directory with `cd deploy-lock`
|
|
3. Run a full lint, build, and test with `make ci`
|
|
4. Run the program's help with `make run-help` or `node out/src/index.js --help`
|
|
|
|
## Testing
|
|
|
|
You can test locally without a real DDB table using https://hub.docker.com/r/amazon/dynamodb-local.
|
|
|
|
1. Launch DynamoDB Local with `podman run --rm -p 8000:8000 docker.io/amazon/dynamodb-local`
|
|
2. Create a profile with `aws configure --profile localddb`
|
|
1. placeholder tokens
|
|
2. us-east-1 region
|
|
3. json output
|
|
3. Create a `locks` table with `aws dynamodb --endpoint-url http://localhost:8000 --profile localddb create-table --attribute-definitions 'AttributeName=path,AttributeType=S' --table-name locks --key-schema 'AttributeName=path,KeyType=HASH' --billing-mode PAY_PER_REQUEST`
|
|
4. Run commands using `AWS_PROFILE=localddb deploy-lock --storage dynamo --table locks --endpoint http://localhost:8000 ...`
|
|
|
|
## Messaging
|
|
|
|
- create a new lock: `locked ${path} for ${type:friendly} until ${expires_at:datetime}`
|
|
- > Locked `apps/acceptance/a` for a deploy until Sat 31 Dec, 12:00
|
|
- > Locked `gitlab/production` for an incident until Sat 31 Dec, 12:00
|
|
- error, existing lock: `error: ${path} is locked until ${expires_at:datetime} by ${type:friendly} in ${source}`
|
|
- > Error: `apps/acceptance` is locked until Sat 31 Dec, 12:00 by an automation run in `testing/staging`.
|
|
|
|
### Friendly Types
|
|
|
|
Friendly strings for `type`:
|
|
|
|
- `automation`: `An automation run`
|
|
- `deploy`: `A deploy`
|
|
- `freeze`: `A release freeze`
|
|
- `incident`: `An incident`
|
|
- `maintenance`: `A maintenance window`
|
|
|
|
## TODOs
|
|
|
|
### Features
|
|
|
|
1. Infer lock source from arguments/environment, like `CI_` variables
|
|
2. SQL data store, with history (don't need to remove old records)
|
|
3. S3 data store
|
|
4. Kubernetes admission controller with configurable paths
|
|
|
|
Other potential data stores could include: flat file, kubernetes configmap, etcd itself, consul, redis.
|
|
|
|
### Questions
|
|
|
|
1. In the [deploy path](../READMDE.md#deploy-path), should account come before region or region before account?
|
|
1. `aws/us-east-1/staging` vs `aws/staging/us-east-1`
|
|
2. This is purely a recommendation in the docs, `lock.path` and `lock.source` will both be slash-delimited or array
|
|
paths.
|
|
2. Should there be an `update` or `replace` command?
|
|
1. Probably not, at least not without lock history or multi-party locks.
|
|
2. When the data store can keep old locks, `replace` could expire an existing lock and create a new one
|
|
3. With multi-party locks, `update` could update the `expires_at` and add a new author
|
|
3. Should `--recursive` be available for `lock` and `unlock`, or only `check`?
|
|
1. TBD
|
|
2. A recursive `lock` would write multiple records
|
|
3. A recursive `unlock` could delete multiple records
|
|
4. Should locks have multiple authors?
|
|
1. TBD
|
|
2. It doesn't make sense to have more than one active lock for the same path
|
|
1. Or does it?
|
|
2. Different levels can use `--allow` without creating multiple locks
|
|
3. But having multiple authors would allow for multi-party locks
|
|
1. for CI: `[gitlab, $GITLAB_USER_NAME]`
|
|
2. for an incident: `[first-responder, incident-commander]`
|
|
4. Each author has to `unlock` before the lock is removed/released
|
|
5. Should `LockData.env` be a string/array, like `LockData.path`?
|
|
1. Done
|
|
2. Very probably yes, because otherwise it will need `env.cloud`, `env.network`, etc, and those
|
|
are not always predictable/present.
|
|
6. Should there be an `--allow`/`LockData.allow` field?
|
|
1. Probably yes
|
|
2. When running `check --type`, if `LockData.allow` includes `--type`, it will be allowed
|
|
1. `freeze` should allow `automation`, but not `deploy`
|
|
2. `incident` could allow `deploy`, but not `automation`
|
|
7. Wildcards in paths?
|
|
1. Probably no, it will become confusing pretty quickly, and KV stores do not support them consistently (or at all).
|
|
8. Authz for API mutations?
|
|
1. If there is a REST API, it might need authn/authz.
|
|
2. Keeping the API private _could_ work.
|
|
3. Authorization should be scoped by path.
|
|
9. How should the `AdmissionReview` fields be mapped to path?
|
|
1. This could vary by user and may need to be configurable.
|
|
2. Probably using an argument, `--admission-path`
|
|
3. Will eventually need to use jsonpath for access to `userInfo.groups` list or maps
|