Skip to content

Commit 039a690

Browse files
committed
PRODENG-2780 MSR cmdbuffer usage
- MKE style cmdbuffer usage - migrating the install and upgrade and pull images phases to use the new cmdbuffer based bootstrap functions Signed-off-by: James Nesbitt <[email protected]>
1 parent da6cc81 commit 039a690

File tree

16 files changed

+253
-188
lines changed

16 files changed

+253
-188
lines changed

.gitignore

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,5 @@ github-release
1515
# go mod vendor folder
1616
vendor
1717

18-
# binaries
19-
bin/
18+
# sometimes an example launchpad.yaml is used
19+
**/launchpad.yaml

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ build-release: clean $(RELEASE_FOLDER)
3636
# the GORELEASER_CURRENT_TAG env var to clarify the version to
3737
# avoid having the wrong tag version applied
3838
$(RELEASE_FOLDER):
39-
goreleaser build --clean --config=.goreleaser.release.yml
39+
SEGMENT_TOKEN=${SEGMENT_TOKEN} goreleaser build --clean --config=.goreleaser.release.yml
4040

4141
.PHONY: create-checksum
4242
create-checksum:

examples/terraform/aws-simple/.terraform.lock.hcl

Lines changed: 0 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/mke/bootstrap.go

Lines changed: 35 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2,69 +2,78 @@ package mke
22

33
import (
44
"bufio"
5+
"errors"
56
"fmt"
67

78
mcclog "github.com/Mirantis/launchpad/pkg/log"
89
common "github.com/Mirantis/launchpad/pkg/product/common/api"
910
"github.com/Mirantis/launchpad/pkg/product/mke/api"
1011
"github.com/Mirantis/launchpad/pkg/util/cmdbuffer"
1112
"github.com/k0sproject/rig/exec"
12-
"github.com/sirupsen/logrus"
1313
)
1414

