Skip to content

Commit

Permalink
OCM-5677 | feat: Added rosa describe autoscaler command
Browse files Browse the repository at this point in the history
  • Loading branch information
robpblake committed Mar 21, 2024
1 parent b049fc4 commit 4c54777
Show file tree
Hide file tree
Showing 37 changed files with 997 additions and 120 deletions.
1 change: 0 additions & 1 deletion cmd/create/autoscaler/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ func run(cmd *cobra.Command, _ []string) {
defer r.Cleanup()

clusterKey := r.GetClusterKey()

cluster := r.FetchCluster()

if cluster.Hypershift().Enabled() {
Expand Down
66 changes: 66 additions & 0 deletions cmd/describe/autoscaler/cmd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package autoscaler

import (
"context"
"fmt"

"github.com/spf13/cobra"

"github.com/openshift/rosa/pkg/clusterautoscaler"
"github.com/openshift/rosa/pkg/ocm"
"github.com/openshift/rosa/pkg/output"
"github.com/openshift/rosa/pkg/rosa"
)

const (
use = "autoscaler"
short = "Show details of the autoscaler for a cluster"
long = short
example = ` # Describe the autoscaler for cluster 'foo'
rosa describe autoscaler --cluster foo`
)

func NewDescribeAutoscalerCommand() *cobra.Command {
cmd := &cobra.Command{
Use: use,
Short: short,
Long: long,
Example: example,
Args: cobra.NoArgs,
Run: rosa.DefaultRunner(rosa.RuntimeWithOCM(), DescribeAutoscalerRunner()),
}

output.AddFlag(cmd)
ocm.AddClusterFlag(cmd)
return cmd
}

func DescribeAutoscalerRunner() rosa.CommandRunner {
return func(_ context.Context, runtime *rosa.Runtime, _ *cobra.Command, _ []string) error {
cluster, err := runtime.OCMClient.GetCluster(runtime.GetClusterKey(), runtime.Creator)
if err != nil {
return err
}

err = clusterautoscaler.IsAutoscalerSupported(runtime, cluster)
if err != nil {
return err
}

autoscaler, err := runtime.OCMClient.GetClusterAutoscaler(cluster.ID())
if err != nil {
return err
}

if autoscaler == nil {
return fmt.Errorf("No autoscaler exists for cluster '%s'", runtime.ClusterKey)
}

if output.HasFlag() {
output.Print(autoscaler)
} else {
fmt.Print(clusterautoscaler.PrintAutoscaler(autoscaler))
}
return nil
}
}
198 changes: 198 additions & 0 deletions cmd/describe/autoscaler/cmd_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
package autoscaler

import (
"context"
"fmt"
"net/http"
"testing"

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
cmv1 "github.com/openshift-online/ocm-sdk-go/clustersmgmt/v1"
. "github.com/openshift-online/ocm-sdk-go/testing"

"github.com/openshift/rosa/pkg/clusterautoscaler"
"github.com/openshift/rosa/pkg/output"
. "github.com/openshift/rosa/pkg/test"
)

func TestDescribeAutoscaler(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "rosa describe autoscaler")
}

var _ = Describe("rosa describe autoscaler", func() {
Context("Create Command", func() {
It("Returns Command", func() {

cmd := NewDescribeAutoscalerCommand()
Expect(cmd).NotTo(BeNil())

Expect(cmd.Use).To(Equal(use))
Expect(cmd.Example).To(Equal(example))
Expect(cmd.Short).To(Equal(short))
Expect(cmd.Long).To(Equal(long))
Expect(cmd.Args).NotTo(BeNil())
Expect(cmd.Run).NotTo(BeNil())

flag := cmd.Flags().Lookup("cluster")
Expect(flag).NotTo(BeNil())

flag = cmd.Flags().Lookup("output")
Expect(flag).NotTo(BeNil())
})
})

Context("Execute command", func() {

var t *TestingRuntime

BeforeEach(func() {
t = NewTestRuntime()
output.SetOutput("")
})

AfterEach(func() {
output.SetOutput("")
})

It("Returns an error if the cluster does not exist", func() {

t.ApiServer.AppendHandlers(RespondWithJSON(http.StatusOK, FormatClusterList(make([]*cmv1.Cluster, 0))))
t.SetCluster("cluster", nil)

runner := DescribeAutoscalerRunner()
err := runner(context.Background(), t.RosaRuntime, nil, nil)
Expect(err).To(HaveOccurred())
Expect(err.Error()).To(
Equal("There is no cluster with identifier or name 'cluster'"))
})

It("Returns an error if the cluster is HCP", func() {
cluster := MockCluster(func(c *cmv1.ClusterBuilder) {
h := &cmv1.HypershiftBuilder{}
h.Enabled(true)
c.Hypershift(h)
})

t.SetCluster(cluster.Name(), cluster)
t.ApiServer.AppendHandlers(RespondWithJSON(http.StatusOK, FormatClusterList([]*cmv1.Cluster{cluster})))

runner := DescribeAutoscalerRunner()
err := runner(context.Background(), t.RosaRuntime, nil, nil)

Expect(err).NotTo(BeNil())
Expect(err.Error()).To(ContainSubstring(clusterautoscaler.NoHCPAutoscalerSupportMessage))
})

It("Returns an error if the cluster is not ready", func() {
cluster := MockCluster(func(c *cmv1.ClusterBuilder) {
c.State(cmv1.ClusterStateInstalling)
})

t.SetCluster(cluster.Name(), cluster)
t.ApiServer.AppendHandlers(RespondWithJSON(http.StatusOK, FormatClusterList([]*cmv1.Cluster{cluster})))

runner := DescribeAutoscalerRunner()
err := runner(context.Background(), t.RosaRuntime, nil, nil)

Expect(err).NotTo(BeNil())
Expect(err.Error()).To(ContainSubstring(" is not yet ready"))
})

It("Returns an error if OCM API fails to return autoscaler", func() {
cluster := MockCluster(func(c *cmv1.ClusterBuilder) {
c.State(cmv1.ClusterStateReady)
})

t.SetCluster(cluster.Name(), cluster)
t.ApiServer.AppendHandlers(RespondWithJSON(http.StatusOK, FormatClusterList([]*cmv1.Cluster{cluster})))
t.ApiServer.RouteToHandler(
"GET",
fmt.Sprintf("/api/clusters_mgmt/v1/clusters/%s/autoscaler", cluster.ID()),
RespondWithJSON(http.StatusInternalServerError, "{}"))

runner := DescribeAutoscalerRunner()
err := runner(context.Background(), t.RosaRuntime, nil, nil)

Expect(err).NotTo(BeNil())
Expect(err.Error()).To(ContainSubstring("status is 500"))

})

It("Returns an error if no autoscaler exists", func() {
cluster := MockCluster(func(c *cmv1.ClusterBuilder) {
c.State(cmv1.ClusterStateReady)
})

t.SetCluster(cluster.Name(), cluster)
t.ApiServer.AppendHandlers(RespondWithJSON(http.StatusOK, FormatClusterList([]*cmv1.Cluster{cluster})))
t.ApiServer.AppendHandlers(RespondWithJSON(http.StatusNotFound, "{}"))

runner := DescribeAutoscalerRunner()
err := runner(context.Background(), t.RosaRuntime, nil, nil)

Expect(err).NotTo(BeNil())
Expect(err.Error()).To(ContainSubstring("No autoscaler exists for cluster 'cluster'"))

})

It("Prints the autoscaler to stdout", func() {
cluster := MockCluster(func(c *cmv1.ClusterBuilder) {
c.State(cmv1.ClusterStateReady)
})

t.SetCluster(cluster.Name(), cluster)
t.ApiServer.AppendHandlers(RespondWithJSON(http.StatusOK, FormatClusterList([]*cmv1.Cluster{cluster})))

autoscaler := MockAutoscaler(nil)
t.ApiServer.AppendHandlers(RespondWithJSON(http.StatusOK, FormatResource(autoscaler)))

runner := DescribeAutoscalerRunner()
err := runner(context.Background(), t.RosaRuntime, nil, nil)

Expect(err).NotTo(HaveOccurred())
})

It("Prints the autoscaler in JSON", func() {
output.SetOutput("json")
Expect(output.HasFlag()).To(BeTrue())

cluster := MockCluster(func(c *cmv1.ClusterBuilder) {
c.State(cmv1.ClusterStateReady)
})

t.SetCluster(cluster.Name(), cluster)
t.ApiServer.AppendHandlers(RespondWithJSON(http.StatusOK, FormatClusterList([]*cmv1.Cluster{cluster})))

autoscaler := MockAutoscaler(nil)
t.ApiServer.AppendHandlers(RespondWithJSON(http.StatusOK, FormatResource(autoscaler)))

runner := DescribeAutoscalerRunner()
err := runner(context.Background(), t.RosaRuntime, nil, nil)

Expect(err).NotTo(HaveOccurred())

})

It("Prints the autoscaler in YAML", func() {
output.SetOutput("yaml")
Expect(output.HasFlag()).To(BeTrue())

cluster := MockCluster(func(c *cmv1.ClusterBuilder) {
c.State(cmv1.ClusterStateReady)
})

t.SetCluster(cluster.Name(), cluster)
t.ApiServer.AppendHandlers(RespondWithJSON(http.StatusOK, FormatClusterList([]*cmv1.Cluster{cluster})))

autoscaler := MockAutoscaler(nil)
t.ApiServer.AppendHandlers(RespondWithJSON(http.StatusOK, FormatResource(autoscaler)))

runner := DescribeAutoscalerRunner()
err := runner(context.Background(), t.RosaRuntime, nil, nil)

Expect(err).NotTo(HaveOccurred())
})
})
})
7 changes: 3 additions & 4 deletions cmd/describe/cluster/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ import (
"github.com/spf13/cobra"

"github.com/openshift/rosa/pkg/ocm"
ocmOutput "github.com/openshift/rosa/pkg/ocm/output"
"github.com/openshift/rosa/pkg/output"
"github.com/openshift/rosa/pkg/rosa"
)
Expand Down Expand Up @@ -185,7 +184,7 @@ func run(cmd *cobra.Command, argv []string) {
subnetsStr := ""
if len(cluster.AWS().SubnetIDs()) > 0 {
subnetsStr = fmt.Sprintf(" - Subnets: %s\n",
ocmOutput.PrintStringSlice(cluster.AWS().SubnetIDs()))
output.PrintStringSlice(cluster.AWS().SubnetIDs()))
}

var machinePools []*cmv1.MachinePool
Expand Down Expand Up @@ -646,13 +645,13 @@ Nodes:
if hasSgsControlPlane {
nodeConfig += fmt.Sprintf(
" - Control Plane: %s\n",
ocmOutput.PrintStringSlice(
output.PrintStringSlice(
cluster.AWS().AdditionalControlPlaneSecurityGroupIds()))
}
if hasSgsInfra {
nodeConfig += fmt.Sprintf(
" - Infra: %s\n",
ocmOutput.PrintStringSlice(
output.PrintStringSlice(
cluster.AWS().AdditionalInfraSecurityGroupIds()))
}
}
Expand Down
2 changes: 2 additions & 0 deletions cmd/describe/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (

"github.com/openshift/rosa/cmd/describe/addon"
"github.com/openshift/rosa/cmd/describe/admin"
"github.com/openshift/rosa/cmd/describe/autoscaler"
"github.com/openshift/rosa/cmd/describe/cluster"
"github.com/openshift/rosa/cmd/describe/externalauthprovider"
"github.com/openshift/rosa/cmd/describe/installation"
Expand Down Expand Up @@ -49,6 +50,7 @@ func init() {
Cmd.AddCommand(tuningconfigs.Cmd)
Cmd.AddCommand(machinepool.Cmd)
Cmd.AddCommand(kubeletconfig.Cmd)
Cmd.AddCommand(autoscaler.NewDescribeAutoscalerCommand())
Cmd.AddCommand(externalauthprovider.Cmd)

flags := Cmd.PersistentFlags()
Expand Down
4 changes: 1 addition & 3 deletions cmd/describe/externalauthprovider/cmd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,13 @@ var _ = Describe("External authentication provider", func() {

Context("Describe external authentication provider command", func() {

mockClusterReady, err := test.MockOCMCluster(func(c *cmv1.ClusterBuilder) {
mockClusterReady := test.MockCluster(func(c *cmv1.ClusterBuilder) {
c.AWS(cmv1.NewAWS().SubnetIDs("subnet-0b761d44d3d9a4663", "subnet-0f87f640e56934cbc"))
c.Region(cmv1.NewCloudRegion().ID("us-east-1"))
c.State(cmv1.ClusterStateReady)
c.Hypershift(cmv1.NewHypershift().Enabled(true))
c.ExternalAuthConfig(cmv1.NewExternalAuthConfig().Enabled(true))
})
Expect(err).To(BeNil())
hypershiftClusterReady := test.FormatClusterList([]*cmv1.Cluster{mockClusterReady})

externalAuths := make([]*cmv1.ExternalAuth, 0)
Expand Down Expand Up @@ -73,7 +72,6 @@ var _ = Describe("External authentication provider", func() {
args.name = externalAuthName
testRuntime.ApiServer.AppendHandlers(RespondWithJSON(http.StatusOK, hypershiftClusterReady))
testRuntime.ApiServer.AppendHandlers(RespondWithJSON(http.StatusOK, test.FormatExternalAuthList(externalAuths)))
Expect(err).To(BeNil())
output := describeExternalAuthProviders(testRuntime.RosaRuntime,
mockClusterReady, test.MockClusterID, test.BuildExternalAuth())
Expect(output).To(Equal(describeStringOutput))
Expand Down
7 changes: 3 additions & 4 deletions cmd/describe/machinepool/cmd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,22 +108,21 @@ var _ = Describe("Upgrade machine pool", func() {
format.TruncatedDiff = false
var testRuntime test.TestingRuntime

mockClusterReady, err := test.MockOCMCluster(func(c *cmv1.ClusterBuilder) {
mockClusterReady := test.MockCluster(func(c *cmv1.ClusterBuilder) {
c.AWS(cmv1.NewAWS().SubnetIDs("subnet-0b761d44d3d9a4663", "subnet-0f87f640e56934cbc"))
c.Region(cmv1.NewCloudRegion().ID("us-east-1"))
c.State(cmv1.ClusterStateReady)
c.Hypershift(cmv1.NewHypershift().Enabled(true))
})
Expect(err).To(BeNil())

hypershiftClusterReady := test.FormatClusterList([]*cmv1.Cluster{mockClusterReady})

mockClassicClusterReady, err := test.MockOCMCluster(func(c *cmv1.ClusterBuilder) {
mockClassicClusterReady := test.MockCluster(func(c *cmv1.ClusterBuilder) {
c.AWS(cmv1.NewAWS().SubnetIDs("subnet-0b761d44d3d9a4663", "subnet-0f87f640e56934cbc"))
c.Region(cmv1.NewCloudRegion().ID("us-east-1"))
c.State(cmv1.ClusterStateReady)
c.Hypershift(cmv1.NewHypershift().Enabled(false))
})
Expect(err).To(BeNil())
classicClusterReady := test.FormatClusterList([]*cmv1.Cluster{mockClassicClusterReady})

nodePoolResponse := formatNodePool()
Expand Down
6 changes: 3 additions & 3 deletions cmd/describe/machinepool/machinepool.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,11 @@ func describeMachinePool(r *rosa.Runtime, cluster *cmv1.Cluster, clusterKey stri
machinePool.InstanceType(),
ocmOutput.PrintLabels(machinePool.Labels()),
ocmOutput.PrintTaints(machinePool.Taints()),
ocmOutput.PrintStringSlice(machinePool.AvailabilityZones()),
ocmOutput.PrintStringSlice(machinePool.Subnets()),
output.PrintStringSlice(machinePool.AvailabilityZones()),
output.PrintStringSlice(machinePool.Subnets()),
ocmOutput.PrintMachinePoolSpot(machinePool),
ocmOutput.PrintMachinePoolDiskSize(machinePool),
ocmOutput.PrintStringSlice(machinePool.AWS().AdditionalSecurityGroupIds()),
output.PrintStringSlice(machinePool.AWS().AdditionalSecurityGroupIds()),
)
fmt.Print(machinePoolOutput)

Expand Down
Loading

0 comments on commit 4c54777

Please sign in to comment.