Skip to content

Commit

Permalink
Updates operator to set service name and process env and envFrom (#22)
Browse files Browse the repository at this point in the history
* Updates operator to set service name and process env and envFrom

* Updates Makefile to include Windows specific tasks
  • Loading branch information
figliold authored Sep 12, 2024
1 parent 83ede9a commit 6ff4cc4
Show file tree
Hide file tree
Showing 9 changed files with 151 additions and 11 deletions.
2 changes: 1 addition & 1 deletion operator/Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
VERSION ?= 0.3.2
VERSION ?= 0.4.0
GIT_TAG := operator_v$(VERSION)
KEIP_INTEGRATION_IMAGE ?= ghcr.io/octoconsulting/keip/minimal-app:latest

Expand Down
2 changes: 1 addition & 1 deletion operator/controller/integrationroute-controller.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ spec:
spec:
containers:
- name: webhook
image: ghcr.io/octoconsulting/keip/route-webhook:0.6.2
image: ghcr.io/octoconsulting/keip/route-webhook:0.7.0
ports:
- containerPort: 7080
name: webhook-http
Expand Down
36 changes: 36 additions & 0 deletions operator/crd/crd.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,42 @@ spec:
type: string
mountPath:
type: string
env:
description: "List of environment variables to set in the container (cannot be updated)"
type: array
items:
type: object
properties:
name:
type: string
value:
type: string
required:
- name
- value
envFrom:
description: "List of sources to populate environment variables in the container (cannot be updated)"
type: array
items:
type: object
properties:
configMapRef:
type: object
properties:
name:
type: string
secretRef:
type: object
properties:
name:
type: string
oneOf:
- properties:
required:
- configMapRef
- properties:
required:
- secretRef
replicas: # not yet implemented
description: "Number of containers running the integration route"
type: integer
Expand Down
14 changes: 13 additions & 1 deletion operator/webhook/Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
VERSION ?= 0.6.2
VERSION ?= 0.7.0
HOST_PORT ?= 7080
GIT_TAG := webhook_v$(VERSION)

Expand Down Expand Up @@ -30,14 +30,26 @@ start-dev-server:
test:
cd test && mkdir -p $(TEST_COVERAGE_DIR) && coverage run --data-file=$(TEST_COVERAGE_FILE) -m pytest -vv

.PHONY: win-test
win-test:
cd test && (if not exist $(TEST_COVERAGE_DIR) mkdir $(TEST_COVERAGE_DIR)) && coverage run --data-file=$(TEST_COVERAGE_FILE) -m pytest -vv

.PHONY: report-test-coverage
report-test-coverage: test
cd test && coverage report --data-file $(TEST_COVERAGE_FILE)

.PHONY: win-report-test-coverage
win-report-test-coverage: win-test
cd test && coverage report --data-file $(TEST_COVERAGE_FILE)

.PHONY: report-test-coverage-html
report-test-coverage-html: test
cd test && coverage html --data-file $(TEST_COVERAGE_FILE) --directory $(TEST_COVERAGE_DIR)/html && open $(TEST_COVERAGE_DIR)/html/index.html

.PHONY: win-report-test-coverage-html
win-report-test-coverage-html: win-test
cd test && coverage html --data-file $(TEST_COVERAGE_FILE) --directory $(TEST_COVERAGE_DIR)/html && start "" $(TEST_COVERAGE_DIR)/html/index.html

.PHONY: deploy
deploy: build
docker push $(FULL_IMAGE_NAME)
Expand Down
2 changes: 2 additions & 0 deletions operator/webhook/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ pip install -r requirements.txt
You should now be able to use the `Makefile` for running tests or starting a dev server, among other
tasks.

> **_NOTE:_** There are some `make` tasks prefixed with `win-` in `Makefile` that are specific to Windows.
#### Code Formatting

To keep diffs small, consider using
Expand Down
22 changes: 17 additions & 5 deletions operator/webhook/introute/sync.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import json
import logging
from pathlib import Path
from pathlib import PurePosixPath
from typing import List, Mapping, Optional

from webhook import config as cfg
Expand Down Expand Up @@ -113,7 +113,7 @@ def get_mounts(self) -> List[Mapping]:
{
"name": secret,
"readOnly": True,
"mountPath": str(Path(SECRETS_ROOT, secret)),
"mountPath": str(PurePosixPath(SECRETS_ROOT, secret)),
}
)

