From bfc40f87fbdbc8dc315a2b4313794a07a8f821ae Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Fri, 8 Mar 2019 12:49:36 -0800 Subject: [PATCH] cmd/openshift-install/upi: Add a user-provided-infrastructure subcommand To support the workflow described in upiLong. I've also replaced openshiftcorp.com with example.com to comply with [1]. That way readers don't need to worry about whether openshiftcorp.com exists and, if so, who owns it. I've updated the docs/user/aws/install.md examples to follow our current (with this PR) output: $ curl -s https://storage.googleapis.com/origin-ci-test/pr-logs/pull/openshift_installer/1393/pull-ci-openshift-installer-master-e2e-aws/4457/artifacts/e2e-aws/installer/.openshift_install.log | grep level=info | head -n13 time="2019-03-12T16:34:33Z" level=info msg="Consuming \"Install Config\" from target directory" time="2019-03-12T16:34:33Z" level=info msg="Creating cluster..." time="2019-03-12T16:51:21Z" level=info msg="Waiting up to 30m0s for the Kubernetes API at https://api.ci-op-j33s61i6-1d3f3.origin-ci-int-aws.dev.rhcloud.com:6443..." time="2019-03-12T16:55:29Z" level=info msg="API v1.12.4+341c822 up" time="2019-03-12T16:55:29Z" level=info msg="Waiting up to 30m0s for the bootstrap-complete event..." time="2019-03-12T17:04:56Z" level=info msg="Destroying the bootstrap resources..." time="2019-03-12T17:05:36Z" level=info msg="Waiting up to 30m0s for the cluster at https://api.ci-op-j33s61i6-1d3f3.origin-ci-int-aws.dev.rhcloud.com:6443 to initialize..." time="2019-03-12T17:14:56Z" level=info msg="Waiting up to 10m0s for the openshift-console route to be created..." time="2019-03-12T17:14:56Z" level=info msg="Install complete!" time="2019-03-12T17:14:56Z" level=info msg="Run 'export KUBECONFIG=/tmp/artifacts/installer/auth/kubeconfig' to manage the cluster with 'oc', the OpenShift CLI." time="2019-03-12T17:14:56Z" level=info msg="The cluster is ready when 'oc login -u kubeadmin -p 3MJb2-RRTfu-SKyuq-5NcCb' succeeds (wait a few minutes)." time="2019-03-12T17:14:56Z" level=info msg="Access the OpenShift web-console here: https://console-openshift-console.apps.ci-op-j33s61i6-1d3f3.origin-ci-int-aws.dev.rhcloud.com" time="2019-03-12T17:14:56Z" level=info msg="Login to the console with user: kubeadmin, password: 3MJb2-RRTfu-SKyuq-5NcCb" [1]: https://tools.ietf.org/html/rfc6761#section-6.5 --- cmd/openshift-install/create.go | 45 ++++++++------- cmd/openshift-install/main.go | 1 + cmd/openshift-install/upi.go | 98 +++++++++++++++++++++++++++++++++ docs/user/aws/install.md | 7 ++- docs/user/customization.md | 2 +- 5 files changed, 129 insertions(+), 24 deletions(-) create mode 100644 cmd/openshift-install/upi.go 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... ... ```