Skip to content

Commit

Permalink
Merge pull request #18 from sttts/sttts-teardown-as-early-as-possible
Browse files Browse the repository at this point in the history
start: tear down bootstrap control plane as early as possible
  • Loading branch information
openshift-merge-robot authored Feb 22, 2019
2 parents f22ee6b + a078c34 commit 05a5c8e
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 13 deletions.
4 changes: 4 additions & 0 deletions pkg/start/bootstrap.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ func (b *bootstrapControlPlane) Start() error {
// Teardown brings down the bootstrap control plane and cleans up the temporary manifests and
// secrets. This function is idempotent.
func (b *bootstrapControlPlane) Teardown() error {
if b == nil {
return nil
}

UserOutput("Tearing down temporary bootstrap control plane...\n")
if err := os.RemoveAll(bootstrapSecretsDir); err != nil {
return err
Expand Down
56 changes: 45 additions & 11 deletions pkg/start/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"os"
"path/filepath"
"strings"
"sync"
"time"

"github.com/openshift/library-go/pkg/assets/create"
Expand All @@ -23,6 +24,8 @@ import (
const (
// how long we wait until the bootstrap pods to be running
bootstrapPodsRunningTimeout = 20 * time.Minute
// how long we wait until the assets must all be created
assetsCreatedTimeout = 60 * time.Minute
)

type Config struct {
Expand Down Expand Up @@ -63,8 +66,8 @@ func (b *startCommand) Run() error {

bcp := newBootstrapControlPlane(b.assetDir, b.podManifestPath)

// Always tear down the bootstrap control plane and clean up manifests and secrets.
defer func() {
// Always tear down the bootstrap control plane and clean up manifests and secrets.
if err := bcp.Teardown(); err != nil {
UserOutput("Error tearing down temporary bootstrap control plane: %v\n", err)
}
Expand All @@ -81,9 +84,6 @@ func (b *startCommand) Run() error {
return err
}

ctx, cancel := context.WithTimeout(context.TODO(), bootstrapPodsRunningTimeout)
defer cancel()

// We don't want the client contact the API servers via load-balancer, but only talk to the local API server.
// This will speed up the initial "where is working API server" process.
localClientConfig := rest.CopyConfig(restConfig)
Expand All @@ -98,23 +98,46 @@ func (b *startCommand) Run() error {
return err
}

if err := create.EnsureManifestsCreated(ctx, filepath.Join(b.assetDir, assetPathManifests), localClientConfig, create.CreateOptions{
Verbose: true,
StdErr: os.Stderr,
}); err != nil {
return err
// create assets against localhost apiserver (in the background) and wait for control plane to be up
createAssetsInBackground := func(ctx context.Context, cancel func(), client *rest.Config) *sync.WaitGroup {
done := sync.WaitGroup{}
done.Add(1)
go func() {
defer done.Done()
if err := create.EnsureManifestsCreated(ctx, filepath.Join(b.assetDir, assetPathManifests), client, create.CreateOptions{
Verbose: true,
StdErr: os.Stderr,
}); err != nil {
select {
case <-ctx.Done():
default:
UserOutput("Assert creation failed: %v\n", err)
cancel()
}
}
}()
return &done
}

if err = waitUntilPodsRunning(client, b.requiredPodPrefixes, bootstrapPodsRunningTimeout); err != nil {
ctx, cancel := context.WithTimeout(context.TODO(), bootstrapPodsRunningTimeout)
defer cancel()
assetsDone := createAssetsInBackground(ctx, cancel, localClientConfig)
if err = waitUntilPodsRunning(ctx, client, b.requiredPodPrefixes); err != nil {
return err
}
cancel()
assetsDone.Wait()

// notify installer that we are ready to tear down the temporary bootstrap control plane
UserOutput("Sending bootstrap-success event.")
if _, err := client.CoreV1().Events("kube-system").Create(makeBootstrapSuccessEvent("kube-system", "bootstrap-success")); err != nil && !apierrors.IsAlreadyExists(err) {
return err
}

// switch over to ELB client and continue with the assets
ctx, cancel = context.WithTimeout(context.Background(), assetsCreatedTimeout)
defer cancel()
assetsDone = createAssetsInBackground(ctx, cancel, restConfig)

// optionally wait for tear down event coming from the installer. This is necessary to
// remove the bootstrap node from the AWS load balancer.
if len(b.waitForTearDownEvent) != 0 {
Expand All @@ -129,6 +152,17 @@ func (b *startCommand) Run() error {
UserOutput("Got %s event.", b.waitForTearDownEvent)
}

// tear down the bootstrap control plane. Set bcp to nil to avoid a second tear down in the defer func.
err = bcp.Teardown()
bcp = nil
if err != nil {
UserOutput("Error tearing down temporary bootstrap control plane: %v\n", err)
}

// wait for the tail of assets to be created after tear down
UserOutput("Waiting for remaining assets to be created.\n")
assetsDone.Wait()

return nil
}

Expand Down
5 changes: 3 additions & 2 deletions pkg/start/status.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package start

import (
"context"
"fmt"
"reflect"
"strings"
Expand All @@ -16,14 +17,14 @@ import (
"k8s.io/client-go/tools/cache"
)

func waitUntilPodsRunning(c kubernetes.Interface, pods map[string][]string, timeout time.Duration) error {
func waitUntilPodsRunning(ctx context.Context, c kubernetes.Interface, pods map[string][]string) error {
sc, err := newStatusController(c, pods)
if err != nil {
return err
}
sc.Run()

if err := wait.Poll(5*time.Second, timeout, sc.AllRunningAndReady); err != nil {
if err := wait.PollImmediateUntil(5*time.Second, sc.AllRunningAndReady, ctx.Done()); err != nil {
return fmt.Errorf("error while checking pod status: %v", err)
}

Expand Down

0 comments on commit 05a5c8e

Please sign in to comment.