Skip to content

Commit 608614a

Browse files
committed
Plumb in top-level context
Plumbs the top-level context into the agent, create, & gather commands and into the asset graph.
1 parent e5544d3 commit 608614a

File tree

14 files changed

+83
-48
lines changed

14 files changed

+83
-48
lines changed

cmd/openshift-install/agent.go

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package main
22

33
import (
4+
"context"
5+
46
"github.com/spf13/cobra"
57

68
"github.com/openshift/installer/cmd/openshift-install/agent"
@@ -14,7 +16,7 @@ import (
1416
"github.com/openshift/installer/pkg/asset/password"
1517
)
1618

17-
func newAgentCmd() *cobra.Command {
19+
func newAgentCmd(ctx context.Context) *cobra.Command {
1820
agentCmd := &cobra.Command{
1921
Use: "agent",
2022
Short: "Commands for supporting cluster installation using agent installer",
@@ -23,7 +25,7 @@ func newAgentCmd() *cobra.Command {
2325
},
2426
}
2527

26-
agentCmd.AddCommand(newAgentCreateCmd())
28+
agentCmd.AddCommand(newAgentCreateCmd(ctx))
2729
agentCmd.AddCommand(agent.NewWaitForCmd())
2830
agentCmd.AddCommand(newAgentGraphCmd())
2931
return agentCmd
@@ -115,8 +117,7 @@ var (
115117
agentTargets = []target{agentConfigTarget, agentManifestsTarget, agentImageTarget, agentPXEFilesTarget, agentConfigImageTarget, agentUnconfiguredIgnitionTarget}
116118
)
117119

118-
func newAgentCreateCmd() *cobra.Command {
119-
120+
func newAgentCreateCmd(ctx context.Context) *cobra.Command {
120121
cmd := &cobra.Command{
121122
Use: "create",
122123
Short: "Commands for generating agent installation artifacts",
@@ -127,7 +128,7 @@ func newAgentCreateCmd() *cobra.Command {
127128

128129
for _, t := range agentTargets {
129130
t.command.Args = cobra.ExactArgs(0)
130-
t.command.Run = runTargetCmd(t.assets...)
131+
t.command.Run = runTargetCmd(ctx, t.assets...)
131132
cmd.AddCommand(t.command)
132133
}
133134

cmd/openshift-install/create.go

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -128,12 +128,10 @@ var (
128128
Short: "Create an OpenShift cluster",
129129
// FIXME: add longer descriptions for our commands with examples for better UX.
130130
// Long: "",
131-
PostRun: func(_ *cobra.Command, _ []string) {
132-
// Setup a context that is canceled when the user presses Ctrl+C,
133-
// or SIGTERM and SIGINT are received, this allows for a clean shutdown.
134-
ctx, cancel := context.WithCancel(context.TODO())
135-
defer cancel()
136-
logrus.RegisterExitHandler(cancel)
131+
PostRun: func(cmd *cobra.Command, _ []string) {
132+
133+
// Get the context that was set in newCreateCmd.
134+
ctx := cmd.Context()
137135

138136
exitCode, err := clusterCreatePostRun(ctx)
139137
if err != nil {
@@ -168,7 +166,7 @@ func clusterCreatePostRun(ctx context.Context) (int, error) {
168166
}
169167

170168
// Handle the case when the API server is not reachable.
171-
if err := handleUnreachableAPIServer(config); err != nil {
169+
if err := handleUnreachableAPIServer(ctx, config); err != nil {
172170
logrus.Fatal(fmt.Errorf("unable to handle api server override: %w", err))
173171
}
174172

@@ -177,7 +175,7 @@ func clusterCreatePostRun(ctx context.Context) (int, error) {
177175
//
178176
timer.StartTimer("Bootstrap Complete")
179177
if err := waitForBootstrapComplete(ctx, config); err != nil {
180-
bundlePath, gatherErr := runGatherBootstrapCmd(command.RootOpts.Dir)
178+
bundlePath, gatherErr := runGatherBootstrapCmd(ctx, command.RootOpts.Dir)
181179
if gatherErr != nil {
182180
logrus.Error("Attempted to gather debug logs after installation failure: ", gatherErr)
183181
}
@@ -278,7 +276,7 @@ func newClientError(errorInfo error) *clusterCreateError {
278276
}
279277
}
280278

281-
func newCreateCmd() *cobra.Command {
279+
func newCreateCmd(ctx context.Context) *cobra.Command {
282280
cmd := &cobra.Command{
283281
Use: "create",
284282
Short: "Create part of an OpenShift cluster",
@@ -289,22 +287,25 @@ func newCreateCmd() *cobra.Command {
289287

290288
for _, t := range targets {
291289
t.command.Args = cobra.ExactArgs(0)
292-
t.command.Run = runTargetCmd(t.assets...)
290+
t.command.Run = runTargetCmd(ctx, t.assets...)
293291
cmd.AddCommand(t.command)
294292
}
295293

296294
return cmd
297295
}
298296

299-
func runTargetCmd(targets ...asset.WritableAsset) func(cmd *cobra.Command, args []string) {
297+
func runTargetCmd(ctx context.Context, targets ...asset.WritableAsset) func(cmd *cobra.Command, args []string) {
300298
runner := func(directory string) error {
301299
fetcher := assetstore.NewAssetsFetcher(directory)
302-
return fetcher.FetchAndPersist(targets)
300+
return fetcher.FetchAndPersist(ctx, targets)
303301
}
304302

305303
return func(cmd *cobra.Command, args []string) {
306304
timer.StartTimer(timer.TotalTimeElapsed)
307305

306+
// Set the context to be used in the PostRun function.
307+
cmd.SetContext(ctx)
308+
308309
cleanup := command.SetupFileHook(command.RootOpts.Dir)
309310
defer cleanup()
310311

@@ -856,15 +857,15 @@ func meetsStabilityThreshold(progressing *configv1.ClusterOperatorStatusConditio
856857
return progressing.Status == configv1.ConditionFalse && time.Since(progressing.LastTransitionTime.Time).Seconds() > coStabilityThreshold
857858
}
858859

859-
func handleUnreachableAPIServer(config *rest.Config) error {
860+
func handleUnreachableAPIServer(ctx context.Context, config *rest.Config) error {
860861
assetStore, err := assetstore.NewStore(command.RootOpts.Dir)
861862
if err != nil {
862863
return fmt.Errorf("failed to create asset store: %w", err)
863864
}
864865

865866
// Ensure that the install is expecting the user to provision their own DNS solution.
866867
installConfig := &installconfig.InstallConfig{}
867-
if err := assetStore.Fetch(installConfig); err != nil {
868+
if err := assetStore.Fetch(ctx, installConfig); err != nil {
868869
return fmt.Errorf("failed to fetch %s: %w", installConfig.Name(), err)
869870
}
870871
switch installConfig.Config.Platform.Name() { //nolint:gocritic
@@ -877,7 +878,7 @@ func handleUnreachableAPIServer(config *rest.Config) error {
877878
}
878879

879880
lbConfig := &lbconfig.Config{}
880-
if err := assetStore.Fetch(lbConfig); err != nil {
881+
if err := assetStore.Fetch(ctx, lbConfig); err != nil {
881882
return fmt.Errorf("failed to fetch %s: %w", lbConfig.Name(), err)
882883
}
883884

cmd/openshift-install/gather.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ import (
3434
_ "github.com/openshift/installer/pkg/gather/gcp"
3535
)
3636

37-
func newGatherCmd() *cobra.Command {
37+
func newGatherCmd(ctx context.Context) *cobra.Command {
3838
cmd := &cobra.Command{
3939
Use: "gather",
4040
Short: "Gather debugging data for a given installation failure",
@@ -47,7 +47,7 @@ to debug the installation failures`,
4747
return cmd.Help()
4848
},
4949
}
50-
cmd.AddCommand(newGatherBootstrapCmd())
50+
cmd.AddCommand(newGatherBootstrapCmd(ctx))
5151
return cmd
5252
}
5353

@@ -58,15 +58,15 @@ var gatherBootstrapOpts struct {
5858
skipAnalysis bool
5959
}
6060

61-
func newGatherBootstrapCmd() *cobra.Command {
61+
func newGatherBootstrapCmd(ctx context.Context) *cobra.Command {
6262
cmd := &cobra.Command{
6363
Use: "bootstrap",
6464
Short: "Gather debugging data for a failing-to-bootstrap control plane",
6565
Args: cobra.ExactArgs(0),
6666
Run: func(_ *cobra.Command, _ []string) {
6767
cleanup := command.SetupFileHook(command.RootOpts.Dir)
6868
defer cleanup()
69-
bundlePath, err := runGatherBootstrapCmd(command.RootOpts.Dir)
69+
bundlePath, err := runGatherBootstrapCmd(ctx, command.RootOpts.Dir)
7070
if err != nil {
7171
logrus.Fatal(err)
7272
}
@@ -87,14 +87,14 @@ func newGatherBootstrapCmd() *cobra.Command {
8787
return cmd
8888
}
8989

90-
func runGatherBootstrapCmd(directory string) (string, error) {
90+
func runGatherBootstrapCmd(ctx context.Context, directory string) (string, error) {
9191
assetStore, err := assetstore.NewStore(directory)
9292
if err != nil {
9393
return "", errors.Wrap(err, "failed to create asset store")
9494
}
9595
// add the default bootstrap key pair to the sshKeys list
9696
bootstrapSSHKeyPair := &tls.BootstrapSSHKeyPair{}
97-
if err := assetStore.Fetch(bootstrapSSHKeyPair); err != nil {
97+
if err := assetStore.Fetch(ctx, bootstrapSSHKeyPair); err != nil {
9898
return "", errors.Wrapf(err, "failed to fetch %s", bootstrapSSHKeyPair.Name())
9999
}
100100
tmpfile, err := os.CreateTemp("", "bootstrap-ssh")
@@ -118,7 +118,7 @@ func runGatherBootstrapCmd(directory string) (string, error) {
118118

119119
if ha.Bootstrap == "" && len(ha.Masters) == 0 {
120120
config := &installconfig.InstallConfig{}
121-
if err := assetStore.Fetch(config); err != nil {
121+
if err := assetStore.Fetch(ctx, config); err != nil {
122122
return "", errors.Wrapf(err, "failed to fetch %s", config.Name())
123123
}
124124

cmd/openshift-install/main.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,17 +44,17 @@ func installerMain() {
4444
logrus.RegisterExitHandler(shutdown)
4545

4646
for _, subCmd := range []*cobra.Command{
47-
newCreateCmd(),
47+
newCreateCmd(ctx),
4848
newDestroyCmd(),
4949
newWaitForCmd(),
50-
newGatherCmd(),
50+
newGatherCmd(ctx),
5151
newAnalyzeCmd(),
5252
newVersionCmd(),
5353
newGraphCmd(),
5454
newCoreOSCmd(),
5555
newCompletionCmd(),
5656
newExplainCmd(),
57-
newAgentCmd(),
57+
newAgentCmd(ctx),
5858
} {
5959
rootCmd.AddCommand(subCmd)
6060
}

pkg/asset/cluster/cluster.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ type Cluster struct {
4242
}
4343

4444
var _ asset.WritableAsset = (*Cluster)(nil)
45+
var _ asset.Generator = (*Cluster)(nil)
4546

4647
// Name returns the human-friendly name of the asset.
4748
func (c *Cluster) Name() string {
@@ -78,7 +79,7 @@ func (c *Cluster) Dependencies() []asset.Asset {
7879
}
7980

8081
// Generate launches the cluster and generates the terraform state file on disk.
81-
func (c *Cluster) Generate(parents asset.Parents) (err error) {
82+
func (c *Cluster) GenerateWithContext(ctx context.Context, parents asset.Parents) (err error) {
8283
if InstallDir == "" {
8384
logrus.Fatalf("InstallDir has not been set for the %q asset", c.Name())
8485
}
@@ -136,7 +137,7 @@ func (c *Cluster) Generate(parents asset.Parents) (err error) {
136137
if err != nil {
137138
return fmt.Errorf("error getting infrastructure provider: %w", err)
138139
}
139-
files, err := provider.Provision(InstallDir, parents)
140+
files, err := provider.Provision(ctx, InstallDir, parents)
140141
if files != nil {
141142
c.FileList = append(c.FileList, files...) // append state files even in case of failure
142143
}
@@ -165,3 +166,9 @@ func (c *Cluster) Load(f asset.FileFetcher) (found bool, err error) {
165166

166167
return false, nil
167168
}
169+
170+
// Generate is implemented so the Cluster Asset maintains compatibility
171+
// with the Asset interface. It should never be called.
172+
func (c *Cluster) Generate(_ asset.Parents) (err error) {
173+
panic("Cluster.Generate was called instead of Cluster.GenerateWithContext")
174+
}

pkg/asset/store.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
package asset
22

3+
import (
4+
"context"
5+
)
6+
37
// Store is a store for the states of assets.
48
type Store interface {
59
// Fetch retrieves the state of the given asset, generating it and its
610
// dependencies if necessary. When purging consumed assets, none of the
711
// assets in assetsToPreserve will be purged.
8-
Fetch(assetToFetch Asset, assetsToPreserve ...WritableAsset) error
12+
Fetch(ctx context.Context, assetToFetch Asset, assetsToPreserve ...WritableAsset) error
913

1014
// Destroy removes the asset from all its internal state and also from
1115
// disk if possible.

pkg/asset/store/assetsfetcher.go

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

33
import (
4+
"context"
45
"fmt"
56

67
"github.com/pkg/errors"
@@ -12,7 +13,7 @@ import (
1213
// AssetsFetcher it's used to retrieve and resolve a specified set of assets.
1314
type AssetsFetcher interface {
1415
// Fetchs and persists all the writable assets from the configured assets store.
15-
FetchAndPersist(assets []asset.WritableAsset) error
16+
FetchAndPersist(context.Context, []asset.WritableAsset) error
1617
}
1718

1819
type fetcher struct {
@@ -36,14 +37,14 @@ func asFileWriter(a asset.WritableAsset) asset.FileWriter {
3637
}
3738

3839
// Fetchs all the writable assets from the configured assets store.
39-
func (f *fetcher) FetchAndPersist(assets []asset.WritableAsset) error {
40+
func (f *fetcher) FetchAndPersist(ctx context.Context, assets []asset.WritableAsset) error {
4041
assetStore, err := NewStore(f.storeDir)
4142
if err != nil {
4243
return fmt.Errorf("failed to create asset store: %w", err)
4344
}
4445

4546
for _, a := range assets {
46-
err := assetStore.Fetch(a, assets...)
47+
err := assetStore.Fetch(ctx, a, assets...)
4748
if err != nil {
4849
err = errors.Wrapf(err, "failed to fetch %s", a.Name())
4950
}

pkg/asset/store/store.go

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package store
22

33
import (
4+
"context"
45
"encoding/json"
56
"os"
67
"path/filepath"
@@ -72,8 +73,8 @@ func newStore(dir string) (*storeImpl, error) {
7273
// Fetch retrieves the state of the given asset, generating it and its
7374
// dependencies if necessary. When purging consumed assets, none of the
7475
// assets in preserved will be purged.
75-
func (s *storeImpl) Fetch(a asset.Asset, preserved ...asset.WritableAsset) error {
76-
if err := s.fetch(a, ""); err != nil {
76+
func (s *storeImpl) Fetch(ctx context.Context, a asset.Asset, preserved ...asset.WritableAsset) error {
77+
if err := s.fetch(ctx, a, ""); err != nil {
7778
return err
7879
}
7980
if err := s.saveStateFile(); err != nil {
@@ -192,7 +193,7 @@ func (s *storeImpl) saveStateFile() error {
192193
// fetch populates the given asset, generating it and its dependencies if
193194
// necessary, and returns whether or not the asset had to be regenerated and
194195
// any errors.
195-
func (s *storeImpl) fetch(a asset.Asset, indent string) error {
196+
func (s *storeImpl) fetch(ctx context.Context, a asset.Asset, indent string) error {
196197
logrus.Debugf("%sFetching %s...", indent, a.Name())
197198

198199
assetState, ok := s.assets[reflect.TypeOf(a)]
@@ -217,13 +218,13 @@ func (s *storeImpl) fetch(a asset.Asset, indent string) error {
217218
dependencies := a.Dependencies()
218219
parents := make(asset.Parents, len(dependencies))
219220
for _, d := range dependencies {
220-
if err := s.fetch(d, increaseIndent(indent)); err != nil {
221+
if err := s.fetch(ctx, d, increaseIndent(indent)); err != nil {
221222
return errors.Wrapf(err, "failed to fetch dependency of %q", a.Name())
222223
}
223224
parents.Add(d)
224225
}
225226
logrus.Debugf("%sGenerating %s...", indent, a.Name())
226-
if err := a.Generate(parents); err != nil {
227+
if err := asAssetGenerator(a).GenerateWithContext(ctx, parents); err != nil {
227228
return errors.Wrapf(err, "failed to generate asset %q", a.Name())
228229
}
229230
assetState.asset = a
@@ -371,3 +372,14 @@ func (s *storeImpl) Load(a asset.Asset) (asset.Asset, error) {
371372

372373
return s.assets[reflect.TypeOf(a)].asset, nil
373374
}
375+
376+
// asAssetGenerator determines if an asset implements the
377+
// Generate with context function, or if it needs an adapter.
378+
func asAssetGenerator(a asset.Asset) asset.Generator {
379+
switch v := a.(type) {
380+
case asset.Generator:
381+
return v
382+
default:
383+
return asset.NewDefaultGenerator(a)
384+
}
385+
}

pkg/infrastructure/aws/sdk/aws.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ type output struct {
6161
}
6262

6363
// Provision creates cluster infrastructure using AWS SDK calls.
64-
func (a InfraProvider) Provision(dir string, parents asset.Parents) ([]*asset.File, error) {
64+
func (a InfraProvider) Provision(ctx context.Context, dir string, parents asset.Parents) ([]*asset.File, error) {
6565
terraformVariables := &tfvarsAsset.TerraformVariables{}
6666
parents.Get(terraformVariables)
6767
// Unmarshall input from tf variables, so we can use it along with
@@ -109,7 +109,7 @@ func (a InfraProvider) Provision(dir string, parents asset.Parents) ([]*asset.Fi
109109
usePublicEndpoints := clusterAWSConfig.PublishStrategy == "External"
110110

111111
logger := logrus.StandardLogger()
112-
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Minute)
112+
ctx, cancel := context.WithTimeout(ctx, 30*time.Minute)
113113
defer cancel()
114114

115115
ec2Client := ec2.New(awsSession)

0 commit comments

Comments
 (0)