Main idea was to add secrets vault. However, ended up with quite a bit of refactoring and changes

This commit is contained in:
Alan Bridgeman 2025-02-12 13:04:52 -06:00
parent b7f67bec68
commit bb94a44877
9 changed files with 946 additions and 185 deletions

157
README.md
View file

@ -39,4 +39,161 @@ cp ./input.example.json <Folder for Helm Chart>/input.json
Then in the directory you want Then in the directory you want
```sh ```sh
create-helm-chart create-helm-chart
```
## Inputs File (`input.json`)
The most basic version is below. Note values between `<>` should be replaced with appropriate values.
```json
{
"chart": {
"apiVersion": "v1",
"appVersion": "1.0.0",
"description": "A Helm chart for deploying <service name>.",
"homepage": "<Helm Chart Homepage>",
"maintainers": [
{
"name": "<Author Name>",
"email": "<Author Email>"
}
],
"name": "<Helm Chart Name>",
"sources": [
"<Helm Chart Source>"
],
"version": "1.0.0"
},
"image": {
"repository": "<Registry URL (if applicable)>/<Image Name>",
"pullPolicy": "IfNotPresent"
},
"ingress": {
"hostname": "<DNS Name Where The App Will Be Hosted>"
}
}
```
### Database (Postgres)
To add a Postgres database include the following in the `inputs.json` file and fill out the values.
```json
{
"db": {
"name": "<Database Name>",
"host": "<Database Host>",
"user": "<Database User>",
"password": "<Database Password>"
}
}
```
### Secrets Vault (Hashicorp Vault)
To add a Hashicorp secrets vault include the following in the `inputs.json` file and fill out the values
```json
{
"vault": {
"image": {
"repository": "<Vault Image Repository>",
"tag": "<Vault Image Tag>"
},
"hostname": "<DNS Name where the vault will be hosted>",
"storageClass": "<Storage Class Name>"
}
}
```
### NoSQL Storage (Mongo)
To add a Mongo instance include the following in the `inputs.json` file and fill out the values.
```json
{
"nosql": {
"dbName": "<NoSQL Database Name>",
"user": "<NoSQL Database User>",
"password": "<NoSQL Database Password>",
"tables": {
"<Table Environment Variable Name>": {
"name": "<Table Intermediate Name (used in Helm template files)>",
"value": "<Actual Table Name>"
}
}
}
}
```
### Cache Database (Redis)
To add a Redis instance include the following in the `inputs.json` file and fill out the values.
```json
{
"cache": {
"password": "<Cache Password>"
}
}
```
### OAuth
To add the OAuth variables include the following in the `inputs.json` file and fill out the values.
```json
{
"oauth": {
"baseAppUrl": "<Base URL of the App>",
"appAbbreviation": "<App Abbreviation>",
"appName": "<App Name>",
"serviceName": "<Service Name>",
"devPort": "<Dev Port>"
}
}
```
### Third Party Services
```json
{
"thirdPartyServices": {
"openai": {
"apiKey": "<OpenAI API Key>"
},
"stripe": {
"publicKey": "<Stripe Public Key>",
"secretKey": "<Stripe Secret Key>",
"testPublicKey": "<Stripe Test Public Key>",
"testSecretKey": "<Stripe Test Secret Key>"
}
}
}
```
### Extra/Other Environment Variables
```json
{
"extraEnvVars": {
"<Sensitive Environment Variable Name>": {
"type": "Secret",
"name": "{{ .Release.Name }}-<Sensitive Value Name (ex. private-token, etc...)>",
"key": "<Key Used Within The Secret (ex. token, etc...)>",
"description": "<Description Of The Environment Variable>",
"value": "<Value for the Environment Variable>"
},
"<Configurable Environment Variable Name>": {
"type": "ConfigMap",
"name": "{{ .Release.Name }}-<Configurable Value Name (ex. external-service-host, etc...)>",
"key": "<Key Used Within The ConfigMap (ex. extern-host, etc...)>",
"description": "<Description Of The Environment Variable>",
"value": "<Value for the Environment Variable>"
},
"<Environment Variable Name>": "'<Quoted Value>'"
}
}
```
### Helm Resitry (for pushing)
```json
{
"registry": "<Helm Registry URL to publish to (if applicable)>"
}
``` ```

View file

