diff --git a/cmd/openshift-install/create.go b/cmd/openshift-install/create.go index 4d53d47e4b8..e3ab927fe59 100644 --- a/cmd/openshift-install/create.go +++ b/cmd/openshift-install/create.go @@ -104,25 +104,18 @@ var ( logrus.Fatal(errors.Wrap(err, "loading kubeconfig")) } - err = destroyBootstrap(ctx, config, rootOpts.dir) + err = waitForBootstrapComplete(ctx, config, rootOpts.dir) if err != nil { logrus.Fatal(err) } - if err := waitForInitializedCluster(ctx, config); err != nil { - logrus.Fatal(err) - } - - consoleURL, err := waitForConsole(ctx, config, rootOpts.dir) + logrus.Info("Destroying the bootstrap resources...") + err = destroybootstrap.Destroy(rootOpts.dir) if err != nil { logrus.Fatal(err) } - if err = addRouterCAToClusterCA(config, rootOpts.dir); err != nil { - logrus.Fatal(err) - } - - err = logComplete(rootOpts.dir, consoleURL) + err = finish(ctx, config, rootOpts.dir) if err != nil { logrus.Fatal(err) } @@ -244,7 +237,7 @@ func addRouterCAToClusterCA(config *rest.Config, directory string) (err error) { // FIXME: pulling the kubeconfig and metadata out of the root // directory is a bit cludgy when we already have them in memory. -func destroyBootstrap(ctx context.Context, config *rest.Config, directory string) (err error) { +func waitForBootstrapComplete(ctx context.Context, config *rest.Config, directory string) (err error) { client, err := kubernetes.NewForConfig(config) if err != nil { return errors.Wrap(err, "creating a Kubernetes client") @@ -253,7 +246,7 @@ func destroyBootstrap(ctx context.Context, config *rest.Config, directory string discovery := client.Discovery() apiTimeout := 30 * time.Minute - logrus.Infof("Waiting up to %v for the Kubernetes API...", apiTimeout) + logrus.Infof("Waiting up to %v for the Kubernetes API at %s...", apiTimeout, config.Host) apiContext, cancel := context.WithTimeout(ctx, apiTimeout) defer cancel() // Poll quickly so we notice changes, but only log when the response @@ -288,12 +281,7 @@ func destroyBootstrap(ctx context.Context, config *rest.Config, directory string eventTimeout := 30 * time.Minute logrus.Infof("Waiting up to %v for the bootstrap-complete event...", eventTimeout) - if err := waitForEvent(ctx, client.CoreV1().RESTClient(), "bootstrap-complete", eventTimeout); err != nil { - return err - } - - logrus.Info("Destroying the bootstrap resources...") - return destroybootstrap.Destroy(rootOpts.dir) + return waitForEvent(ctx, client.CoreV1().RESTClient(), "bootstrap-complete", eventTimeout) } // waitForEvent watches the events in the kube-system namespace, waits @@ -331,7 +319,7 @@ func waitForEvent(ctx context.Context, client cache.Getter, name string, timeout // that the cluster has been initialized. func waitForInitializedCluster(ctx context.Context, config *rest.Config) error { timeout := 30 * time.Minute - logrus.Infof("Waiting up to %v for the cluster to initialize...", timeout) + logrus.Infof("Waiting up to %v for the cluster at %s to initialize...", timeout, config.Host) cc, err := configclient.NewForConfig(config) if err != nil { return errors.Wrap(err, "failed to create a config client") @@ -454,3 +442,20 @@ func logComplete(directory, consoleURL string) error { logrus.Infof("Login to the console with user: kubeadmin, password: %s", pw) return nil } + +func finish(ctx context.Context, config *rest.Config, directory string) error { + if err := waitForInitializedCluster(ctx, config); err != nil { + return err + } + + consoleURL, err := waitForConsole(ctx, config, rootOpts.dir) + if err != nil { + return err + } + + if err = addRouterCAToClusterCA(config, rootOpts.dir); err != nil { + return err + } + + return logComplete(rootOpts.dir, consoleURL) +} diff --git a/cmd/openshift-install/main.go b/cmd/openshift-install/main.go index 4971cac8447..51b3a9fd8c8 100644 --- a/cmd/openshift-install/main.go +++ b/cmd/openshift-install/main.go @@ -46,6 +46,7 @@ func installerMain() { for _, subCmd := range []*cobra.Command{ newCreateCmd(), newDestroyCmd(), + newUPICmd(), newVersionCmd(), newGraphCmd(), newCompletionCmd(), diff --git a/cmd/openshift-install/upi.go b/cmd/openshift-install/upi.go new file mode 100644 index 00000000000..3cce1e04dd8 --- /dev/null +++ b/cmd/openshift-install/upi.go @@ -0,0 +1,98 @@ +package main + +import ( + "context" + "path/filepath" + + "github.com/pkg/errors" + "github.com/sirupsen/logrus" + "github.com/spf13/cobra" + "k8s.io/client-go/tools/clientcmd" +) + +var ( + upiLong = `Entry-points for user-provided infrastructure. + +Most users will want to use 'create cluster' to have the installer +create the required infrastructure for their cluster. But in some +installations the infrastructure needs to be adapted in ways that +installer-created infrastructure does not support. This command +provides entry points to support the following workflow: + +1. Call 'create ignition-configs' to create the bootstrap Ignition + config and admin kubeconfig. +2. Creates all required cluster resources, after which the cluster + will being bootstrapping. +3. Call 'user-provided-infrastructure bootstrap-complete' to wait + until the bootstrap phase has completed. +4. Destroy the bootstrap resources. +5. Call 'user-provided-infrastructure finish' to wait until the + cluster finishes deploying its initial version. This also + retrieves the router certificate authority from the cluster and + inserts it into the admin kubeconfig.` +) + +func newUPICmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "user-provided-infrastructure", + Aliases: []string{"upi"}, + Short: "Entry-points for user-provided infrastructure", + Long: upiLong, + RunE: func(cmd *cobra.Command, args []string) error { + return cmd.Help() + }, + } + cmd.AddCommand(newUPIBootstrapCompleteCmd()) + cmd.AddCommand(newUPIFinishCmd()) + return cmd +} + +func newUPIBootstrapCompleteCmd() *cobra.Command { + return &cobra.Command{ + Use: "bootstrap-complete", + Short: "Wait until cluster bootstrapping has completed", + Args: cobra.ExactArgs(0), + Run: func(_ *cobra.Command, _ []string) { + ctx := context.Background() + + cleanup := setupFileHook(rootOpts.dir) + defer cleanup() + + config, err := clientcmd.BuildConfigFromFlags("", filepath.Join(rootOpts.dir, "auth", "kubeconfig")) + if err != nil { + logrus.Fatal(errors.Wrap(err, "loading kubeconfig")) + } + + err = waitForBootstrapComplete(ctx, config, rootOpts.dir) + if err != nil { + logrus.Fatal(err) + } + + logrus.Info("It is now safe to remove the bootstrap resources") + }, + } +} + +func newUPIFinishCmd() *cobra.Command { + return &cobra.Command{ + Use: "finish", + Short: "Wait for the cluster to finish updating and update local resources", + Args: cobra.ExactArgs(0), + Run: func(cmd *cobra.Command, args []string) { + ctx := context.Background() + + cleanup := setupFileHook(rootOpts.dir) + defer cleanup() + + config, err := clientcmd.BuildConfigFromFlags("", filepath.Join(rootOpts.dir, "auth", "kubeconfig")) + if err != nil { + logrus.Fatal(errors.Wrap(err, "loading kubeconfig")) + } + + err = finish(ctx, config, rootOpts.dir) + if err != nil { + logrus.Fatal(err) + } + }, + } +} diff --git a/docs/user/aws/install.md b/docs/user/aws/install.md index 117510ee242..012b0234424 100644 --- a/docs/user/aws/install.md +++ b/docs/user/aws/install.md @@ -12,7 +12,7 @@ Step 3: Download the Installer. ? SSH Public Key /home/user_id/.ssh/id_rsa.pub ? Platform aws ? Region us-east-1 -? Base Domain openshiftcorp.com +? Base Domain example.com ? Cluster Name test ? Pull Secret [? for help] ``` @@ -21,15 +21,16 @@ Step 3: Download the Installer. ```console [~]$ openshift-install-linux-amd64 create cluster -INFO Waiting up to 30m0s for the Kubernetes API... +INFO Waiting up to 30m0s for the Kubernetes API at https://api.test.example.com:6443... INFO API v1.11.0+85a0623 up INFO Waiting up to 30m0s for the bootstrap-complete event... INFO Destroying the bootstrap resources... +INTO Waiting up to 30m0s for the cluster at https://api.test.example.com:6443 to initialize... INFO Waiting up to 10m0s for the openshift-console route to be created... INFO Install complete! INFO Run 'export KUBECONFIG=/home/user/auth/kubeconfig' to manage the cluster with 'oc', the OpenShift CLI. INFO The cluster is ready when 'oc login -u kubeadmin -p XXXX' succeeds (wait a few minutes). -INFO Access the OpenShift web-console here: https://console-openshift-console.apps.test.openshiftcorp.com +INFO Access the OpenShift web-console here: https://console-openshift-console.apps.test.example.com INFO Login to the console with user: kubeadmin, password: XXXX ``` diff --git a/docs/user/customization.md b/docs/user/customization.md index 9ef68a0551d..b64f1e8757b 100644 --- a/docs/user/customization.md +++ b/docs/user/customization.md @@ -159,7 +159,7 @@ For example: INFO Consuming "Master Machines" from target directory INFO Consuming "Common Manifests" from target directory INFO Creating cluster... - INFO Waiting up to 30m0s for the Kubernetes API... + INFO Waiting up to 30m0s for the Kubernetes API at https://api.test-cluster.example.com:6443... ... ```