Skip to content

Commit

Permalink
Merge pull request #9 from cloudtruth/environments_in_pms
Browse files Browse the repository at this point in the history
Environments in pms
  • Loading branch information
wr0ngway authored Jul 7, 2021
2 parents 37daf2b + f72bbd7 commit 913833a
Show file tree
Hide file tree
Showing 41 changed files with 1,239 additions and 8,251 deletions.
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,4 @@ gem 'clamp'
gem 'graphql-client'
gem 'kubeclient'
gem 'liquid'
gem 'yaml-safe_load_stream'
2 changes: 2 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ GEM
addressable (>= 2.3.6)
crack (>= 0.3.2)
hashdiff (>= 0.4.0, < 2.0.0)
yaml-safe_load_stream (0.1.1)
zeitwerk (2.4.2)

PLATFORMS
Expand All @@ -129,6 +130,7 @@ DEPENDENCIES
simplecov
vcr
webmock
yaml-safe_load_stream

BUNDLED WITH
2.1.4
52 changes: 46 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ you would like to configure with CloudTruth
helm repo add cloudtruth https://packages.cloudtruth.com/charts/
helm install \
--set appSettings.apiKey=<api_key> \
--set appSettings.environment=<environment> \
--set projectMappings.root.environment=<environment> \
kubetruth cloudtruth/kubetruth
```

Expand All @@ -35,14 +35,14 @@ helm repo remove cloudtruth

## Usage

Parameterize the helm install with `--set appSettings.**` to control how kubetruth matches against your organization's naming conventions:
Parameterize the helm install with `--set *` or `--values yourConfig.yaml` to control how kubetruth matches against your organization's naming conventions:

| Parameter | Description | Type | Default | Required |
|-----------|-------------|------|---------|:--------:|
| appSettings.apiKey | The CloudTruth api key. Read only access is sufficient | string | n/a | yes |
| appSettings.environment | The CloudTruth environment to lookup parameter values for. Use a separate helm install for each environment | string | `default` | yes |
| appSettings.pollingInterval | Interval to poll CloudTruth api for changes | integer | 300 | no |
| appSettings.debug | Debug logging and behavior | flag | false | no |
| projectMappings.root.environment | The CloudTruth environment to lookup parameter values for. | string | `default` | yes |
| projectMappings.root.project_selector | A regexp to limit the projects acted against (client-side). Supplies any named matches for template evaluation | string | "" | no |
| projectMappings.root.key_selector | A regexp to limit the keys acted against (client-side). Supplies any named matches for template evaluation | string | "" | no |
| projectMappings.root.skip | Skips the generation of resources for the selected projects | flag | false | no |
Expand Down Expand Up @@ -126,9 +126,10 @@ Kubetruth uses a CustomResourceDefinition called
[ProjectMapping(.kubetruth.cloudtruth.com)](helm/kubetruth/crds/projectmapping.yaml)
for additional configuration. The ProjectMapping CRD has two types identified
by the `scope` property, the `root` scope and the `override` scope. The `root`
scope is required, and there can be only one. It sets up the global behavior
for mapping the CloudTruth projects to kubernetes resources. You can edit it in
the standard ways, e.g. `kubectl edit projectmapping kubetruth-root`. The
scope is required, and there can be only one per namespace (see
[below](#multi-instance-config)). It sets up the global behavior for mapping
the CloudTruth projects to kubernetes resources. You can edit it in the
standard ways, e.g. `kubectl edit projectmapping kubetruth-root`. The
`override` scope allows you to override the root scope's behavior for those
CloudTruth projects whose names match its `project_selector` pattern.

Expand All @@ -148,6 +149,8 @@ liquid variables:
| Liquid Variables | Description |
|-----------------|-------------|
| `template` | The name of the template currently being rendered. |
| `kubetruth_namespace` | The namespace kubetruth is installed in. |
| `mapping_namespace` | The namespace that the current set of mappings exist in. |
| `project` | The project name. |
| `project_heirarchy` | The `included_projects` tree that this project includes. (useful to debug when using complex `included_projects`) |
| `debug` | Indicates if kubetruth is operating in debug (logging) mode. |
Expand Down Expand Up @@ -201,6 +204,23 @@ timeout parameter is getting its value from the `myService` project, and if you
removed it from there, it would then get it from the `commonService` project,
and if you removed that, it would then get it from the `common` project.

### Multi Instance Config

By default, Kubetruth is setup with a single set of ProjectMapping CRDs
installed into the same namespace it was installed to. These are the `primary`
CRDs. For systems that use independent kubernetes clusters per environment,
this is all that you need. If, however, you'd like to be able to run multiple
`environments` in the same cluster, you can make use of the multi-instance
feature of kubetruth.

To do so, one simply needs to create ProjectMapping CRDs in namespaces other
than the primary. These CRDs will automatically inherit the contents of the CRD
of the same name from the primary namespace, and you can then selectively
override the attributes you need to change for the supplemental instance. This
allows you to reuse all the templates/logic/etc that you setup in the primary,
and only have to change the differing dimension. See the `environment` [example
below](#environment-per-namespace)

### Example Config

The `projectmapping` resource has a shortname of `pm` for convenience when using kubectl.
Expand Down Expand Up @@ -269,6 +289,26 @@ spec:
EOF
```

