Skip to content

Commit 691dc23

Browse files
authored
[minor] Support IBM entitlement key mgmt (#39)
1 parent 2587c15 commit 691dc23

8 files changed

Lines changed: 166 additions & 2 deletions

File tree

.secrets.baseline

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"files": "^.secrets.baseline$",
44
"lines": null
55
},
6-
"generated_at": "2024-10-18T09:38:24Z",
6+
"generated_at": "2024-11-24T13:39:40Z",
77
"plugins_used": [
88
{
99
"name": "AWSKeyDetector"
@@ -77,6 +77,16 @@
7777
}
7878
],
7979
"results": {
80+
"src/mas/devops/templates/ibm-entitlement-dockerconfig.json.j2": [
81+
{
82+
"hashed_secret": "d2e2ab0f407e4ee3cf2ab87d61c31b25a74085e5",
83+
"is_secret": false,
84+
"is_verified": false,
85+
"line_number": 28,
86+
"type": "Secret Keyword",
87+
"verified_result": null
88+
}
89+
],
8090
"test/src/test_db2.py": [
8191
{
8292
"hashed_secret": "a4b48a81cdab1e1a5dd37907d6c85ca1c61ddc7c",
@@ -87,6 +97,24 @@
8797
"verified_result": null
8898
}
8999
],
100+
"test/src/test_mas.py": [
101+
{
102+
"hashed_secret": "94f5ed592906089c107208b29e178ddf1f9f5143",
103+
"is_secret": false,
104+
"is_verified": false,
105+
"line_number": 35,
106+
"type": "Secret Keyword",
107+
"verified_result": null
108+
},
109+
{
110+
"hashed_secret": "a9410d9785f49750b9f8672794fc288558c1611c",
111+
"is_secret": false,
112+
"is_verified": false,
113+
"line_number": 48,
114+
"type": "Secret Keyword",
115+
"verified_result": null
116+
}
117+
],
90118
"test/test_cases/manage_fail/db2set.txt": [
91119
{
92120
"hashed_secret": "bd78032d1e51d595c52a633d3041cf7a22bddbf5",

MANIFEST.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
1+
include src/mas/devops/templates/*.json.j2
12
include src/mas/devops/templates/*.yml.j2
23
include src/mas/devops/data/catalogs/*.yaml

setup.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,8 @@ def get_version(rel_path):
5959
'openshift', # Apache Software License
6060
'kubernetes', # Apache Software License
6161
'kubeconfig', # BSD License
62-
'jinja2' # BSD License
62+
'jinja2', # BSD License
63+
'jinja2-base64-filters' # MIT License
6364
],
6465
extras_require={
6566
'dev': [

src/mas/devops/mas.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,13 @@
1010

1111
import logging
1212
import re
13+
import yaml
14+
from os import path
1315
from types import SimpleNamespace
16+
from kubernetes.dynamic.resource import ResourceInstance
1417
from openshift.dynamic import DynamicClient
1518
from openshift.dynamic.exceptions import NotFoundError, UnauthorizedError
19+
from jinja2 import Environment, FileSystemLoader
1620

1721
from .ocp import getStorageClasses
1822

@@ -135,3 +139,36 @@ def verifyMasInstance(dynClient: DynamicClient, instanceId: str) -> bool:
135139
except UnauthorizedError:
136140
logger.error("Error: Unable to verify MAS instance due to failed authorization: {e}")
137141
return False
142+
143+
144+
def updateIBMEntitlementKey(dynClient: DynamicClient, namespace: str, icrUsername: str, icrPassword: str, artifactoryUsername: str = None, artifactoryPassword: str = None, secretName: str = "ibm-entitlement") -> ResourceInstance:
145+
if artifactoryUsername is not None:
146+
logger.info(f"Updating IBM Entitlement ({secretName}) in namespace '{namespace}' (with Artifactory access)")
147+
else:
148+
logger.info(f"Updating IBM Entitlement ({secretName}) in namespace '{namespace}'")
149+
150+
templateDir = path.join(path.abspath(path.dirname(__file__)), "templates")
151+
env = Environment(
152+
loader=FileSystemLoader(searchpath=templateDir),
153+
extensions=["jinja2_base64_filters.Base64Filters"]
154+
)
155+
156+
contentTemplate = env.get_template("ibm-entitlement-dockerconfig.json.j2")
157+
dockerConfig = contentTemplate.render(
158+
artifactory_username=artifactoryUsername,
159+
artifactory_token=artifactoryPassword,
160+
icr_username=icrUsername,
161+
icr_password=icrPassword
162+
)
163+
164+
template = env.get_template("ibm-entitlement-secret.yml.j2")
165+
renderedTemplate = template.render(
166+
name=secretName,
167+
namespace=namespace,
168+
docker_config=dockerConfig
169+
)
170+
secret = yaml.safe_load(renderedTemplate)
171+
secretsAPI = dynClient.resources.get(api_version="v1", kind="Secret")
172+
173+
secret = secretsAPI.apply(body=secret, namespace=namespace)
174+
return secret

src/mas/devops/olm.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,9 @@ def applySubscription(dynClient: DynamicClient, namespace: str, packageName: str
6262
Usage:
6363
createSubscription(dynClient, "testns1", "sub1", "ibm-sls") # use default channel, & auto-detect CatalogSource
6464
"""
65+
if catalogSourceNamespace is None:
66+
catalogSourceNamespace = "openshift-marketplace"
67+
6568
labelSelector = f"operators.coreos.com/{packageName}.{namespace}"
6669
templateDir = path.join(path.abspath(path.dirname(__file__)), "templates")
6770
env = Environment(
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
{
2+
"auths": {
3+
{%- if artifactory_username is defined and artifactory_username != "" %}
4+
"docker-na-public.artifactory.swg-devops.com/wiotp-docker-local": {
5+
"username": "{{ artifactory_username }}",
6+
"password": "{{ artifactory_token }}",
7+
"auth": "{{ (artifactory_username ~ ':' ~ artifactory_token) | b64encode }}"
8+
},
9+
"docker-na-proxy-svl.artifactory.swg-devops.com/wiotp-docker-local": {
10+
"username": "{{ artifactory_username }}",
11+
"password": "{{ artifactory_token }}",
12+
"auth": "{{ (artifactory_username ~ ':' ~ artifactory_token) | b64encode }}"
13+
},
14+
"docker-na-proxy-rtp.artifactory.swg-devops.com/wiotp-docker-local": {
15+
"username": "{{ artifactory_username }}",
16+
"password": "{{ artifactory_token }}",
17+
"auth": "{{ (artifactory_username ~ ':' ~ artifactory_token) | b64encode }}"
18+
{%- if icr_username is defined and icr_username != "" %}
19+
},
20+
{%- else %}
21+
}
22+
{%- endif %}
23+
{%- endif %}
24+
{%- if icr_username is defined and icr_username != "" %}
25+
"cp.icr.io/cp": {
26+
"username": "{{ icr_username }}",
27+
"password": "{{ icr_password }}",
28+
"auth": "{{ (icr_username ~ ':' ~ icr_password) | b64encode }}"
29+
}
30+
{%- endif %}
31+
}
32+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
---
2+
apiVersion: v1
3+
kind: Secret
4+
type: kubernetes.io/dockerconfigjson
5+
metadata:
6+
name: "{{ name }}"
7+
namespace: "{{ namespace }}"
8+
data:
9+
.dockerconfigjson: "{{ docker_config | b64encode }}"

test/src/test_mas.py

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# *****************************************************************************
2+
# Copyright (c) 2024 IBM Corporation and other Contributors.
3+
#
4+
# All rights reserved. This program and the accompanying materials
5+
# are made available under the terms of the Eclipse Public License v1.0
6+
# which accompanies this distribution, and is available at
7+
# http://www.eclipse.org/legal/epl-v10.html
8+
#
9+
# *****************************************************************************
10+
11+
from openshift import dynamic
12+
from kubernetes import config
13+
from kubernetes.client import api_client
14+
from kubernetes.dynamic.resource import ResourceInstance
15+
16+
from mas.devops import mas
17+
18+
dynClient = dynamic.DynamicClient(
19+
api_client.ApiClient(configuration=config.load_kube_config())
20+
)
21+
22+
23+
def test_entitlement():
24+
icrUsername = "testing-i"
25+
icrPassword = "not-a-real-password-i"
26+
27+
secret = mas.updateIBMEntitlementKey(dynClient, "default", icrUsername, icrPassword)
28+
assert secret is not None
29+
assert isinstance(secret, ResourceInstance)
30+
assert secret.metadata.name == "ibm-entitlement"
31+
32+
33+
def test_entitlement_with_artifactory():
34+
artifactoryUsername = "testing-a"
35+
artifactoryPassword = "not-a-real-password-a"
36+
37+
icrUsername = "testing-i"
38+
icrPassword = "not-a-real-password-i"
39+
40+
secret = mas.updateIBMEntitlementKey(dynClient, "default", icrUsername, icrPassword, artifactoryUsername, artifactoryPassword)
41+
assert secret is not None
42+
assert isinstance(secret, ResourceInstance)
43+
assert secret.metadata.name == "ibm-entitlement"
44+
45+
46+
def test_entitlement_alt_name():
47+
icrUsername = "testing-i"
48+
icrPassword = "not-a-real-password-i"
49+
50+
secret = mas.updateIBMEntitlementKey(dynClient, "default", icrUsername, icrPassword, secretName="ibm-entitlement-key")
51+
assert secret is not None
52+
assert isinstance(secret, ResourceInstance)
53+
assert secret.metadata.name == "ibm-entitlement-key"

0 commit comments

Comments
 (0)