Skip to content

Commit fd30059

Browse files
Merge pull request #9941 from zaneb/interactive-unconfigured
AGENT-1302,OCPBUGS-61668: Merge interactive ignition into unconfigured-ignition
2 parents 7c2208e + bfcc946 commit fd30059

File tree

11 files changed

+85
-67
lines changed

11 files changed

+85
-67
lines changed

cmd/openshift-install/testdata/agent/unconfigured-ignition/configurations/interactive.txt

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -90,11 +90,12 @@ status:
9090
debugInfo:
9191
eventsURL: ""
9292
-- expected/rendezvous-host.env --
93+
#{{ $$isIPv6 := false }}{{ $$host := .RendezvousIP }}{{ range ( len .RendezvousIP ) }}{{if eq ( index ( slice $$host . ) 0 ) ':'}}{{ $$isIPv6 = true }}{{ end }}{{ end }}
9394
NODE_ZERO_IP={{.RendezvousIP}}
94-
SERVICE_BASE_URL=http://{{.RendezvousIP}}:8090/
95-
IMAGE_SERVICE_BASE_URL=http://{{.RendezvousIP}}:8888/
95+
SERVICE_BASE_URL=http://{{ if $$isIPv6 }}{{ printf "[%s]" .RendezvousIP }}{{ else }}{{ .RendezvousIP }}{{ end }}:8090/
96+
IMAGE_SERVICE_BASE_URL=http://{{ if $$isIPv6 }}{{ printf "[%s]" .RendezvousIP }}{{ else }}{{ .RendezvousIP }}{{ end }}:8888/
9697
PULL_SECRET_TOKEN=
9798
USER_AUTH_TOKEN=
9899
WORKFLOW_TYPE=install-interactive-disconnected
99-
AIUI_APP_API_URL=http://{{.RendezvousIP}}:8090/
100-
AIUI_URL=http://{{.RendezvousIP}}:3001/
100+
AIUI_APP_API_URL=http://{{ if $$isIPv6 }}{{ printf "[%s]" .RendezvousIP }}{{ else }}{{ .RendezvousIP }}{{ end }}:8090/
101+
AIUI_URL=http://{{ if $$isIPv6 }}{{ printf "[%s]" .RendezvousIP }}{{ else }}{{ .RendezvousIP }}{{ end }}:3001/

