Skip to content

Commit

Permalink
Scale components (#105)
Browse files Browse the repository at this point in the history
* Manually Scale components, add reset command

* deprecate start component command

* cleanup, use deprecated and example fields

* better description of reset command
  • Loading branch information
Richard87 authored Sep 12, 2024
1 parent 2160624 commit c0ab9f4
Show file tree
Hide file tree
Showing 17 changed files with 1,725 additions and 195 deletions.
74 changes: 14 additions & 60 deletions cmd/scale.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,75 +15,29 @@
package cmd

import (
"errors"
"strconv"

"github.com/equinor/radix-cli/generated-client/client/component"
"github.com/equinor/radix-cli/pkg/client"
"github.com/equinor/radix-cli/pkg/flagnames"
"github.com/spf13/cobra"
)

// scaleCmd represents the scale command
// startCmd represents the start command
var scaleCmd = &cobra.Command{
Use: "scale",
Short: "Scale component replicas",
Long: `Used for scaling up or down replicas of a Radix application component.
Examples:
# Scale up component to 2 replicas
rx scale --application radix-test --environment dev --component component-abc --replicas 2
# Short version of scaling up component to 0 replicas
rx scale -a radix-test -e dev -n component-abc -r 2
`,
Use: "scale",
Short: "Scale component replicas",
Long: `Scale component replicas.`,
Deprecated: "Please use 'rx scale component' instead. Will be removed after September 2025",
RunE: func(cmd *cobra.Command, args []string) error {
appName, err := getAppNameFromConfigOrFromParameter(cmd, flagnames.Application)
if err != nil {
return err
}
envName, err := cmd.Flags().GetString(flagnames.Environment)
if err != nil {
return err
}
cmpName, err := cmd.Flags().GetString(flagnames.Component)
if err != nil {
return err
}
replicas, err := cmd.Flags().GetInt(flagnames.Replicas)
if err != nil {
return err
}
if appName == nil || *appName == "" || envName == "" || cmpName == "" {
return errors.New("application name, environment name and component name are required fields")
}
if replicas < 0 || replicas > 20 {
return errors.New("required field replicas must be between 0 and 20")
}

cmd.SilenceUsage = true

parameters := component.NewScaleComponentParams().
WithAppName(*appName).
WithEnvName(envName).
WithComponentName(cmpName).
WithReplicas(strconv.Itoa(replicas))

apiClient, err := client.GetForCommand(cmd)
if err != nil {
return err
}
_, err = apiClient.Component.ScaleComponent(parameters, nil)
return err
return scaleComponentCmd.RunE(cmd, args)
},
}

func init() {
rootCmd.AddCommand(scaleCmd)
scaleCmd.Flags().StringP(flagnames.Application, "a", "", "Name of the application namespace")
scaleCmd.Flags().StringP(flagnames.Environment, "e", "", "Name of the environment of the application")
scaleCmd.Flags().StringP(flagnames.Component, "n", "", "Name of the component to scale")
scaleCmd.Flags().IntP(flagnames.Replicas, "r", 1, "The new desired number of replicas")
setContextSpecificPersistentFlags(scaleCmd)
scaleCmd.PersistentFlags().StringP(flagnames.Application, "a", "", "Name of the application namespace")
scaleCmd.PersistentFlags().StringP(flagnames.Environment, "e", "", "Name of the environment of the application")
scaleCmd.PersistentFlags().StringP(flagnames.Component, "n", "", "Name of the component to scale")
scaleCmd.PersistentFlags().IntP(flagnames.Replicas, "r", 1, "The new desired number of replicas")
scaleCmd.PersistentFlags().Bool(flagnames.Reset, false, "Reset manualy scaled component to use replica count from RadixConfig or managed by horizontal autoscaling")
scaleCmd.MarkFlagsOneRequired(flagnames.Replicas, flagnames.Reset)
scaleCmd.MarkFlagsMutuallyExclusive(flagnames.Replicas, flagnames.Reset)
setContextSpecificPersistentFlags(scaleComponentCmd)
}
119 changes: 119 additions & 0 deletions cmd/scaleComponent.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
// Copyright © 2023
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package cmd

import (
"errors"
"strconv"

apiclient "github.com/equinor/radix-cli/generated-client/client"
"github.com/equinor/radix-cli/generated-client/client/component"
"github.com/equinor/radix-cli/pkg/client"
"github.com/equinor/radix-cli/pkg/flagnames"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)

// scaleCmd represents the scale command
var scaleComponentCmd = &cobra.Command{
Use: "component",
Short: "Scale component replicas",
Long: `Used for manually scaling up or down replicas of a Radix application component.
Note: Manual scaling will persist across deployments, and will disable autoscaling.
`,
Example: `
# Scale up component to 2 replicas
rx scale component --application radix-test --environment dev --component component-abc --replicas 2
# Short version of scaling up component to 0 replicas
rx scale component -a radix-test -e dev -n component-abc -r 2
# Reset manual scaling to resume normal operations:
rx scale component --application radix-test --environment dev --component component-abc --reset
`,
RunE: func(cmd *cobra.Command, args []string) error {
appName, err := getAppNameFromConfigOrFromParameter(cmd, flagnames.Application)
if err != nil {
return err
}
envName, err := cmd.Flags().GetString(flagnames.Environment)
if err != nil {
return err
}
cmpName, err := cmd.Flags().GetString(flagnames.Component)
if err != nil {
return err
}
replicas, err := cmd.Flags().GetInt(flagnames.Replicas)
if err != nil {
return err
}
reset, err := cmd.Flags().GetBool(flagnames.Reset)
if err != nil {
return err
}
if appName == nil || *appName == "" || envName == "" || cmpName == "" {
return errors.New("application name, environment name and component name are required fields")
}
if !reset && (replicas < 0 || replicas > 20) {
return errors.New("required field replicas must be between 0 and 20")
}

apiClient, err := client.GetForCommand(cmd)
if err != nil {
return err
}

cmd.SilenceUsage = true

if reset {
return resetScaledComponent(apiClient, *appName, envName, cmpName)
}
return scaleComponent(apiClient, *appName, envName, cmpName, strconv.Itoa(replicas))
},
}

func scaleComponent(apiClient *apiclient.Radixapi, appName, envName, cmpName, replicas string) error {
parameters := component.NewScaleComponentParams().
WithAppName(appName).
WithEnvName(envName).
WithComponentName(cmpName).
WithReplicas(replicas)

if _, err := apiClient.Component.ScaleComponent(parameters, nil); err != nil {
return err
}

logrus.Infof("%s Successfully scaled to %s replicas", cmpName, replicas)
return nil
}

func resetScaledComponent(apiClient *apiclient.Radixapi, appName, envName, cmpName string) error {
parameters := component.NewResetScaledComponentParams().
WithAppName(appName).
WithEnvName(envName).
WithComponentName(cmpName)

if _, err := apiClient.Component.ResetScaledComponent(parameters, nil); err != nil {
return err
}

logrus.Infof("%s Successfully reset to normal scaling", cmpName)
return nil
}

func init() {
scaleCmd.AddCommand(scaleComponentCmd)
}
15 changes: 12 additions & 3 deletions cmd/startComponent.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"github.com/equinor/radix-cli/generated-client/client/component"
"github.com/equinor/radix-cli/pkg/client"
"github.com/equinor/radix-cli/pkg/flagnames"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)

Expand All @@ -28,8 +29,11 @@ var startComponentCmd = &cobra.Command{
Use: "component",
Short: "Start a component",
Long: `Start a component
- Pulls new image from image hub in radix configuration
- Starts the container using up to date image`,
Deprecated: Use 'rx scale component --reset' instead
Resets a manully scaled component to resume normal operations again.`,
Deprecated: " Use 'rx scale component --reset' instead. Will be removed after September 2025",
RunE: func(cmd *cobra.Command, args []string) error {
appName, err := getAppNameFromConfigOrFromParameter(cmd, flagnames.Application)
if err != nil {
Expand Down Expand Up @@ -60,7 +64,12 @@ var startComponentCmd = &cobra.Command{
}

_, err = apiClient.Component.StartComponent(parameters, nil)
return err
if err != nil {
return err
}

logrus.Infof("%s Successfully reset to normal scaling", cmpName)
return nil
},
}

Expand Down
43 changes: 42 additions & 1 deletion generated-client/client/application/application_client.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit c0ab9f4

Please sign in to comment.