Skip to content

Commit 6ff4cc4

Browse files
authored
Updates operator to set service name and process env and envFrom (#22)
* Updates operator to set service name and process env and envFrom * Updates Makefile to include Windows specific tasks
1 parent 83ede9a commit 6ff4cc4

File tree

9 files changed

+151
-11
lines changed

9 files changed

+151
-11
lines changed

operator/Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
VERSION ?= 0.3.2
1+
VERSION ?= 0.4.0
22
GIT_TAG := operator_v$(VERSION)
33
KEIP_INTEGRATION_IMAGE ?= ghcr.io/octoconsulting/keip/minimal-app:latest
44

operator/controller/integrationroute-controller.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ spec:
5050
spec:
5151
containers:
5252
- name: webhook
53-
image: ghcr.io/octoconsulting/keip/route-webhook:0.6.2
53+
image: ghcr.io/octoconsulting/keip/route-webhook:0.7.0
5454
ports:
5555
- containerPort: 7080
5656
name: webhook-http

operator/crd/crd.yaml

+36
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,42 @@ spec:
6969
type: string
7070
mountPath:
7171
type: string
72+
env:
73+
description: "List of environment variables to set in the container (cannot be updated)"
74+
type: array
75+
items:
76+
type: object
77+
properties:
78+
name:
79+
type: string
80+
value:
81+
type: string
82+
required:
83+
- name
84+
- value
85+
envFrom:
86+
description: "List of sources to populate environment variables in the container (cannot be updated)"
87+
type: array
88+
items:
89+
type: object
90+
properties:
91+
configMapRef:
92+
type: object
93+
properties:
94+
name:
95+
type: string
96+
secretRef:
97+
type: object
98+
properties:
99+
name:
100+
type: string
101+
oneOf:
102+
- properties:
103+
required:
104+
- configMapRef
105+
- properties:
106+
required:
107+
- secretRef
72108
replicas: # not yet implemented
73109
description: "Number of containers running the integration route"
74110
type: integer

operator/webhook/Makefile

+13-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
VERSION ?= 0.6.2
1+
VERSION ?= 0.7.0
22
HOST_PORT ?= 7080
33
GIT_TAG := webhook_v$(VERSION)
44

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

33+
.PHONY: win-test
34+
win-test:
35+
cd test && (if not exist $(TEST_COVERAGE_DIR) mkdir $(TEST_COVERAGE_DIR)) && coverage run --data-file=$(TEST_COVERAGE_FILE) -m pytest -vv
36+
3337
.PHONY: report-test-coverage
3438
report-test-coverage: test
3539
cd test && coverage report --data-file $(TEST_COVERAGE_FILE)
3640

41+
.PHONY: win-report-test-coverage
42+
win-report-test-coverage: win-test
43+
cd test && coverage report --data-file $(TEST_COVERAGE_FILE)
44+
3745
.PHONY: report-test-coverage-html
3846
report-test-coverage-html: test
3947
cd test && coverage html --data-file $(TEST_COVERAGE_FILE) --directory $(TEST_COVERAGE_DIR)/html && open $(TEST_COVERAGE_DIR)/html/index.html
4048

49+
.PHONY: win-report-test-coverage-html
50+
win-report-test-coverage-html: win-test
51+
cd test && coverage html --data-file $(TEST_COVERAGE_FILE) --directory $(TEST_COVERAGE_DIR)/html && start "" $(TEST_COVERAGE_DIR)/html/index.html
52+
4153
.PHONY: deploy
4254
deploy: build
4355
docker push $(FULL_IMAGE_NAME)

operator/webhook/README.md

+2
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ pip install -r requirements.txt
2424
You should now be able to use the `Makefile` for running tests or starting a dev server, among other
2525
tasks.
2626

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

2931
To keep diffs small, consider using

operator/webhook/introute/sync.py

+17-5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import json
22
import logging
3-
from pathlib import Path
3+
from pathlib import PurePosixPath
44
from typing import List, Mapping, Optional
55

66
from webhook import config as cfg
@@ -113,7 +113,7 @@ def get_mounts(self) -> List[Mapping]:
113113
{
114114
"name": secret,
115115
"readOnly": True,
116-
"mountPath": str(Path(SECRETS_ROOT, secret)),
116+
"mountPath": str(PurePosixPath(SECRETS_ROOT, secret)),
117117
}
118118
)
119119

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

184184
if not keystore:
185185
return None
186-
186+
187187
return {
188188
"ssl": {
189189
"key-alias": "certificate",
190-
"key-store": str(Path(KEYSTORE_PATH, keystore["key"])),
190+
"key-store": str(PurePosixPath(KEYSTORE_PATH, keystore["key"])),
191191
"key-store-type": keystore["type"].upper()
192192
},
193193
"port": 8443
194194
}
195195

