Skip to content

Commit 6bd9c7b

Browse files
schnatterernihussmann
authored andcommitted
Move creation of example-apps pull secrets to new Content class
Registry does not have anything to do with this. It's only for the content, because we add the secrets to the content namespaces. Also: The namespaces need to be created before adding the secrets. Why should Registry.groovy create these Namespaces? It's not a concern of the registry! Similar to Mailhog, Vault, etc that create their own secrets. The rest of the content remains in ArgoCD.groovy for now, but we will refactor it to Content.groovy in the future.
1 parent eb13386 commit 6bd9c7b

File tree

9 files changed

+180
-113
lines changed

9 files changed

+180
-113
lines changed

src/main/groovy/com/cloudogu/gitops/cli/GitopsPlaygroundCliMainScripted.groovy

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ class GitopsPlaygroundCliMainScripted {
113113
new Jenkins(config, executor, fileSystemUtils, new GlobalPropertyManager(jenkinsApiClient),
114114
new JobManager(jenkinsApiClient), new UserManager(jenkinsApiClient),
115115
new PrometheusConfigurator(jenkinsApiClient)),
116+
new Content(config,k8sClient),
116117
new ArgoCD(config, k8sClient, helmClient, fileSystemUtils, scmmRepoProvider),
117118
new IngressNginx(config, fileSystemUtils, deployer, k8sClient, airGappedUtils),
118119
new Mailhog(config, fileSystemUtils, deployer, k8sClient, airGappedUtils),
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package com.cloudogu.gitops.features
2+
3+
import com.cloudogu.gitops.Feature
4+
import com.cloudogu.gitops.config.Configuration
5+
import com.cloudogu.gitops.utils.K8sClient
6+
import groovy.util.logging.Slf4j
7+
import io.micronaut.core.annotation.Order
8+
import jakarta.inject.Singleton
9+
10+
@Slf4j
11+
@Singleton
12+
@Order(80)
13+
class Content extends Feature {
14+
15+
Map config
16+
K8sClient k8sClient
17+
18+
Content(
19+
Configuration config,
20+
K8sClient k8sClient
21+
) {
22+
this.config = config.getConfig()
23+
this.k8sClient = k8sClient
24+
}
25+
26+
27+
@Override
28+
boolean isEnabled() {
29+
return true // for now always on. Once we refactor from Argo CD class we add a param to enable
30+
}
31+
32+
@Override
33+
void enable() {
34+
if (config.registry['createImagePullSecrets']) {
35+
String registryUsername = config.registry['readOnlyUsername'] ?: config.registry['username']
36+
String registryPassword = config.registry['readOnlyPassword'] ?: config.registry['password']
37+
38+
// Name prefix is added by k8sClient
39+
List exampleAppNamespaces = [ "example-apps-staging", "example-apps-production"]
40+
exampleAppNamespaces.each {
41+
def namespace = it as String
42+
def registrySecretName = 'registry'
43+
44+
k8sClient.createNamespace(it)
45+
46+
k8sClient.createImagePullSecret(registrySecretName, namespace,
47+
config.registry['url'] as String /* Only domain matters, path would be ignored */,
48+
registryUsername, registryPassword)
49+
50+
k8sClient.patch('serviceaccount', 'default', namespace,
51+
[ imagePullSecrets: [ [name: registrySecretName] ]])
52+
53+
if (config.registry['twoRegistries']) {
54+
k8sClient.createImagePullSecret('proxy-registry', namespace,
55+
config.registry['proxyUrl'] as String, config.registry['proxyUsername'] as String,
56+
config.registry['proxyPassword'] as String)
57+
}
58+
}
59+
}
60+
}
61+
}

src/main/groovy/com/cloudogu/gitops/features/Jenkins.groovy

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import jakarta.inject.Singleton
1515

1616
@Slf4j
1717
@Singleton
18-
@Order(90)
18+
@Order(70)
1919
class Jenkins extends Feature {
2020

2121
private Map config

src/main/groovy/com/cloudogu/gitops/features/Registry.groovy

Lines changed: 8 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import java.nio.file.Path
1515

1616
@Slf4j
1717
@Singleton
18-
@Order(60)
18+
@Order(50)
1919
class Registry extends Feature {
2020

2121
/**
@@ -45,65 +45,34 @@ class Registry extends Feature {
4545

4646
@Override
4747
boolean isEnabled() {
48-
return true // For now, we either deploy an internal or configure an external instance
48+
return config.registry['internal']
4949
}
5050

5151
@Override
5252
void enable() {
53-
54-
if (config.registry['internal']) {
55-
deployRegistry()
56-
}
57-
58-
if (config.registry['createImagePullSecrets']) {
59-
String registryUsername = config.registry['readOnlyUsername'] ?: config.registry['username']
60-
String registryPassword = config.registry['readOnlyPassword'] ?: config.registry['password']
61-
62-
// Name prefix is added by k8sClient
63-
List exampleAppNamespaces = [ "example-apps-staging", "example-apps-production"]
64-
exampleAppNamespaces.each {
65-
def namespace = it as String
66-
def registrySecretName = 'registry'
67-
k8sClient.createImagePullSecret(registrySecretName, namespace,
68-
config.registry['url'] as String/* Only domain matters, path would be ignored */,
69-
registryUsername, registryPassword)
70-
71-
k8sClient.patch('serviceaccount', 'default', namespace,
72-
[ imagePullSecrets: [ [name: registrySecretName] ]])
73-
74-
if (config.registry['twoRegistries']) {
75-
k8sClient.createImagePullSecret('proxy-registry', namespace,
76-
config.registry['proxyUrl'] as String, config.registry['proxyUsername'] as String,
77-
config.registry['proxyPassword'] as String)
78-
}
79-
}
80-
}
81-
82-
}
8353

