Skip to content

Commit c4143dd

Browse files
Merge pull request #3091 from hunterkepley/ocm-20194
OCM-20194 | feat: Win-Li support (machinepool type flag)
2 parents f773f4b + 46ecb42 commit c4143dd

File tree

8 files changed

+152
-7
lines changed

8 files changed

+152
-7
lines changed

cmd/create/machinepool/cmd.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,10 @@ func CreateMachinepoolRunner(userOptions *mpOpts.CreateMachinepoolUserOptions) r
7777
return err
7878
}
7979

80+
if err := machinepool.ValidateImageType(cmd, options.args, cluster); err != nil {
81+
return err
82+
}
83+
8084
r.AWSClient, err = aws.NewClient().
8185
Region(cluster.Region().ID()).
8286
Logger(r.Logger).

cmd/rosa/structure_test/command_args/rosa/create/machinepool/command_args.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,4 @@
2626
- name: use-spot-instances
2727
- name: version
2828
- name: capacity-reservation-id
29+
- name: type

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ require (
2929
github.com/nathan-fiscaletti/consolesize-go v0.0.0-20210105204122-a87d9f614b9d
3030
github.com/onsi/ginkgo/v2 v2.17.1
3131
github.com/onsi/gomega v1.30.0
32+
github.com/openshift-online/ocm-api-model/clientapi v0.0.437
3233
github.com/openshift-online/ocm-common v0.0.31
3334
github.com/openshift-online/ocm-sdk-go v0.1.482
3435
github.com/pkg/errors v0.9.1
@@ -50,7 +51,6 @@ require (
5051
github.com/aws/aws-sdk-go-v2/service/ram v1.26.1 // indirect
5152
github.com/go-jose/go-jose/v4 v4.0.2 // indirect
5253
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
53-
github.com/openshift-online/ocm-api-model/clientapi v0.0.437 // indirect
5454
github.com/openshift-online/ocm-api-model/model v0.0.437 // indirect
5555
go.yaml.in/yaml/v2 v2.4.3 // indirect
5656
)

pkg/helper/machinepools/helpers.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"k8s.io/apimachinery/pkg/util/errors"
1111
"k8s.io/apimachinery/pkg/util/validation"
1212

13+
v1 "github.com/openshift-online/ocm-api-model/clientapi/clustersmgmt/v1"
1314
commonUtils "github.com/openshift-online/ocm-common/pkg/utils"
1415
cmv1 "github.com/openshift-online/ocm-sdk-go/clustersmgmt/v1"
1516
"github.com/spf13/cobra"
@@ -32,6 +33,10 @@ const (
3233
MaxNodeDrainTimeInHours = 168
3334
)
3435

36+
var (
37+
ImageTypes = []string{string(v1.ImageTypeDefault), string(v1.ImageTypeWindows)}
38+
)
39+
3540
var allowedTaintEffects = []string{
3641
"NoSchedule",
3742
"NoExecute",
@@ -363,3 +368,12 @@ func ValidateUpgradeMaxSurgeUnavailable(val interface{}) error {
363368

364369
return nil
365370
}
371+
372+
func IsValidImageType(imageType string) bool {
373+
for t := range ImageTypes {
374+
if ImageTypes[t] == imageType {
375+
return true
376+
}
377+
}
378+
return false
379+
}

pkg/machinepool/helper.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,22 @@ func ValidateLabels(cmd *cobra.Command, args *mpOpts.CreateMachinepoolUserOption
5959
return nil
6060
}
6161

62+
// Validate that the image type is a real one
63+
func ValidateImageType(cmd *cobra.Command, args *mpOpts.CreateMachinepoolUserOptions, cluster *cmv1.Cluster) error {
64+
if cmd.Flags().Changed("type") {
65+
if !cluster.Hypershift().Enabled() {
66+
return fmt.Errorf("the '--type' flag can only be used with Hosted Control Plane clusters")
67+
}
68+
imageType := args.Type
69+
70+
if mpHelpers.IsValidImageType(imageType) {
71+
return nil
72+
}
73+
return fmt.Errorf("invalid image type: '%s' - please use one of: %v", imageType, prettyPrintImageTypes())
74+
}
75+
return nil
76+
}
77+
6278
// Validate the cluster's state is ready
6379
func ValidateClusterState(cluster *cmv1.Cluster, clusterKey string) error {
6480
if cluster.State() != cmv1.ClusterStateReady {
@@ -462,3 +478,15 @@ func isDedicatedHost(machinePool *cmv1.MachinePool, runtime *rosa.Runtime) strin
462478
}
463479
return displayValueNo
464480
}
481+
482+
func prettyPrintImageTypes() string {
483+
s := "'"
484+
for i, t := range mpHelpers.ImageTypes {
485+
if i == 0 {
486+
s += t
487+
} else {
488+
s += "', '" + t
489+
}
490+
}
491+
return s + "'"
492+
}

pkg/machinepool/helper_test.go

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,13 @@ import (
99
ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types"
1010
. "github.com/onsi/ginkgo/v2"
1111
. "github.com/onsi/gomega"
12+
v1 "github.com/openshift-online/ocm-api-model/clientapi/clustersmgmt/v1"
1213
cmv1 "github.com/openshift-online/ocm-sdk-go/clustersmgmt/v1"
1314
"github.com/spf13/cobra"
1415

1516
mock "github.com/openshift/rosa/pkg/aws"
1617
"github.com/openshift/rosa/pkg/helper/features"
18+
mpHelpers "github.com/openshift/rosa/pkg/helper/machinepools"
1719
mpOpts "github.com/openshift/rosa/pkg/options/machinepool"
1820
"github.com/openshift/rosa/pkg/reporter"
1921
"github.com/openshift/rosa/pkg/rosa"
@@ -909,3 +911,71 @@ var _ = Describe("isDedicatedHost Function", func() {
909911
Expect(result).To(Equal(displayValueUnknown))
910912
})
911913
})
914+
915+
var _ = Describe("ValidateImageType", func() {
916+
It("OK: Pass Windows + Default string as image type", func() {
917+
Expect(mpHelpers.IsValidImageType(string(v1.ImageTypeWindows))).To(BeTrue())
918+
Expect(mpHelpers.IsValidImageType(string(v1.ImageTypeDefault))).To(BeTrue())
919+
})
920+
It("KO: Do not pass anything else as image type", func() {
921+
Expect(mpHelpers.IsValidImageType("")).To(BeFalse())
922+
Expect(mpHelpers.IsValidImageType("win-li")).To(BeFalse())
923+
Expect(mpHelpers.IsValidImageType("windows")).To(BeFalse())
924+
Expect(mpHelpers.IsValidImageType("unix")).To(BeFalse())
925+
Expect(mpHelpers.IsValidImageType("123123123")).To(BeFalse())
926+
})
927+
It("OK: Validate full flow works", func() {
928+
cmd := &cobra.Command{}
929+
args := &mpOpts.CreateMachinepoolUserOptions{}
930+
cmd.Flags().StringVar(&args.Type, "type", "", "")
931+
cluster, err := cmv1.NewCluster().Hypershift(cmv1.NewHypershift().Enabled(true)).Build()
932+
Expect(err).ToNot(HaveOccurred())
933+
934+
args.Type = string(v1.ImageTypeWindows)
935+
cmd.SetArgs([]string{fmt.Sprintf("--type=%s", args.Type)})
936+
Expect(cmd.Execute()).ToNot(HaveOccurred())
937+
err = ValidateImageType(cmd, args, cluster)
938+
Expect(err).ToNot(HaveOccurred())
939+
940+
args.Type = string(v1.ImageTypeDefault)
941+
cmd.SetArgs([]string{fmt.Sprintf("--type=%s", args.Type)})
942+
Expect(cmd.Execute()).ToNot(HaveOccurred())
943+
err = ValidateImageType(cmd, args, cluster)
944+
Expect(err).ToNot(HaveOccurred())
945+
})
946+
It("KO: Validate full flow fails", func() {
947+
cmd := &cobra.Command{}
948+
args := &mpOpts.CreateMachinepoolUserOptions{}
949+
cluster, err := cmv1.NewCluster().Hypershift(cmv1.NewHypershift().Enabled(true)).Build()
950+
Expect(err).ToNot(HaveOccurred())
951+
952+
cmd.Flags().StringVar(&args.Type, "type", "", "")
953+
954+
args.Type = ""
955+
cmd.SetArgs([]string{fmt.Sprintf("--type=%s", args.Type)})
956+
Expect(cmd.Execute()).ToNot(HaveOccurred())
957+
err = ValidateImageType(cmd, args, cluster)
958+
Expect(err).To(HaveOccurred())
959+
960+
args.Type = "windows"
961+
cmd.SetArgs([]string{fmt.Sprintf("--type=%s", args.Type)})
962+
Expect(cmd.Execute()).ToNot(HaveOccurred())
963+
err = ValidateImageType(cmd, args, cluster)
964+
Expect(err).To(HaveOccurred())
965+
966+
args.Type = "w123123123"
967+
cmd.SetArgs([]string{fmt.Sprintf("--type=%s", args.Type)})
968+
Expect(cmd.Execute()).ToNot(HaveOccurred())
969+
err = ValidateImageType(cmd, args, cluster)
970+
Expect(err).To(HaveOccurred())
971+
972+
clusterClassic, err := cmv1.NewCluster().Hypershift(cmv1.NewHypershift().Enabled(false)).Build()
973+
Expect(err).ToNot(HaveOccurred())
974+
975+
args.Type = "w123123123"
976+
cmd.SetArgs([]string{fmt.Sprintf("--type=%s", args.Type)})
977+
Expect(cmd.Execute()).ToNot(HaveOccurred())
978+
err = ValidateImageType(cmd, args, clusterClassic)
979+
Expect(err).To(HaveOccurred())
980+
})
981+
})

pkg/machinepool/machinepool.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -540,6 +540,28 @@ func (m *machinePool) CreateNodePools(r *rosa.Runtime, cmd *cobra.Command, clust
540540
return fmt.Errorf("expected a valid name for the machine pool")
541541
}
542542

543+
imageType := ""
544+
if args.Type != "" && cluster.Hypershift().Enabled() {
545+
imageType = args.Type
546+
}
547+
548+
// Image type (supports things such as WinLI // Windows VMs)
549+
if interactive.Enabled() && cluster.Hypershift().Enabled() {
550+
imageType, err = interactive.GetOption(interactive.Input{
551+
Question: "Image Type",
552+
Default: cmv1.ImageTypeDefault,
553+
Required: false,
554+
Options: mpHelpers.ImageTypes,
555+
})
556+
if err != nil {
557+
return fmt.Errorf("expected a valid image type: '%s'", err)
558+
}
559+
}
560+
561+
if imageType != "" && !mpHelpers.IsValidImageType(imageType) {
562+
return fmt.Errorf("expected a valid image type for the machine pool: '%s'", imageType)
563+
}
564+
543565
// OpenShift version:
544566
isVersionSet := cmd.Flags().Changed("version")
545567
version := args.Version
@@ -1025,6 +1047,10 @@ func (m *machinePool) CreateNodePools(r *rosa.Runtime, cmd *cobra.Command, clust
10251047
}
10261048
}
10271049

