Skip to content

Commit

Permalink
Merge pull request #22 from arvancloud/fix-migrate-issue
Browse files Browse the repository at this point in the history
Fix migrate issue
  • Loading branch information
pjfa authored Nov 9, 2022
2 parents 7432662 + 5b8477b commit d0f77a5
Show file tree
Hide file tree
Showing 7 changed files with 133 additions and 28 deletions.
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ export GOPROXY=https://proxy.golang.org,direct

export ENV=development

LDFLAGS+=-X k8s.io/client-go/pkg/version.gitVersion=v1.0.2
LDFLAGS+=-X k8s.io/client-go/pkg/version.gitVersion=v1.2.2
LDFLAGS+=-X k8s.io/client-go/pkg/version.gitCommit=4f75300
LDFLAGS+=-X github.com/openshift/oc/pkg/version.versionFromGit=v1.0.2
LDFLAGS+=-X github.com/openshift/oc/pkg/version.versionFromGit=v1.2.2
LDFLAGS+=-X github.com/openshift/oc/pkg/version.commitFromGit=4f75300
build:
go build -v -o $(ROOT)/bin/arvan -ldflags="$(LDFLAGS)" $(ROOT)/cmd/arvan/*.go
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ require (
github.com/spf13/cobra v1.1.1
github.com/xeipuuv/gojsonschema v1.2.0 // indirect
golang.org/x/sys v0.0.0-20220808155132-1c4a2a72c664 // indirect
golang.org/x/text v0.3.4
gopkg.in/yaml.v2 v2.3.0
k8s.io/api v0.20.0-beta.2
k8s.io/apimachinery v0.20.0-beta.2
Expand Down
15 changes: 15 additions & 0 deletions pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,20 @@ import (
"io/ioutil"
"sync"

"github.com/arvancloud/cli/pkg/utl"

"gopkg.in/yaml.v2"
)

const (
regionsEndpoint = "/paas/v1/regions/"
)

type configFile struct {
ApiVersion string `yaml:"apiVersion"`
Server string `yaml:"server"`
ApiKey string `yaml:"apikey"`
Region string `yaml:"region,omitempty"`
}

var instance *ConfigInfo
Expand Down Expand Up @@ -40,8 +47,16 @@ func LoadConfigFile() (bool, error) {
if err != nil {
return false, err
}

arvanConfig.apiKey = configFileStruct.ApiKey
arvanConfig.server = configFileStruct.Server

if configFileStruct.Region != "" {
arvanConfig.server = configFileStruct.Server + regionsEndpoint + configFileStruct.Region
_, err = arvanConfig.SaveConfig()
utl.CheckErr(err)
}

return true, nil
}

Expand Down
11 changes: 7 additions & 4 deletions pkg/config/config_info.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,24 +25,26 @@ type ConfigInfo struct {

// path to arvan config directroy e.g /home/jane/.arvan
homeDir string

region string
}

//GetServer returns base url to access arvan api server
// GetServer returns base url to access arvan api server
func (c *ConfigInfo) GetServer() string {
return c.server
}

//GetApiKey returns an api key used to authorize request to arvan api server
// GetApiKey returns an api key used to authorize request to arvan api server
func (c *ConfigInfo) GetApiKey() string {
return c.apiKey
}

//GetConfigFilePath returns path to arvan config file e.g /home/jane/.arvan/config
// GetConfigFilePath returns path to arvan config file e.g /home/jane/.arvan/config
func (c *ConfigInfo) GetConfigFilePath() string {
return c.configFilePath
}

//GetHomeDir returns path to arvan config directroy e.g /home/jane/.arvan
// GetHomeDir returns path to arvan config directroy e.g /home/jane/.arvan
func (c *ConfigInfo) GetHomeDir() string {
return c.homeDir
}
Expand Down Expand Up @@ -94,6 +96,7 @@ func (c *ConfigInfo) SaveConfig() (bool, error) {
ApiVersion: configFileApiVersion,
Server: c.server,
ApiKey: c.apiKey,
Region: c.region,
}

configFileStr, err := yaml.Marshal(&configFileStruct)
Expand Down
18 changes: 9 additions & 9 deletions pkg/paas/login.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ func NewCmdSwitchRegion(in io.Reader, out, errout io.Writer) *cobra.Command {
_, err = arvanConfig.SaveConfig()
utl.CheckErr(err)

err = prepareConfig(c)
err = prepareConfigSwtichRegion(c)
utl.CheckErr(err)

fmt.Fprintf(explainOut, "Region Switched successfully.\n")
Expand Down Expand Up @@ -145,14 +145,14 @@ func getSelectedRegion(in io.Reader, writer io.Writer) (*config.Zone, error) {
return nil, errors.New("invalid region info")
}

activeZones, inactiveZones := getActiveAndInactiveZones(regions.Zones)
upZones, downZones := getUpAndDownZones(regions.Zones)

if len(activeZones) < 1 {
if len(upZones) < 1 {
return nil, errors.New("no active region available")
}

explain := "Select arvan region:\n"
explain += sprintRegions(activeZones, inactiveZones)
explain += sprintRegions(upZones, downZones)

_, err = fmt.Fprint(writer, explain)
if err != nil {
Expand All @@ -162,17 +162,17 @@ func getSelectedRegion(in io.Reader, writer io.Writer) (*config.Zone, error) {

defaultVal := "1"

if len(activeZones) == 1 {
if len(upZones) == 1 {
fmt.Fprintf(writer, inputExplain+"1\n")
return &activeZones[0], nil
return &upZones[0], nil
}

validator := regionValidator{len(activeZones)}
validator := regionValidator{len(upZones)}

regionIndex := utl.ReadInput(inputExplain, defaultVal, writer, in, validator.validate)
intIndex, _ := strconv.Atoi(regionIndex)

return &activeZones[intIndex-1], nil
return &upZones[intIndex-1], nil
}

type regionValidator struct {
Expand Down Expand Up @@ -218,7 +218,7 @@ func sprintRegions(activeZones, inactiveRegions []config.Zone) string {
return result
}

func getActiveAndInactiveZones(zones []config.Zone) ([]config.Zone, []config.Zone) {
func getUpAndDownZones(zones []config.Zone) ([]config.Zone, []config.Zone) {
var activeZones, inactiveZones []config.Zone
for i := 0; i < len(zones); i++ {
if zones[i].Status == "UP" {
Expand Down
43 changes: 30 additions & 13 deletions pkg/paas/migration.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,17 @@ import (
"github.com/olekukonko/tablewriter"
"github.com/openshift/oc/pkg/helpers/term"
"github.com/spf13/cobra"
"golang.org/x/text/cases"
"golang.org/x/text/language"
"k8s.io/client-go/rest"
)

var (
migrateLong = `
Migration of user's namespaces from one region to another
`
)

const (
migrationEndpoint = "/paas/v1/%s/migrate"
redColor = "\033[31m"
Expand Down Expand Up @@ -97,7 +105,7 @@ func NewCmdMigrate(in io.Reader, out, errout io.Writer) *cobra.Command {
cmd := &cobra.Command{
Use: "migrate",
Short: "Migrate namespaces to destination region",
Long: loginLong,
Long: migrateLong,
Run: func(c *cobra.Command, args []string) {
explainOut := term.NewResponsiveWriter(out)
c.SetOutput(explainOut)
Expand Down Expand Up @@ -180,6 +188,16 @@ func reMigrationConfirm(in io.Reader, writer io.Writer) bool {
return value == "y"
}

// newProjectConfirm makes sure that user enters yes/no correctly.
func newProjectConfirm(in io.Reader, writer io.Writer) bool {
inputExplain := "Do you want to continue?[y/N]: "

defaultVal := "N"

value := utl.ReadInput(inputExplain, defaultVal, writer, in, confirmationValidate)
return value == "y"
}

// confirmationValidate checks yes/no entry
func confirmationValidate(input string) (bool, error) {
if input != "y" && input != "N" {
Expand Down Expand Up @@ -266,13 +284,13 @@ func sprintProjects(projects []string) string {

// migrationConfirm gets confirmation of proceeding namespace migration by asking user to enter namespace's name.
func migrationConfirm(project, region string, in io.Reader, writer io.Writer) bool {
explain := fmt.Sprintf("\nYou're about to migrate \"%s\" from region \"%s\" to \"%s\".\n", project, getCurrentRegion(), region)
explain := fmt.Sprintf("\nYou're about to migrate \"%s\" from region \"%s\" to \"%s\".\n\n"+yellowColor+"WARNING:\nThis will STOP applications during migration process. Your data would still be safe and available in source region. Migration is running in the background and may take a while. You can optionally detach(Ctrl+C) for now and continue monitoring the process after using 'arvan paas migrate'."+resetColor+"\n\n", project, getCurrentRegion(), region)

_, err := fmt.Fprint(writer, explain)
if err != nil {
return false
}
inputExplain := fmt.Sprintf(yellowColor+"\nWARNING:\nThis will STOP applications during migration process. Your data would still be safe and available in source region. Migration is running in the background and may take a while. You can optionally detach(Ctrl+C) for now and continue monitoring the process after using 'arvan paas migrate'."+resetColor+"\n\nPlease enter project's name [%s] to proceed: ", project)
inputExplain := fmt.Sprintf("Please enter project's name [%s] to proceed: ", project)

defaultVal := ""

Expand Down Expand Up @@ -362,7 +380,9 @@ func sprintResponse(response ProgressResponse, w io.Writer) error {
detail = s.Data.Detail
}

responseStr += fmt.Sprintf("\t%s \t\t\t%s\t%s\n", s.Title, strings.Title(s.State), detail)
caser := cases.Title(language.English)

responseStr += fmt.Sprintf("\t%s \t\t\t%s\t%s\n", s.Title, caser.String(s.State), detail)
}

fmt.Fprintf(w, "%s", responseStr)
Expand Down Expand Up @@ -456,6 +476,7 @@ func httpGet(endpoint string) (*ProgressResponse, error) {
var response ProgressResponse
err = json.Unmarshal(responseBody, &response)
if err != nil {
failureOutput("Migration is running in the background. You can continue monitoring the process using 'arvan paas migrate'.")
return nil, err
}

Expand Down Expand Up @@ -521,9 +542,7 @@ func successOutput(data StepData) {
}

nonFreeDomainTable.Render()
}

if len(freeSourceDomains) > 0 {
gatewayTable := tablewriter.NewWriter(os.Stdout)
gatewayTable.SetHeader([]string{"old gateway", "new gateway"})

Expand All @@ -543,19 +562,17 @@ func getZoneByName(name string) (*config.Zone, error) {
return nil, errors.New("invalid region info")
}

activeZones, _ := getActiveAndInactiveZones(regions.Zones)
upZones, _ := getUpAndDownZones(regions.Zones)

if len(activeZones) < 1 {
if len(upZones) < 1 {
return nil, errors.New("no active region available")
}

for i, zone := range activeZones {
for i, zone := range upZones {
if zone.Name == name {
return &activeZones[i], nil
return &upZones[i], nil
}
}

log.Printf("destination region not found")

return nil, nil
return nil, errors.New("destination region not found")
}
69 changes: 69 additions & 0 deletions pkg/paas/paas.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,36 @@ func NewCmdPaas() *cobra.Command {
fmt.Fprint(w, strings.Repeat("*", 50))
fmt.Fprint(w, "\n")
}

// To warn user not to duplicate projects if they have a migration plan
if cmd.Name() == "new-project" {
regions, err := api.GetZones()
if err != nil {
failureOutput("failed to get zones")
utl.CheckErr(errors.New("failed to get zones"))
}

if len(regions.Zones) < 1 {
failureOutput("invalid region info")
utl.CheckErr(errors.New("invalid region info"))
}

currentRegionAbbr := getCurrentRegion()

currentRegionName := currentRegionAbbr[strings.LastIndex(currentRegionAbbr, "-")+1:]

currentRegion, err := getZoneByName(currentRegionName)
utl.CheckErr(err)

_, inactiveZones := getActiveAndInactiveZones(regions.Zones)
if len(inactiveZones) > 0 && currentRegion.Active {
fmt.Print(yellowColor + "\nWARNING: " + resetColor + "If you have any intention to migrate projects, do not try to create a new project in destination region!\n\n")

if !newProjectConfirm(in, out) {
utl.CheckErr(errors.New(""))
}
}
}
}

return paasCommand
Expand Down Expand Up @@ -105,6 +135,33 @@ func prepareConfig(cmd *cobra.Command) error {
return nil
}

func prepareConfigSwtichRegion(cmd *cobra.Command) error {
// #TODO do not use InsecureSkipVerify
http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
username, httpStatusCode, err := whoAmI()
if err != nil {
if httpStatusCode == 401 {
return fmt.Errorf("%v\n%s", err, `Try "arvan login".`)
}
if httpStatusCode >= 500 {
return fmt.Errorf("%v\n%s", err, `Please try again later`)
}
return err
}

projects, err := projectList()
if err != nil {
return err
}

kubeConfigPath := paasConfigPath()
err = syncKubeConfig(kubeConfigPath, username, projects)
if err != nil {
return err
}
return nil
}

func prepareCommand(cmd *cobra.Command) error {
arvanConfig := config.GetConfigInfo()
kubeConfigPath := paasConfigPath()
Expand Down Expand Up @@ -304,3 +361,15 @@ func getArvanServerDomainPort() (string, error) {
result := hostnameEscaped + ":" + port
return result, nil
}

func getActiveAndInactiveZones(zones []config.Zone) ([]config.Zone, []config.Zone) {
var activeZones, inactiveZones []config.Zone
for i := 0; i < len(zones); i++ {
if zones[i].Active {
activeZones = append(activeZones, zones[i])
} else {
inactiveZones = append(inactiveZones, zones[i])
}
}
return activeZones, inactiveZones
}

0 comments on commit d0f77a5

Please sign in to comment.