@ -3,6 +3,7 @@ import json
from src.Ingress import Ingress from src.Ingress import Ingress
from src.Service import Service from src.Service import Service
from src.Database import Database from src.Database import Database
from src.HashicorpVault import HashicorpVault
from src.MongoDB import MongoDB from src.MongoDB import MongoDB
from src.Redis import Redis from src.Redis import Redis
from src.OAuth import OAuth from src.OAuth import OAuth
@ -36,45 +37,111 @@ if __name__ == '__main__':
hostname = data['ingress']['hostname'] hostname = data['ingress']['hostname']
db_name = data['db']['name']
db_host = data['db']['host']
db_user = data['db']['user']
db_password = data['db']['password']
nosql_db_name = data['nosql']['dbName']
nosql_user = data['nosql']['user']
nosql_password = data['nosql']['password']
tables = data['nosql']['tables']
cache_password = data['cache']['password']
base_app_url = data['oauth']['baseAppUrl']
app_abbreviation = data['oauth']['appAbbreviation']
app_name = data['oauth']['appName']
service_name = data['oauth']['serviceName']
dev_port = data['oauth']['devPort']
client_id = data['oauth']['clientId']
client_secret = data['oauth']['clientSecret']
extra_env_vars = data['extraEnvVars']
for key, value in extra_env_vars.items():
if not isinstance(value, dict) and value.find("'") != -1:
extra_env_vars[key] = value.replace("'", '"')
openai_api_key = data['thirdPartyServices']['openai']['apiKey']
helm_registry = data['registry']
ingress = Ingress(hostname) ingress = Ingress(hostname)
service = Service() service = Service()
db = Database(db_name, db_host, db_user, db_password)
mongo = MongoDB(nosql_db_name, nosql_user, nosql_password, tables) templates = [ingress, service]
redis = Redis(cache_password)
oauth = OAuth(base_app_url, app_abbreviation, app_name, service_name, dev_port, client_id, client_secret) uses_db = False
openai = ThirdPartyService('openai', True, api_key=openai_api_key) uses_secrets_vault = False
deployment = Deployment(image_repository, image_pull_policy=image_pull_policy, uses_db=True, nosql=mongo, uses_cache=True, third_party_services=[openai], **extra_env_vars) nosql = None
templates = [ingress, service, db, mongo, redis, oauth, deployment, openai] uses_cache = False
third_party_services = []
extra_env_vars = {}
if 'db' in data and data['db'] != False:
db_name = data['db']['name']
db_host = data['db']['host']
db_user = data['db']['user']
db_password = data['db']['password']
db = Database(db_name, db_host, db_user, db_password)
uses_db = True
templates.append(db)
if 'vault' in data and data['vault'] != False:
vault_image = {
'repository': data['vault']['image']['repository'],
'tag': data['vault']['image']['tag']
}
vault_hostname = data['vault']['hostname']
vault_storage_class = data['vault']['storageClass']
vault = HashicorpVault(image=vault_image, hostname=vault_hostname, storage_class=vault_storage_class)
uses_secrets_vault = True
templates.append(vault)
if 'nosql' in data and data['nosql'] != False:
nosql_db_name = data['nosql']['dbName']
nosql_user = data['nosql']['user']
nosql_password = data['nosql']['password']
tables = data['nosql']['tables']
mongo = MongoDB(nosql_db_name, nosql_user, nosql_password, tables)
nosql = mongo
templates.append(mongo)
if 'cache' in data and data['cache'] != False:
cache_password = data['cache']['password']
redis = Redis(cache_password)
uses_cache = True
templates.append(redis)
if 'oauth' in data and data['oauth'] != False:
base_app_url = data['oauth']['baseAppUrl']
app_abbreviation = data['oauth']['appAbbreviation']
app_name = data['oauth']['appName']
service_name = data['oauth']['serviceName']
dev_port = data['oauth']['devPort']
oauth = OAuth(base_app_url, app_abbreviation, app_name, service_name, dev_port)
templates.append(oauth)
if 'thirdPartyServices' in data:
if 'openai' in data['thirdPartyServices']:
openai_api_key = data['thirdPartyServices']['openai']['apiKey']
openai = ThirdPartyService('openai', False, api_key=openai_api_key)
third_party_services.append(openai)
templates.append(openai)
if 'stripe' in data['thirdPartyServices']:
stripe_public_key = data['thirdPartyServices']['stripe']['publicKey']
stripe_secret_key = data['thirdPartyServices']['stripe']['secretKey']
stripe_test_public_key = data['thirdPartyServices']['stripe']['testPublicKey']
stripe_test_secret_key = data['thirdPartyServices']['stripe']['testSecretKey']
stripe = ThirdPartyService('stripe', True, public_key=stripe_public_key, secret_key=stripe_secret_key, test_public_key=stripe_test_public_key, test_secret_key=stripe_test_secret_key)
third_party_services.append(stripe)
templates.append(stripe)
if 'extraEnvVars' in data:
extra_env_vars = data['extraEnvVars']
for key, value in extra_env_vars.items():
if not isinstance(value, dict) and value.find("'") != -1:
extra_env_vars[key] = value.replace("'", '"')
deployment = Deployment(image_repository, image_pull_policy=image_pull_policy, uses_db=uses_db, uses_secrets_vault=uses_secrets_vault, nosql=nosql, uses_cache=uses_cache, third_party_services=third_party_services, **extra_env_vars)
templates.append(deployment)
#templates = [ingress, service, db, vault, mongo, redis, oauth, deployment, stripe, openai]
helmChart = HelmChart(chart_name, chart_description, maintainers, chart_homepage, sources, app_version, chart_version, api_version, *templates) helmChart = HelmChart(chart_name, chart_description, maintainers, chart_homepage, sources, app_version, chart_version, api_version, *templates)
helmChart.create_templates_folder() helmChart.create_templates_folder()
helmChart.write_yaml() helmChart.write_yaml()
@ -84,11 +151,13 @@ if __name__ == '__main__':
try: try:
helmChart.package() helmChart.package()
try: if 'registry' in data:
helmChart.push(helm_registry) helm_registry = data['registry']
except Exception as ex: try:
print('Push to the registry failed. Please check the error message below:') helmChart.push(helm_registry)
print(ex) except Exception as ex:
print('Push to the registry failed. Please check the error message below:')
print(ex)
except Exception as e: except Exception as e:
print('Packaging the Helm chart failed. Please check the error message below:') print('Packaging the Helm chart failed. Please check the error message below:')
print(e) print(e)

View file