1050+
if imageType != "" {
1051+
npBuilder.ImageType(cmv1.ImageType(imageType))
1052+
}
1053+
10281054
if version != "" {
10291055
npBuilder.Version(cmv1.NewVersion().ID(version))
10301056
}

pkg/options/machinepool/create.go

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ type CreateMachinepoolUserOptions struct {
3535
MaxUnavailable string
3636
EC2MetadataHttpTokens string
3737
CapacityReservationId string
38+
Type string
3839
}
3940

4041
const (
@@ -65,12 +66,6 @@ func NewCreateMachinepoolUserOptions() *CreateMachinepoolUserOptions {
6566
return &CreateMachinepoolUserOptions{}
6667
}
6768

68-
func NewCreateMachinepoolOptions() *CreateMachinepoolOptions {
69-
return &CreateMachinepoolOptions{
70-
args: &CreateMachinepoolUserOptions{},
71-
}
72-
}
73-
7469
func (m *CreateMachinepoolOptions) Machinepool() *CreateMachinepoolUserOptions {
7570
return m.args
7671
}
@@ -279,6 +274,13 @@ func BuildMachinePoolCreateCommandWithOptions() (*cobra.Command, *CreateMachinep
279274
"",
280275
"The ID of an AWS On-Demand Capacity Reservation. The 'capacity-reservation-id' must be pre-created "+
281276
"in advance, before creating a NodePool.")
277+
278+
flags.StringVar(&options.Type,
279+
"type",
280+
"",
281+
"Specifies the type of AMI this machinepool uses. You may supply '--type Windows' for example if you want "+
282+
"support for Windows VMs.")
283+
282284
output.AddFlag(cmd)
283285
interactive.AddFlag(flags)
284286
return cmd, options

0 commit comments

Comments
 (0)