From cdd441cf1c13a723ceffc2ca5fb3ac19c8991f39 Mon Sep 17 00:00:00 2001 From: Manfred Touron Date: Mon, 7 Sep 2015 00:27:57 +0200 Subject: [PATCH] Added 'scw _userdata local' option (fix #166) --- README.md | 1 + pkg/api/api.go | 57 +++++++++++++++++++++++++++++++++++++------ pkg/cli/main.go | 10 +++++++- pkg/cli/x_userdata.go | 27 ++++++++++++++++---- 4 files changed, 81 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 971d0dbe49..23155c2ead 100644 --- a/README.md +++ b/README.md @@ -1133,6 +1133,7 @@ $ scw inspect myserver | jq '.[0].public_ip.address' * `scw info` now prints user/organization info from the API ([#142](https://github.com/scaleway/scaleway-cli/issues/130) * Added helpers to manipulate new `user_data` API ([#150](https://github.com/scaleway/scaleway-cli/issues/150)) * Support of `scw rm -f/--force` option ([#158](https://github.com/scaleway/scaleway-cli/issues/158)) +* Added `scw _userdata local ...` option which interacts with the Metadata API without authentication ([#166](https://github.com/scaleway/scaleway-cli/issues/166)) #### Fixes diff --git a/pkg/api/api.go b/pkg/api/api.go index b2eea2f9ec..a70569777e 100644 --- a/pkg/api/api.go +++ b/pkg/api/api.go @@ -28,8 +28,9 @@ import ( // Default values var ( - ComputeAPI string = "https://api.scaleway.com/" - AccountAPI string = "https://account.scaleway.com/" + ComputeAPI string = "https://api.scaleway.com/" + AccountAPI string = "https://account.scaleway.com/" + MetadataAPI string = "http://169.254.42.42/" ) // ScalewayAPI is the interface used to communicate with the Scaleway API @@ -55,8 +56,9 @@ type ScalewayAPI struct { // Cache is used to quickly resolve identifiers from names Cache *ScalewayCache - client *http.Client - anonuuid anonuuid.AnonUUID + client *http.Client + anonuuid anonuuid.AnonUUID + isMetadata bool } // ScalewayAPIError represents a Scaleway API Error @@ -1355,7 +1357,14 @@ type ScalewayUserdatas struct { // GetUserdatas gets list of userdata for a server func (s *ScalewayAPI) GetUserdatas(serverID string) (*ScalewayUserdatas, error) { - resp, err := s.GetResponse("servers/" + serverID + "/user_data") + var url string + if s.isMetadata { + url = "/user_data" + } else { + url = fmt.Sprintf("servers/%s/user_data", serverID) + } + + resp, err := s.GetResponse(url) if err != nil { return nil, err } @@ -1381,7 +1390,14 @@ func (s *ScalewayAPI) GetUserdata(serverID string, key string) (*ScalewayUserdat var data ScalewayUserdata var err error - resp, err := s.GetResponse("servers/" + serverID + "/user_data/" + key) + var url string + if s.isMetadata { + url = fmt.Sprintf("/user_data/%s", key) + } else { + url = fmt.Sprintf("servers/%s/user_data/%s", serverID, key) + } + + resp, err := s.GetResponse(url) if err != nil { return nil, err } @@ -1397,7 +1413,13 @@ func (s *ScalewayAPI) GetUserdata(serverID string, key string) (*ScalewayUserdat // PatchUserdata sets a user data func (s *ScalewayAPI) PatchUserdata(serverID string, key string, value []byte) error { - resource := fmt.Sprintf("servers/%s/user_data/%s", serverID, key) + var resource string + if s.isMetadata { + resource = fmt.Sprintf("/user_data/%s", key) + } else { + resource = fmt.Sprintf("servers/%s/user_data/%s", serverID, key) + } + uri := fmt.Sprintf("%s/%s", strings.TrimRight(s.APIUrl, "/"), resource) payload := new(bytes.Buffer) payload.Write(value) @@ -1432,7 +1454,14 @@ func (s *ScalewayAPI) PatchUserdata(serverID string, key string, value []byte) e // DeleteUserdata deletes a server user_data func (s *ScalewayAPI) DeleteUserdata(serverID string, key string) error { - resp, err := s.DeleteResponse(fmt.Sprintf("servers/%s/user_data/%s", serverID, key)) + var url string + if s.isMetadata { + url = fmt.Sprintf("/user_data/%s", key) + } else { + url = fmt.Sprintf("servers/%s/user_data/%s", serverID, key) + } + + resp, err := s.DeleteResponse(url) if err != nil { return err } @@ -1687,6 +1716,18 @@ func (s *ScalewayAPI) DisableAccountAPI() { s.APIUrl = s.ComputeAPI } +// EnableMetadataAPI enable metadataAPI +func (s *ScalewayAPI) EnableMetadataAPI() { + s.APIUrl = MetadataAPI + s.isMetadata = true +} + +// DisableMetadataAPI disable metadataAPI +func (s *ScalewayAPI) DisableMetadataAPI() { + s.APIUrl = s.ComputeAPI + s.isMetadata = false +} + // SetPassword register the password func (s *ScalewayAPI) SetPassword(password string) { s.password = password diff --git a/pkg/cli/main.go b/pkg/cli/main.go index da465c9c95..1b3334077f 100644 --- a/pkg/cli/main.go +++ b/pkg/cli/main.go @@ -96,7 +96,15 @@ func Start(rawArgs []string, streams *commands.Streams) (int, error) { if err != nil { return 1, fmt.Errorf("usage: scw %s", cmd.UsageLine) } - if cmd.Name() != "login" && cmd.Name() != "help" && cmd.Name() != "version" { + switch cmd.Name() { + case "login", "help", "version": + // commands that don't need API + case "_userdata": + // commands that may need API + api, _ := getScalewayAPI() + cmd.API = api + default: + // commands that do need API if cfgErr != nil { if name != "login" && config == nil { logrus.Debugf("cfgErr: %v", cfgErr) diff --git a/pkg/cli/x_userdata.go b/pkg/cli/x_userdata.go index 8abaa7dcf5..3cf168d094 100644 --- a/pkg/cli/x_userdata.go +++ b/pkg/cli/x_userdata.go @@ -7,6 +7,8 @@ package cli import ( "fmt" "strings" + + "github.com/scaleway/scaleway-cli/pkg/api" ) var cmdUserdata = &Command{ @@ -39,12 +41,27 @@ func runUserdata(cmd *Command, args []string) error { } ctx := cmd.GetContext(args) - serverID := ctx.API.GetServerID(args[0]) + 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 := ctx.API.GetUserdatas(serverID) + res, err := Api.GetUserdatas(serverID) if err != nil { return err } @@ -57,7 +74,7 @@ func runUserdata(cmd *Command, args []string) error { switch len(parts) { case 1: // Get userdatas - res, err := ctx.API.GetUserdata(serverID, key) + res, err := Api.GetUserdata(serverID, key) if err != nil { return err } @@ -66,14 +83,14 @@ func runUserdata(cmd *Command, args []string) error { value := parts[1] if value != "" { // Set userdata - err := ctx.API.PatchUserdata(serverID, key, []byte(value)) + err := Api.PatchUserdata(serverID, key, []byte(value)) if err != nil { return err } fmt.Fprintln(ctx.Stdout, key) } else { // Delete userdata - err := ctx.API.DeleteUserdata(serverID, key) + err := Api.DeleteUserdata(serverID, key) if err != nil { return err }