Skip to content

Commit 469bd3f

Browse files
Merge pull request openshift#7157 from bfournie/config-iso
AGENT-563: Create configuration image
2 parents 73b4b2a + 386d4aa commit 469bd3f

File tree

6 files changed

+403
-24
lines changed

6 files changed

+403
-24
lines changed

cmd/openshift-install/agent.go

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"github.com/openshift/installer/cmd/openshift-install/agent"
77
"github.com/openshift/installer/pkg/asset"
88
"github.com/openshift/installer/pkg/asset/agent/agentconfig"
9+
"github.com/openshift/installer/pkg/asset/agent/configimage"
910
"github.com/openshift/installer/pkg/asset/agent/image"
1011
"github.com/openshift/installer/pkg/asset/agent/manifests"
1112
"github.com/openshift/installer/pkg/asset/agent/mirror"
@@ -70,6 +71,21 @@ var (
7071
},
7172
}
7273

74+
agentConfigImageTarget = target{
75+
name: "Agent Config Image",
76+
command: &cobra.Command{
77+
Use: "config-image",
78+
Short: "Generates an ISO containing configuration files only",
79+
Args: cobra.ExactArgs(0),
80+
},
81+
assets: []asset.WritableAsset{
82+
&configimage.ConfigImage{},
83+
&kubeconfig.AgentAdminClient{},
84+
&password.KubeadminPassword{},
85+
},
86+
}
87+
88+
//nolint:varcheck,deadcode
7389
agentPXEFilesTarget = target{
7490
name: "Agent PXE Files",
7591
command: &cobra.Command{
@@ -84,7 +100,7 @@ var (
84100
},
85101
}
86102

87-
agentTargets = []target{agentConfigTarget, agentManifestsTarget, agentImageTarget, agentPXEFilesTarget}
103+
agentTargets = []target{agentConfigTarget, agentManifestsTarget, agentImageTarget, agentPXEFilesTarget, agentConfigImageTarget}
88104
)
89105

90106
func newAgentCreateCmd() *cobra.Command {

cmd/openshift-install/agent_internal_integration_test.go

Lines changed: 66 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ func runIntegrationTest(t *testing.T, testFolder string) {
107107
Cmds: map[string]func(*testscript.TestScript, bool, []string){
108108
"isocmp": isoCmp,
109109
"ignitionImgContains": ignitionImgContains,
110+
"configImgContains": configImgContains,
110111
"initrdImgContains": initrdImgContains,
111112
},
112113
})
@@ -123,12 +124,39 @@ func ignitionImgContains(ts *testscript.TestScript, neg bool, args []string) {
123124
isoPath, eFilePath := args[0], args[1]
124125
isoPathAbs := filepath.Join(workDir, isoPath)
125126

126-
_, err := extractFileFromIgnitionImg(isoPathAbs, eFilePath)
127+
_, err := extractArchiveFile(isoPathAbs, "/images/ignition.img", eFilePath)
127128
ts.Check(err)
128129
}
129130