84-
private void deployRegistry() {
8554
def helmConfig = config['registry']['helm']
86-
55+
8756
Map yaml = [
8857
service: [
8958
nodePort: ApplicationConfigurator.DEFAULT_REGISTRY_PORT,
90-
type : 'NodePort'
59+
type: 'NodePort'
9160
]
9261
]
9362
log.trace("Helm yaml to be applied: ${yaml}")
9463
fileSystemUtils.writeYaml(yaml, tmpHelmValues.toFile())
95-
64+
9665
if (config['registry']['internalPort'] != ApplicationConfigurator.DEFAULT_REGISTRY_PORT) {
9766
/* Add additional node port
9867
30000 is needed as a static by docker via port mapping of k3d, e.g. 32769 -> 30000 on server-0 container
9968
See "-p 30000" in init-cluster.sh
10069
e.g 32769 is needed so the kubelet can access the image inside the server-0 container
10170
*/
102-
k8sClient.createServiceNodePort('docker-registry-internal-port',
71+
k8sClient.createServiceNodePort('docker-registry-internal-port',
10372
CONTAINER_PORT, config['registry']['internalPort'] as String,
10473
'default')
10574
}
106-
75+
10776
deployer.deployFeature(
10877
helmConfig['repoURL'] as String,
10978
'registry',
@@ -113,5 +82,6 @@ class Registry extends Feature {
11382
'docker-registry',
11483
tmpHelmValues
11584
)
85+
11686
}
11787
}

src/main/groovy/com/cloudogu/gitops/features/ScmManager.groovy

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import jakarta.inject.Singleton
1313

1414
@Slf4j
1515
@Singleton
16-
@Order(80)
16+
@Order(60)
1717
class ScmManager extends Feature {
1818

1919
static final String HELM_VALUES_PATH = "scm-manager/values.ftl.yaml"

src/test/groovy/com/cloudogu/gitops/ApplicationTest.groovy

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,6 @@ class ApplicationTest {
2626
.getBean(Application)
2727
def features = application.features.collect { it.class.simpleName }
2828

29-
assertThat(features).isEqualTo(["Registry", "ScmManager", "Jenkins", "ArgoCD", "IngressNginx", "Mailhog", "PrometheusStack", "ExternalSecretsOperator", "Vault"])
29+
assertThat(features).isEqualTo(["Registry", "ScmManager", "Jenkins", "Content", "ArgoCD", "IngressNginx", "Mailhog", "PrometheusStack", "ExternalSecretsOperator", "Vault"])
3030
}
3131
}

src/test/groovy/com/cloudogu/gitops/cli/GitopsPlaygroundCliMainScriptedTest.groovy

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ class GitopsPlaygroundCliMainScriptedTest {
8383
.enableAnnotationInfo()
8484
.scan().withCloseable { scanResult ->
8585
scanResult.getAllClasses().each { ClassInfo classInfo ->
86-
if (classInfo.name.endsWith("Test")) {
86+
if (classInfo.name.endsWith("Test") || classInfo.isAbstract()) {
8787
return
8888
}
8989

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
package com.cloudogu.gitops.features
2+
3+
import com.cloudogu.gitops.config.Configuration
4+
import com.cloudogu.gitops.utils.K8sClientForTest
5+
import groovy.yaml.YamlSlurper
6+
import org.junit.jupiter.api.Test
7+
8+
import static org.assertj.core.api.Assertions.assertThat
9+
10+
class ContentTest {
11+
12+
Map config = [
13+
registry : [
14+
url : 'reg-url',
15+
path : 'reg-path',
16+
username : 'reg-user',
17+
password : 'reg-pw',
18+
createImagePullSecrets: false,
19+
],
20+
application: [
21+
namePrefix: "foo-",
22+
],
23+
]
24+
K8sClientForTest k8sClient = new K8sClientForTest(config)
25+
26+
27+
@Test
28+
void 'deploys image pull secrets'() {
29+
config['registry']['createImagePullSecrets'] = true
30+
31+
createContent().install()
32+
33+
assertRegistrySecrets('reg-user', 'reg-pw')
34+
}
35+
36+
@Test
37+
void 'deploys image pull secrets from read-only vars'() {
38+
config['registry']['createImagePullSecrets'] = true
39+
config['registry']['readOnlyUsername'] = 'other-user'
40+
config['registry']['readOnlyPassword'] = 'other-pw'
41+
42+
createContent().install()
43+
44+
assertRegistrySecrets('other-user', 'other-pw')
45+
}
46+
47+
@Test
48+
void 'deploys image pull secrets for proxy registry'() {
49+
config['registry']['createImagePullSecrets'] = true
50+
config['registry']['twoRegistries'] = true
51+
config['registry']['proxyUrl'] = 'proxy-url'
52+
config['registry']['proxyUsername'] = 'proxy-user'
53+
config['registry']['proxyPassword'] = 'proxy-pw'
54+
55+
createContent().install()
56+
57+
assertRegistrySecrets('reg-user', 'reg-pw')
58+
59+
k8sClient.commandExecutorForTest.assertExecuted('kubectl create namespace foo-example-apps-staging')
60+
k8sClient.commandExecutorForTest.assertExecuted('kubectl create namespace foo-example-apps-production')
61+
k8sClient.commandExecutorForTest.assertExecuted(
62+
'kubectl create secret docker-registry proxy-registry -n foo-example-apps-staging' +
63+
' --docker-server proxy-url --docker-username proxy-user --docker-password proxy-pw')
64+
k8sClient.commandExecutorForTest.assertExecuted(
65+
'kubectl create secret docker-registry proxy-registry -n foo-example-apps-production' +
66+
' --docker-server proxy-url --docker-username proxy-user --docker-password proxy-pw')
67+
68+
}
69+
70+
private void assertRegistrySecrets(String regUser, String regPw) {
71+
List expectedNamespaces = ["foo-example-apps-staging", "foo-example-apps-production"]
72+
expectedNamespaces.each {
73+
74+
k8sClient.commandExecutorForTest.assertExecuted(
75+
"kubectl create secret docker-registry registry -n ${it}" +
76+
" --docker-server reg-url --docker-username $regUser --docker-password ${regPw}" +
77+
' --dry-run=client -oyaml | kubectl apply -f-')
78+
79+
def patchCommand = k8sClient.commandExecutorForTest.assertExecuted(
80+
"kubectl patch serviceaccount default -n ${it}")
81+
String patchFile = (patchCommand =~ /--patch-file=([\S]+)/)?.findResult { (it as List)[1] }
82+
assertThat(parseActualYaml(new File(patchFile))['imagePullSecrets'] as List).hasSize(1)
83+
assertThat((parseActualYaml(new File(patchFile))['imagePullSecrets'] as List)[0] as Map).containsEntry('name', 'registry')
84+
}
85+
}
86+
87+
private Content createContent() {
88+
new Content(new Configuration(config), k8sClient)
89+
}
90+
91+
private parseActualYaml(File pathToYamlFile) {
92+
def ys = new YamlSlurper()
93+
return ys.parse(pathToYamlFile)
94+
}
95+
}

src/test/groovy/com/cloudogu/gitops/features/RegistryTest.groovy

Lines changed: 11 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,13 @@ class RegistryTest {
1818

1919
Map config = [
2020
registry : [
21-
internal : true,
22-
url : 'reg-url',
23-
path : 'reg-path',
24-
username : 'reg-user',
25-
password : 'reg-pw',
26-
internalPort : ApplicationConfigurator.DEFAULT_REGISTRY_PORT,
27-
createImagePullSecrets: false,
28-
helm : [
21+
internal : true,
22+
url : '',
23+
path : '',
24+
username : '',
25+
password : '',
26+
internalPort: ApplicationConfigurator.DEFAULT_REGISTRY_PORT,
27+
helm : [
2928
chart : 'docker-registry',
3029
repoURL: 'https://charts.helm.sh/stable',
3130
version: '1.9.4'
@@ -41,7 +40,7 @@ class RegistryTest {
4140
File temporaryYamlFile
4241

4342
@Test
44-
void 'does not deploy internal registry, when external registry is configured'() {
43+
void 'is disabled when external registry is configured'() {
4544
config.registry['internal'] = false
4645

4746
createRegistry().install()
@@ -75,66 +74,7 @@ class RegistryTest {
7574

7675
assertThat(k8sClient.commandExecutorForTest.actualCommands[0]).contains("--node-port $expectedNodePort")
7776
}
78-
79-
@Test
80-
void 'deploys image pull secrets'() {
81-
config['registry']['createImagePullSecrets'] = true
82-
83-
createRegistry().install()
84-
85-
assertRegistrySecrets('reg-user', 'reg-pw')
86-
}
87-
88-
@Test
89-
void 'deploys image pull secrets from read-only vars'() {
90-
config['registry']['createImagePullSecrets'] = true
91-
config['registry']['readOnlyUsername'] = 'other-user'
92-
config['registry']['readOnlyPassword'] = 'other-pw'
93-
94-
createRegistry().install()
95-
96-
assertRegistrySecrets('other-user', 'other-pw')
97-
98-
}
99-
100-
@Test
101-
void 'deploys image pull secrets for proxy registry'() {
102-
config['registry']['createImagePullSecrets'] = true
103-
config['registry']['twoRegistries'] = true
104-
config['registry']['proxyUrl'] = 'proxy-url'
105-
config['registry']['proxyUsername'] = 'proxy-user'
106-
config['registry']['proxyPassword'] = 'proxy-pw'
107-
108-
createRegistry().install()
109-
110-
assertRegistrySecrets('reg-user', 'reg-pw')
111-
112-
k8sClient.commandExecutorForTest.assertExecuted(
113-
'kubectl create secret docker-registry proxy-registry -n foo-example-apps-staging' +
114-
' --docker-server proxy-url --docker-username proxy-user --docker-password proxy-pw')
115-
k8sClient.commandExecutorForTest.assertExecuted(
116-
'kubectl create secret docker-registry proxy-registry -n foo-example-apps-production' +
117-
' --docker-server proxy-url --docker-username proxy-user --docker-password proxy-pw')
118-
119-
}
120-
121-
private void assertRegistrySecrets(String regUser, String regPw) {
122-
List expectedNamespaces = ["foo-example-apps-staging", "foo-example-apps-production"]
123-
expectedNamespaces.each {
124-
125-
k8sClient.commandExecutorForTest.assertExecuted(
126-
"kubectl create secret docker-registry registry -n ${it}" +
127-
" --docker-server reg-url --docker-username $regUser --docker-password ${regPw}" +
128-
' --dry-run=client -oyaml | kubectl apply -f-')
129-
130-
def patchCommand = k8sClient.commandExecutorForTest.assertExecuted(
131-
"kubectl patch serviceaccount default -n ${it}")
132-
String patchFile = (patchCommand =~ /--patch-file=([\S]+)/)?.findResult { (it as List)[1] }
133-
assertThat(parseActualYaml(new File(patchFile))['imagePullSecrets'] as List).hasSize(1)
134-
assertThat((parseActualYaml(new File(patchFile))['imagePullSecrets'] as List)[0] as Map).containsEntry('name', 'registry')
135-
}
136-
}
137-
77+
13878
private Registry createRegistry() {
13979
// We use the real FileSystemUtils and not a mock to make sure file editing works as expected
14080

@@ -149,8 +89,8 @@ class RegistryTest {
14989
}, k8sClient, new HelmStrategy(new Configuration(config), helmClient))
15090
}
15191

152-
private parseActualYaml(File pathToYamlFile = temporaryYamlFile) {
92+
private parseActualYaml() {
15393
def ys = new YamlSlurper()
154-
return ys.parse(pathToYamlFile)
94+
return ys.parse(temporaryYamlFile)
15595
}
15696
}

0 commit comments

Comments
 (0)