196+
def _service_name_env_var(parent) -> Mapping[str, str]:
197+
return {
198+
"name": "SERVICE_NAME",
199+
"value": parent["metadata"]["name"]
200+
}
196201

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

246251
return {
247252
"name": "JDK_JAVA_OPTIONS",
248-
"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()}"
253+
"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()}"
249254
}
250255

251256

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

270+
env_vars.append(_service_name_env_var(parent))
271+
272+
env_vars.extend(parent["spec"].get("env", []))
265273

266274
return env_vars
267275

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

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

335+
envFrom = parent["spec"].get("envFrom")
336+
if envFrom:
337+
pod_template["spec"]["containers"][0]["envFrom"] = envFrom
338+
327339
return pod_template
328340

329341

operator/webhook/test/json/full-iroute-request.json

+22
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,28 @@
3535
}
3636
}
3737
],
38+
"env": [
39+
{
40+
"name": "ADDITIONAL_ENV_VAR_1",
41+
"value": "myvalue1"
42+
},
43+
{
44+
"name": "ADDITIONAL_ENV_VAR_2",
45+
"value": "myvalue2"
46+
}
47+
],
48+
"envFrom": [
49+
{
50+
"configMapRef": {
51+
"name": "my-config"
52+
}
53+
},
54+
{
55+
"secretRef": {
56+
"name": "my-secret"
57+
}
58+
}
59+
],
3860
"replicas": 2,
3961
"routeConfigMap": "testroute-xml",
4062
"secretSources": [

operator/webhook/test/json/full-response.json

+24
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,30 @@
120120
"key": "password"
121121
}
122122
}
123+
},
124+
{
125+
"name": "SERVICE_NAME",
126+
"value": "testroute"
127+
},
128+
{
129+
"name": "ADDITIONAL_ENV_VAR_1",
130+
"value": "myvalue1"
131+
},
132+
{
133+
"name": "ADDITIONAL_ENV_VAR_2",
134+
"value": "myvalue2"
135+
}
136+
],
137+
"envFrom": [
138+
{
139+
"configMapRef": {
140+
"name": "my-config"
141+
}
142+
},
143+
{
144+
"secretRef": {
145+
"name": "my-secret"
146+
}
123147
}
124148
]
125149
}

operator/webhook/test/test_sync.py

+35-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import copy
22
import json
3+
from pathlib import PurePosixPath
34
from typing import Mapping
45

56
import pytest
@@ -71,7 +72,7 @@ def test_spring_app_config_json_missing_props_and_secret_sources(full_route):
7172

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

74-
expected_json = {"spring": {"application": {"name": "testroute"}}, "server": {"ssl": {"key-alias": "certificate", "key-store": "/etc/keystore/test-keystore.jks", "key-store-type": "JKS"}, "port": 8443}}
75+
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}}
7576

7677
assert json_props == expected_json
7778

@@ -132,7 +133,7 @@ def test_jdk_options_pkcs12_type(full_route):
132133

133134
assert options["name"] == JDK_OPTIONS_ENV_NAME
134135

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

138139

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

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

150151

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

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

159+
def test_env_var_service_name(full_route):
160+
actual_env_vars = _generate_container_env_vars(full_route)
161+
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)
162+
expected_service_name_env_var = {"name": "SERVICE_NAME", "value": "testroute"}
163+
assert expected_service_name_env_var == actual_service_name_env_var
164+
165+
166+
def test_no_additional_env_vars(full_route):
167+
additional_env_vars_to_remove_from_expected_response = ["ADDITIONAL_ENV_VAR_1", "ADDITIONAL_ENV_VAR_2"]
168+
169+
expected_response = load_json("json/full-response.json")
170+
env_vars_in_response = list(expected_response["children"][0]["spec"]["template"]["spec"]["containers"][0]["env"])
171+
for env_var in env_vars_in_response:
172+
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]:
173+
expected_response["children"][0]["spec"]["template"]["spec"]["containers"][0]["env"].remove(env_var)
174+
175+
del full_route["spec"]["env"]
176+
actual_response = sync(full_route)
177+
178+
assert expected_response == actual_response
179+
180+
181+
def test_no_env_from(full_route):
182+
expected_response = load_json("json/full-response.json")
183+
del expected_response["children"][0]["spec"]["template"]["spec"]["containers"][0]["envFrom"]
184+
185+
del full_route["spec"]["envFrom"]
186+
actual_response = sync(full_route)
187+
188+
assert expected_response == actual_response
189+
158190

159191
def test_deployment_missing_labels(full_route):
160192
del full_route["spec"]["labels"]

0 commit comments

Comments
 (0)