Expand Down Expand Up @@ -183,16 +183,21 @@ def _get_server_ssl_config(parent) -> Optional[Mapping]:

if not keystore:
return None

return {
"ssl": {
"key-alias": "certificate",
"key-store": str(Path(KEYSTORE_PATH, keystore["key"])),
"key-store": str(PurePosixPath(KEYSTORE_PATH, keystore["key"])),
"key-store-type": keystore["type"].upper()
},
"port": 8443
}

def _service_name_env_var(parent) -> Mapping[str, str]:
return {
"name": "SERVICE_NAME",
"value": parent["metadata"]["name"]
}

def _spring_app_config_env_var(parent) -> Optional[Mapping]:
metadata = parent["metadata"]
Expand Down Expand Up @@ -245,7 +250,7 @@ def _get_java_jdk_options(tls) -> Optional[Mapping[str, str]]:

return {
"name": "JDK_JAVA_OPTIONS",
"value": f"-Djavax.net.ssl.trustStore={str(Path(TRUSTSTORE_PATH, truststore['key']))} -Djavax.net.ssl.trustStorePassword={truststore_password} -Djavax.net.ssl.trustStoreType={tls_type.upper()}"
"value": f"-Djavax.net.ssl.trustStore={str(PurePosixPath(TRUSTSTORE_PATH, truststore['key']))} -Djavax.net.ssl.trustStorePassword={truststore_password} -Djavax.net.ssl.trustStoreType={tls_type.upper()}"
}


Expand All @@ -262,6 +267,9 @@ def _generate_container_env_vars(parent) -> List[Mapping[str, str]]:
if keystore_password_env := _get_keystore_password_env(tls):
env_vars.append(keystore_password_env)

env_vars.append(_service_name_env_var(parent))

env_vars.extend(parent["spec"].get("env", []))

return env_vars

Expand Down Expand Up @@ -324,6 +332,10 @@ def _create_pod_template(parent, labels, integration_image):

pod_template["spec"]["containers"][0]["env"] = _generate_container_env_vars(parent)

envFrom = parent["spec"].get("envFrom")
if envFrom:
pod_template["spec"]["containers"][0]["envFrom"] = envFrom

return pod_template


Expand Down
22 changes: 22 additions & 0 deletions operator/webhook/test/json/full-iroute-request.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,28 @@
}
}
],
"env": [
{
"name": "ADDITIONAL_ENV_VAR_1",
"value": "myvalue1"
},
{
"name": "ADDITIONAL_ENV_VAR_2",
"value": "myvalue2"
}
],
"envFrom": [
{
"configMapRef": {
"name": "my-config"
}
},
{
"secretRef": {
"name": "my-secret"
}
}
],
"replicas": 2,
"routeConfigMap": "testroute-xml",
"secretSources": [
Expand Down
24 changes: 24 additions & 0 deletions operator/webhook/test/json/full-response.json
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,30 @@
"key": "password"
}
}
},
{
"name": "SERVICE_NAME",
"value": "testroute"
},
{
"name": "ADDITIONAL_ENV_VAR_1",
"value": "myvalue1"
},
{
"name": "ADDITIONAL_ENV_VAR_2",
"value": "myvalue2"
}
],
"envFrom": [
{
"configMapRef": {
"name": "my-config"
}
},
{
"secretRef": {
"name": "my-secret"
}
}
]
}
Expand Down
38 changes: 35 additions & 3 deletions operator/webhook/test/test_sync.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import copy
import json
from pathlib import PurePosixPath
from typing import Mapping

