Skip to content

Commit 05a5c8e

Browse files
Merge pull request #18 from sttts/sttts-teardown-as-early-as-possible
start: tear down bootstrap control plane as early as possible
2 parents f22ee6b + a078c34 commit 05a5c8e

File tree

3 files changed

+52
-13
lines changed

3 files changed

+52
-13
lines changed

pkg/start/bootstrap.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,10 @@ func (b *bootstrapControlPlane) Start() error {
4848
// Teardown brings down the bootstrap control plane and cleans up the temporary manifests and
4949
// secrets. This function is idempotent.
5050
func (b *bootstrapControlPlane) Teardown() error {
51+
if b == nil {
52+
return nil
53+
}
54+
5155
UserOutput("Tearing down temporary bootstrap control plane...\n")
5256
if err := os.RemoveAll(bootstrapSecretsDir); err != nil {
5357
return err

pkg/start/start.go

Lines changed: 45 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"os"
99
"path/filepath"
1010
"strings"
11+
"sync"
1112
"time"
1213

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

2831
type Config struct {
@@ -63,8 +66,8 @@ func (b *startCommand) Run() error {
6366

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

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

84-
ctx, cancel := context.WithTimeout(context.TODO(), bootstrapPodsRunningTimeout)
85-
defer cancel()
86-
8787
// We don't want the client contact the API servers via load-balancer, but only talk to the local API server.
8888
// This will speed up the initial "where is working API server" process.
8989
localClientConfig := rest.CopyConfig(restConfig)
@@ -98,23 +98,46 @@ func (b *startCommand) Run() error {
9898
return err
9999
}
100100

101-
if err := create.EnsureManifestsCreated(ctx, filepath.Join(b.assetDir, assetPathManifests), localClientConfig, create.CreateOptions{
102-
Verbose: true,
103-
StdErr: os.Stderr,
104-
}); err != nil {
105-
return err
101+
// create assets against localhost apiserver (in the background) and wait for control plane to be up
102+
createAssetsInBackground := func(ctx context.Context, cancel func(), client *rest.Config) *sync.WaitGroup {
103+
done := sync.WaitGroup{}
104+
done.Add(1)
105+
go func() {
106+
defer done.Done()
107+
if err := create.EnsureManifestsCreated(ctx, filepath.Join(b.assetDir, assetPathManifests), client, create.CreateOptions{
108+
Verbose: true,
109+
StdErr: os.Stderr,
110+
}); err != nil {
111+
select {
112+
case <-ctx.Done():
113+
default:
114+
UserOutput("Assert creation failed: %v\n", err)
115+
cancel()
116+
}
117+
}
118+
}()
119+
return &done
106120
}
107-
108-
if err = waitUntilPodsRunning(client, b.requiredPodPrefixes, bootstrapPodsRunningTimeout); err != nil {
121+
ctx, cancel := context.WithTimeout(context.TODO(), bootstrapPodsRunningTimeout)
122+
defer cancel()
123+
assetsDone := createAssetsInBackground(ctx, cancel, localClientConfig)
124+
if err = waitUntilPodsRunning(ctx, client, b.requiredPodPrefixes); err != nil {
109125
return err
110126
}
127+
cancel()
128+
assetsDone.Wait()
111129

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

136+
// switch over to ELB client and continue with the assets
137+
ctx, cancel = context.WithTimeout(context.Background(), assetsCreatedTimeout)
138+
defer cancel()
139+
assetsDone = createAssetsInBackground(ctx, cancel, restConfig)
140+
118141
// optionally wait for tear down event coming from the installer. This is necessary to
119142
// remove the bootstrap node from the AWS load balancer.
120143
if len(b.waitForTearDownEvent) != 0 {
@@ -129,6 +152,17 @@ func (b *startCommand) Run() error {
129152
UserOutput("Got %s event.", b.waitForTearDownEvent)
130153
}
131154

155+
// tear down the bootstrap control plane. Set bcp to nil to avoid a second tear down in the defer func.
156+
err = bcp.Teardown()
157+
bcp = nil
158+
if err != nil {
159+
UserOutput("Error tearing down temporary bootstrap control plane: %v\n", err)
160+
}
161+
162+
// wait for the tail of assets to be created after tear down
163+
UserOutput("Waiting for remaining assets to be created.\n")
164+
assetsDone.Wait()
165+
132166
return nil
133167
}
134168

pkg/start/status.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package start
22

33
import (
4+
"context"
45
"fmt"
56
"reflect"
67
"strings"
@@ -16,14 +17,14 @@ import (
1617
"k8s.io/client-go/tools/cache"
1718
)
1819

19-
func waitUntilPodsRunning(c kubernetes.Interface, pods map[string][]string, timeout time.Duration) error {
20+
func waitUntilPodsRunning(ctx context.Context, c kubernetes.Interface, pods map[string][]string) error {
2021
sc, err := newStatusController(c, pods)
2122
if err != nil {
2223
return err
2324
}
2425
sc.Run()
2526

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

0 commit comments

Comments
 (0)