tpt-rails 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +127 -0
  3. data/Rakefile +32 -0
  4. data/app/assets/config/tpt_rails_manifest.js +1 -0
  5. data/app/assets/stylesheets/tpt/rails/application.css +15 -0
  6. data/app/controllers/tpt/rails/application_controller.rb +5 -0
  7. data/app/controllers/tpt/rails/error_tests_controller.rb +21 -0
  8. data/app/controllers/tpt/rails/health_checks_controller.rb +18 -0
  9. data/app/helpers/tpt/rails/application_helper.rb +4 -0
  10. data/app/jobs/tpt/rails/application_job.rb +4 -0
  11. data/app/mailers/tpt/rails/application_mailer.rb +6 -0
  12. data/app/models/tpt/rails/application_record.rb +5 -0
  13. data/app/views/layouts/tpt/rails/application.html.erb +15 -0
  14. data/config/routes.rb +6 -0
  15. data/lib/generators/tpt_rails/configuration/configuration_generator.rb +10 -0
  16. data/lib/generators/tpt_rails/configuration/templates/config/initializers/tpt_rails.rb +10 -0
  17. data/lib/generators/tpt_rails/continuous_integration/continuous_integration_generator.rb +17 -0
  18. data/lib/generators/tpt_rails/continuous_integration/templates/ci/Dockerfile.tt +31 -0
  19. data/lib/generators/tpt_rails/continuous_integration/templates/ci/docker-compose.yaml.tt +26 -0
  20. data/lib/generators/tpt_rails/continuous_integration/templates/ci/tasks/project.test.unit +12 -0
  21. data/lib/generators/tpt_rails/continuous_integration/templates/ci/test.Jenkinsfile.tt +40 -0
  22. data/lib/generators/tpt_rails/continuous_integration/templates/ci/test.config.xml.tt +76 -0
  23. data/lib/generators/tpt_rails/continuous_integration/templates/ci/tptcd.Jenkinsfile.tt +7 -0
  24. data/lib/generators/tpt_rails/continuous_integration/templates/ci/tptci.Jenkinsfile.tt +7 -0
  25. data/lib/generators/tpt_rails/kubernetes/kubernetes_generator.rb +156 -0
  26. data/lib/generators/tpt_rails/kubernetes/templates/Dockerfile.tt +41 -0
  27. data/lib/generators/tpt_rails/kubernetes/templates/entrypoint.sh +13 -0
  28. data/lib/generators/tpt_rails/kubernetes/templates/kubernetes/helm/Chart.yaml.tt +16 -0
  29. data/lib/generators/tpt_rails/kubernetes/templates/kubernetes/helm/README.md +142 -0
  30. data/lib/generators/tpt_rails/kubernetes/templates/kubernetes/helm/requirements.yaml.tt +8 -0
  31. data/lib/generators/tpt_rails/kubernetes/templates/kubernetes/helm/templates/NOTES.txt.tt +8 -0
  32. data/lib/generators/tpt_rails/kubernetes/templates/kubernetes/helm/templates/_env.yaml +15 -0
  33. data/lib/generators/tpt_rails/kubernetes/templates/kubernetes/helm/templates/_helpers.tpl.tt +63 -0
  34. data/lib/generators/tpt_rails/kubernetes/templates/kubernetes/helm/templates/autoscaler.yaml.tt +21 -0
  35. data/lib/generators/tpt_rails/kubernetes/templates/kubernetes/helm/templates/deployment.yaml.tt +96 -0
  36. data/lib/generators/tpt_rails/kubernetes/templates/kubernetes/helm/templates/hooks/db-migrate.yaml.tt +59 -0
  37. data/lib/generators/tpt_rails/kubernetes/templates/kubernetes/helm/templates/service.yaml.tt +52 -0
  38. data/lib/generators/tpt_rails/kubernetes/templates/kubernetes/helm/values.prod.yaml.tt +52 -0
  39. data/lib/generators/tpt_rails/kubernetes/templates/kubernetes/helm/values.staging.yaml.tt +52 -0
  40. data/lib/generators/tpt_rails/kubernetes/templates/kubernetes/helm/values.yaml.tt +171 -0
  41. data/lib/generators/tpt_rails/postman/postman.yaml.tt +2 -0
  42. data/lib/tasks/tpt/rails_tasks.rake +23 -0
  43. data/lib/tpt/rails.rb +65 -0
  44. data/lib/tpt/rails/config.rb +77 -0
  45. data/lib/tpt/rails/engine.rb +7 -0
  46. data/lib/tpt/rails/internal.rb +3 -0
  47. data/lib/tpt/rails/internal/datadog.rb +66 -0
  48. data/lib/tpt/rails/internal/error_reporter.rb +68 -0
  49. data/lib/tpt/rails/internal/health_checks.rb +32 -0
  50. data/lib/tpt/rails/version.rb +5 -0
  51. metadata +153 -0
