diff --git a/cmd/openshift-install/agent.go b/cmd/openshift-install/agent.go index 025a53cae7..fb19102dd2 100644 --- a/cmd/openshift-install/agent.go +++ b/cmd/openshift-install/agent.go @@ -2,7 +2,6 @@ package main import ( "context" - "log" "github.com/spf13/cobra" @@ -13,7 +12,6 @@ import ( "github.com/openshift/installer/pkg/asset/agent/image" "github.com/openshift/installer/pkg/asset/agent/manifests" "github.com/openshift/installer/pkg/asset/agent/mirror" - "github.com/openshift/installer/pkg/asset/agent/workflow" "github.com/openshift/installer/pkg/asset/kubeconfig" "github.com/openshift/installer/pkg/asset/password" "github.com/openshift/installer/pkg/asset/tls" @@ -109,7 +107,7 @@ var ( command: &cobra.Command{ Use: "unconfigured-ignition", Short: "Generates an agent ignition that excludes cluster configuration", - Args: cobra.MaximumNArgs(1), + Args: cobra.ExactArgs(0), Hidden: true, }, assets: []asset.WritableAsset{ @@ -146,31 +144,15 @@ func newAgentCreateCmd(ctx context.Context) *cobra.Command { }, } - agentCtx := agent.NewContextWrapper(ctx) for _, t := range agentTargets { t.command.Args = cobra.ExactArgs(0) - t.command.Run = runTargetCmd(agentCtx, t.assets...) + t.command.Run = runTargetCmd(ctx, t.assets...) cmd.AddCommand(t.command) } - setUnconfiguredIgnitionFlag(agentCtx) - return cmd } -func setUnconfiguredIgnitionFlag(ctx *agent.ContextWrapper) { - agentUnconfiguredIgnitionTarget.command.PersistentFlags().Bool("interactive", false, "Enable the interactive disconnected workflow support") - agentUnconfiguredIgnitionTarget.command.PreRun = func(cmd *cobra.Command, args []string) { - isInteractive, err := cmd.Flags().GetBool("interactive") - if err != nil { - log.Fatal(err) - } - if isInteractive { - ctx.AddValue(workflow.WorkflowTypeKey, string(workflow.AgentWorkflowTypeInstallInteractiveDisconnected)) - } - } -} - func newAgentGraphCmd() *cobra.Command { cmd := &cobra.Command{ Use: "graph", diff --git a/cmd/openshift-install/agent/contextwrapper.go b/cmd/openshift-install/agent/contextwrapper.go deleted file mode 100644 index fb4fdef7f8..0000000000 --- a/cmd/openshift-install/agent/contextwrapper.go +++ /dev/null @@ -1,43 +0,0 @@ -package agent - -import ( - "context" - "time" -) - -// ContextWrapper is a context decorator. -type ContextWrapper struct { - ctx context.Context //nolint:containedctx -} - -// NewContextWrapper creates a new ContextWrapper instance. -func NewContextWrapper(ctx context.Context) *ContextWrapper { - return &ContextWrapper{ - ctx: ctx, - } -} - -// Deadline returns the context Deadline. -func (a *ContextWrapper) Deadline() (deadline time.Time, ok bool) { - return a.ctx.Deadline() -} - -// Done returns the context Done channel. -func (a *ContextWrapper) Done() <-chan struct{} { - return a.ctx.Done() -} - -// Err returns the context current error. -func (a *ContextWrapper) Err() error { - return a.ctx.Err() -} - -// Value returns the context Value. -func (a *ContextWrapper) Value(key any) any { - return a.ctx.Value(key) -} - -// AddValue allows to add a new value in the context. -func (a *ContextWrapper) AddValue(key, value interface{}) { - a.ctx = context.WithValue(a.ctx, key, value) -} diff --git a/cmd/openshift-install/testdata/agent/unconfigured-ignition/configurations/interactive.txt b/cmd/openshift-install/testdata/agent/unconfigured-ignition/configurations/interactive.txt deleted file mode 100644 index 7c596b8a58..0000000000 --- a/cmd/openshift-install/testdata/agent/unconfigured-ignition/configurations/interactive.txt +++ /dev/null @@ -1,100 +0,0 @@ -# Verify that the --interactive flag generates the expected resources required for the interactive workflow. - -expandFile cluster-manifests/cluster-image-set.yaml - -exec openshift-install agent create unconfigured-ignition --interactive --dir $WORK - -exists $WORK/unconfigured-agent.ign -! exists $WORK/auth/kubeconfig -! exists $WORK/auth/kubeadmin-password - -unconfiguredIgnContains /etc/assisted/manifests/pull-secret.yaml -! unconfiguredIgnContains /etc/assisted/manifests/agent-cluster-install.yaml -! unconfiguredIgnContains /etc/assisted/manifests/cluster-deployment.yaml - -unconfiguredIgnCmp /etc/assisted/manifests/cluster-image-set.yaml expected/cluster-image-set.yaml -unconfiguredIgnCmp /etc/assisted/manifests/infraenv.yaml expected/infraenv.yaml -unconfiguredIgnCmp /etc/assisted/rendezvous-host.env expected/rendezvous-host.env - -unconfiguredIgnContains /etc/assisted/no-config-image -unconfiguredIgnContains /etc/assisted/interactive-ui - --- cluster-manifests/infraenv.yaml -- -apiVersion: agent-install.openshift.io/v1beta1 -kind: InfraEnv -metadata: - name: ostest - namespace: cluster0 -spec: - cpuArchitecture: x86_64 - pullSecretRef: - name: ostest-pull-secret - sshAuthorizedKey: ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDK6UTEydcEKzuNdPaofn8Z2DwgHqdcionLZBiPf/zIRNco++etLsat7Avv7yt04DINQd5zjxIFgG8jblaUB5E5C9ClUcMwb52GO0ay2Y9v1uBv1a4WhI3peKktAzYNk0EBMQlJtXPjRMrC9ylBPh+DsBHMu+KmDnfk7PIwyN4efC8k5kSRuPWoNdme1rz2+umU8FSmaWTHIajrbspf4GQbsntA5kuKEtDbfoNCU97o2KrRnUbeg3a8hwSjfh3u6MhlnGcg5K2Ij+zivEsWGCLKYUtE1ErqwfIzwWmJ6jnV66XCQGHf4Q1iIxqF7s2a1q24cgG2Z/iDXfqXrCIfy4P7b/Ztak3bdT9jfAdVZtdO5/r7I+O5hYhF86ayFlDWzZWP/ByiSb+q4CQbfVgK3BMmiAv2MqLHdhesmD/SmIcoOWUF6rFmRKZVFFpKpt5ATNTgUJ3JRowoXrrDruVXClUGRiCS6Zabd1rZ3VmTchaPJwtzQMdfIWISXj+Ig+C4UK0= - --- cluster-manifests/pull-secret.yaml -- -apiVersion: v1 -kind: Secret -metadata: - name: ostest-pull-secret - namespace: cluster0 -stringData: - .dockerconfigjson: |- - { - "auths": { - "quay.io": { - "auth": "c3VwZXItc2VjcmV0Cg==" - } - } - } - --- cluster-manifests/cluster-image-set.yaml -- -apiVersion: hive.openshift.io/v1 -kind: ClusterImageSet -metadata: - name: cluster0-image-set - namespace: cluster0 -spec: - releaseImage: $RELEASE_IMAGE - --- expected/cluster-image-set.yaml -- -apiVersion: hive.openshift.io/v1 -kind: ClusterImageSet -metadata: - name: cluster0-image-set - namespace: cluster0 -spec: - releaseImage: $RELEASE_IMAGE - --- expected/infraenv.yaml -- -apiVersion: agent-install.openshift.io/v1beta1 -kind: InfraEnv -metadata: - name: ostest - namespace: cluster0 -spec: - cpuArchitecture: x86_64 - ipxeScriptType: "" - nmStateConfigLabelSelector: {} - pullSecretRef: - name: ostest-pull-secret - sshAuthorizedKey: ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDK6UTEydcEKzuNdPaofn8Z2DwgHqdcionLZBiPf/zIRNco++etLsat7Avv7yt04DINQd5zjxIFgG8jblaUB5E5C9ClUcMwb52GO0ay2Y9v1uBv1a4WhI3peKktAzYNk0EBMQlJtXPjRMrC9ylBPh+DsBHMu+KmDnfk7PIwyN4efC8k5kSRuPWoNdme1rz2+umU8FSmaWTHIajrbspf4GQbsntA5kuKEtDbfoNCU97o2KrRnUbeg3a8hwSjfh3u6MhlnGcg5K2Ij+zivEsWGCLKYUtE1ErqwfIzwWmJ6jnV66XCQGHf4Q1iIxqF7s2a1q24cgG2Z/iDXfqXrCIfy4P7b/Ztak3bdT9jfAdVZtdO5/r7I+O5hYhF86ayFlDWzZWP/ByiSb+q4CQbfVgK3BMmiAv2MqLHdhesmD/SmIcoOWUF6rFmRKZVFFpKpt5ATNTgUJ3JRowoXrrDruVXClUGRiCS6Zabd1rZ3VmTchaPJwtzQMdfIWISXj+Ig+C4UK0= -status: - agentLabelSelector: {} - bootArtifacts: - discoveryIgnitionURL: "" - initrd: "" - ipxeScript: "" - kernel: "" - rootfs: "" - debugInfo: - eventsURL: "" --- expected/rendezvous-host.env -- -#{{ $$isIPv6 := false }}{{ $$host := .RendezvousIP }}{{ range ( len .RendezvousIP ) }}{{if eq ( index ( slice $$host . ) 0 ) ':'}}{{ $$isIPv6 = true }}{{ end }}{{ end }} -NODE_ZERO_IP={{.RendezvousIP}} -SERVICE_BASE_URL=http://{{ if $$isIPv6 }}{{ printf "[%s]" .RendezvousIP }}{{ else }}{{ .RendezvousIP }}{{ end }}:8090/ -IMAGE_SERVICE_BASE_URL=http://{{ if $$isIPv6 }}{{ printf "[%s]" .RendezvousIP }}{{ else }}{{ .RendezvousIP }}{{ end }}:8888/ -PULL_SECRET_TOKEN= -USER_AUTH_TOKEN= -WORKFLOW_TYPE=install-interactive-disconnected -AIUI_APP_API_URL=http://{{ if $$isIPv6 }}{{ printf "[%s]" .RendezvousIP }}{{ else }}{{ .RendezvousIP }}{{ end }}:8090/ -AIUI_URL=http://{{ if $$isIPv6 }}{{ printf "[%s]" .RendezvousIP }}{{ else }}{{ .RendezvousIP }}{{ end }}:3001/ diff --git a/docs/user/agent/agent-services.md b/docs/user/agent/agent-services.md index 21bc8f075c..d233fe7b4f 100644 --- a/docs/user/agent/agent-services.md +++ b/docs/user/agent/agent-services.md @@ -53,13 +53,13 @@ so no connectivity checks to the release image is needed. ---- -## Interactive workflow (unconfigured ignition --interactive) +## Install workflow with OpenShift Virtualizaton Engine (OVE) -![Interactive workflow](./agent_installer_services-interactive.svg) +OpenShift Virtualization Engine (OVE) is a standalone OpenShift deployment for virtualization workloads, distributed as a pre-built appliance image. This allows the user to install a cluster by using the assisted UI running on the rendezvous node. The agent-tui is also used interactively to configure which node will be the rendezvous host, and to configure accordingly the other nodes. -The interactive workflow allows the user to install a cluster by using the assisted UI running on the rendezvous node. In this workflow -the agent-tui is also used interactively to configure which node will be the rendezvous host, and to configure accordingly the other nodes. +The installer detects the `/etc/assisted/interactive-ui` sentinel file embedded in the appliance's system ignition to enable interactive installation, which provides: * agent-extract-tui - extracts agent-tui and nmstate libraries from the agent-installer-utils image during boot * agent-ui - runs the assisted UI on the rendezvous node +The appliance embeds this sentinel file during image creation. After first reboot, MCO manages registry and certificate configuration. diff --git a/pkg/asset/agent/agentconfig/agenthosts.go b/pkg/asset/agent/agentconfig/agenthosts.go index d92d975630..272d4900f0 100644 --- a/pkg/asset/agent/agentconfig/agenthosts.go +++ b/pkg/asset/agent/agentconfig/agenthosts.go @@ -90,10 +90,6 @@ func (a *AgentHosts) Generate(_ context.Context, dependencies asset.Parents) err } } - case workflow.AgentWorkflowTypeInstallInteractiveDisconnected: - // Not required - return nil - case workflow.AgentWorkflowTypeAddNodes: a.Hosts = append(a.Hosts, addNodesConfig.Config.Hosts...) diff --git a/pkg/asset/agent/image/unconfigured_ignition.go b/pkg/asset/agent/image/unconfigured_ignition.go index 3f66f0cdad..2e3f8dcb14 100644 --- a/pkg/asset/agent/image/unconfigured_ignition.go +++ b/pkg/asset/agent/image/unconfigured_ignition.go @@ -18,7 +18,6 @@ import ( "github.com/openshift/installer/pkg/asset/agent/agentconfig" "github.com/openshift/installer/pkg/asset/agent/common" "github.com/openshift/installer/pkg/asset/agent/manifests" - "github.com/openshift/installer/pkg/asset/agent/mirror" "github.com/openshift/installer/pkg/asset/agent/workflow" "github.com/openshift/installer/pkg/asset/ignition" "github.com/openshift/installer/pkg/asset/ignition/bootstrap" @@ -84,13 +83,13 @@ func (a *UnconfiguredIgnition) Dependencies() []asset.Asset { &manifests.AgentPullSecret{}, &manifests.ClusterImageSet{}, &manifests.NMStateConfig{}, - &mirror.RegistriesConf{}, - &mirror.CaBundle{}, &common.InfraEnvID{}, } } // Generate generates the agent installer unconfigured ignition. +// The appliance embeds both registries.conf and CA certificates in the image's +// system ignition for the bootstrap phase. After first reboot, MCO manages these. func (a *UnconfiguredIgnition) Generate(_ context.Context, dependencies asset.Parents) error { agentWorkflow := &workflow.AgentWorkflow{} infraEnvAsset := &manifests.InfraEnvFile{} @@ -101,6 +100,10 @@ func (a *UnconfiguredIgnition) Generate(_ context.Context, dependencies asset.Pa agentConfig := &agentconfig.AgentConfig{} dependencies.Get(agentWorkflow, infraEnvAsset, clusterImageSetAsset, pullSecretAsset, nmStateConfigs, infraEnvIDAsset, agentConfig) + if agentWorkflow.Workflow != workflow.AgentWorkflowTypeInstall { + return fmt.Errorf("AgentWorkflowType value not supported: %s", agentWorkflow.Workflow) + } + infraEnv := infraEnvAsset.Config clusterImageSet := clusterImageSetAsset.Config @@ -133,10 +136,6 @@ func (a *UnconfiguredIgnition) Generate(_ context.Context, dependencies asset.Pa return err } - registriesConfig := &mirror.RegistriesConf{} - registryCABundle := &mirror.CaBundle{} - dependencies.Get(registriesConfig, registryCABundle) - infraEnvID := infraEnvIDAsset.ID logrus.Debug("Generated random infra-env id ", infraEnvID) @@ -155,9 +154,9 @@ func (a *UnconfiguredIgnition) Generate(_ context.Context, dependencies asset.Pa PullSecret: pullSecretAsset.GetPullSecretData(), ReleaseImages: releaseImageList, ReleaseImage: clusterImageSet.Spec.ReleaseImage, - ReleaseImageMirror: mirror.GetMirrorFromRelease(clusterImageSet.Spec.ReleaseImage, registriesConfig), - HaveMirrorConfig: len(registriesConfig.MirrorConfig) > 0, - PublicContainerRegistries: getPublicContainerRegistries(registriesConfig), + ReleaseImageMirror: "", + HaveMirrorConfig: true, + PublicContainerRegistries: "", InfraEnvID: infraEnvID, OSImage: osImage, Proxy: infraEnv.Spec.Proxy, @@ -180,27 +179,7 @@ func (a *UnconfiguredIgnition) Generate(_ context.Context, dependencies asset.Pa config.Storage.Files = append(config.Storage.Files, rendezvousHostFile) } - switch agentWorkflow.Workflow { - case workflow.AgentWorkflowTypeInstall: - agentTemplateData.ConfigImageFiles = strings.Join(GetConfigImageFiles(), ",") - - case workflow.AgentWorkflowTypeInstallInteractiveDisconnected: - // Add the rendezvous host file. Agent TUI will interact with that file in case - // the rendezvous IP wasn't previously configured, by managing it as a template file. - if rendezvousIP == "" { - rendezvousHostFile := ignition.FileFromString(rendezvousHostEnvPath, "root", 0644, rendezvousHostTemplateData) - config.Storage.Files = append(config.Storage.Files, rendezvousHostFile) - } - - // Explicitly disable the load-config-iso service, not required in the current flow - // (even though disabled by default, the udev rule may require it). - config.Storage.Files = append(config.Storage.Files, ignition.FileFromString("/etc/assisted/no-config-image", "root", 0644, "")) - - // Enable the UI service. - interactiveUIFile := ignition.FileFromString("/etc/assisted/interactive-ui", "root", 0644, "") - config.Storage.Files = append(config.Storage.Files, interactiveUIFile) - - } + agentTemplateData.ConfigImageFiles = strings.Join(GetConfigImageFiles(), ",") // Required by assisted-service. a.ignAddFolders(&config, "/opt/agent/tls") @@ -249,8 +228,6 @@ func (a *UnconfiguredIgnition) Generate(_ context.Context, dependencies asset.Pa return err } - addMirrorData(&config, registriesConfig, registryCABundle) - a.Config = &config if err := a.generateFile(unconfiguredIgnitionFilename); err != nil { diff --git a/pkg/asset/agent/image/unconfigured_ignition_test.go b/pkg/asset/agent/image/unconfigured_ignition_test.go index d83477cbc9..858c62fc73 100644 --- a/pkg/asset/agent/image/unconfigured_ignition_test.go +++ b/pkg/asset/agent/image/unconfigured_ignition_test.go @@ -15,7 +15,6 @@ import ( "github.com/openshift/installer/pkg/asset/agent/agentconfig" "github.com/openshift/installer/pkg/asset/agent/common" "github.com/openshift/installer/pkg/asset/agent/manifests" - "github.com/openshift/installer/pkg/asset/agent/mirror" "github.com/openshift/installer/pkg/asset/agent/workflow" ) @@ -42,43 +41,6 @@ func TestUnconfiguredIgnition_Generate(t *testing.T) { "agent-check-config-image.service": true, "agent-extract-tui.service": true}, }, - { - name: "interactive-disconnected-workflow-should-have-agent-extract-tui-service-enabled", - overrideDeps: []asset.Asset{ - &workflow.AgentWorkflow{Workflow: workflow.AgentWorkflowTypeInstallInteractiveDisconnected}, - }, - serviceEnabledMap: map[string]bool{ - "agent-extract-tui.service": true}, - }, - { - name: "with-mirror-configs", - overrideDeps: []asset.Asset{ - &mirror.RegistriesConf{ - File: &asset.File{ - Filename: mirror.RegistriesConfFilename, - Data: []byte(""), - }, - MirrorConfig: []mirror.RegistriesConfig{ - { - Location: "some.registry.org/release", - Mirrors: []string{"some.mirror.org"}, - }, - }, - }, - &mirror.CaBundle{ - File: &asset.File{ - Filename: "my.crt", - Data: []byte("my-certificate"), - }, - }, - }, - expectedFiles: generatedFilesUnconfiguredIgnition(registriesConfPath, - registryCABundlePath, "/usr/local/bin/pre-network-manager-config.sh", "/usr/local/bin/oci-eval-user-data.sh"), - serviceEnabledMap: map[string]bool{ - "pre-network-manager-config.service": false, - "oci-eval-user-data.service": true, - "agent-check-config-image.service": true}, - }, { name: "with-nmstateconfigs", overrideDeps: []asset.Asset{ @@ -132,8 +94,6 @@ func buildUnconfiguredIgnitionAssetDefaultDependencies(t *testing.T) []asset.Ass &agentPullSecret, &clusterImageSet, &manifests.NMStateConfig{}, - &mirror.RegistriesConf{}, - &mirror.CaBundle{}, &common.InfraEnvID{}, &agentconfig.AgentConfig{}, } diff --git a/pkg/asset/agent/manifests/clusterimageset.go b/pkg/asset/agent/manifests/clusterimageset.go index 00246987c7..3d4b9d7ec4 100644 --- a/pkg/asset/agent/manifests/clusterimageset.go +++ b/pkg/asset/agent/manifests/clusterimageset.go @@ -57,7 +57,7 @@ func (a *ClusterImageSet) Generate(ctx context.Context, dependencies asset.Paren dependencies.Get(releaseImage, installConfig, agentWorkflow, clusterInfo) switch agentWorkflow.Workflow { - case workflow.AgentWorkflowTypeInstall, workflow.AgentWorkflowTypeInstallInteractiveDisconnected: + case workflow.AgentWorkflowTypeInstall: currentVersion, err := version.Version() if err != nil { return err diff --git a/pkg/asset/agent/mirror/cabundle.go b/pkg/asset/agent/mirror/cabundle.go index 0c45c9f73b..6d9fe0a755 100644 --- a/pkg/asset/agent/mirror/cabundle.go +++ b/pkg/asset/agent/mirror/cabundle.go @@ -58,10 +58,6 @@ func (i *CaBundle) Generate(_ context.Context, dependencies asset.Parents) error } additionalTrustBundle = installConfig.Config.AdditionalTrustBundle - case workflow.AgentWorkflowTypeInstallInteractiveDisconnected: - // Not required - return nil - case workflow.AgentWorkflowTypeAddNodes: additionalTrustBundle = clusterInfo.UserCaBundle diff --git a/pkg/asset/agent/mirror/registriesconf.go b/pkg/asset/agent/mirror/registriesconf.go index c035a4cbbd..aa5e3eb971 100644 --- a/pkg/asset/agent/mirror/registriesconf.go +++ b/pkg/asset/agent/mirror/registriesconf.go @@ -164,10 +164,6 @@ func (i *RegistriesConf) Generate(_ context.Context, dependencies asset.Parents) deprecatedImageContentSources = clusterInfo.DeprecatedImageContentSources image = clusterInfo.ReleaseImage - case workflow.AgentWorkflowTypeInstallInteractiveDisconnected: - // Not required - return nil - default: return fmt.Errorf("AgentWorkflowType value not supported: %s", agentWorkflow.Workflow) } diff --git a/pkg/asset/agent/workflow/agentworkflow.go b/pkg/asset/agent/workflow/agentworkflow.go index e4b341a662..260c7047bc 100644 --- a/pkg/asset/agent/workflow/agentworkflow.go +++ b/pkg/asset/agent/workflow/agentworkflow.go @@ -33,11 +33,6 @@ func (a *AgentWorkflow) Generate(ctx context.Context, dependencies asset.Parents // Set install workflow as a default a.Workflow = AgentWorkflowTypeInstall - // Extract the workflow type from the context, if available. - if w, ok := ctx.Value(WorkflowTypeKey).(string); ok { - a.Workflow = AgentWorkflowType(w) - } - a.File = &asset.File{ Filename: agentWorkflowFilename, Data: []byte(a.Workflow), diff --git a/pkg/asset/agent/workflow/commons.go b/pkg/asset/agent/workflow/commons.go index eb543fe4b4..6fb1fa6280 100644 --- a/pkg/asset/agent/workflow/commons.go +++ b/pkg/asset/agent/workflow/commons.go @@ -13,11 +13,6 @@ const ( AgentWorkflowTypeInstall AgentWorkflowType = "install" // AgentWorkflowTypeAddNodes identifies the add nodes workflow. AgentWorkflowTypeAddNodes AgentWorkflowType = "addnodes" - // AgentWorkflowTypeInstallInteractiveDisconnected identifies a specific kind of - // disconnected install workflow. The installation details will be provided through - // a dedicated UI running on the rendezvous node, and in addition no external registry - // will be required for an air-gapped deployment. - AgentWorkflowTypeInstallInteractiveDisconnected AgentWorkflowType = "install-interactive-disconnected" agentWorkflowFilename = ".agentworkflow" )