15-
// BootstrapConfig configure options for the Bootstrap.
16-
type BootstrapConfig struct {
17-
Config api.ClusterConfig // REQUIRED: the cluster config is needed
18-
Operation string // REQUIRED: the MKE bootstrapper operation to run (e.g. install, reset)
19-
OperationFlags common.Flags // OPTIONAL: flags to pass to the bootstrapper command
20-
CleanupDisabled bool // OPTIONAL: if true, then the bootstrapper container will not be removed
21-
ExecOptions []exec.Option // OPTIONAL: additional rig exec options to pass down to rig
15+
// BootstrapOptions configure options for the Bootstrap.
16+
type BootstrapOptions struct {
17+
OperationFlags common.Flags // OPTIONAL: flags to pass to the bootstrapper command
18+
CleanupDisabled bool // OPTIONAL: if true, then the bootstrapper container will not be removed
19+
ExecOptions []exec.Option // OPTIONAL: additional rig exec options to pass down to rig
2220
}
2321

2422
// Bootstrap a leader host using the MKE bootsrapper as docker run, returning output.
25-
func Bootstrap(bootconf BootstrapConfig) (string, error) {
26-
image := bootconf.Config.Spec.MKE.GetBootstrapperImage()
27-
leader := bootconf.Config.Spec.SwarmLeader()
23+
func Bootstrap(operation string, config api.ClusterConfig, bootoptions BootstrapOptions) (output string, err error) {
24+
image := config.Spec.MKE.GetBootstrapperImage()
25+
leader := config.Spec.SwarmLeader()
2826

2927
if mcclog.Debug {
30-
bootconf.OperationFlags.AddUnlessExist("--debug")
28+
bootoptions.OperationFlags.AddUnlessExist("--debug")
3129
}
3230

3331
runFlags := common.Flags{"-i", "-v /var/run/docker.sock:/var/run/docker.sock"}
3432

35-
if !bootconf.CleanupDisabled {
33+
if !bootoptions.CleanupDisabled {
3634
runFlags.Add("--rm")
3735
}
3836

3937
if leader.Configurer.SELinuxEnabled(leader) {
4038
runFlags.Add("--security-opt label=disable")
4139
}
4240

43-
cmd := leader.Configurer.DockerCommandf("run %s %s %s %s", runFlags.Join(), image, bootconf.Operation, bootconf.OperationFlags.Join())
44-
output := ""
41+
cmd := leader.Configurer.DockerCommandf("run %s %s %s %s", runFlags.Join(), image, operation, bootoptions.OperationFlags.Join())
4542
buf := cmdbuffer.NewBuffer() // an io.Reader which .Read() doesn't eof until .eof() is run. On eof is blocks the .Read
4643

47-
if wait, err := leader.ExecStreams(cmd, nil, buf, buf, bootconf.ExecOptions...); err != nil {
44+
if wait, err := leader.ExecStreams(cmd, nil, buf, buf, bootoptions.ExecOptions...); err != nil {
4845
return output, fmt.Errorf("mke bootstrap exec error: %w", err)
4946
} else { //nolint: revive
5047
go func() {
51-
if err := wait.Wait(); err != nil {
52-
logrus.Error(err)
48+
if waitErr := wait.Wait(); waitErr != nil {
49+
err = errors.Join(err, fmt.Errorf("mke bootstrap %s failure; %w", operation, waitErr))
5350
}
5451
buf.EOF()
5552
}()
5653
}
5754

58-
sc := bufio.NewScanner(buf)
59-
for sc.Scan() {
60-
line := sc.Text()
61-
output += line
55+
scanner := bufio.NewScanner(buf)
56+
for scanner.Scan() {
57+
line := scanner.Text()
6258

63-
cmdbuffer.LogrusLine(cmdbuffer.LogrusParseText(line))
59+
if le, parseErr := cmdbuffer.LogrusParseText(line); parseErr == nil {
60+
// output was logrus, so pipe it to launchpad logrus
61+
output += fmt.Sprintf("%s\n", le.Msg)
62+
le.Msg = fmt.Sprintf("MKE %s: %s", operation, le.Msg)
63+
cmdbuffer.LogrusLine(le)
64+
65+
if le.Level == "fatal" {
66+
err = errors.Join(err, fmt.Errorf("mke bootstrap %s failure; %s", operation, le.Msg)) //nolint
67+
}
68+
} else {
69+
// output line was not logrus, so just output it
70+
output += fmt.Sprintf("%s\n", line)
71+
fmt.Println(line)
72+
}
6473
}
65-
if err := sc.Err(); err != nil {
66-
return output, fmt.Errorf("mke bootstrap output scan error: %w", err)
74+
if scanErr := scanner.Err(); scanErr != nil {
75+
err = errors.Join(err, fmt.Errorf("mke bootstrap output scan error: %w", scanErr))
6776
}
6877

69-
return output, nil
78+
return output, err
7079
}

pkg/msr/bootstrap.go

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
package msr
2+
3+
import (
4+
"bufio"
5+
"errors"
6+
"fmt"
7+
8+
mcclog "github.com/Mirantis/launchpad/pkg/log"
9+
common "github.com/Mirantis/launchpad/pkg/product/common/api"
10+
"github.com/Mirantis/launchpad/pkg/product/mke/api"
11+
"github.com/Mirantis/launchpad/pkg/util/cmdbuffer"
12+
"github.com/k0sproject/rig/exec"
13+
"github.com/sirupsen/logrus"
14+
)
15+
16+
// BootstrapOptions configure options for the Bootstrap.
17+
type BootstrapOptions struct {
18+
OperationFlags common.Flags // OPTIONAL: flags to pass to the bootstrapper command
19+
CleanupDisabled bool // OPTIONAL: if true, then the bootstrapper container will not be removed
20+
ExecOptions []exec.Option // OPTIONAL: additional rig exec options to pass down to rig
21+
}
22+
23+
// Bootstrap a leader host using the MKE bootsrapper as docker run, returning output.
24+
func Bootstrap(operation string, config api.ClusterConfig, bootoptions BootstrapOptions) (output string, err error) {
25+
image := config.Spec.MSR.GetBootstrapperImage()
26+
leader := config.Spec.MSRLeader()
27+
managers := config.Spec.Managers()
28+
29+
if checkErr := config.Spec.CheckMKEHealthRemote(managers); err != nil {
30+
return "", fmt.Errorf("%s: failed to health check mke, try to set `--ucp-url` installFlag and check connectivity: %w", leader, checkErr)
31+
}
32+
33+
if mcclog.Debug && operation != "images" {
34+
bootoptions.OperationFlags.AddUnlessExist("--debug")
35+
}
36+
37+
runFlags := common.Flags{"-i"}
38+
39+
if !bootoptions.CleanupDisabled {
40+
runFlags.Add("--rm")
41+
}
42+
43+
if leader.Configurer.SELinuxEnabled(leader) {
44+
runFlags.Add("--security-opt label=disable")
45+
}
46+
47+
cmd := leader.Configurer.DockerCommandf("run %s %s %s %s", runFlags.Join(), image, operation, bootoptions.OperationFlags.Join())
48+
49+
buf := cmdbuffer.NewBuffer()
50+
51+
if wait, err := leader.ExecStreams(cmd, nil, buf, buf, bootoptions.ExecOptions...); err != nil {
52+
return output, fmt.Errorf("msr bootstrap exec error: %w", err)
53+
} else { //nolint: revive
54+
go func() {
55+
if waitErr := wait.Wait(); waitErr != nil {
56+
err = errors.Join(err, fmt.Errorf("msr bootstrap %s failure; %w", operation, waitErr))
57+
logrus.Error(err)
58+
}
59+
buf.EOF()
60+
}()
61+
}
62+
63+
scanner := bufio.NewScanner(buf)
64+
for scanner.Scan() {
65+
line := scanner.Text()
66+
67+
if le, parseErr := cmdbuffer.LogrusParseText(line); parseErr == nil {
68+
// output was logrus, so pipe it to launchpad logrus
69+
output += fmt.Sprintf("%s\n", le.Msg)
70+
le.Msg = fmt.Sprintf("MSR %s: %s", operation, le.Msg)
71+
cmdbuffer.LogrusLine(le)
72+
73+
if le.Level == "fatal" {
74+
err = errors.Join(err, fmt.Errorf("msr bootstrap %s failure; %s", operation, le.Msg)) //nolint
75+
}
76+
} else {
77+
// output line was not logrus, so just output it
78+
output += fmt.Sprintf("%s\n", line)
79+
fmt.Println(line)
80+
}
81+
}
82+
if scanErr := scanner.Err(); scanErr != nil {
83+
err = errors.Join(err, fmt.Errorf("msr bootstrap output scan error: %w", scanErr)) //nolint
84+
}
85+
86+
return output, nil
87+
}

pkg/product/mke/phase/install_mke.go

Lines changed: 10 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import (
99
mcclog "github.com/Mirantis/launchpad/pkg/log"
1010
"github.com/Mirantis/launchpad/pkg/mke"
1111
"github.com/Mirantis/launchpad/pkg/phase"
12-
common "github.com/Mirantis/launchpad/pkg/product/common/api"
1312
"github.com/Mirantis/launchpad/pkg/product/mke/api"
1413
"github.com/Mirantis/launchpad/pkg/util/installutil"
1514
"github.com/k0sproject/rig/exec"
@@ -35,18 +34,16 @@ func (p *InstallMKE) Title() string {
3534
// Run the installer container.
3635
func (p *InstallMKE) Run() error {
3736
p.leader = p.Config.Spec.SwarmLeader()
38-
h := p.leader
3937

4038
p.EventProperties = map[string]interface{}{
4139
"mke_version": p.Config.Spec.MKE.Version,
4240
}
4341

4442
if p.Config.Spec.MKE.Metadata.Installed {
45-
log.Infof("%s: MKE already installed at version %s, not running installer", h, p.Config.Spec.MKE.Metadata.InstalledVersion)
43+
log.Infof("%s: MKE already installed at version %s, not running installer", p.leader, p.Config.Spec.MKE.Metadata.InstalledVersion)
4644
return nil
4745
}
4846

49-
image := p.Config.Spec.MKE.GetBootstrapperImage()
5047
installFlags := p.Config.Spec.MKE.InstallFlags
5148

5249
if mcclog.Debug {
@@ -55,18 +52,18 @@ func (p *InstallMKE) Run() error {
5552

5653
if p.Config.Spec.MKE.ConfigData != "" {
5754
defer func() {
58-
err := h.Exec(h.Configurer.DockerCommandf("config rm %s", configName))
55+
err := p.leader.Exec(p.leader.Configurer.DockerCommandf("config rm %s", configName))
5956
if err != nil {
6057
log.Warnf("Failed to remove the temporary MKE installer configuration %s : %s", configName, err)
6158
}
6259
}()
6360

6461
installFlags.AddUnlessExist("--existing-config")
6562
log.Info("Creating MKE configuration")
66-
configCmd := h.Configurer.DockerCommandf("config create %s -", configName)
67-
err := h.Exec(configCmd, exec.Stdin(p.Config.Spec.MKE.ConfigData))
63+
configCmd := p.leader.Configurer.DockerCommandf("config create %s -", configName)
64+
err := p.leader.Exec(configCmd, exec.Stdin(p.Config.Spec.MKE.ConfigData))
6865
if err != nil {
69-
return fmt.Errorf("%s: failed to create MKE configuration: %w", h, err)
66+
return fmt.Errorf("%s: failed to create MKE configuration: %w", p.leader, err)
7067
}
7168
}
7269

@@ -94,27 +91,18 @@ func (p *InstallMKE) Run() error {
9491
// In case of custom repo, don't let MKE check the images
9592
installFlags.AddUnlessExist("--pull never")
9693
}
97-
runFlags := common.Flags{"-i", "-v /var/run/docker.sock:/var/run/docker.sock"}
98-
if !p.CleanupDisabled() {
99-
runFlags.Add("--rm")
100-
}
101-
102-
if h.Configurer.SELinuxEnabled(h) {
103-
runFlags.Add("--security-opt label=disable")
104-
}
10594

10695
if p.Config.Spec.MKE.AdminUsername != "" {
10796
installFlags.AddUnlessExist(fmt.Sprintf("--admin-username='%s'", p.Config.Spec.MKE.AdminUsername))
10897
}
109-
11098
if p.Config.Spec.MKE.AdminPassword != "" {
11199
installFlags.AddUnlessExist(fmt.Sprintf("--admin-password='%s'", p.Config.Spec.MKE.AdminPassword))
112100
}
113101

114-
installCmd := h.Configurer.DockerCommandf("run %s %s install %s", runFlags.Join(), image, installFlags.Join())
115-
output, err := h.ExecOutput(installCmd, exec.StreamOutput(), exec.RedactString(p.Config.Spec.MKE.AdminUsername, p.Config.Spec.MKE.AdminPassword))
102+
log.Debugf("%s: install flags: %s", p.leader, installFlags.Join())
103+
output, err := mke.Bootstrap("install", *p.Config, mke.BootstrapOptions{OperationFlags: installFlags, CleanupDisabled: p.CleanupDisabled(), ExecOptions: []exec.Option{exec.StreamOutput(), exec.RedactString(p.Config.Spec.MKE.AdminUsername, p.Config.Spec.MKE.AdminPassword)}})
116104
if err != nil {
117-
return fmt.Errorf("%s: failed to run MKE installer: \n output: %s \n error: %w", h, output, err)
105+
return fmt.Errorf("%s: failed to run MKE installer: \n output: %s \n error: %w", p.leader, output, err)
118106
}
119107

120108
if installFlags.GetValue("--admin-password") == "" {
@@ -130,9 +118,9 @@ func (p *InstallMKE) Run() error {
130118
}
131119
}
132120

133-
err = mke.CollectFacts(h, p.Config.Spec.MKE.Metadata)
121+
err = mke.CollectFacts(p.leader, p.Config.Spec.MKE.Metadata)
134122
if err != nil {
135-
return fmt.Errorf("%s: failed to collect existing MKE details: %w", h, err)
123+
return fmt.Errorf("%s: failed to collect existing MKE details: %w", p.leader, err)
136124
}
137125

138126
return nil

pkg/product/mke/phase/install_msr.go

Lines changed: 1 addition & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import (
55

66
"github.com/Mirantis/launchpad/pkg/msr"
77
"github.com/Mirantis/launchpad/pkg/phase"
8-
common "github.com/Mirantis/launchpad/pkg/product/common/api"
98
"github.com/Mirantis/launchpad/pkg/product/mke/api"
109
"github.com/alessio/shellescape"
1110
"github.com/k0sproject/rig/exec"
@@ -36,32 +35,14 @@ func (p *InstallMSR) ShouldRun() bool {
3635
// Run the installer container.
3736
func (p *InstallMSR) Run() error {
3837
h := p.leader
39-
4038
if h.MSRMetadata == nil {
4139
h.MSRMetadata = &api.MSRMetadata{}
4240
}
4341

44-
managers := p.Config.Spec.Managers()
45-
46-
err := p.Config.Spec.CheckMKEHealthRemote(managers)
47-
if err != nil {
48-
return fmt.Errorf("%s: failed to health check mke, try to set `--ucp-url` installFlag and check connectivity: %w", h, err)
49-
}
50-
5142
p.EventProperties = map[string]interface{}{
5243
"msr_version": p.Config.Spec.MSR.Version,
5344
}
5445

55-
image := p.Config.Spec.MSR.GetBootstrapperImage()
56-
57-
runFlags := common.Flags{"-i"}
58-
if !p.CleanupDisabled() {
59-
runFlags.Add("--rm")
60-
}
61-
62-
if h.Configurer.SELinuxEnabled(h) {
63-
runFlags.Add("--security-opt label=disable")
64-
}
6546
installFlags := p.Config.Spec.MSR.InstallFlags
6647
redacts := []string{installFlags.GetValue("--ucp-username"), installFlags.GetValue("--ucp-password")}
6748

@@ -104,9 +85,7 @@ func (p *InstallMSR) Run() error {
10485
log.Infof("%s: installing MSR version %s", h, p.Config.Spec.MSR.Version)
10586
}
10687

107-
installCmd := h.Configurer.DockerCommandf("run %s %s install %s", runFlags.Join(), image, installFlags.Join())
108-
err = h.Exec(installCmd, exec.StreamOutput(), exec.RedactString(redacts...))
109-
if err != nil {
88+
if _, err := msr.Bootstrap("install", *p.Config, msr.BootstrapOptions{OperationFlags: installFlags, CleanupDisabled: p.CleanupDisabled(), ExecOptions: []exec.Option{exec.RedactString(redacts...)}}); err != nil {
11089
return fmt.Errorf("%s: failed to run MSR installer: %w", h, err)
11190
}
11291

0 commit comments

Comments
 (0)