@ -29,10 +29,18 @@
"user": "<Database User>", "user": "<Database User>",
"password": "<Database Password>" "password": "<Database Password>"
}, },
"vault": {
"image": {
"repository": "<Vault Image Repository>",
"tag": "<Vault Image Tag>"
},
"hostname": "<DNS Name where the vault will be hosted>",
"storageClass": "<Storage Class Name>"
},
"nosql": { "nosql": {
"dbName": "<NoSQL Database Name>", "dbName": "<NoSQL Database Name>",
"user": "<NoSQL Database User>", "user": "<NoSQL Database User>",
"password": "", "password": "<NoSQL Database Password>",
"tables": { "tables": {
"<Table Environment Variable Name>": { "<Table Environment Variable Name>": {
"name": "<Table Intermediate Name (used in Helm template files)>", "name": "<Table Intermediate Name (used in Helm template files)>",
@ -55,6 +63,12 @@
"thirdPartyServices": { "thirdPartyServices": {
"openai": { "openai": {
"apiKey": "<OpenAI API Key>" "apiKey": "<OpenAI API Key>"
},
"stripe": {
"publicKey": "<Stripe Public Key>",
"secretKey": "<Stripe Secret Key>",
"testPublicKey": "<Stripe Test Public Key>",
"testSecretKey": "<Stripe Test Secret Key>"
} }
}, },
"extraEnvVars": { "extraEnvVars": {

25
src/AzureKeyVault.py Normal file
View file

@ -0,0 +1,25 @@
from .SecretsVault import SecretsVault
class AzureKeyVault(SecretsVault):
def __init__(self, name: str, client_id: str, client_secret: str, tenant_id: str):
super().__init__('azure')
self.name = name
self.client_id = client_id
self.client_secret = client_secret
self.tenant_id = tenant_id
def write(self):
with open('templates/vault-keyvault-secret.yaml', 'w') as f:
f.write('{{- if and (.Values.vault.enabled) (eq .Values.vault.type "azure") -}}' + '\n')
f.write('apiVersion: v1' + '\n')
f.write('kind: Secret' + '\n')
f.write('metadata:' + '\n')
f.write(' ' + 'name: {{ .Release.Name }}-vault-secret' + '\n')
f.write('type: opaque' + '\n')
f.write('data:' + '\n')
f.write(' ' + 'client-id: {{ .Values.vault.clientId | b64enc }}' + '\n')
f.write(' ' + 'client-secret: {{ .Values.vault.clientSecret | b64enc }}' + '\n')
f.write(' ' + 'name: {{ .Values.vault.vaultName | b64enc }}' + '\n')
f.write(' ' + 'tenant-id: {{ .Values.vault.tenantId | b64enc }}' + '\n')
f.write('{{- end -}}')

View file

@ -3,7 +3,7 @@ from .NoSQL import NoSQL
from .ThirdPartyService import ThirdPartyService from .ThirdPartyService import ThirdPartyService
class Deployment (Template): class Deployment (Template):
def __init__(self, image_repository: str, image_tag: str = 'v1.0.0', image_pull_policy: str = 'IfNotPresent', replica_count: int = 1, port: int = 8080, env: str = 'production', uses_oauth: bool = True, uses_db: bool = False, nosql: NoSQL | None = None, uses_cache: bool = False, third_party_services: list[ThirdPartyService] = [], **extra_env_vars: dict[str, str | dict[str, str]]): def __init__(self, image_repository: str, image_tag: str = 'v1.0.0', image_pull_policy: str = 'IfNotPresent', replica_count: int = 1, port: int = 8080, env: str = 'production', uses_oauth: bool = True, uses_db: bool = False, uses_secrets_vault: bool = False, nosql: NoSQL | None = None, uses_cache: bool = False, third_party_services: list[ThirdPartyService] = [], **extra_env_vars: dict[str, str | dict[str, str]]):
"""A class for creating a/some template(s) related to the Deployment for the app. """A class for creating a/some template(s) related to the Deployment for the app.
Args: Args:
@ -15,6 +15,7 @@ class Deployment (Template):
env (str, Optional): The environment the app will be running in. Default 'production' env (str, Optional): The environment the app will be running in. Default 'production'
uses_oauth (bool, Optional): Whether or not OAuth is to be used. Determines if OAuth related environment variables need to be set on the Deployment. Default True uses_oauth (bool, Optional): Whether or not OAuth is to be used. Determines if OAuth related environment variables need to be set on the Deployment. Default True
uses_db (bool, Optional): Whether or not a database is to be used. Determines if database related environment variables need to be set on the Deployment. Default False uses_db (bool, Optional): Whether or not a database is to be used. Determines if database related environment variables need to be set on the Deployment. Default False
uses_secrets_vault (bool, Optional): Whether or not a secrets vault is to be used. Determines if secrets vault related environment variables need to be set on the Deployment. Default False
nosql (NoSQL, Optional): The NoSQL template. If set, Determines if NoSQL database related environment variables need to be set on the Deployment. We require the object to get table names to set appropriate environment variables on the Deployment. Default None nosql (NoSQL, Optional): The NoSQL template. If set, Determines if NoSQL database related environment variables need to be set on the Deployment. We require the object to get table names to set appropriate environment variables on the Deployment. Default None
uses_cache (bool, Optional): Whether or not a cache server is to be used. Determines if cache related environment variables need to be set on the Deployment. Default False uses_cache (bool, Optional): Whether or not a cache server is to be used. Determines if cache related environment variables need to be set on the Deployment. Default False
third_party_services (list[ThirdPartyService], Optional): The third party services to be used. Determines if third party service related environment variables need to be set on the Deployment. Default empty list (`[]`) third_party_services (list[ThirdPartyService], Optional): The third party services to be used. Determines if third party service related environment variables need to be set on the Deployment. Default empty list (`[]`)
@ -31,34 +32,291 @@ class Deployment (Template):
self.port = port self.port = port
self.uses_oauth = uses_oauth self.uses_oauth = uses_oauth
self.uses_db = uses_db self.uses_db = uses_db
self.uses_secrets_vault = uses_secrets_vault
self.nosql = nosql self.nosql = nosql
self.uses_cache = uses_cache self.uses_cache = uses_cache
self.third_party_services = third_party_services self.third_party_services = third_party_services
self.extra_env_vars = extra_env_vars self.extra_env_vars = extra_env_vars
def write(self): def write_extra_env_vars_secret_file(self, env_var_details: dict[str, str]):
"""Write the Deployment template to a file.""" """Writes a Secret file for the extra environment variable.
Args:
env_var_details (dict[str, str]): The details of the environment variable.
"""
filename = env_var_details['name']
if filename.startswith('{{ .Release.Name }}'):
filename = filename.replace('{{ .Release.Name }}-', '')
camel_case_name = filename.split('-')[0]
for token in filename.split('-'):
if token != camel_case_name:
camel_case_name += token.capitalize()
with open(f'templates/{filename}-secret.yaml', 'w') as f:
f.write('apiVersion: v1' + '\n')
f.write('kind: Secret' + '\n')
f.write('metadata:' + '\n')
f.write(' ' + f'name: {env_var_details["name"]}' + '\n')
f.write('type: Opaque' + '\n')
f.write('data:' + '\n')
f.write(' ' + f'{env_var_details["key"]}: ' + '{{ .Values.' + camel_case_name + ' | b64enc }}' + '\n')
def write_extra_env_vars_configmap_file(self, env_var_details: dict[str, str]):
"""Writes a ConfigMap file for the extra environment variable.
Args:
env_var_details (dict[str, str]): The details of the environment variable.
"""
filename = env_var_details['name']
if filename.startswith('{{ .Release.Name }}'):
filename = filename.replace('{{ .Release.Name }}-', '')
camel_case_name = filename.split('-')[0]
for token in filename.split('-'):
if token != camel_case_name:
camel_case_name += token.capitalize()
with open(f'templates/{filename}-configmap.yaml', 'w') as f:
f.write('apiVersion: v1' + '\n')
f.write('kind: ConfigMap' + '\n')
f.write('metadata:' + '\n')
f.write(' ' + f'name: {env_var_details["name"]}' + '\n')
f.write('data:' + '\n')
f.write(' ' + f'{env_var_details["key"]}: {{ .Values.{camel_case_name} }}' + '\n')
def write_extra_env_vars_files(self):
"""Writes any needed secret or configmap files for the extra environment variables."""
for value in self.extra_env_vars.values(): for value in self.extra_env_vars.values():
# We only need to crate a secret or configmap file if the value is a dictionary
# Because if it's a string we'll just use it as the value of the environment variable
if isinstance(value, dict): if isinstance(value, dict):
if value['type'] == 'Secret': if value['type'] == 'Secret':
filename = value['name'] self.write_extra_env_vars_secret_file(value)
if filename.startswith('{{ .Release.Name }}'): elif value['type'] == 'ConfigMap':
filename = filename.replace('{{ .Release.Name }}-', '') self.write_extra_env_vars_configmap_file(value)
snake_case_name = filename.split('-')[0]
for token in filename.split('-'):
if token != snake_case_name:
snake_case_name += token.capitalize()
with open(f'templates/{filename}-secret.yaml', 'w') as f: def create_extra_env_vars_deployment_env_vars(self) -> str:
f.write('apiVersion: v1' + '\n') """Creates the extra environment variables actual variables for the Deployment."""
f.write('kind: Secret' + '\n')
f.write('metadata:' + '\n') output = ''
f.write(' ' + f'name: {value["name"]}' + '\n')
f.write('type: Opaque' + '\n') for key, value in self.extra_env_vars.items():
f.write('data:' + '\n') # Check if the value is a dictionary or a string
f.write(' ' + f'{value["key"]}: ' + '{{ .Values.' + snake_case_name + ' | b64enc }}' + '\n') if isinstance(value, dict):
output += ' ' + ' ' + ' ' + ' ' + f'- name: {key.upper()}' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + 'valueFrom:' + '\n'
if value['type'] == 'Secret':
output += ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'secretKeyRef:' + '\n'
elif value['type'] == 'ConfigMap':
output += ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'configMapKeyRef:' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'name: ' + value['name'] + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'key: ' + value['key'] + '\n'
else:
# Because the value is a string just use the value literally
output += ' ' + ' ' + ' ' + ' ' + f'- name: {key.upper()}' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + f'value: {value}' + '\n'
return output
def create_oauth_deployment_env_vars(self) -> str:
"""Creates the OAuth related environment variables for the Deployment."""
output = ''
output += ' ' + ' ' + ' ' + ' ' + '# OAuth Implementation Stuff' + '\n'
output += ' ' + ' ' + ' ' + ' ' + '- name: BASE_APP_URL' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + 'valueFrom:' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'configMapKeyRef:' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'name: {{ .Release.Name }}-oauth-credentials' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'key: base-app-url' + '\n'
output += ' ' + ' ' + ' ' + ' ' + '- name: APP_ABBRV' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + 'valueFrom:' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'configMapKeyRef:' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'name: {{ .Release.Name }}-oauth-credentials' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'key: app-abbreviation' + '\n'
output += ' ' + ' ' + ' ' + ' ' + '- name: APP_NAME' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + 'valueFrom:' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'configMapKeyRef:' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'name: {{ .Release.Name }}-oauth-credentials' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'key: app-name' + '\n'
output += ' ' + ' ' + ' ' + ' ' + '- name: SERVICE_NAME' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + 'valueFrom:' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'configMapKeyRef:' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'name: {{ .Release.Name }}-oauth-credentials' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'key: service-name' + '\n'
output += ' ' + ' ' + ' ' + ' ' + '- name: DEV_PORT' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + 'valueFrom:' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'configMapKeyRef:' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'name: {{ .Release.Name }}-oauth-credentials' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'key: dev-port' + '\n'
return output
def create_db_deployment_env_vars(self) -> str:
"""Creates the database related environment variables for the Deployment."""
output = ''
output += ' ' + ' ' + ' ' + ' ' + '# Database credentials' + '\n'
output += ' ' + ' ' + ' ' + ' ' + '- name: DB_HOST' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + 'valueFrom:' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'configMapKeyRef:' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'name: {{ .Release.Name }}-db-credentials' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'key: db-host' + '\n'
output += ' ' + ' ' + ' ' + ' ' + '- name: DB_NAME' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + 'valueFrom:' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'configMapKeyRef:' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'name: {{ .Release.Name }}-db-credentials' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'key: db-name' + '\n'
output += ' ' + ' ' + ' ' + ' ' + '- name: DB_PASSWORD' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + 'valueFrom:' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'secretKeyRef:' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'name: {{ .Release.Name }}-db-password' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'key: password' + '\n'
output += ' ' + ' ' + ' ' + ' ' + '- name: DB_PORT' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + 'valueFrom:' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'configMapKeyRef:' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'name: {{ .Release.Name }}-db-credentials' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'key: db-port' + '\n'
output += ' ' + ' ' + ' ' + ' ' + '- name: DB_USER' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + 'valueFrom:' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'configMapKeyRef:' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'name: {{ .Release.Name }}-db-credentials' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'key: db-user' + '\n'
return output
def create_nosql_deployment_env_vars(self) -> str:
"""Creates the NoSQL related environment variables for the Deployment."""
output = ''
output += ' ' + ' ' + ' ' + ' ' + '# NoSQL Credentials' + '\n'
output += ' ' + ' ' + ' ' + ' ' + '{{- if eq .Values.nosql.type "mongodb" }}' + '\n'
output += ' ' + ' ' + ' ' + ' ' + '- name: STORAGE_ACCOUNT_CONNECTION_STRING' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + 'valueFrom:' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'secretKeyRef:' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'name: {{ .Release.Name }}-mongo-credentials' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'key: connection-string' + '\n'
output += ' ' + ' ' + ' ' + ' ' + '{{- else if eq .Values.nosql.type "azure" }}' + '\n'
output += ' ' + ' ' + ' ' + ' ' + '- name: STORAGE_ACCOUNT_KEY' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + 'valueFrom:' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'secretKeyRef:' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'name: {{ .Release.Name }}-azure-tables-credentials' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'key: key' + '\n'
output += ' ' + ' ' + ' ' + ' ' + '- name: STORAGE_ACCOUNT_NAME' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + 'valueFrom:' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'configMapKeyRef:' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'name: {{ .Release.Name }}-azure-tables-config' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'key: name' + '\n'
output += ' ' + ' ' + ' ' + ' ' + '{{- end }}' + '\n'
output += ' ' + ' ' + ' ' + ' ' + '# NoSQL Table Names' + '\n'
for key, value in self.nosql.tables.items():
output += ' ' + ' ' + ' ' + ' ' + f'- name: {key.upper()}' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + 'valueFrom:' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'configMapKeyRef:' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'name: {{ .Release.Name }}-storage-tables' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + f'key: {value["name"]}' + '\n'
return output
def create_secret_vault_deployment_env_vars(self) -> str:
"""Creates the secret vault related environment variables for the Deployment."""
output = ''
output += ' ' + ' ' + ' ' + ' ' + '# -- Secrets Vault (Hashicorp Vault OR Azure Key Vault) --' + '\n'
output += ' ' + ' ' + ' ' + ' ' + '{{- if .Values.vault.enabled }}' + '\n'
output += ' ' + ' ' + ' ' + ' ' + '{{- if eq .Values.vault.type "azure" }}' + '\n'
output += ' ' + ' ' + ' ' + ' ' + '- name: KEYVAULT_CLIENT_ID' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + 'valueFrom:' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'secretKeyRef:' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'name: {{ .Release.Name }}-vault-secret' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'key: client-id' + '\n'
output += ' ' + ' ' + ' ' + ' ' + '- name: KEYVAULT_CLIENT_SECRET' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + 'valueFrom:' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'secretKeyRef:' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'name: {{ .Release.Name }}-vault-secret' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'key: client-secret' + '\n'
output += ' ' + ' ' + ' ' + ' ' + '- name: KEYVAULT_NAME' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + 'valueFrom:' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'secretKeyRef:' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'name: {{ .Release.Name }}-vault-secret' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'key: name' + '\n'
output += ' ' + ' ' + ' ' + ' ' + '- name: KEYVAULT_TENANT_ID' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + 'valueFrom:' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'secretKeyRef:' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'name: {{ .Release.Name }}-vault-secret' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'key: tenant-id' + '\n'
output += ' ' + ' ' + ' ' + ' ' + '{{- else if eq .Values.vault.type "hashicorp" }}' + '\n'
output += ' ' + ' ' + ' ' + ' ' + '- name: VAULT_NAME' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + 'valueFrom:' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'secretKeyRef:' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'name: {{ .Release.Name }}-vault-secret' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'key: vault-name' + '\n'
output += ' ' + ' ' + ' ' + ' ' + '- name: VAULT_PORT' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + 'valueFrom:' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'secretKeyRef:' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'name: {{ .Release.Name }}-vault-secret' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'key: vault-port' + '\n'
output += ' ' + ' ' + ' ' + ' ' + '{{- end }}' + '\n'
output += ' ' + ' ' + ' ' + ' ' + '{{- end }}' + '\n'
return output
def create_cache_deployment_env_vars(self) -> str:
"""Creates the cache related environment variables for the Deployment."""
output = ''
output += ' ' + ' ' + ' ' + ' ' + '# Caching Server Variables' + '\n'
output += ' ' + ' ' + ' ' + ' ' + '- name: CACHE_HOSTNAME' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + 'valueFrom:' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'configMapKeyRef:' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'name: {{ .Relese.name }}-cache-configmap' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'key: hostname' + '\n'
output += ' ' + ' ' + ' ' + ' ' + '- name: CACHE_PORT' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + 'valueFrom:' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'configMapKeyRef:' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'name: {{ .Release.Name }}-cache-configmap' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'key: port' + '\n'
output += ' ' + ' ' + ' ' + ' ' + '- name: CACHE_PASSWORD' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + 'valueFrom:' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'secretKeyRef:' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'name: {{ .Release.Name }}-cache-credentials' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'key: password' + '\n'
return output
def create_third_party_services_deployment_env_vars(self) -> str:
"""Creates the third party services related environment variables for the Deployment."""
output = ''
output += ' ' + ' ' + ' ' + ' ' + '# Third-Party Integrations' + '\n'
for third_party in self.third_party_services:
output += ' ' + ' ' + ' ' + ' ' + '{{- if .Values.thirdParty.' + third_party.name + '.enabled }}' + '\n'
for var in third_party.vars:
output += ' ' + ' ' + ' ' + ' ' + '- name: ' + third_party.name.upper() + '_' + var.upper() + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + 'valueFrom:' + '\n'
output += ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'secretKeyRef:' + '\n'
output += ' ' + ' ' ' ' + ' ' + ' ' + ' ' + ' ' + 'name: {{ .Release.Name }}-' + third_party.name + '-secret' + '\n'
output += ' ' + ' ' ' ' + ' ' + ' ' + ' ' + ' ' + f'key: {var.replace("_", "-")}' + '\n'
output += ' ' + ' ' + ' ' + ' ' + '{{- end }}' + '\n'
return output
def write_deployment_file(self):
"""Writes the Deployment file for the app."""
with open(f'templates/deployment.yaml', 'w') as f: with open(f'templates/deployment.yaml', 'w') as f:
f.write('apiVersion: apps/v1' + '\n') f.write('apiVersion: apps/v1' + '\n')
@ -89,133 +347,46 @@ class Deployment (Template):
f.write(' ' + ' ' + ' ' + ' ' + '- name: PORT' + '\n') f.write(' ' + ' ' + ' ' + ' ' + '- name: PORT' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + 'value: "{{ .Values.container.port }}"' + '\n') f.write(' ' + ' ' + ' ' + ' ' + ' ' + 'value: "{{ .Values.container.port }}"' + '\n')
for key, value in self.extra_env_vars.items(): # Add extra environment variables
# Check if the value is a dictionary or a string f.write(self.create_extra_env_vars_deployment_env_vars())
if isinstance(value, dict):
f.write(' ' + ' ' + ' ' + ' ' + f'- name: {key.upper()}' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + 'valueFrom:' + '\n')
if value['type'] == 'Secret':
f.write(' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'secretKeyRef:' + '\n')
elif value['type'] == 'ConfigMap':
f.write(' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'configMapKeyRef:' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'name: ' + value['name'] + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'key: ' + value['key'] + '\n')
else:
f.write(' ' + ' ' + ' ' + ' ' + f'- name: {key.upper()}' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + f'value: {value}' + '\n')
if self.uses_oauth: if self.uses_oauth:
f.write(' ' + ' ' + ' ' + ' ' + '# OAuth Implementation Stuff' + '\n') f.write(self.create_oauth_deployment_env_vars())
f.write(' ' + ' ' + ' ' + ' ' + '- name: BASE_APP_URL' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + 'valueFrom:' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'configMapKeyRef:' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'name: {{ .Release.Name }}-oauth-credentials' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'key: base-app-url' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + '- name: APP_ABBRV' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + 'valueFrom:' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'configMapKeyRef:' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'name: {{ .Release.Name }}-oauth-credentials' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'key: app-abbreviation' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + '- name: APP_NAME' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + 'valueFrom:' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'configMapKeyRef:' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'name: {{ .Release.Name }}-oauth-credentials' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'key: app-name' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + '- name: SERVICE_NAME' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + 'valueFrom:' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'configMapKeyRef:' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'name: {{ .Release.Name }}-oauth-credentials' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'key: service-name' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + '- name: DEV_PORT' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + 'valueFrom:' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'configMapKeyRef:' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'name: {{ .Release.Name }}-oauth-credentials' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'key: dev-port' + '\n')
if self.uses_db: if self.uses_db:
f.write(' ' + ' ' + ' ' + ' ' + '# Database credentials' + '\n') f.write(self.create_db_deployment_env_vars())
f.write(' ' + ' ' + ' ' + ' ' + '- name: DB_HOST' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + 'valueFrom:' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'configMapKeyRef:' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'name: {{ .Release.Name }}-db-credentials' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'key: db-host' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + '- name: DB_NAME' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + 'valueFrom:' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'configMapKeyRef:' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'name: {{ .Release.Name }}-db-credentials' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'key: db-name' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + '- name: DB_PASSWORD' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + 'valueFrom:' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'secretKeyRef:' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'name: {{ .Release.Name }}-db-password' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'key: password' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + '- name: DB_PORT' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + 'valueFrom:' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'configMapKeyRef:' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'name: {{ .Release.Name }}-db-credentials' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'key: db-port' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + '- name: DB_USER' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + 'valueFrom:' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'configMapKeyRef:' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'name: {{ .Release.Name }}-db-credentials' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'key: db-user' + '\n')
if self.nosql is not None: if self.nosql is not None:
f.write(' ' + ' ' + ' ' + ' ' + '# NoSQL Credentials' + '\n') f.write(self.create_nosql_deployment_env_vars())
f.write(' ' + ' ' + ' ' + ' ' + '{{- if eq .Values.nosql.type "mongodb" }}' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + '- name: STORAGE_ACCOUNT_CONNECTION_STRING' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + 'valueFrom:' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'secretKeyRef:' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'name: {{ .Release.Name }}-mongo-credentials' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'key: connection-string' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + '{{- else if eq .Values.nosql.type "azure" }}' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + '- name: STORAGE_ACCOUNT_KEY' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + 'valueFrom:' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'secretKeyRef:' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'name: {{ .Release.Name }}-azure-tables-credentials' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'key: key' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + '- name: STORAGE_ACCOUNT_NAME' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + 'valueFrom:' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'configMapKeyRef:' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'name: {{ .Release.Name }}-azure-tables-config' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'key: name' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + '{{- end }}' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + '# NoSQL Table Names' + '\n')
for key, value in self.nosql.tables.items():
f.write(' ' + ' ' + ' ' + ' ' + f'- name: {key.upper()}' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + 'valueFrom:' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'configMapKeyRef:' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'name: {{ .Release.Name }}-storage-tables' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + f'key: {value["name"]}' + '\n')
if self.uses_secrets_vault:
f.write(self.create_secret_vault_deployment_env_vars())
if self.uses_cache: if self.uses_cache:
f.write(' ' + ' ' + ' ' + ' ' + '# Caching Server Variables' + '\n') f.write(self.create_cache_deployment_env_vars())
f.write(' ' + ' ' + ' ' + ' ' + '- name: CACHE_HOSTNAME' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + 'valueFrom:' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'configMapKeyRef:' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'name: {{ .Relese.name }}-cache-configmap' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'key: hostname' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + '- name: CACHE_PORT' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + 'valueFrom:' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'configMapKeyRef:' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'name: {{ .Release.Name }}-cache-configmap' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'key: port' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + '- name: CACHE_PASSWORD' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + 'valueFrom:' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'secretKeyRef:' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'name: {{ .Release.Name }}-cache-credentials' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'key: password' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + '# Third-Party Integrations' + '\n') if len(self.third_party_services) > 0:
for third_party in self.third_party_services: f.write(self.create_third_party_services_deployment_env_vars())
f.write(' ' + ' ' + ' ' + ' ' + '{{- if .Values.thirdParty.' + third_party.name + '.enabled }}' + '\n')
# Because of the way we implement Hashicorp Vault we need to mount the role_vars shared volume
for var in third_party.vars: # This is because the Vault container populates this shared volume with the app credentials.
f.write(' ' + ' ' + ' ' + ' ' + '- name: ' + third_party.name.upper() + '_' + var.upper() + '\n') # It's done this way because we don't know the credentials needed to access the vault at start time (because their generated by the Vault container)
f.write(' ' + ' ' + ' ' + ' ' + ' ' + 'valueFrom:' + '\n') # So, we need a mechanism to get these credentials in relatively real-time once they've been generated
f.write(' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'secretKeyRef:' + '\n') if self.uses_secrets_vault:
f.write(' ' + ' ' ' ' + ' ' + ' ' + ' ' + ' ' + 'name: {{ .Release.Name }}-' + third_party.name + '-secret' + '\n') f.write(' ' + ' ' + ' ' + ' ' + 'volumeMounts:' + '\n')
f.write(' ' + ' ' ' ' + ' ' + ' ' + ' ' + ' ' + f'key: {var.replace("_", "-")}' + '\n') f.write(' ' + ' ' + ' ' + ' ' + '- name: role-vars' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + 'mountPath: /role_vars' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + '{{- end }}' + '\n') f.write(' ' + ' ' + ' ' + ' ' + ' ' + 'readOnly: true' + '\n')
f.write(' ' + ' ' + ' ' + 'volumes:' + '\n')
f.write(' ' + ' ' + ' ' + '- name: role-vars' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + 'persistentVolumeClaim:' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + 'claimName: {{ .Release.Name }}-vault-role-vars' + '\n')
def write(self):
"""Writes files related to the Deployment of the app."""
# Create any needed secrets or configmaps for the extra environment variables
self.write_extra_env_vars_files()
# Create the Deployment file
self.write_deployment_file()

161
src/HashicorpVault.py Normal file
View file

@ -0,0 +1,161 @@
from .SecretsVault import SecretsVault
class HashicorpVault(SecretsVault):
def __init__(self, create: bool = True, image: dict[str, str] | None = None, hostname: str | None = None, port: int = 8200, storage_class: str | None = None, storage_size: str = '512Mi'):
super().__init__('hashicorp')
self.create = create
self.image = image
self.hostname = hostname
self.port = port
self.storage_class = storage_class
self.storage_size = storage_size
def write_ingress(self):
with open('templates/vault-ingress.yaml', 'w') as f:
f.write('{{- if .Values.vault.create.ingress.enabled -}}' + '\n')
f.write('apiVersion: networking.k8s.io/v1' + '\n')
f.write('kind: Ingress' + '\n')
f.write('metadata:' + '\n')
f.write(' ' + 'name: {{ .Release.Name }}-vault-ingress' + '\n')
f.write(' ' + 'labels:' + '\n')
f.write(' ' + ' ' + 'app: {{ .Release.Name }}-vault' + '\n')
f.write('spec:' + '\n')
f.write(' ' + 'ingressClassName: nginx' + '\n')
f.write(' ' + 'rules:' + '\n')
f.write(' ' + ' ' + '- host: {{ .Values.vault.create.ingress.host }}' + '\n')
f.write(' ' + ' ' + ' ' + 'http:' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + 'paths:' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + '- path: /' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + 'pathType: Prefix' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + 'backend:' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'service:' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'name: {{ .Release.Name }}-vault' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'port:' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + 'number: 80' + '\n')
f.write('{{- end -}}')
def write_service(self):
with open('templates/vault-service.yaml', 'w') as f:
f.write('{{- if .Values.vault.create.enabled -}}' + '\n')
f.write('apiVersion: v1' + '\n')
f.write('kind: Service' + '\n')
f.write('metadata:' + '\n')
f.write(' ' + 'name: {{ .Release.Name }}-vault' + '\n')
f.write(' ' + 'labels:' + '\n')
f.write(' ' + ' ' + 'app: {{ .Release.Name }}-vault' + '\n')
f.write('spec:' + '\n')
f.write(' ' + 'selector:' + '\n')
f.write(' ' + ' ' + 'app: {{ .Release.Name }}-vault' + '\n')
f.write(' ' + 'ports:' + '\n')
f.write(' ' + ' ' + '- protocol: TCP' + '\n')
f.write(' ' + ' ' + ' ' + 'port: 80' + '\n')
f.write(' ' + ' ' + ' ' + 'targetPort: 8200' + '\n')
f.write('{{- end -}}')
def write_role_vars_persistent_volume_claim(self):
with open('templates/vault-role-vars-persistent-volume-claim.yaml', 'w') as f:
f.write('{{- if .Values.vault.create.enabled -}}' + '\n')
f.write('apiVersion: v1' + '\n')
f.write('kind: PersistentVolumeClaim' + '\n')
f.write('metadata:' + '\n')
f.write(' ' + 'name: {{ .Release.Name }}-vault-role-vars' + '\n')
f.write(' ' + 'labels:' + '\n')
f.write(' ' + ' ' + 'app: {{ .Release.Name }}-vault' + '\n')
f.write('spec:' + '\n')
f.write(' ' + 'storageClassName: {{ .Values.vault.create.storage.storageClass }}' + '\n')
f.write(' ' + 'accessModes:' + '\n')
f.write(' ' + ' ' + '- ReadWriteMany' + '\n')
f.write(' ' + 'resources:' + '\n')
f.write(' ' + ' ' + 'requests:' + '\n')
f.write(' ' + ' ' + ' ' + 'storage: {{ .Values.vault.create.storage.size }}' + '\n')
f.write('{{- end -}}')
def write_deployment(self):
with open('templates/vault-deployment.yaml', 'w') as f:
f.write('{{- if and (.Values.vault.create.enabled) (eq .Values.vault.type "hashicorp") -}}' + '\n')
f.write('apiVersion: apps/v1' + '\n')
f.write('kind: Deployment' + '\n')
f.write('metadata:' + '\n')
f.write(' ' + 'name: {{ .Release.Name }}-vault' + '\n')
f.write(' ' + 'labels:' + '\n')
f.write(' ' + ' ' + 'app: {{ .Release.Name }}-vault' + '\n')
f.write('spec:' + '\n')
f.write(' ' + 'replicas: 1' + '\n')
f.write(' ' + 'selector:' + '\n')
f.write(' ' + ' ' + 'matchLabels:' + '\n')
f.write(' ' + ' ' + ' ' + 'app: {{ .Release.Name }}-vault' + '\n')
f.write(' ' + 'template:' + '\n')
f.write(' ' + ' ' + 'metadata:' + '\n')
f.write(' ' + ' ' + ' ' + 'labels:' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + 'app: {{ .Release.Name }}-vault' + '\n')
f.write(' ' + ' ' + 'spec:' + '\n')
f.write(' ' + ' ' + ' ' + 'containers:' + '\n')
f.write(' ' + ' ' + ' ' + '- name: {{ .Release.Name }}-vault' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + 'image: {{ .Values.vault.create.image.repository }}:{{ .Values.vault.create.image.tag }}' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + 'ports:' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + '- containerPort: 8200' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + '- containerPort: 8201' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + 'env:' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + '- name: VAULT_ADDR' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + 'value: http://0.0.0.0:8200' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + '- name: ROLE_ID_SECRET_NAME' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + 'value: VAULT_ROLE_ID' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + '- name: SECRET_ID_SECRET_NAME' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + 'value: VAULT_SECRET_ID' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + 'volumeMounts:' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + '- name: vault-data' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + 'mountPath: /vault/data' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + '- name: vault-log' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + 'mountPath: /vault/logs' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + '- name: vault-creds' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + 'mountPath: /vault/creds' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + '- name: vault-role-vars' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + 'mountPath: /role_vars' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + 'capAdd:' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + '- IPC_LOCK' + '\n')
f.write(' ' + ' ' + ' ' + 'volumes:' + '\n')
f.write(' ' + ' ' + ' ' + '- name: vault-data' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + 'emptyDir: {}' + '\n')
f.write(' ' + ' ' + ' ' + '- name: vault-log' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + 'emptyDir: {}' + '\n')
f.write(' ' + ' ' + ' ' + '- name: vault-creds' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + 'emptyDir: {}' + '\n')
f.write(' ' + ' ' + ' ' + '- name: vault-role-vars' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + 'persistentVolumeClaim:' + '\n')
f.write(' ' + ' ' + ' ' + ' ' + ' ' + 'claimName: {{ .Release.Name }}-vault-role-vars' + '\n')
f.write('{{- end -}}')
def write_secret(self):
with open('templates/vault-hashicorp-secret.yaml', 'w') as f:
f.write('{{- if and (.Values.vault.enabled) (eq .Values.vault.type "hashicorp") -}}' + '\n')
f.write('apiVersion: v1' + '\n')
f.write('kind: Secret' + '\n')
f.write('metadata:' + '\n')
f.write(' ' + 'name: {{ .Release.Name }}-vault-secret' + '\n')
f.write('type: opaque' + '\n')
f.write('data:' + '\n')
f.write(' ' + '{{- if .Values.vault.create.enabled }}' + '\n')
f.write(' ' + '# Because we create the Hashicorp Vault instance as part of the Helm chart, ' + '\n')
f.write(' ' + '# we can use the name of the created resource (utilizing k8s built-in container connections)' + '\n')
f.write(' ' + '# to connect to the Vault instance without having to hard-code the Vault name.' + '\n')
f.write(' ' + 'vault-name: {{ printf "%s-vault" .Release.Name | b64enc }}' + '\n')
f.write(' ' + '# Because we create the Hashicorp Vault instance as part of the Helm chart,' + '\n')
f.write(' ' + '# We know the port that the Vault instance is running on.' + '\n')
f.write(' ' + 'vault-port: {{ printf "%d" 80 | b64enc }}' + '\n')
f.write(' ' + '{{- else }}' + '\n')
f.write(' ' + '# Because the Vault wasn\'t created as part of the Helm chart,' + '\n')
f.write(' ' + '# we need the deployer to specify the name of the Vault instance to connect to.' + '\n')
f.write(' ' + 'vault-name: {{ .Values.vault.vaultName | b64enc }}' + '\n')
f.write(' ' + '# Because the Vault wasn\'t created as part of the Helm chart,' + '\n')
f.write(' ' + '# we need the deployer to specify the port that the Vault instance is running on.' + '\n')
f.write(' ' + 'vault-port: {{ .Values.passVault.vaultPort | b64enc }}' + '\n')
f.write(' ' + '{{- end }}' + '\n')
f.write('{{- end -}}')
def write(self):
self.write_ingress()
self.write_service()
self.write_role_vars_persistent_volume_claim()
self.write_deployment()
self.write_secret()

View file

@ -3,6 +3,9 @@ import os, subprocess
from .Template import Template from .Template import Template
from .Ingress import Ingress from .Ingress import Ingress
from .Database import Database from .Database import Database
from .SecretsVault import SecretsVault
from .HashicorpVault import HashicorpVault
from .AzureKeyVault import AzureKeyVault
from .NoSQL import NoSQL from .NoSQL import NoSQL
from .MongoDB import MongoDB from .MongoDB import MongoDB
from .AzureTableStorage import AzureTableStorage from .AzureTableStorage import AzureTableStorage
@ -294,6 +297,151 @@ class HelmChart:
return output return output
def create_secrets_vault_section_of_values_yaml(self) -> str:
"""Create the Secrets Vault section of the `values.yaml` file for the Helm chart.
The Secrets Vault section is used to define the Secrets Vault configuration that the app will use.
Returns:
str: The Secrets Vault section of the `values.yaml` file
"""
output = ''
# Get the Secrets Vault template from the templates provided
secrets_vault_template = next(template for template in self.templates if isinstance(template, SecretsVault))
output += '# Configurations for the secrets vault' + '\n'
output += 'vault:' + '\n'
output += ' ' + '# If a secrets vault should be used' + '\n'
output += ' ' + '# That is, if a dedicated software for secret management should be used' + '\n'
output += ' ' + '# This should virtually always be true if storing any kind of sensitive information as it\'s the most secure option' + '\n'
output += ' ' + 'enabled: true' + '\n'
output += ' ' + '\n'
output += ' ' + '# The type of secrets vault to use.' + '\n'
output += ' ' + '# ' + '\n'
output += ' ' + '# Vaults' + '\n'
output += ' ' + '# ------' + '\n'
output += ' ' + '# The following table lists the supported vault types:' + '\n'
output += ' ' + '# ' + '\n'
output += ' ' + '# | Type | Description | Current Status | Required Fields |' + '\n'
output += ' ' + '# | ----------- | -------------------- | -------------- | --------------------------------------------------- |' + '\n'
output += ' ' + '# | `hashicorp` | Uses Hashicorp Vault | Implemented | `vaultName` (if `create` not true) |' + '\n'
output += ' ' + '# | `azure` | Uses Azure Key Vault | Implemented | `vaultName`, `clientId`, `clientSecret`, `tenantId` |' + '\n'
output += ' ' + '# ' + '\n'
output += ' ' + f'type: "{secrets_vault_template.type}"' + '\n'
output += ' ' + '\n'
output += ' ' + '# Configurations to create a Hashicorp Vault instance as part of the Helm chart' + '\n'
output += ' ' + '# ' + '\n'
output += ' ' + '# THIS IS ONLY RELEVANT IF `type` IS SET TO `hashicorp`' + '\n'
output += ' ' + 'create:' + '\n'
output += ' ' + ' ' + '# If a Hashicorp Vault instance should be created as part of the Helm chart' + '\n'
if isinstance(secrets_vault_template, HashicorpVault):
output += ' ' + ' ' + f'enabled: {str(secrets_vault_template.create).lower()}' + '\n'
else:
output += ' ' + ' ' + 'enabled: <true/false>' + '\n'
output += ' ' + ' ' + '\n'
output += ' ' + ' ' + '# Configurations for the image to use if creating the Hashicorp Vault instance' + '\n'
output += ' ' + ' ' + '# as part of the Helm chart' + '\n'
output += ' ' + ' ' + 'image:' + '\n'
output += ' ' + ' ' + ' ' + '# The repository of the image to use' + '\n'
if isinstance(secrets_vault_template, HashicorpVault):
output += ' ' + ' ' + ' ' + f'repository: {secrets_vault_template.image["repository"]}' + '\n'
else:
output += ' ' + ' ' + ' ' + 'repository: <image repository>' + '\n'
output += ' ' + ' ' + ' ' + '\n'
output += ' ' + ' ' + ' ' + '# The tag of the image to use' + '\n'
if isinstance(secrets_vault_template, HashicorpVault):
output += ' ' + ' ' + ' ' + f'tag: {secrets_vault_template.image["tag"]}' + '\n'
else:
output += ' ' + ' ' + ' ' + 'tag: <image tag>' + '\n'
output += ' ' + ' ' + '\n'
output += ' ' + ' ' + '# Configurations for the ingress of the created Hashicorp Vault instance' + '\n'
output += ' ' + ' ' + 'ingress:' + '\n'
output += ' ' + ' ' + ' ' + '# If an ingress should be created for the created Hashicorp Vault instance' + '\n'
if isinstance(secrets_vault_template, HashicorpVault):
output += ' ' + ' ' + ' ' + f'enabled: {str(secrets_vault_template.create and secrets_vault_template.hostname != None).lower()}' + '\n'
else:
output += ' ' + ' ' + ' ' + 'enabled: <true/false>' + '\n'
output += ' ' + ' ' + ' ' + '\n'
output += ' ' + ' ' + ' ' + '# The host of the ingress for the created Hashicorp Vault instance' + '\n'
if isinstance(secrets_vault_template, HashicorpVault):
output += ' ' + ' ' + ' ' + f'host: {secrets_vault_template.hostname}' + '\n'
else:
output += ' ' + ' ' + ' ' + 'host: <DNS Name for vault>' + '\n'
output += ' ' + ' ' + '\n'
output += ' ' + ' ' + '# Configurations for the storage of the created Hashicorp Vault instance' + '\n'
output += ' ' + ' ' + 'storage:' + '\n'
output += ' ' + ' ' + ' ' + '# The storage class to use for the created Hashicorp Vault instance\'s Persistent Volume Claim' + '\n'
if isinstance(secrets_vault_template, HashicorpVault):
if secrets_vault_template.create:
output += ' ' + ' ' + ' ' + f'class: {secrets_vault_template.storage_class}' + '\n'
else:
output += ' ' + ' ' + ' ' + 'class: <storage class>' + '\n'
else:
output += ' ' + ' ' + ' ' + 'class: <storage class>' + '\n'
output += ' ' + ' ' + ' ' + '\n'
output += ' ' + ' ' + ' ' + '# The size of the created Hashicorp Vault instance\'s Persistent Volume Claim' + '\n'
if isinstance(secrets_vault_template, HashicorpVault):
if secrets_vault_template.create:
output += ' ' + ' ' + ' ' + f'size: {secrets_vault_template.storage_size}' + '\n'
else:
output += ' ' + ' ' + ' ' + 'size: <storage size>' + '\n'
else:
output += ' ' + ' ' + ' ' + 'size: <storage size>' + '\n'
output += ' ' + '\n'
output += ' ' + '# The name of the vault instance to connect to' + '\n'
output += ' ' + '# ' + '\n'
output += ' ' + '# This is relevant if type is set to `hashicorp` or `azure`' + '\n'
output += ' ' + '# Note, if `create` is true this is ignored' + '\n'
output += ' ' + '# ' + '\n'
output += ' ' + '# For `hashicorp`, this is generally the hostname of the Hashicorp Vault instance to connect to' + '\n'
output += ' ' + '# For `azure`, this is the name of the Azure Key Vault instance to connect to' + '\n'
if isinstance(secrets_vault_template, HashicorpVault):
if secrets_vault_template.create:
output += ' ' + f'#vaultName: "<vault name>"' + '\n'
else:
output += ' ' + f'vaultName: "{secrets_vault_template.hostname}"' + '\n'
elif isinstance(secrets_vault_template, AzureKeyVault):
output += ' ' + f'vaultName: "{secrets_vault_template.name}"' + '\n'
output += ' ' + '\n'
output += ' ' + '# The port of the vault instance to connect to' + '\n'
output += ' ' + '# ' + '\n'
output += ' ' + '# ONLY RELEVANT iF `type` IS SET TO `hashicorp` AND `create` IS NOT TRUE' + '\n'
if isinstance(secrets_vault_template, HashicorpVault):
if not secrets_vault_template.create:
output += ' ' + f'#vaultPort: {secrets_vault_template.port}' + '\n'
else:
output += ' ' + f'vaultPort: {secrets_vault_template.port}' + '\n'
else:
output += ' ' + '#vaultPort: <vault port>' + '\n'
output += ' ' + '\n'
output += ' ' + '# The client ID of the Azure Key Vault instance' + '\n'
output += ' ' + '# ' + '\n'
output += ' ' + '# ONLY RELEVANT IF `type` IS SET TO `azure`' + '\n'
if isinstance(secrets_vault_template, AzureKeyVault):
output += ' ' + f'client-id: "{secrets_vault_template.client_id}"' + '\n'
else:
output += ' ' + '#client-id: <Azure Key Vault Client ID>' + '\n'
output += ' ' + '\n'
output += ' ' + '# The client secret of the Azure Key Vault instance' + '\n'
output += ' ' + '# ' + '\n'
output += ' ' + '# ONLY RELEVANT IF `type` IS SET TO `azure`' + '\n'
if isinstance(secrets_vault_template, AzureKeyVault):
output += ' ' + f'client-secret: "{secrets_vault_template.client_secret}"' + '\n'
else:
output += ' ' + '#client-secret: <Azure Key Vault Client Secret>' + '\n'
output += ' ' + '\n'
output += ' ' + '# The tenant ID of the Azure Key Vault instance' + '\n'
output += ' ' + '# ' + '\n'
output += ' ' + '# ONLY RELEVANT IF `type` IS SET TO `azure`' + '\n'
if isinstance(secrets_vault_template, AzureKeyVault):
output += ' ' + f'tenant-id: "{secrets_vault_template.tenant_id}"' + '\n'
else:
output += ' ' + '#tenant-id: <Azure Key Vault Tenant ID>' + '\n'
return output
def create_nosql_section_of_values_yaml(self) -> str: def create_nosql_section_of_values_yaml(self) -> str:
"""Create the NoSQL section of the `values.yaml` file for the Helm chart. """Create the NoSQL section of the `values.yaml` file for the Helm chart.
@ -502,6 +650,8 @@ class HelmChart:
output += ' ' + ' ' + f'{camel_case_name}: {value}' + '\n' output += ' ' + ' ' + f'{camel_case_name}: {value}' + '\n'
output += ' ' + ' ' + '\n' output += ' ' + ' ' + '\n'
return output
def write_values_yaml(self): def write_values_yaml(self):
"""Write the `values.yaml` file for the Helm chart. """Write the `values.yaml` file for the Helm chart.
@ -536,6 +686,10 @@ class HelmChart:
if any(isinstance(template, Database) for template in self.templates): if any(isinstance(template, Database) for template in self.templates):
f.write(self.create_database_section_of_values_yaml()) f.write(self.create_database_section_of_values_yaml())
# If a Secrets Vault template is included in the provided templates than we want to include the appropriate section to the `values.yaml` file.
if any(isinstance(template, SecretsVault) for template in self.templates):
f.write(self.create_secrets_vault_section_of_values_yaml())
# If a Database template is included in the provided templates than we want to include the appropriate section to the `values.yaml` file. # If a Database template is included in the provided templates than we want to include the appropriate section to the `values.yaml` file.
if any(isinstance(template, NoSQL) for template in self.templates): if any(isinstance(template, NoSQL) for template in self.templates):
f.write(self.create_nosql_section_of_values_yaml()) f.write(self.create_nosql_section_of_values_yaml())

View file

@ -1,7 +1,7 @@
from .Template import Template from .Template import Template
class OAuth (Template): class OAuth (Template):
def __init__(self, base_app_url: str, app_abbreviation: str, app_name: str, service_name: str, dev_port: str, client_id: str, client_secret: str): def __init__(self, base_app_url: str, app_abbreviation: str, app_name: str, service_name: str, dev_port: str):
"""A class for creating a/some template(s) related to OAuth implementation.""" """A class for creating a/some template(s) related to OAuth implementation."""
self.base_app_url = base_app_url self.base_app_url = base_app_url

10
src/SecretsVault.py Normal file
View file

@ -0,0 +1,10 @@
from .Template import Template
class SecretsVault(Template):
def __init__(self, type: str):
super().__init__()
self.type = type
def write(self):
pass