import pytest
Expand Down Expand Up @@ -71,7 +72,7 @@ def test_spring_app_config_json_missing_props_and_secret_sources(full_route):

assert spring_conf["name"] == "SPRING_APPLICATION_JSON"

expected_json = {"spring": {"application": {"name": "testroute"}}, "server": {"ssl": {"key-alias": "certificate", "key-store": "/etc/keystore/test-keystore.jks", "key-store-type": "JKS"}, "port": 8443}}
expected_json = {"spring": {"application": {"name": "testroute"}}, "server": {"ssl": {"key-alias": "certificate", "key-store": str(PurePosixPath("/", "etc", "keystore", "test-keystore.jks")), "key-store-type": "JKS"}, "port": 8443}}

assert json_props == expected_json

Expand Down Expand Up @@ -132,7 +133,7 @@ def test_jdk_options_pkcs12_type(full_route):

assert options["name"] == JDK_OPTIONS_ENV_NAME

expected_options = "-Djavax.net.ssl.trustStore=/etc/cabundle/test-truststore.p12 -Djavax.net.ssl.trustStorePassword= -Djavax.net.ssl.trustStoreType=PKCS12"
expected_options = "-Djavax.net.ssl.trustStore=" + str(PurePosixPath("/", "etc", "cabundle", "test-truststore.p12")) + " -Djavax.net.ssl.trustStorePassword= -Djavax.net.ssl.trustStoreType=PKCS12"
assert options["value"] == expected_options


Expand All @@ -144,7 +145,7 @@ def test_jdk_options_jks_type(full_route):
options = _get_java_jdk_options(tls_config)
assert options["name"] == JDK_OPTIONS_ENV_NAME

expected_options = "-Djavax.net.ssl.trustStore=/etc/cabundle/test-truststore.jks -Djavax.net.ssl.trustStorePassword=changeit -Djavax.net.ssl.trustStoreType=JKS"
expected_options = "-Djavax.net.ssl.trustStore=" + str(PurePosixPath("/", "etc", "cabundle", "test-truststore.jks")) + " -Djavax.net.ssl.trustStorePassword=changeit -Djavax.net.ssl.trustStoreType=JKS"
assert options["value"] == expected_options


Expand All @@ -155,6 +156,37 @@ def test_env_vars_no_keystore(full_route):

assert not any(x for x in options if x.get('name') == 'SERVER_SSL_KEYSTOREPASSWORD')

def test_env_var_service_name(full_route):
actual_env_vars = _generate_container_env_vars(full_route)
actual_service_name_env_var = next((actual_env_var for actual_env_var in actual_env_vars if actual_env_var['name'] == 'SERVICE_NAME'), None)
expected_service_name_env_var = {"name": "SERVICE_NAME", "value": "testroute"}
assert expected_service_name_env_var == actual_service_name_env_var


def test_no_additional_env_vars(full_route):
additional_env_vars_to_remove_from_expected_response = ["ADDITIONAL_ENV_VAR_1", "ADDITIONAL_ENV_VAR_2"]

expected_response = load_json("json/full-response.json")
env_vars_in_response = list(expected_response["children"][0]["spec"]["template"]["spec"]["containers"][0]["env"])
for env_var in env_vars_in_response:
if env_var["name"] == additional_env_vars_to_remove_from_expected_response[0] or env_var["name"] == additional_env_vars_to_remove_from_expected_response[1]:
expected_response["children"][0]["spec"]["template"]["spec"]["containers"][0]["env"].remove(env_var)

del full_route["spec"]["env"]
actual_response = sync(full_route)

assert expected_response == actual_response


def test_no_env_from(full_route):
expected_response = load_json("json/full-response.json")
del expected_response["children"][0]["spec"]["template"]["spec"]["containers"][0]["envFrom"]

del full_route["spec"]["envFrom"]
actual_response = sync(full_route)

assert expected_response == actual_response


def test_deployment_missing_labels(full_route):
del full_route["spec"]["labels"]
Expand Down

0 comments on commit 6ff4cc4

Please sign in to comment.