131+
// [!] configImgContains `isoPath` `file` check if the specified file `file`
132+
// is stored within the config image ISO.
133+
func configImgContains(ts *testscript.TestScript, neg bool, args []string) {
134+
if len(args) != 2 {
135+
ts.Fatalf("usage: configImgContains isoPath file")
136+
}
137+
138+
workDir := ts.Getenv("WORK")
139+
isoPath, eFilePath := args[0], args[1]
140+
isoPathAbs := filepath.Join(workDir, isoPath)
141+
142+
_, err := extractArchiveFile(isoPathAbs, eFilePath, "")
143+
ts.Check(err)
144+
}
145+
146+
// archiveFileNames `isoPath` get the names of the archive files to use
147+
// based on the name of the ISO image.
148+
func archiveFileNames(isoPath string) (string, string, error) {
149+
if strings.HasPrefix(isoPath, "agent.") {
150+
return "/images/ignition.img", "config.ign", nil
151+
} else if strings.HasPrefix(isoPath, "agentconfig.") {
152+
return "/config.gz", "", nil
153+
}
154+
155+
return "", "", errors.NotFound(fmt.Sprintf("ISO %s has unrecognized prefix", isoPath))
156+
}
157+
130158
// [!] isoCmp `isoPath` `isoFile` `expectedFile` check that the content of the file
131-
// `isoFile` - extracted from the ISO embedded ignition configuration file referenced
159+
// `isoFile` - extracted from the ISO embedded configuration file referenced
132160
// by `isoPath` - matches the content of the local file `expectedFile`.
133161
func isoCmp(ts *testscript.TestScript, neg bool, args []string) {
134162
if len(args) != 3 {
@@ -139,7 +167,12 @@ func isoCmp(ts *testscript.TestScript, neg bool, args []string) {
139167
isoPath, aFilePath, eFilePath := args[0], args[1], args[2]
140168
isoPathAbs := filepath.Join(workDir, isoPath)
141169

142-
aData, err := readFileFromISOIgnitionCfg(isoPathAbs, aFilePath)
170+
archiveFile, ignitionFile, err := archiveFileNames(isoPath)
171+
if err != nil {
172+
ts.Check(err)
173+
}
174+
175+
aData, err := readFileFromISO(isoPathAbs, archiveFile, ignitionFile, aFilePath)
143176
ts.Check(err)
144177

145178
eFilePathAbs := filepath.Join(workDir, eFilePath)
@@ -171,26 +204,16 @@ func isoCmp(ts *testscript.TestScript, neg bool, args []string) {
171204
ts.Fatalf("%s and %s differ", aFilePath, eFilePath)
172205
}
173206

174-
func readFileFromISOIgnitionCfg(isoPath string, nodePath string) ([]byte, error) {
175-
config, err := extractIgnitionCfg(isoPath)
207+
func readFileFromISO(isoPath, archiveFile, ignitionFile, nodePath string) ([]byte, error) {
208+
config, err := extractCfgData(isoPath, archiveFile, ignitionFile, nodePath)
176209
if err != nil {
177210
return nil, err
178211
}
179212

180-
for _, f := range config.Storage.Files {
181-
if f.Node.Path == nodePath {
182-
actualData, err := dataurl.DecodeString(*f.FileEmbedded1.Contents.Source)
183-
if err != nil {
184-
return nil, err
185-
}
186-
return actualData.Data, nil
187-
}
188-
}
189-
190-
return nil, errors.NotFound(nodePath)
213+
return config, nil
191214
}
192215

193-
func extractFileFromIgnitionImg(isoPath string, fileName string) ([]byte, error) {
216+
func extractArchiveFile(isoPath, archive, fileName string) ([]byte, error) {
194217
disk, err := diskfs.OpenWithMode(isoPath, diskfs.ReadOnly)
195218
if err != nil {
196219
return nil, err
@@ -201,7 +224,7 @@ func extractFileFromIgnitionImg(isoPath string, fileName string) ([]byte, error)
201224
return nil, err
202225
}
203226

204-
ignitionImg, err := fs.OpenFile("/images/ignition.img", os.O_RDONLY)
227+
ignitionImg, err := fs.OpenFile(archive, os.O_RDONLY)
205228
if err != nil {
206229
return nil, err
207230
}
@@ -223,7 +246,8 @@ func extractFileFromIgnitionImg(isoPath string, fileName string) ([]byte, error)
223246
return nil, err
224247
}
225248

226-
if header.Name == fileName {
249+
// If the file is not in ignition return it directly
250+
if fileName == "" || header.Name == fileName {
227251
rawContent, err := io.ReadAll(cpioReader)
228252
if err != nil {
229253
return nil, err
@@ -232,11 +256,20 @@ func extractFileFromIgnitionImg(isoPath string, fileName string) ([]byte, error)
232256
}
233257
}
234258

235-
return nil, errors.NotFound(fmt.Sprintf("File %s not found within the /images/ignition.img archive", fileName))
259+
return nil, errors.NotFound(fmt.Sprintf("File %s not found within the %s archive", fileName, archive))
236260
}
237261

238-
func extractIgnitionCfg(isoPath string) (*igntypes.Config, error) {
239-
rawContent, err := extractFileFromIgnitionImg(isoPath, "config.ign")
262+
func extractCfgData(isoPath, archiveFile, ignitionFile, nodePath string) ([]byte, error) {
263+
if ignitionFile == "" {
264+
// If the archive is not part of an ignition file return the archive data
265+
rawContent, err := extractArchiveFile(isoPath, archiveFile, nodePath)
266+
if err != nil {
267+
return nil, err
268+
}
269+
return rawContent, nil
270+
}
271+
272+
rawContent, err := extractArchiveFile(isoPath, archiveFile, ignitionFile)
240273
if err != nil {
241274
return nil, err
242275
}
@@ -247,7 +280,17 @@ func extractIgnitionCfg(isoPath string) (*igntypes.Config, error) {
247280
return nil, err
248281
}
249282

250-
return &config, nil
283+
for _, f := range config.Storage.Files {
284+
if f.Node.Path == nodePath {
285+
actualData, err := dataurl.DecodeString(*f.FileEmbedded1.Contents.Source)
286+
if err != nil {
287+
return nil, err
288+
}
289+
return actualData.Data, nil
290+
}
291+
}
292+
293+
return nil, errors.NotFound(fmt.Sprintf("File %s not found within the %s archive", nodePath, archiveFile))
251294
}
252295

253296
// [!] initrdImgContains `isoPath` `file` check if the specified file `file`
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# Verify that the most relevant assets are properly generated in the ISO
2+
3+
exec openshift-install agent create config-image --dir $WORK
4+
5+
exists $WORK/agentconfig.noarch.iso
6+
7+
configImgContains agentconfig.noarch.iso /config.gz
8+
9+
-- install-config.yaml --
10+
apiVersion: v1
11+
baseDomain: test.metalkube.org
12+
controlPlane:
13+
name: master
14+
replicas: 1
15+
compute:
16+
- name: worker
17+
replicas: 0
18+
metadata:
19+
namespace: cluster0
20+
name: ostest
21+
networking:
22+
clusterNetwork:
23+
- cidr: 10.128.0.0/14
24+
hostPrefix: 23
25+
networkType: OVNKubernetes
26+
machineNetwork:
27+
- cidr: 192.168.111.0/24
28+
serviceNetwork:
29+
- 172.30.0.0/16
30+
platform:
31+
none: {}
32+
sshKey: ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDK6UTEydcEKzuNdPaofn8Z2DwgHqdcionLZBiPf/zIRNco++etLsat7Avv7yt04DINQd5zjxIFgG8jblaUB5E5C9ClUcMwb52GO0ay2Y9v1uBv1a4WhI3peKktAzYNk0EBMQlJtXPjRMrC9ylBPh+DsBHMu+KmDnfk7PIwyN4efC8k5kSRuPWoNdme1rz2+umU8FSmaWTHIajrbspf4GQbsntA5kuKEtDbfoNCU97o2KrRnUbeg3a8hwSjfh3u6MhlnGcg5K2Ij+zivEsWGCLKYUtE1ErqwfIzwWmJ6jnV66XCQGHf4Q1iIxqF7s2a1q24cgG2Z/iDXfqXrCIfy4P7b/Ztak3bdT9jfAdVZtdO5/r7I+O5hYhF86ayFlDWzZWP/ByiSb+q4CQbfVgK3BMmiAv2MqLHdhesmD/SmIcoOWUF6rFmRKZVFFpKpt5ATNTgUJ3JRowoXrrDruVXClUGRiCS6Zabd1rZ3VmTchaPJwtzQMdfIWISXj+Ig+C4UK0=
33+
pullSecret: '{"auths": {"quay.io": {"auth": "c3VwZXItc2VjcmV0Cg=="}}}'
34+
35+
-- agent-config.yaml --
36+
apiVersion: v1alpha1
37+
metadata:
38+
name: ostest
39+
namespace: cluster0
40+
rendezvousIP: 192.168.111.20
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
# Verify that the basic manifests are properly generated within the /etc/assisted/manifests folder
2+
3+
exec openshift-install agent create config-image --dir $WORK
4+
5+
exists $WORK/agentconfig.noarch.iso
6+
7+
isocmp agentconfig.noarch.iso /etc/assisted/manifests/agent-cluster-install.yaml expected/agent-cluster-install.yaml
8+
isocmp agentconfig.noarch.iso /etc/assisted/manifests/cluster-image-set.yaml expected/cluster-image-set.yaml
9+
isocmp agentconfig.noarch.iso /etc/assisted/manifests/pull-secret.yaml expected/pull-secret.yaml
10+
isocmp agentconfig.noarch.iso /etc/assisted/manifests/cluster-deployment.yaml expected/cluster-deployment.yaml
11+
12+
-- install-config.yaml --
13+
apiVersion: v1
14+
baseDomain: test.metalkube.org
15+
controlPlane:
16+
name: master
17+
replicas: 1
18+
compute:
19+
- name: worker
20+
replicas: 0
21+
metadata:
22+
namespace: cluster0
23+
name: ostest
24+
networking:
25+
clusterNetwork:
26+
- cidr: 10.128.0.0/14
27+
hostPrefix: 23
28+
networkType: OVNKubernetes
29+
machineNetwork:
30+
- cidr: 192.168.111.0/24
31+
serviceNetwork:
32+
- 172.30.0.0/16
33+
platform:
34+
none: {}
35+
sshKey: ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDK6UTEydcEKzuNdPaofn8Z2DwgHqdcionLZBiPf/zIRNco++etLsat7Avv7yt04DINQd5zjxIFgG8jblaUB5E5C9ClUcMwb52GO0ay2Y9v1uBv1a4WhI3peKktAzYNk0EBMQlJtXPjRMrC9ylBPh+DsBHMu+KmDnfk7PIwyN4efC8k5kSRuPWoNdme1rz2+umU8FSmaWTHIajrbspf4GQbsntA5kuKEtDbfoNCU97o2KrRnUbeg3a8hwSjfh3u6MhlnGcg5K2Ij+zivEsWGCLKYUtE1ErqwfIzwWmJ6jnV66XCQGHf4Q1iIxqF7s2a1q24cgG2Z/iDXfqXrCIfy4P7b/Ztak3bdT9jfAdVZtdO5/r7I+O5hYhF86ayFlDWzZWP/ByiSb+q4CQbfVgK3BMmiAv2MqLHdhesmD/SmIcoOWUF6rFmRKZVFFpKpt5ATNTgUJ3JRowoXrrDruVXClUGRiCS6Zabd1rZ3VmTchaPJwtzQMdfIWISXj+Ig+C4UK0=
36+
pullSecret: '{"auths": {"quay.io": {"auth": "c3VwZXItc2VjcmV0Cg=="}}}'
37+
38+
-- agent-config.yaml --
39+
apiVersion: v1alpha1
40+
metadata:
41+
name: ostest
42+
namespace: cluster0
43+
rendezvousIP: 192.168.111.20
44+
45+
-- expected/agent-cluster-install.yaml --
46+
metadata:
47+
creationTimestamp: null
48+
name: ostest
49+
namespace: cluster0
50+
spec:
51+
clusterDeploymentRef:
52+
name: ostest
53+
imageSetRef:
54+
name: openshift-was not built correctly
55+
networking:
56+
clusterNetwork:
57+
- cidr: 10.128.0.0/14
58+
hostPrefix: 23
59+
machineNetwork:
60+
- cidr: 192.168.111.0/24
61+
networkType: OVNKubernetes
62+
serviceNetwork:
63+
- 172.30.0.0/16
64+
platformType: None
65+
provisionRequirements:
66+
controlPlaneAgents: 1
67+
sshPublicKey: ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDK6UTEydcEKzuNdPaofn8Z2DwgHqdcionLZBiPf/zIRNco++etLsat7Avv7yt04DINQd5zjxIFgG8jblaUB5E5C9ClUcMwb52GO0ay2Y9v1uBv1a4WhI3peKktAzYNk0EBMQlJtXPjRMrC9ylBPh+DsBHMu+KmDnfk7PIwyN4efC8k5kSRuPWoNdme1rz2+umU8FSmaWTHIajrbspf4GQbsntA5kuKEtDbfoNCU97o2KrRnUbeg3a8hwSjfh3u6MhlnGcg5K2Ij+zivEsWGCLKYUtE1ErqwfIzwWmJ6jnV66XCQGHf4Q1iIxqF7s2a1q24cgG2Z/iDXfqXrCIfy4P7b/Ztak3bdT9jfAdVZtdO5/r7I+O5hYhF86ayFlDWzZWP/ByiSb+q4CQbfVgK3BMmiAv2MqLHdhesmD/SmIcoOWUF6rFmRKZVFFpKpt5ATNTgUJ3JRowoXrrDruVXClUGRiCS6Zabd1rZ3VmTchaPJwtzQMdfIWISXj+Ig+C4UK0=
68+
status:
69+
debugInfo:
70+
eventsURL: ""
71+
logsURL: ""
72+
progress:
73+
totalPercentage: 0
74+
-- expected/cluster-deployment.yaml --
75+
apiVersion: v1
76+
kind: ClusterDeployment
77+
metadata:
78+
creationTimestamp: null
79+
name: ostest
80+
namespace: cluster0
81+
spec:
82+
baseDomain: test.metalkube.org
83+
clusterInstallRef:
84+
group: extensions.hive.openshift.io
85+
kind: AgentClusterInstall
86+
name: ostest
87+
version: v1beta1
88+
clusterName: ostest
89+
controlPlaneConfig:
90+
servingCertificates: {}
91+
installed: false
92+
platform: {}
93+
pullSecretRef:
94+
name: ostest-pull-secret
95+
status: {}
96+
-- expected/cluster-image-set.yaml --
97+
metadata:
98+
creationTimestamp: null
99+
name: openshift-was not built correctly
100+
namespace: cluster0
101+
spec:
102+
releaseImage: registry.ci.openshift.org/origin/release:4.14
103+
status: {}
104+
-- expected/pull-secret.yaml --
105+
apiVersion: v1
106+
kind: Secret
107+
metadata:
108+
creationTimestamp: null
109+
name: ostest-pull-secret
110+
namespace: cluster0
111+
stringData:
112+
.dockerconfigjson: |-
113+
{
114+
"auths": {
115+
"quay.io": {
116+
"auth": "c3VwZXItc2VjcmV0Cg=="
117+
}
118+
}
119+
}

0 commit comments

Comments
 (0)