@@ -0,0 +1,76 @@
1
+ <?xml version='1.1' encoding='UTF-8'?><org.jenkinsci.plugins.workflow.multibranch.WorkflowMultiBranchProject plugin="workflow-multibranch@2.21">
2
+ <actions/>
3
+ <description></description>
4
+ <displayName><%= Tpt::Rails.app_name %>-test</displayName>
5
+ <properties>
6
+ <org.jenkinsci.plugins.workflow.libs.FolderLibraries plugin="workflow-cps-global-lib@2.13">
7
+ <libraries>
8
+ <org.jenkinsci.plugins.workflow.libs.LibraryConfiguration>
9
+ <name>jenkins-pipeline-library</name>
10
+ <retriever class="org.jenkinsci.plugins.workflow.libs.SCMSourceRetriever">
11
+ <scm class="jenkins.plugins.git.GitSCMSource" plugin="git@3.9.3">
12
+ <id>31643265-3634-6665-6262-343134326436</id>
13
+ <remote>git@github.com:TeachersPayTeachers/jenkins-pipeline-library.git</remote>
14
+ <credentialsId>jenkins-master-rsa-key</credentialsId>
15
+ <traits>
16
+ <jenkins.plugins.git.traits.BranchDiscoveryTrait/>
17
+ </traits>
18
+ </scm>
19
+ </retriever>
20
+ <implicit>false</implicit>
21
+ <allowVersionOverride>true</allowVersionOverride>
22
+ <includeInChangesets>true</includeInChangesets>
23
+ </org.jenkinsci.plugins.workflow.libs.LibraryConfiguration>
24
+ </libraries>
25
+ </org.jenkinsci.plugins.workflow.libs.FolderLibraries>
26
+ <org.jenkinsci.plugins.pipeline.modeldefinition.config.FolderConfig plugin="pipeline-model-definition@1.3.7">
27
+ <dockerLabel/>
28
+ <registry plugin="docker-commons@1.14"/>
29
+ </org.jenkinsci.plugins.pipeline.modeldefinition.config.FolderConfig>
30
+ </properties>
31
+ <folderViews class="jenkins.branch.MultiBranchProjectViewHolder" plugin="branch-api@2.4.0">
32
+ <owner class="org.jenkinsci.plugins.workflow.multibranch.WorkflowMultiBranchProject" reference="../.."/>
33
+ </folderViews>
34
+ <healthMetrics>
35
+ <com.cloudbees.hudson.plugins.folder.health.WorstChildHealthMetric plugin="cloudbees-folder@6.8">
36
+ <nonRecursive>false</nonRecursive>
37
+ </com.cloudbees.hudson.plugins.folder.health.WorstChildHealthMetric>
38
+ <jenkins.branch.PrimaryBranchHealthMetric plugin="branch-api@2.4.0"/>
39
+ </healthMetrics>
40
+ <icon class="jenkins.branch.MetadataActionFolderIcon" plugin="branch-api@2.4.0">
41
+ <owner class="org.jenkinsci.plugins.workflow.multibranch.WorkflowMultiBranchProject" reference="../.."/>
42
+ </icon>
43
+ <orphanedItemStrategy class="com.cloudbees.hudson.plugins.folder.computed.DefaultOrphanedItemStrategy" plugin="cloudbees-folder@6.8">
44
+ <pruneDeadBranches>true</pruneDeadBranches>
45
+ <daysToKeep>-1</daysToKeep>
46
+ <numToKeep>5</numToKeep>
47
+ </orphanedItemStrategy>
48
+ <triggers/>
49
+ <disabled>false</disabled>
50
+ <sources class="jenkins.branch.MultiBranchProject$BranchSourceList" plugin="branch-api@2.4.0">
51
+ <data>
52
+ <jenkins.branch.BranchSource>
53
+ <source class="org.jenkinsci.plugins.github_branch_source.GitHubSCMSource" plugin="github-branch-source@2.4.5">
54
+ <id>65633436-6138-6163-6638-323663356636</id>
55
+ <credentialsId>tpt-github-source-credential</credentialsId>
56
+ <repoOwner>TeachersPayTeachers</repoOwner>
57
+ <repository><%= Tpt::Rails.app_name %></repository>
58
+ <traits>
59
+ <org.jenkinsci.plugins.github__branch__source.BranchDiscoveryTrait>
60
+ <strategyId>3</strategyId>
61
+ </org.jenkinsci.plugins.github__branch__source.BranchDiscoveryTrait>
62
+ <org.jenkinsci.plugins.github__branch__source.TagDiscoveryTrait/>
63
+ </traits>
64
+ </source>
65
+ <strategy class="jenkins.branch.DefaultBranchPropertyStrategy">
66
+ <properties class="empty-list"/>
67
+ </strategy>
68
+ </jenkins.branch.BranchSource>
69
+ </data>
70
+ <owner class="org.jenkinsci.plugins.workflow.multibranch.WorkflowMultiBranchProject" reference="../.."/>
71
+ </sources>
72
+ <factory class="org.jenkinsci.plugins.workflow.multibranch.WorkflowBranchProjectFactory">
73
+ <owner class="org.jenkinsci.plugins.workflow.multibranch.WorkflowMultiBranchProject" reference="../.."/>
74
+ <scriptPath>ci/test.Jenkinsfile</scriptPath>
75
+ </factory>
76
+ </org.jenkinsci.plugins.workflow.multibranch.WorkflowMultiBranchProject>
@@ -0,0 +1,7 @@
1
+ @Library('tpt-pipeline-library') _
2
+
3
+ def ci = new tpt.CI(this)
4
+ ci.project = '<%= Tpt::Rails.app_name %>'
5
+ ci.buildCredentials = [[ id: '<%= Tpt::Rails.app_name %>-rails-master-key', var: '<%= Tpt::Rails.app_name.underscore.upcase %>_RAILS_MASTER_KEY' ]]
6
+
7
+ tptcdPipeline(ci: ci)
@@ -0,0 +1,7 @@
1
+ @Library('tpt-pipeline-library') _
2
+
3
+ def ci = new tpt.CI(this)
4
+ ci.project = '<%= Tpt::Rails.app_name %>'
5
+ ci.buildCredentials = [[ id: '<%= Tpt::Rails.app_name %>-rails-master-key', var: '<%= Tpt::Rails.app_name.underscore.upcase %>_RAILS_MASTER_KEY' ]]
6
+
7
+ tptciPipeline(ci: ci, ode: '') // we don't need an ode, just test this service
@@ -0,0 +1,156 @@
1
+ class Tpt::Rails::KubernetesGenerator < ::Rails::Generators::Base
2
+ VALID_APP_NAME = /^([a-z0-9]-?)+[a-z0-9]$/
3
+ ODE_KUBE_CONTEXT = 'kubernetes-eks-poc'
4
+
5
+ desc 'Set up the app with kubernetes'
6
+
7
+ source_root File.expand_path('templates', __dir__)
8
+
9
+ def setup_kubernetes
10
+ if !valid_app_name?
11
+ say("ERROR: App name #{Tpt::Rails.app_name.inspect} will not be valid for DNS usage.")
12
+ abort
13
+ end
14
+
15
+ check_dependencies
16
+
17
+ secrets_name = "#{Tpt::Rails.app_name}-secrets"
18
+
19
+ tpt_yaml = generate_tpt_yaml
20
+ team_name = tpt_yaml.fetch('owner')
21
+ app_type = tpt_yaml.fetch('target')
22
+
23
+ tpt_config = get_tpt_config
24
+ tpt_user_alias = tpt_config.fetch('user.alias')
25
+
26
+ default_email = get_default_email_address
27
+ email = ask("What's the maintainer email address? (#{default_email})").strip
28
+ email = email.presence || default_email || 'FIXME'
29
+
30
+ template 'Dockerfile'
31
+ template 'entrypoint.sh'
32
+ template '.dockerignore'
33
+
34
+ directory(
35
+ 'kubernetes',
36
+ team_name: team_name,
37
+ secrets_name: secrets_name,
38
+ maintainer_email: email,
39
+ app_type: app_type,
40
+ )
41
+
42
+ inside('kubernetes/helm') do
43
+ run('helm dependency update', abort_on_failure: true)
44
+ end
45
+
46
+ add_kube_secret(secrets_name)
47
+
48
+ say(<<~MESSAGE)
49
+
50
+ ********************************************************************************
51
+ * Success! Your project has been configured for Kubernetes!
52
+ ********************************************************************************
53
+
54
+ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
55
+ ! Follow-up actions required:
56
+ !
57
+ ! 1. Review and commit these changes
58
+ ! 2. Push your changes up to a Github repository
59
+ ! 3. Run `tpt project check`
60
+ ! 4. Deploy to an ODE with `tpt project push`
61
+ ! 5. Give "Read-only" access to the Docker Hub "readonly" user:
62
+ ! - Go to https://hub.docker.com/repository/docker/teacherspayteachers/#{Tpt::Rails.app_name}/permissions
63
+ ! - Choose "readonly" in the "Team" dropdown box
64
+ ! - Choose "Read-only" in the "Permission" box
65
+ ! - Click the "+" button on the right-hand side
66
+ ! 6. Monitor the status of your ODE deploy with:
67
+ ! kubectl get pods --namespace #{tpt_user_alias} | grep #{Tpt::Rails.app_name}
68
+ ! 7. When your ODE is ready you can visit it here:
69
+ ! http://#{Tpt::Rails.app_name}--#{tpt_user_alias}.ode.tptpm.info/#{Tpt::Rails::Engine.instance.routes.url_helpers.health_check_path}
70
+ !
71
+ ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
72
+
73
+ MESSAGE
74
+ end
75
+
76
+ private
77
+
78
+ def check_dependencies
79
+ say('Checking dependencies…')
80
+ check_dependency('config/master.key', 'test -f config/master.key')
81
+ check_dependency('jq', 'which jq')
82
+ check_dependency('tpt network', 'nc -G1 -w1 chartmuseum.tptpm.info 443')
83
+ check_dependency('tpt-cli', 'tpt version')
84
+ check_dependency('tpt config', 'tpt config get') # fails if tpt config has not been initialized
85
+ check_dependency('docker', 'docker version') # fails if docker isn't running
86
+ check_dependency('kubectl', 'kubectl version') # fails if kubectl isn't set up
87
+ check_dependency('kubeval', 'which kubeval') # needed for `tpt project push`. See https://kubeval.instrumenta.dev/installation/
88
+ check_dependency('helm', 'helm search justtesting') # fails if helm isn't installed + initialized (~/.helm directory created)
89
+ check_dependency('helm tpt repo', "helm repo list | egrep '^tpt '") # fails if tpt helm repo isn't added
90
+ end
91
+
92
+ def check_dependency(name, command)
93
+ say("Checking for dependency: #{name}")
94
+ run(command, abort_on_failure: true, capture: true) # capture: true makes the output nicer
95
+ rescue Exception => e
96
+ say "Error! #{name} does not seem to be available. `#{command}` returned: #{e.inspect}"
97
+ abort
98
+ end
99
+
100
+ # Dasherize the app name for kube usage, and verify that it will be valid for DNS usage.
101
+ # Note: Rails itself also verifies that the name does not start with a number so that it is a valid
102
+ # Ruby identifier.
103
+ def valid_app_name?
104
+ Tpt::Rails.app_name =~ VALID_APP_NAME
105
+ end
106
+
107
+ def generate_tpt_yaml
108
+ # TODO: Add an options to `tpt project init` that allows passing in these values
109
+ say(<<~TEXT)
110
+
111
+ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
112
+ ! IMPORTANT !
113
+ ! In the prompt below, please enter "#{Tpt::Rails.app_name}" for the "project name"
114
+ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
115
+
116
+ TEXT
117
+
118
+ run('tpt project init --force', abort_on_failure: true)
119
+
120
+ YAML.load(run('cat tpt.yaml', capture: true, abort_on_failure: true))
121
+ end
122
+
123
+ def get_tpt_config
124
+ conf = run('tpt config get', capture: true, abort_on_failure: true)
125
+ YAML.load(conf)
126
+ end
127
+
128
+ def get_default_email_address
129
+ run('git config user.email', capture: true, abort_on_failure: false)&.strip.presence
130
+ end
131
+
132
+ def add_kube_secret(secrets_name)
133
+ secret = run('cat config/master.key', capture: true, abort_on_failure: true).strip
134
+ key_exists = run("kubectl get secret #{secrets_name} --context='#{ODE_KUBE_CONTEXT}' >/dev/null 2>&1", abort_on_failure: false)
135
+
136
+ if key_exists
137
+ say "Kube secret #{secrets_name} already exists. Updating it…"
138
+ ENV['KUBE_GENERATOR_RAILS_MASTER_KEY'] = Base64.strict_encode64(secret)
139
+ run(
140
+ <<~CMD,
141
+ kubectl get secret #{secrets_name} --context=#{ODE_KUBE_CONTEXT} --output=json \
142
+ | jq --arg key $KUBE_GENERATOR_RAILS_MASTER_KEY '.data["rails-master-key"]=$key' \
143
+ | kubectl apply --context=#{ODE_KUBE_CONTEXT} -f -
144
+ CMD
145
+ abort_on_failure: true,
146
+ )
147
+ else
148
+ say "Kube secret #{secrets_name} not found. Creating it…"
149
+ run(
150
+ "kubectl create secret generic #{secrets_name} --from-literal='rails-master-key=#{secret}' --context='#{ODE_KUBE_CONTEXT}'",
151
+ abort_on_failure: true,
152
+ )
153
+ end
154
+ end
155
+
156
+ end
@@ -0,0 +1,41 @@
1
+ FROM ruby:<%= RUBY_VERSION %>
2
+
3
+ RUN mkdir /app
4
+ WORKDIR /app
5
+
6
+ RUN curl -sL https://deb.nodesource.com/setup_12.x | bash \
7
+ && apt-get update && apt-get install -y nodejs && rm -rf /var/lib/apt/lists/* \
8
+ && curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - \
9
+ && echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list \
10
+ && apt-get update && apt-get install -y yarn && rm -rf /var/lib/apt/lists/*
11
+
12
+ COPY package.json yarn.lock /app/
13
+ RUN yarn install --check-files
14
+
15
+ # Set production env for asset compilation
16
+ ARG RAILS_ENV=production
17
+ ARG APP_ENV=production
18
+ ARG APP_NAME=<%= Tpt::Rails.app_name %>
19
+
20
+ ARG <%= Tpt::Rails.app_name.underscore.upcase %>_RAILS_MASTER_KEY
21
+ # GITHUB_TOKEN allows accessing our private tpt-rails gem on Github
22
+ ARG GITHUB_TOKEN
23
+
24
+ COPY Gemfile /app/Gemfile
25
+ COPY Gemfile.lock /app/Gemfile.lock
26
+ RUN gem update bundler
27
+ RUN BUNDLE_GITHUB__COM="${GITHUB_TOKEN}:x-oauth-basic" bundle install --without development test
28
+
29
+ # Add a script to be executed every time the container starts.
30
+ COPY entrypoint.sh /usr/bin/
31
+ RUN chmod +x /usr/bin/entrypoint.sh
32
+
33
+ ADD . /app
34
+
35
+ RUN RAILS_MASTER_KEY=${<%= Tpt::Rails.app_name.underscore.upcase %>_RAILS_MASTER_KEY} bin/rails assets:precompile
36
+
37
+ EXPOSE 3000
38
+
39
+ # TODO: Delete this?
40
+ ENTRYPOINT ["entrypoint.sh"]
41
+ CMD ["rails", "server", "-b", "0.0.0.0"]
@@ -0,0 +1,13 @@
1
+ #!/bin/bash
2
+ set -e
3
+
4
+ if [ -f /app/tmp/pids/server.pid ]; then
5
+ rm /app/tmp/pids/server.pid
6
+ fi
7
+
8
+ echo "Preparing database"
9
+ # In Kubernetes this should always be a no-op because our migration hook will already have run.
10
+ rails db:prepare
11
+
12
+ echo "Starting server"
13
+ exec "$@"
@@ -0,0 +1,16 @@
1
+ # This is the entrypoint to the Helm Chart
2
+ # Most properties here are pretty self explanatory
3
+
4
+ name: <%= Tpt::Rails.app_name %>
5
+ # Chart version - increase this whenever you change anything in the helm/ folder. tpt-cli will warn
6
+ # you if you don't.
7
+ version: 0.0.1
8
+ # Application version - can be useful if we run multiple versions of the app at the same time.
9
+ appVersion: 0.0.1
10
+ description: <%= Tpt::Rails.app_name %> service
11
+ keywords: [odev2, rails, service-template, '<%= Tpt::Rails.app_name %>', '<%= config.fetch(:app_type) %>']
12
+ home: https://www.teacherspayteachers.com
13
+ icon: https://static1.teacherspayteachers.com/tpt-frontend/releases/production/current/a24f03b12028dbc93cf182318e6993e5.svg
14
+ sources: ['https://github.com/TeachersPayTeachers/<%= Tpt::Rails.app_name %>']
15
+ maintainers: [{name: '<%= config.fetch(:team_name) %>', email: '<%= config.fetch(:maintainer_email) %>'}]
16
+ engine: gotpl # yaml parsing engine, just leave this alone
@@ -0,0 +1,142 @@
1
+ # Example Helm Chart
2
+
3
+ This is an example [Helm Chart](https://helm.sh/docs/developing_charts/).
4
+ Helm sits a layer above Kubernetes, and provides a simpler interface for defining Kubernetes entities across environments. It also provides a mechanism for declaring dependencies between Kubernetes services, although we're not currently using that feature. You can think of Helm as a package manager and deployment tool for Kubernetes entities.
5
+
6
+ Currently, we use Helm to manage deployments and updates to our On Demand Environments (ODEs). Production deploys use Kubernetes directly, except for graphapi which is also using Helm.
7
+
8
+ If you'd like your service to deploy to an ODE (you should!), you'll need to build a Chart for it and reference that chart from our [Charts repo](https://github.com/TeachersPayTeachers/charts). See [this branch](https://github.com/TeachersPayTeachers/charts/compare/adding-service-example) for a reference on how to do this.
9
+
10
+ ## General Chart Overview
11
+
12
+ There are a couple files that constitute a Chart. Here is an overview:
13
+
14
+ ```
15
+ (Project Root)
16
+ └── kubernetes
17
+ └── helm
18
+ ├── charts
19
+ │ ├── copy-secrets-1.1.5.tgz
20
+ ├── templates
21
+ │ ├── _helpers.tpl
22
+ │ ├── autoscaler.yaml
23
+ │ ├── deployment.yaml
24
+ │ ├── NOTES.txt
25
+ │ └── service.yaml
26
+ ├── .helmignore
27
+ ├── Chart.yaml
28
+ ├── README.md
29
+ ├── requirements.lock
30
+ ├── requirements.yaml
31
+ ├── values.dev.yaml
32
+ ├── values.staging.yaml
33
+ └── values.yaml
34
+ ```
35
+
36
+ ### Chart.yaml
37
+
38
+ This is Helm's entrypoint to the Chart. Here the high level metadata is specified, including the Chart name and description.
39
+
40
+ ### values.yaml
41
+
42
+ Here you can configure any variables that your Chart will depend on. This includes properties like application secrets, and endpoint configuration of service dependencies. These variables can then be referenced in the Chart definition, to construct your Kubernetes entity.
43
+
44
+ Usually, you want different configurations for different deployment environments. We use `values.yaml` to configure a standard production deployment, and then use `values.{env}.yaml` to override values where a given environment differs from production. In this service, we have created `values.dev.yaml` for configuring ODE deployments and `values.staging.yaml` to configure deployments to staging.
45
+
46
+ ### Secrets
47
+
48
+ See [this wiki page](https://teacherspayteachers.atlassian.net/wiki/spaces/ENGINEERING/pages/64946180/Using+Secrets+in+Kubernetes) for information on how to define a secret in Kubernetes. After adding the secret to the cluster, you can reference it in a `values` file which will cause it to be passed to your application as an environmental variable:
49
+
50
+ ```yaml
51
+ secrets:
52
+ - name: BUGSNAG_API_KEY
53
+ valueFrom:
54
+ secretKeyRef:
55
+ name: service-template-node-bugsnag
56
+ key: apiKey
57
+ ```
58
+
59
+ If you wish to use a secret in ODEs environnments as well, will need to use the `copy-secrets` dependency chart so that the secrets are copied from the default namespace when a user spins up an ODE. See the [documentation for the chart](https://github.com/TeachersPayTeachers/charts/tree/master/copy-secrets) for more information. A service which needed a secret called `super-secret` when running in ODEs would have something like this in its `values.dev.yaml` file:
60
+
61
+ ```yaml
62
+ secrets:
63
+ - name: SUPER_SECRET
64
+ valueFrom:
65
+ secretKeyRef:
66
+ name: super-secret
67
+ key: key
68
+
69
+ copy-secrets:
70
+ secrets:
71
+ - super-secret
72
+ ```
73
+
74
+ ### /templates
75
+
76
+ Helm will process all files in this directory, and combine them into a Kubernetes entity definition. These files might look like the Kube deployment specifications you're used to (e.g. for [tpt-frontend](https://github.com/TeachersPayTeachers/tpt-frontend/blob/master/kubernetes/deployment.production.yaml)), with one major difference: they can reference variables. These variables can come from a couple places, described in more detail below.
77
+
78
+ ### requirements.yaml
79
+
80
+ This optional file lists dependencies for your chart. After adding or changing an entry in this file, you can download all dependencies into the `charts` folder and update `requirements.lock` with the command `helm dependency update`. Right now, the only dependency included is the `copy-secrets` chart mentioned above.
81
+
82
+ ## Template file syntax
83
+
84
+ The meat of the Helm Chart is the `/templates` directory, which contains all the resources needed for Helm to construct and deploy a Kubernetes resource. These files mostly look like Kubernetes entity definitions, but with reference to variables. You can find documentation on what's available [here](https://helm.sh/docs/chart_template_guide/#built-in-objects), but below are couple common patterns you'll see.
85
+
86
+ ### myProperty: {{ .Values.foo.bar }}
87
+
88
+ Inserts `someValue` as the value of myProperty, where `someValue` was defined in your `values.yaml` file:
89
+
90
+ ```yaml
91
+ foo:
92
+ bar: someValue
93
+ ```
94
+
95
+ ### myProperty: {{ template "foo.bar" }}
96
+
97
+ References a property that was specified by `_helpers.tpl`
98
+
99
+ ```
100
+ {{- define "foo.bar" -}}
101
+ {{- if .Values.fullnameOverride -}}
102
+ {{- .Values.fullnameOverride -}}
103
+ {{- else -}}
104
+ {{- .Values.nameOverride -}}
105
+ {{- end -}}
106
+ {{- end -}}
107
+ ```
108
+
109
+ This is a good way of bringing in variables that need a bit of processing to transform them from raw `values.yaml` properties.
110
+
111
+ ### myProperty: "{{ .Release.Name }}"
112
+
113
+ References Helm defined variables
114
+
115
+ ## Testing Your Helm Charts
116
+
117
+ If this prints the contents of your helm charts without erroring, there are no syntax errors.
118
+
119
+ `helm install --dry-run --debug </path/to/helm/chart/dir>`
120
+
121
+ The TpT-CLI tool should be used to ensure your service will work with TpT ODEs v2.
122
+
123
+ [TpT-CLI Github Repo](https://github.com/TeachersPayTeachers/tpt-cli)
124
+
125
+ [ODE v2 Reference](https://teacherspayteachers.atlassian.net/wiki/spaces/ODE/pages/586678286/IN+PROGRESS+Getting+Started+with+ODE+Evolution+v+2.0+-+TpT-CLI)
126
+
127
+ ## Testing Your Service
128
+ ### Contract and API Functional Testing (IN PROGRESS)
129
+ Helm test charts can be used to test your service in isolation. If you have tests defined in Postman (SUPPORTED) or your service repo (IN PROGRESS), you can execute them using the TpT-CLI test command (IN PROGRESS).
130
+
131
+ **_Do not use `helm test` directly to run tests. This requires some extra coordination to not leave test pods running and still have access to test results. TpT-CLI will be updated with a tet command to handle this orchestration._**
132
+
133
+ #### Usage
134
+ 1) Create a helm test chart under [templates/tests](templates/tests). See [test.apiFunctional.postman.yaml](templates/tests/test.apiFunctional.postman.yaml)
135
+ 2) Add any test configuration to the appropriate values.yaml.
136
+ 3) Verify your changes using `tpt project check`.
137
+ 4) Commit your changes.
138
+ 5) Release your charts using `tpt project push`.
139
+ 6) (IN PROGRESS) Execute the tests via the TPT-CLI test command.
140
+
141
+ ### Example Postman Tests
142
+ https://tptapis.postman.co/collections/5817358-93d711ed-3181-480d-bba5-ab68b0a29eae?version=latest&workspace=d9a6b5ae-1a22-4d0b-b706-2cc818031f79