#### Environment per namespace

To setup an environment per namespace:
```
# Disable output from the primary (optional)
kubectl patch pm kubetruth-root --type json --patch '[{"op": "replace", "path": "/spec/skip", "value": "true"}]'
# Tag each namespace that you'd like to have its own environment
kubectl --namespace <your_namespace> apply -f - <<EOF
apiVersion: kubetruth.cloudtruth.com/v1
kind: ProjectMapping
metadata:
name: kubetruth-root
spec:
scope: root
environment: loadtest
skip: false
EOF
```

#### More specific project selection

To limit the Projects processed to those whose names start with `service`, except for `serviceOddball`:
Expand Down
3 changes: 3 additions & 0 deletions helm/helmv2/templates/projectmapping.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ spec:
key_selector:
type: string
description: A regexp to limit the keys acted against
environment:
type: string
description: A environment to use to determine parameter values
skip:
type: boolean
description: Skips the generation of resources for the selected projects. Useful for excluding projects that should only be included into others.
Expand Down
3 changes: 3 additions & 0 deletions helm/kubetruth/crds/projectmapping.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ spec:
key_selector:
type: string
description: A regexp to limit the keys acted against
environment:
type: string
description: A environment to use to determine parameter values
skip:
type: boolean
description: Skips the generation of resources for the selected projects
Expand Down
3 changes: 3 additions & 0 deletions helm/kubetruth/templates/clusterrole.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,7 @@ rules:
- apiGroups: [""]
resources: ["namespaces"]
verbs: ["get", "list", "create"]
- apiGroups: ["kubetruth.cloudtruth.com"]
resources: ["projectmappings"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
{{- end -}}
4 changes: 0 additions & 4 deletions helm/kubetruth/templates/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,6 @@ spec:
name: {{ include "kubetruth.fullname" . }}
args:
- app
{{- if .Values.appSettings.environment }}
- --environment
- {{ .Values.appSettings.environment | quote }}
{{- end }}
{{- if .Values.appSettings.pollingInterval }}
- --polling-interval
- "{{ .Values.appSettings.pollingInterval }}"
Expand Down
4 changes: 2 additions & 2 deletions helm/kubetruth/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@ affinity: {}

appSettings:
apiKey:
environment:
pollingInterval:
debug: false

Expand All @@ -85,13 +84,14 @@ appSettings:
projectMappings:
root:
scope: "root"
environment: "default"
project_selector: ""
key_selector: ""
skip: false
included_projects: []
context:
resource_name: "{{ project | dns_safe }}"
resource_namespace: ""
resource_namespace: "{{ mapping_namespace }}"
skip_secrets: false
resource_templates:
configmap: |
Expand Down
18 changes: 3 additions & 15 deletions lib/kubetruth/cli.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
require_relative 'cli_base'
require_relative 'project'
require_relative 'ctapi'
require_relative 'etl'

module Kubetruth
Expand All @@ -11,14 +11,6 @@ class CLI < CLIBase
values to
EOF

option "--environment",
'ENV', "The cloudtruth environment",
environment_variable: 'CT_ENV',
default: "default"

option "--organization",
'ORG', "The cloudtruth organization"

option "--api-key",
'APIKEY', "The cloudtruth api key",
environment_variable: 'CLOUDTRUTH_API_KEY',
Expand Down Expand Up @@ -46,18 +38,14 @@ class CLI < CLIBase
def execute
super

ct_context = {
organization: organization,
environment: environment,
api_key: api_key
}
kube_context = {
namespace: kube_namespace,
token: kube_token,
api_url: kube_url
}

Project.ctapi_context = ct_context
Kubetruth.ctapi_setup(api_key: api_key)

etl = ETL.new(kube_context: kube_context, dry_run: dry_run?)

Signal.trap("HUP") do
Expand Down
8 changes: 6 additions & 2 deletions lib/kubetruth/config.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@ class DuplicateSelection < Kubetruth::Error; end

ProjectSpec = Struct.new(
:scope,
:name,
:project_selector,
:key_selector,
:environment,
:skip,
:included_projects,
:context,
Expand Down Expand Up @@ -45,8 +47,10 @@ def convert_types(hash)

DEFAULT_SPEC = {
scope: 'override',
name: '',
project_selector: '',
key_selector: '',
environment: 'default',
skip: false,
included_projects: [],
context: {},
Expand Down Expand Up @@ -99,9 +103,9 @@ def spec_for_project(project_name)
logger.debug {"Using root spec for project '#{project_name}'"}
when 1
spec = specs.first
logger.debug {"Using override spec '#{spec.project_selector.source}' for project '#{project_name}'"}
logger.debug {"Using override spec '#{spec.name}:#{spec.project_selector.source}' for project '#{project_name}'"}
else
dupes = specs.collect {|s| "'#{s.project_selector}'" }
dupes = specs.collect {|s| "'#{s.name}:#{s.project_selector.source}'" }
raise DuplicateSelection, "Multiple configuration specs (#{dupes.inspect}) match the project '#{project_name}': }"
end

Expand Down
Loading

0 comments on commit 913833a

Please sign in to comment.