// deleteRunningServer terminates the server and waits until it is removed. func deleteRunningServer(scaleway *api.ScalewayAPI, server *api.ScalewayServer) error { err := scaleway.PostServerAction(server.Identifier, "terminate") if err != nil { if serr, ok := err.(api.ScalewayAPIError); ok { if serr.StatusCode == 404 { return nil } } return err } return resource.Retry(20*time.Minute, func() *resource.RetryError { _, err := scaleway.GetServer(server.Identifier) if err == nil { return resource.RetryableError(fmt.Errorf("Waiting for server %q to be deleted", server.Identifier)) } if serr, ok := err.(api.ScalewayAPIError); ok { if serr.StatusCode == 404 { return nil } } return resource.RetryableError(err) }) }
func waitForServerState(scaleway *api.ScalewayAPI, serverID, targetState string) error { pending := []string{} for _, state := range allStates { if state != targetState { pending = append(pending, state) } } stateConf := &resource.StateChangeConf{ Pending: pending, Target: []string{targetState}, Refresh: func() (interface{}, string, error) { s, err := scaleway.GetServer(serverID) if err == nil { return 42, s.State, nil } if serr, ok := err.(api.ScalewayAPIError); ok { if serr.StatusCode == 404 { return 42, "stopped", nil } } return 42, s.State, err }, Timeout: 60 * time.Minute, MinTimeout: 5 * time.Second, Delay: 5 * time.Second, } _, err := stateConf.WaitForState() return err }
// DetachIP detaches an IP from a server func DetachIP(s *api.ScalewayAPI, ipID string) error { var update struct { Address string `json:"address"` ID string `json:"id"` Organization string `json:"organization"` } ip, err := s.GetIP(ipID) if err != nil { return err } update.Address = ip.IP.Address update.ID = ip.IP.ID update.Organization = ip.IP.Organization resp, err := s.PutResponse(api.ComputeAPI, fmt.Sprintf("ips/%s", ipID), update) if err != nil { return err } if resp.StatusCode != http.StatusOK { return err } resp.Body.Close() return nil }
// deleteStoppedServer needs to cleanup attached root volumes. this is not done // automatically by Scaleway func deleteStoppedServer(scaleway *api.ScalewayAPI, server *api.ScalewayServer) error { if err := scaleway.DeleteServer(server.Identifier); err != nil { return err } if rootVolume, ok := server.Volumes["0"]; ok { if err := scaleway.DeleteVolume(rootVolume.Identifier); err != nil { return err } } return nil }
func UpdateScwApiBootscripts(Api *api.ScalewayAPI, cache *Cache) { for { logrus.Infof("Fetching bootscripts from the Api...") bootscripts, err := Api.GetBootscripts() if err != nil { logrus.Errorf("Failed to retrieve bootscripts list from the Api: %v", err) } else { cache.Api.Bootscripts = bootscripts logrus.Infof("Bootscripts fetched: %d bootscripts", len(*bootscripts)) } time.Sleep(5 * time.Minute) } }
func UpdateScwApiImages(Api *api.ScalewayAPI, cache *Cache) { for { logrus.Infof("Fetching images from the Api...") images, err := Api.GetImages() if err != nil { logrus.Errorf("Failed to retrieve images list from the Api: %v", err) } else { cache.Api.Images = images logrus.Infof("Images fetched: %d images", len(*images)) cache.MapImages() } time.Sleep(5 * time.Minute) } }
func deleteServerSafe(s *api.ScalewayAPI, serverID string) error { server, err := s.GetServer(serverID) if err != nil { return err } if server.State != "stopped" { if err := s.PostServerAction(serverID, "poweroff"); err != nil { return err } if err := waitForServerState(s, serverID, "stopped"); err != nil { return err } } if err := s.DeleteServer(serverID); err != nil { return err } if rootVolume, ok := server.Volumes["0"]; ok { if err := s.DeleteVolume(rootVolume.Identifier); err != nil { return err } } return nil }
// deleteRunningServer terminates the server and waits until it is removed. func deleteRunningServer(scaleway *api.ScalewayAPI, server *api.ScalewayServer) error { err := scaleway.PostServerAction(server.Identifier, "terminate") if err != nil { if serr, ok := err.(api.ScalewayAPIError); ok { if serr.StatusCode == 404 { return nil } } return err } return waitForServerState(scaleway, server.Identifier, "stopped") }
func waitForServerState(scaleway *api.ScalewayAPI, serverID, targetState string) error { return resource.Retry(20*time.Minute, func() *resource.RetryError { s, err := scaleway.GetServer(serverID) if err != nil { return resource.NonRetryableError(err) } if s.State != targetState { return resource.RetryableError(fmt.Errorf("Waiting for server to enter %q state", targetState)) } return nil }) }
func waitForServerState(s *api.ScalewayAPI, serverID string, targetState string) error { var server *api.ScalewayServer var err error var currentState string for { server, err = s.GetServer(serverID) if err != nil { return err } if currentState != server.State { log.Printf("[DEBUG] Server changed state to %q\n", server.State) currentState = server.State } if server.State == targetState { break } time.Sleep(1 * time.Second) } return nil }
// uploadSSHKeys uploads an SSH Key func uploadSSHKeys(apiConnection *api.ScalewayAPI, newKey string) { user, err := apiConnection.GetUser() if err != nil { logrus.Errorf("Unable to contact ScalewayAPI: %s", err) } else { user.SSHPublicKeys = append(user.SSHPublicKeys, api.ScalewayKeyDefinition{Key: strings.Trim(newKey, "\n")}) SSHKeys := api.ScalewayUserPatchSSHKeyDefinition{ SSHPublicKeys: user.SSHPublicKeys, } userID, err := apiConnection.GetUserID() if err != nil { logrus.Errorf("Unable to get userID: %s", err) } else { if err = apiConnection.PatchUserSSHKey(userID, SSHKeys); err != nil { logrus.Errorf("Unable to patch SSHkey: %v", err) } } } }
func runUserdata(cmd *Command, args []string) error { if userdataHelp { return cmd.PrintUsage() } if len(args) < 1 { return cmd.PrintShortUsage() } ctx := cmd.GetContext(args) var Api *api.ScalewayAPI var err error var serverID string if args[0] == "local" { Api, err = api.NewScalewayAPI("", "", "", "") if err != nil { return err } Api.EnableMetadataAPI() } else { if ctx.API == nil { return fmt.Errorf("You need to login first: 'scw login'") } serverID = ctx.API.GetServerID(args[0]) Api = ctx.API } switch len(args) { case 1: // List userdata res, err := Api.GetUserdatas(serverID) if err != nil { return err } for _, key := range res.UserData { fmt.Fprintln(ctx.Stdout, key) } default: parts := strings.Split(args[1], "=") key := parts[0] switch len(parts) { case 1: // Get userdatas res, err := Api.GetUserdata(serverID, key) if err != nil { return err } fmt.Fprintf(ctx.Stdout, "%s\n", res.String()) default: value := parts[1] if value != "" { // Set userdata err := Api.PatchUserdata(serverID, key, []byte(value)) if err != nil { return err } fmt.Fprintln(ctx.Stdout, key) } else { // Delete userdata err := Api.DeleteUserdata(serverID, key) if err != nil { return err } } } } return nil }
func runUserdata(cmd *Command, args []string) error { if userdataHelp { return cmd.PrintUsage() } if len(args) < 1 { return cmd.PrintShortUsage() } metadata := false ctx := cmd.GetContext(args) var API *api.ScalewayAPI var err error var serverID string if args[0] == "local" { API, err = api.NewScalewayAPI("", "", scwversion.UserAgent(), *flRegion) if err != nil { return err } metadata = true } else { if ctx.API == nil { return fmt.Errorf("You need to login first: 'scw login'") } serverID, err = ctx.API.GetServerID(args[0]) if err != nil { return err } API = ctx.API } switch len(args) { case 1: // List userdata res, errGetUserdata := API.GetUserdatas(serverID, metadata) if errGetUserdata != nil { return errGetUserdata } for _, key := range res.UserData { fmt.Fprintln(ctx.Stdout, key) } default: parts := strings.Split(args[1], "=") key := parts[0] switch len(parts) { case 1: // Get userdatas res, errGetUserdata := API.GetUserdata(serverID, key, metadata) if errGetUserdata != nil { return errGetUserdata } fmt.Fprintf(ctx.Stdout, "%s\n", res.String()) default: value := args[1][len(parts[0])+1:] if value != "" { var data []byte // Set userdata if value[0] == '@' { if len(value) > 1 && value[1] == '~' { home, err := config.GetHomeDir() if err != nil { return err } value = "@" + home + value[2:] } data, err = ioutil.ReadFile(value[1:]) if err != nil { return err } } else { data = []byte(value) } err := API.PatchUserdata(serverID, key, data, metadata) if err != nil { return err } fmt.Fprintln(ctx.Stdout, key) } else { // Delete userdata err := API.DeleteUserdata(serverID, key, metadata) if err != nil { return err } } } } return nil }
func SetupLogger(s *api.ScalewayAPI) { s.Logger = NewCliLogger(s) }