data/data/agent/files/usr/local/bin/install-status.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ inactive_services() {
99

1010
if [ -f "/etc/assisted/interactive-ui" ]; then
1111
# interactive workflow
12-
services+=" agent-start-ui.service"
12+
services+=" agent-ui.service"
1313
elif [ -f "/etc/assisted/add-nodes.env" ]; then
1414
# add nodes workflow
1515
services+=" agent-import-cluster.service agent-register-infraenv.service apply-host-config.service agent-add-node.service"
@@ -53,7 +53,7 @@ check_host_config() {
5353

5454
check_ui() {
5555
local ui_issue="90_ui-availability"
56-
if systemctl is-active --quiet "agent-start-ui"; then
56+
if systemctl is-active --quiet "agent-ui"; then
5757
printf '\\e{green}Please go to \\e{lightgreen}%s\\e{reset}\\e{green} in your browser to continue the installation\\e{reset}' "${AIUI_URL}" | set_issue "${ui_issue}"
5858
else
5959
clear_issue "${ui_issue}"

data/data/agent/systemd/units/agent-check-config-image.service

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
Description=Displays message to console if config image has not been inserted or mounted in unconfigured-ignition environment
33
Wants=network-online.target
44
After=network-online.target
5+
ConditionPathExists=!/etc/assisted/no-config-image
56

67
[Service]
78
Type=oneshot
Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
[Unit]
22
Description=Extract agent-tui at boot
33
After=selinux.service start-local-registry.service
4-
Before=agent-interactive-console.service
5-
ConditionPathExists=/etc/assisted/rendezvous-host.env
4+
ConditionPathExists=/etc/assisted/rendezvous-host.env.template
65
ConditionPathExists=/etc/assisted/interactive-ui
6+
ConditionPathExists=!/usr/local/bin/agent-tui
77

88
[Service]
99
Type=oneshot
1010
ExecStart=/usr/local/bin/agent-extract-tui.sh
1111
TimeoutStartSec=300s
1212

1313
[Install]
14-
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
1-
### This is currently a draft placeholder for running the UI, to be completed
2-
31
[Unit]
4-
Description=Service that runs the Agent Installer UI
2+
Description=Agent Installer Web UI
53
Wants=network-online.target assisted-service.service
6-
Conflicts=agent-register-cluster.service agent-import-cluster.service
74
After=network-online.target assisted-service.service
85
PartOf=assisted-service-pod.service
96
ConditionPathExists=/etc/assisted/node0
@@ -13,15 +10,15 @@ ConditionPathExists=/etc/assisted/interactive-ui
1310
Environment=PODMAN_SYSTEMD_UNIT=%n
1411
EnvironmentFile=/usr/local/share/assisted-service/agent-images.env
1512
EnvironmentFile=/etc/assisted/rendezvous-host.env
13+
Restart=on-failure
1614
ExecStartPre=/bin/rm -f %t/%n.ctr-id
1715
ExecStartPre=/usr/local/bin/wait-for-assisted-service.sh
18-
ExecStart=/usr/bin/podman run --net host --cidfile=%t/%n.ctr-id --cgroups=no-conmon --log-driver=journald --restart=on-failure:10 --pod-id-file=%t/assisted-service-pod.pod-id --replace -d --name=agent-installer-ui --env AIUI_APP_API_URL $INSTALLER_UI_IMAGE
16+
ExecStart=/usr/bin/podman run --net host --cidfile=%t/%n.ctr-id --cgroups=no-conmon --log-driver=journald --rm --pod-id-file=%t/assisted-service-pod.pod-id --replace -d --name=agent-installer-ui --env AIUI_APP_API_URL $INSTALLER_UI_IMAGE
1917
ExecStop=/usr/bin/podman stop --ignore --cidfile=%t/%n.ctr-id
2018
ExecStopPost=/usr/bin/podman rm -f --ignore --cidfile=%t/%n.ctr-id
2119

2220
KillMode=mixed
23-
Type=oneshot
24-
RemainAfterExit=true
21+
Type=notify
2522

2623
[Install]
2724
WantedBy=multi-user.target

docs/user/agent/agent-services.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,5 +61,5 @@ The interactive workflow allows the user to install a cluster by using the assis
6161
the agent-tui is also used interactively to configure which node will be the rendezvous host, and to configure accordingly the other nodes.
6262

6363
* agent-extract-tui - extracts agent-tui and nmstate libraries from the agent-installer-utils image during boot
64-
* agent-start-ui - runs the assisted UI on the rendezvous node
64+
* agent-ui - runs the assisted UI on the rendezvous node
6565

internal/tshelpers/custom_commands.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,9 @@ func archiveFileNames(isoPath string) (string, string, error) {
397397

398398
func expand(ts *testscript.TestScript, s []byte) string {
399399
return os.Expand(string(s), func(key string) string {
400+
if key == "$" {
401+
return "$"
402+
}
400403
return ts.Getenv(key)
401404
})
402405
}
@@ -431,7 +434,7 @@ func byteCompareInternal(ts *testscript.TestScript, neg bool, aData, eData []byt
431434
return
432435
}
433436

434-
ts.Logf(aText)
437+
ts.Logf("%s", aText)
435438

436439
var sb strings.Builder
437440
if err := diff.Text(eFilePath, aFilePath, eText, aText, &sb); err != nil {

pkg/asset/agent/image/ignition.go

Lines changed: 36 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
package image
22

33
import (
4+
"bytes"
45
"context"
56
"encoding/json"
67
"fmt"
78
"html/template"
89
"net"
9-
"net/url"
1010
"path"
1111
"path/filepath"
1212
"strings"
@@ -306,7 +306,7 @@ func (a *Ignition) Generate(ctx context.Context, dependencies asset.Parents) err
306306

307307
rendezvousHostFile := ignition.FileFromString(rendezvousHostEnvPath,
308308
"root", 0644,
309-
getRendezvousHostEnv(agentTemplateData.ServiceProtocol, a.RendezvousIP, authConfig.AgentAuthToken, authConfig.UserAuthToken, agentWorkflow.Workflow))
309+
getRendezvousHostEnv(agentTemplateData, a.RendezvousIP, agentWorkflow.Workflow))
310310
config.Storage.Files = append(config.Storage.Files, rendezvousHostFile)
311311

312312
err = addBootstrapScripts(&config, agentManifests.ClusterImageSet.Spec.ReleaseImage)
@@ -370,11 +370,13 @@ func (a *Ignition) Generate(ctx context.Context, dependencies asset.Parents) err
370370

371371
func getDefaultEnabledServices() []string {
372372
return []string{
373+
"agent-extract-tui.service",
373374
"agent-interactive-console.service",
374375
375376
"agent-register-cluster.service",
376377
"agent-import-cluster.service",
377378
"agent-register-infraenv.service",
379+
"agent-ui.service",
378380
"agent.service",
379381
"assisted-service-db.service",
380382
"assisted-service-pod.service",
@@ -446,17 +448,12 @@ func getTemplateData(name, pullSecret, releaseImageList, releaseImage, releaseIm
446448
}
447449
}
448450

449-
func getRendezvousHostEnv(serviceProtocol, nodeZeroIP, agentAuthtoken, userAuthToken string, workflowType workflow.AgentWorkflowType) string {
450-
serviceBaseURL := url.URL{
451-
Scheme: serviceProtocol,
452-
Host: net.JoinHostPort(nodeZeroIP, "8090"),
453-
Path: "/",
454-
}
455-
imageServiceBaseURL := url.URL{
456-
Scheme: serviceProtocol,
457-
Host: net.JoinHostPort(nodeZeroIP, "8888"),
458-
Path: "/",
459-
}
451+
func getRendezvousHostEnvTemplate(data *agentTemplateData, workflowType workflow.AgentWorkflowType) string {
452+
host := "{{ if $isIPv6 }}{{ printf \"[%s]\" .RendezvousIP }}{{ else }}{{ .RendezvousIP }}{{ end }}"
453+
serviceBaseURL := fmt.Sprintf("%s://%s:8090/", data.ServiceProtocol, host)
454+
imageServiceBaseURL := fmt.Sprintf("%s://%s:8888/", data.ServiceProtocol, host)
455+
uiBaseURL := fmt.Sprintf("%s://%s:3001/", data.ServiceProtocol, host)
456+
460457
// USER_AUTH_TOKEN is required to authenticate API requests against agent-installer-local auth type
461458
// and for the endpoints marked with userAuth security definition in assisted-service swagger.yaml.
462459
// PULL_SECRET_TOKEN contains the AGENT_AUTH_TOKEN and is required for the endpoints marked with agentAuth security definition in assisted-service swagger.yaml.
@@ -469,27 +466,40 @@ func getRendezvousHostEnv(serviceProtocol, nodeZeroIP, agentAuthtoken, userAuthT
469466
// and ensure successful authentication.
470467
// In the absence of PULL_SECRET_TOKEN, the cluster installation will wait forever.
471468

472-
rendezvousHostEnv := fmt.Sprintf(`NODE_ZERO_IP=%s
469+
rendezvousHostEnvTemplate := fmt.Sprintf(`#{{ $isIPv6 := false }}{{ $host := .RendezvousIP }}{{ range ( len .RendezvousIP ) }}{{if eq ( index ( slice $host . ) 0 ) ':'}}{{ $isIPv6 = true }}{{ end }}{{ end }}
470+
NODE_ZERO_IP={{.RendezvousIP}}
473471
SERVICE_BASE_URL=%s
474472
IMAGE_SERVICE_BASE_URL=%s
475473
PULL_SECRET_TOKEN=%s
476474
USER_AUTH_TOKEN=%s
477475
WORKFLOW_TYPE=%s
478-
`, nodeZeroIP, serviceBaseURL.String(), imageServiceBaseURL.String(), agentAuthtoken, userAuthToken, workflowType)
479-
480-
if workflowType == workflow.AgentWorkflowTypeInstallInteractiveDisconnected {
481-
uiBaseURL := url.URL{
482-
Scheme: serviceProtocol,
483-
Host: net.JoinHostPort(nodeZeroIP, "3001"),
484-
Path: "/",
485-
}
486-
uiEnv := fmt.Sprintf(`AIUI_APP_API_URL=%s
476+
AIUI_APP_API_URL=%s
487477
AIUI_URL=%s
488-
`, serviceBaseURL.String(), uiBaseURL.String())
489-
rendezvousHostEnv = fmt.Sprintf("%s%s", rendezvousHostEnv, uiEnv)
478+
`, serviceBaseURL, imageServiceBaseURL, data.AgentAuthToken, data.UserAuthToken, workflowType, serviceBaseURL, uiBaseURL)
479+
480+
return rendezvousHostEnvTemplate
481+
}
482+
483+
func getRendezvousHostEnvFromTemplate(hostEnvTemplate, nodeZeroIP string) (string, error) {
484+
tmpl, err := template.New("rendezvous-host.env").Parse(hostEnvTemplate)
485+
if err != nil {
486+
return "", err
487+
}
488+
buf := &bytes.Buffer{}
489+
if err := tmpl.Execute(buf, struct{ RendezvousIP string }{nodeZeroIP}); err != nil {
490+
return "", err
490491
}
492+
return buf.String(), nil
493+
}
491494

492-
return rendezvousHostEnv
495+
func getRendezvousHostEnv(data *agentTemplateData, nodeZeroIP string, workflowType workflow.AgentWorkflowType) string {
496+
env, err := getRendezvousHostEnvFromTemplate(
497+
getRendezvousHostEnvTemplate(data, workflowType),
498+
nodeZeroIP)
499+
if err != nil {
500+
panic(err)
501+
}
502+
return env
493503
}
494504

495505
func getAddNodesEnv(clusterInfo joiner.ClusterInfo, authTokenExpiry string) string {

pkg/asset/agent/image/ignition_test.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,9 +124,13 @@ func TestIgnition_getRendezvousHostEnv(t *testing.T) {
124124
nodeZeroIP := "2001:db8::dead:beef"
125125
agentAuthtoken := "agentAuthtoken"
126126
userAuthToken := "userAuthToken"
127-
rendezvousHostEnv := getRendezvousHostEnv("http", nodeZeroIP, agentAuthtoken, userAuthToken, workflow.AgentWorkflowTypeInstall)
127+
rendezvousHostEnv := getRendezvousHostEnv(&agentTemplateData{
128+
ServiceProtocol: "http",
129+
AgentAuthToken: agentAuthtoken,
130+
UserAuthToken: userAuthToken,
131+
}, nodeZeroIP, workflow.AgentWorkflowTypeInstall)
128132
assert.Equal(t,
129-
"NODE_ZERO_IP="+nodeZeroIP+"\nSERVICE_BASE_URL=http://["+nodeZeroIP+"]:8090/\nIMAGE_SERVICE_BASE_URL=http://["+nodeZeroIP+"]:8888/\nPULL_SECRET_TOKEN="+agentAuthtoken+"\nUSER_AUTH_TOKEN="+userAuthToken+"\nWORKFLOW_TYPE=install\n",
133+
"#\nNODE_ZERO_IP="+nodeZeroIP+"\nSERVICE_BASE_URL=http://["+nodeZeroIP+"]:8090/\nIMAGE_SERVICE_BASE_URL=http://["+nodeZeroIP+"]:8888/\nPULL_SECRET_TOKEN="+agentAuthtoken+"\nUSER_AUTH_TOKEN="+userAuthToken+"\nWORKFLOW_TYPE=install\nAIUI_APP_API_URL=http://["+nodeZeroIP+"]:8090/\nAIUI_URL=http://["+nodeZeroIP+"]:3001/\n",
130134
rendezvousHostEnv)
131135
}
132136

pkg/asset/agent/image/unconfigured_ignition.go

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ package image
22

33
import (
44
"context"
5-
"net/url"
5+
"fmt"
66
"os"
77
"path"
88
"path/filepath"
@@ -151,6 +151,7 @@ func (a *UnconfiguredIgnition) Generate(_ context.Context, dependencies asset.Pa
151151
a.CPUArch = *osImage.CPUArchitecture
152152

153153
agentTemplateData := &agentTemplateData{
154+
ServiceProtocol: "http",
154155
PullSecret: pullSecretAsset.GetPullSecretData(),
155156
ReleaseImages: releaseImageList,
156157
ReleaseImage: clusterImageSet.Spec.ReleaseImage,
@@ -160,46 +161,45 @@ func (a *UnconfiguredIgnition) Generate(_ context.Context, dependencies asset.Pa
160161
InfraEnvID: infraEnvID,
161162
OSImage: osImage,
162163
Proxy: infraEnv.Spec.Proxy,
164+
AuthType: "none",
163165
}
164166

165167
enabledServices := getDefaultEnabledServices()
166168

169+
rendezvousHostTemplateData := getRendezvousHostEnvTemplate(agentTemplateData, agentWorkflow.Workflow)
170+
rendezvousHostTemplateFile := ignition.FileFromString(fmt.Sprintf("%s.template", rendezvousHostEnvPath), "root", 0644, rendezvousHostTemplateData)
171+
config.Storage.Files = append(config.Storage.Files, rendezvousHostTemplateFile)
172+
173+
rendezvousIP, err := RetrieveRendezvousIP(agentConfig.Config, nil, nmStateConfigs.Config)
174+
if err == nil {
175+
rendezvousHostData, err := getRendezvousHostEnvFromTemplate(rendezvousHostTemplateData, rendezvousIP)
176+
if err != nil {
177+
return err
178+
}
179+
rendezvousHostFile := ignition.FileFromString(rendezvousHostEnvPath, "root", 0644, rendezvousHostData)
180+
config.Storage.Files = append(config.Storage.Files, rendezvousHostFile)
181+
}
182+
167183
switch agentWorkflow.Workflow {
168184
case workflow.AgentWorkflowTypeInstall:
169185
agentTemplateData.ConfigImageFiles = strings.Join(GetConfigImageFiles(), ",")
170186

171-
// Enable the agent-check-config-image.service for the current workflow.
172-
enabledServices = append(enabledServices, "agent-check-config-image.service")
173-
174187
case workflow.AgentWorkflowTypeInstallInteractiveDisconnected:
175188
// Add the rendezvous host file. Agent TUI will interact with that file in case
176189
// the rendezvous IP wasn't previously configured, by managing it as a template file.
177-
rendezvousIP := "{{.RendezvousIP}}"
178-
if agentConfig.Config != nil {
179-
rendezvousIP = agentConfig.Config.RendezvousIP
180-
}
181-
// Avoids escaping in case the template parameter was used.
182-
rendezvousHostData, err := url.QueryUnescape(getRendezvousHostEnv("http", rendezvousIP, "", "", agentWorkflow.Workflow))
183-
if err != nil {
184-
return err
190+
if rendezvousIP == "" {
191+
rendezvousHostFile := ignition.FileFromString(rendezvousHostEnvPath, "root", 0644, rendezvousHostTemplateData)
192+
config.Storage.Files = append(config.Storage.Files, rendezvousHostFile)
185193
}
186-
rendezvousHostFile := ignition.FileFromString(rendezvousHostEnvPath, "root", 0644, rendezvousHostData)
187-
config.Storage.Files = append(config.Storage.Files, rendezvousHostFile)
188194

189195
// Explicitly disable the load-config-iso service, not required in the current flow
190196
// (even though disabled by default, the udev rule may require it).
191197
config.Storage.Files = append(config.Storage.Files, ignition.FileFromString("/etc/assisted/no-config-image", "root", 0644, ""))
192198

193199
// Enable the UI service.
194-
enabledServices = append(enabledServices, "agent-start-ui.service")
195200
interactiveUIFile := ignition.FileFromString("/etc/assisted/interactive-ui", "root", 0644, "")
196201
config.Storage.Files = append(config.Storage.Files, interactiveUIFile)
197202

198-
// Enable the agent-extract-tui service
199-
enabledServices = append(enabledServices, "agent-extract-tui.service")
200-
201-
// Let's disable the assisted-service authentication.
202-
agentTemplateData.AuthType = "none"
203203
}
204204

205205
// Required by assisted-service.
@@ -242,6 +242,8 @@ func (a *UnconfiguredIgnition) Generate(_ context.Context, dependencies asset.Pa
242242
config.Storage.Files = append(config.Storage.Files, manifestFile)
243243
}
244244

245+
// the agent-check-config-image.service added only to the unconfigured ignition
246+
enabledServices = append(enabledServices, "agent-check-config-image.service")
245247
err = bootstrap.AddSystemdUnits(&config, "agent/systemd/units", agentTemplateData, enabledServices)
246248
if err != nil {
247249
return err

0 commit comments

Comments
 (0)