From 145b265ba63815403cf6990061dcd81f4fc1fdaa Mon Sep 17 00:00:00 2001 From: Prathab Date: Wed, 14 Jul 2021 12:52:02 +0530 Subject: [PATCH] Migrated maas-client to new maas-client-go repo --- go.mod | 4 +- go.sum | 12 +- pkg/maas/dns/dns.go | 2 +- pkg/maas/machine/machine.go | 4 +- pkg/maas/scope/client.go | 2 +- pkg/maasclient/bootresource.go | 134 ----------------- pkg/maasclient/bootresource_test.go | 47 ------ pkg/maasclient/client.go | 224 ---------------------------- pkg/maasclient/dns.go | 97 ------------ pkg/maasclient/dns_test.go | 105 ------------- pkg/maasclient/machine.go | 144 ------------------ pkg/maasclient/machine_test.go | 140 ----------------- pkg/maasclient/oauth1/LICENSE | 21 --- pkg/maasclient/oauth1/README.md | 57 ------- pkg/maasclient/oauth1/oauth1.go | 64 -------- 15 files changed, 14 insertions(+), 1043 deletions(-) delete mode 100644 pkg/maasclient/bootresource.go delete mode 100644 pkg/maasclient/bootresource_test.go delete mode 100644 pkg/maasclient/client.go delete mode 100644 pkg/maasclient/dns.go delete mode 100644 pkg/maasclient/dns_test.go delete mode 100644 pkg/maasclient/machine.go delete mode 100644 pkg/maasclient/machine_test.go delete mode 100644 pkg/maasclient/oauth1/LICENSE delete mode 100644 pkg/maasclient/oauth1/README.md delete mode 100644 pkg/maasclient/oauth1/oauth1.go diff --git a/go.mod b/go.mod index 6617a61..b3834e0 100644 --- a/go.mod +++ b/go.mod @@ -6,13 +6,13 @@ require ( github.com/go-logr/logr v0.3.0 github.com/pkg/errors v0.9.1 github.com/prometheus/common v0.10.0 + github.com/spectrocloud/maas-client-go v0.0.0-20210714065108-3d1cbf51760c github.com/spf13/pflag v1.0.5 - github.com/stretchr/testify v1.6.1 k8s.io/api v0.17.9 k8s.io/apimachinery v0.17.9 k8s.io/client-go v0.17.9 k8s.io/klog v1.0.0 - k8s.io/utils v0.0.0-20210111153108-fddb29f9d009 + k8s.io/utils v0.0.0-20210709001253-0e1f9d693477 sigs.k8s.io/cluster-api v0.3.14 sigs.k8s.io/controller-runtime v0.5.14 ) diff --git a/go.sum b/go.sum index 9ee27d6..1bd7ac4 100644 --- a/go.sum +++ b/go.sum @@ -207,6 +207,8 @@ github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OI github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs= +github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= github.com/googleapis/gnostic v0.3.1 h1:WeAefnSUHlBb0iJKwxFDZdbfGwkd7xRNuV+IpXMJhYk= @@ -373,6 +375,8 @@ github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1 github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spectrocloud/maas-client-go v0.0.0-20210714065108-3d1cbf51760c h1:VLN+7vmPV1u5AMoSVMNcRlp8SxIkuoKjZ2rK0tMwUnM= +github.com/spectrocloud/maas-client-go v0.0.0-20210714065108-3d1cbf51760c/go.mod h1:2uKR/gd6gsmGjRYAdGxcxZrUOHFrCTyk0PIFficZbgg= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= @@ -396,8 +400,8 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= @@ -631,8 +635,8 @@ k8s.io/kube-openapi v0.0.0-20200410145947-bcb3869e6f29 h1:NeQXVJ2XFSkRoPzRo8AId0 k8s.io/kube-openapi v0.0.0-20200410145947-bcb3869e6f29/go.mod h1:F+5wygcW0wmRTnM3cOgIqGivxkwSWIWT5YdsDbeAOaU= k8s.io/utils v0.0.0-20191114184206-e782cd3c129f/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= k8s.io/utils v0.0.0-20200619165400-6e3d28b6ed19/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -k8s.io/utils v0.0.0-20210111153108-fddb29f9d009 h1:0T5IaWHO3sJTEmCP6mUlBvMukxPKUQWqiI/YuiBNMiQ= -k8s.io/utils v0.0.0-20210111153108-fddb29f9d009/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= +k8s.io/utils v0.0.0-20210709001253-0e1f9d693477 h1:AuP1OP6ExD2U8pP9w85xHtmgBn/Ob3pngZwWMe12GBQ= +k8s.io/utils v0.0.0-20210709001253-0e1f9d693477/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= modernc.org/cc v1.0.0/go.mod h1:1Sk4//wdnYJiUIxnW8ddKpaOJCF37yAdqYnkxUpaYxw= modernc.org/golex v1.0.0/go.mod h1:b/QX9oBD/LhixY6NDh+IdGv17hgB+51fET1i2kPSmvk= modernc.org/mathutil v1.0.0/go.mod h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03k= diff --git a/pkg/maas/dns/dns.go b/pkg/maas/dns/dns.go index 17d2eb4..4b34392 100644 --- a/pkg/maas/dns/dns.go +++ b/pkg/maas/dns/dns.go @@ -5,7 +5,7 @@ import ( "github.com/pkg/errors" infrav1 "github.com/spectrocloud/cluster-api-provider-maas/api/v1alpha3" "github.com/spectrocloud/cluster-api-provider-maas/pkg/maas/scope" - "github.com/spectrocloud/cluster-api-provider-maas/pkg/maasclient" + "github.com/spectrocloud/maas-client-go/maasclient" "k8s.io/apimachinery/pkg/util/sets" ) diff --git a/pkg/maas/machine/machine.go b/pkg/maas/machine/machine.go index 86e8a43..dcd9b60 100644 --- a/pkg/maas/machine/machine.go +++ b/pkg/maas/machine/machine.go @@ -6,7 +6,7 @@ import ( "github.com/prometheus/common/log" infrav1 "github.com/spectrocloud/cluster-api-provider-maas/api/v1alpha3" "github.com/spectrocloud/cluster-api-provider-maas/pkg/maas/scope" - "github.com/spectrocloud/cluster-api-provider-maas/pkg/maasclient" + "github.com/spectrocloud/maas-client-go/maasclient" "k8s.io/utils/pointer" clusterv1 "sigs.k8s.io/cluster-api/api/v1alpha3" ) @@ -119,7 +119,7 @@ func fromSDKTypeToMachine(m *maasclient.Machine) *infrav1.Machine { Hostname: m.Hostname, State: infrav1.MachineState(m.State), Powered: m.PowerState == "on", - AvailabilityZone: m.AvailabilityZone, + AvailabilityZone: m.Zone.Name, } if m.FQDN != "" { diff --git a/pkg/maas/scope/client.go b/pkg/maas/scope/client.go index c13b59b..7dcfd1f 100644 --- a/pkg/maas/scope/client.go +++ b/pkg/maas/scope/client.go @@ -1,7 +1,7 @@ package scope import ( - "github.com/spectrocloud/cluster-api-provider-maas/pkg/maasclient" + "github.com/spectrocloud/maas-client-go/maasclient" "os" ) diff --git a/pkg/maasclient/bootresource.go b/pkg/maasclient/bootresource.go deleted file mode 100644 index 9fcf0c3..0000000 --- a/pkg/maasclient/bootresource.go +++ /dev/null @@ -1,134 +0,0 @@ -package maasclient - -import ( - "bytes" - "context" - "fmt" - "io" - "mime/multipart" - "net/http" - "net/url" - "os" - "path/filepath" -) - -type BootResource struct { - Id int `json:"id"` - Type string `json:"type"` - Name string `json:"name"` - Architecture string `json:"architecture"` - SubArches string `json:"subarches"` - ResourceURI string `json:"resource_uri"` - Title string `json:"title"` -} - -func (c *Client) ListBootResources(ctx context.Context) ([]*BootResource, error) { - q := url.Values{} - var res []*BootResource - if err := c.send(ctx, http.MethodGet, "/boot-resources/", q, &res); err != nil { - return nil, err - } - return res, nil -} - -func (c *Client) BootResourcesImporting(ctx context.Context) (*bool, error) { - q := url.Values{} - q.Add("op", "is_importing") - var res *bool - if err := c.send(ctx, http.MethodGet, "/boot-resources/", q, &res); err != nil { - return nil, err - } - return res, nil -} - -type UploadBootResourceInput struct { - Name string - Architecture string - Digest string - Size string - Title string - File string -} - -func (c *Client) UploadBootResource(ctx context.Context, input UploadBootResourceInput) (*BootResource, error) { - q := url.Values{} - - q.Add("name", input.Name) - q.Add("architecture", input.Architecture) - q.Add("sha256", input.Digest) - q.Add("size", input.Size) - q.Add("title", input.Title) - - - buf := new(bytes.Buffer) - writer := multipart.NewWriter(buf) - err := writeMultiPartFiles(writer, map[string]string{ - filepath.Base(input.File): input.File, - }) - if err != nil { - return nil, err - } - - err = writeMultiPartParams(writer, q) - if err != nil { - return nil, err - } - writer.Close() - - var res *BootResource - if err := c.sendRequestWithBody(ctx, http.MethodPost, "/boot-resources/", writer.FormDataContentType(),q, buf, &res); err != nil { - return nil, err - } - - return res, nil -} - - -func writeMultiPartFiles(writer *multipart.Writer, files map[string]string) error { - for fileName, filePath := range files { - fw, err := writer.CreateFormFile(fileName, fileName) - if err != nil { - return err - } - file, err := os.Open(filePath) - if err != nil { - return nil - } - io.Copy(fw, file) - } - return nil -} - -func writeMultiPartParams(writer *multipart.Writer, params url.Values) error { - for key, values := range params { - for _, value := range values { - fw, err := writer.CreateFormField(key) - if err != nil { - return err - } - buffer := bytes.NewBufferString(value) - io.Copy(fw, buffer) - } - } - return nil - -} - -func (c *Client) GetBootResource(ctx context.Context, id string) (*BootResource, error) { - q := url.Values{} - var res *BootResource - if err := c.send(ctx, http.MethodGet, fmt.Sprintf("/boot-resources/%s/", id), q, &res); err != nil { - return nil, err - } - return res, nil -} - -func (c *Client) DeleteBootResource(ctx context.Context, id string) error { - q := url.Values{} - var res interface{} - if err := c.send(ctx, http.MethodDelete, fmt.Sprintf("/boot-resources/%s/", id), q, &res); err != nil { - return err - } - return nil -} - diff --git a/pkg/maasclient/bootresource_test.go b/pkg/maasclient/bootresource_test.go deleted file mode 100644 index 942511f..0000000 --- a/pkg/maasclient/bootresource_test.go +++ /dev/null @@ -1,47 +0,0 @@ -package maasclient - -import ( - "context" - "github.com/stretchr/testify/assert" - "os" - "testing" -) - -func TestGetBootResources(t *testing.T) { - c := NewClient(os.Getenv("MAAS_ENDPOINT"), os.Getenv("MAAS_API_KEY")) - - ctx := context.Background() - - t.Run("list-all", func(t *testing.T) { - list, err := c.ListBootResources(ctx) - assert.Nil(t, err, "expecting nil error") - assert.NotEmpty(t, list) - }) - - t.Run("list-by-id", func(t *testing.T) { - resource, err := c.GetBootResource(ctx, "7") - assert.Nil(t, err) - assert.NotNil(t, resource) - }) - - t.Run("list-importing", func(t *testing.T) { - status, err := c.BootResourcesImporting(ctx) - assert.Nil(t, err, "expecting nil error") - assert.NotNil(t, status) - assert.False(t, *status) - }) - - - t.Run("import image", func(t *testing.T) { - status, err := c.UploadBootResource(ctx, UploadBootResourceInput{ - Name: "test-image", - Architecture: "amd64/generic", - Digest: "e9844638c7345d182c5d88e1eaeae74749d02beeca38587a530207fddc0a280a", - Size: "1262032476", - Title: "dstestimage", - File: "/Users/deepak/maas/ubuntu.tar.gz", - }) - assert.NotNil(t, err) - assert.NotNil(t, status) - }) -} diff --git a/pkg/maasclient/client.go b/pkg/maasclient/client.go deleted file mode 100644 index 2b60e01..0000000 --- a/pkg/maasclient/client.go +++ /dev/null @@ -1,224 +0,0 @@ -package maasclient - -import ( - "context" - "encoding/json" - "fmt" - "github.com/spectrocloud/cluster-api-provider-maas/pkg/maasclient/oauth1" - "io" - "io/ioutil" - "net/http" - "net/url" - "strings" - "time" -) - -// Client -type Client struct { - baseURL string - HTTPClient *http.Client - apiKey string - auth oauth1.OAuth1 -} - -// NewClient creates new MaaS client with given API key -func NewClient(maasEndpoint string, apiKey string) *Client { - - return &Client{ - apiKey: apiKey, - HTTPClient: http.DefaultClient, - //HTTPClient: config.Client(oauth1.NoContext, token), - baseURL: fmt.Sprintf("%s/api/2.0", maasEndpoint), - } -} - -// send sends the request -// Content-type and body should be already added to req -func (c *Client) send(ctx context.Context, method string, apiPath string, params url.Values, v interface{}) error { - - var err error - var req *http.Request - - if method == http.MethodGet { - req, err = http.NewRequestWithContext( - ctx, - method, - fmt.Sprintf("%s%s", c.baseURL, apiPath), - nil, - ) - if err != nil { - return err - } - - req.URL.RawQuery = params.Encode() - } else { - req, err = http.NewRequestWithContext( - ctx, - method, - fmt.Sprintf("%s%s", c.baseURL, apiPath), - strings.NewReader(params.Encode()), - ) - if err != nil { - return err - } - } - - return c.sendRequest(req, params, v) -} - -// send sends the request -// Content-type and body should be already added to req -func (c *Client) sendRequestWithBody(ctx context.Context, method string, apiPath string, contenttype string, params url.Values, body io.Reader, v interface{}) error { - - var err error - var req *http.Request - - req, err = http.NewRequestWithContext( - ctx, - method, - fmt.Sprintf("%s%s", c.baseURL, apiPath), - body, - ) - if err != nil { - return err - } - - return c.sendRequestUpload(req, params, contenttype, v) -} - -func (c *Client) sendRequest(req *http.Request, params url.Values, v interface{}) error { - //func (c *Client) sendRequest(req *http.Request, urlValues *url.Values, v interface{}) error { - req.Header.Set("Accept", "application/json; charset=utf-8") - req.Header.Set("Content-Type", "application/x-www-form-urlencoded") - - - - authHeader := authHeader(req, params, c.apiKey) - req.Header.Set("Authorization", authHeader) - - - - res, err := c.HTTPClient.Do(req) - if err != nil { - return err - } - - defer res.Body.Close() - - //debugBody(res) - - // Try to unmarshall into errorResponse - if res.StatusCode != http.StatusOK && res.StatusCode != http.StatusNoContent { - bodyBytes, err := ioutil.ReadAll(res.Body) - if err != nil { - return err - } - - return fmt.Errorf("unknown error, status code: %d, body: %s", res.StatusCode, string(bodyBytes)) - } else if res.StatusCode == http.StatusNoContent { - return nil - } - - if err = json.NewDecoder(res.Body).Decode(v); err != nil { - return err - } - - - return nil -} - -func (c *Client) sendRequestUpload(req *http.Request, params url.Values, contenttype string, v interface{}) error { - //func (c *Client) sendRequest(req *http.Request, urlValues *url.Values, v interface{}) error { - req.Header.Set("Accept", "application/json; charset=utf-8") - req.Header.Set("Content-Type", contenttype) - - - // for post requests longer than 300 seconds - ticker := time.NewTicker(2 * time.Minute) - done := make(chan bool) - go func() { - for { - select { - case <-done: - return - case t := <-ticker.C: - fmt.Println("refresing auth token", time.Unix(t.Unix(), 0).Format(time.RFC3339)) - authHeader := authHeader(req, params, c.apiKey) - req.Header.Set("Authorization", authHeader) - } - } - }() - - - defer func() { - ticker.Stop() - done <- true - }() - - - authHeader := authHeader(req, params, c.apiKey) - req.Header.Set("Authorization", authHeader) - - res, err := c.HTTPClient.Do(req) - if err != nil { - return err - } - - defer res.Body.Close() - - //debugBody(res) - - // Try to unmarshall into errorResponse - if res.StatusCode != http.StatusOK && res.StatusCode != http.StatusNoContent { - bodyBytes, err := ioutil.ReadAll(res.Body) - if err != nil { - return err - } - - return fmt.Errorf("unknown error, status code: %d, body: %s", res.StatusCode, string(bodyBytes)) - } else if res.StatusCode == http.StatusNoContent { - return nil - } - - if err = json.NewDecoder(res.Body).Decode(v); err != nil { - return err - } - - return nil -} - - -func authHeader(req *http.Request, queryParams url.Values, apiKey string) string { - key := strings.SplitN(apiKey, ":", 3) - //config := oauth1.NewConfig(key[0], "") - //token := oauth1 - - auth := oauth1.OAuth1{ - ConsumerKey: key[0], - ConsumerSecret: "", - AccessToken: key[1], - AccessSecret: key[2], - } - - //queryParams, _ := url.ParseQuery(req.URL.RawQuery) - params := make(map[string]string) - if req.Method != http.MethodPut { - // for some bizarre-reason PUT doesn't need this - for k, v := range queryParams { - params[k] = v[0] - } - } - - authHeader := auth.BuildOAuth1Header(req.Method, req.URL.String(), params) - return authHeader -} - -func debugBody(res *http.Response) { - bodyBytes, err := ioutil.ReadAll(res.Body) - if err != nil { - return - } - bodyString := string(bodyBytes) - - fmt.Println(bodyString) -} diff --git a/pkg/maasclient/dns.go b/pkg/maasclient/dns.go deleted file mode 100644 index a90d3f4..0000000 --- a/pkg/maasclient/dns.go +++ /dev/null @@ -1,97 +0,0 @@ -package maasclient - -import ( - "context" - "fmt" - "net/http" - "net/url" - "strings" -) - -// DNSResource -type DNSResource struct { - ID int `json:"id"` - FQDN string `json:"fqdn"` - AddressTTL *int `json:"address_ttl"` - IpAddresses []*IpAddress `json:"ip_addresses"` -} - -type IpAddress struct { - IpAddress string `json:"ip"` - //Interfaces []*Interface `json:"interface_set"` -} - -//type Interface struct { -// SystemID string `json:"system_id"` -//} - -type GetDNSResourcesOptions struct { - FQDN *string -} - -func (c *Client) GetDNSResources(ctx context.Context, options *GetDNSResourcesOptions) ([]*DNSResource, error) { - - q := url.Values{} - if options != nil { - addParam(q, "fqdn", options.FQDN) - } - - var res []*DNSResource - if err := c.send(ctx, http.MethodGet, "/dnsresources/", q, &res); err != nil { - return nil, err - } - - return res, nil -} - -type CreateDNSResourcesOptions struct { - FQDN string - AddressTTL string - IpAddresses []string -} - -func (c *Client) CreateDNSResources(ctx context.Context, options CreateDNSResourcesOptions) (*DNSResource, error) { - - q := url.Values{} - q.Add("fqdn", options.FQDN) - q.Add("address_ttl", options.AddressTTL) - q.Add("ip_addresses", strings.Join(options.IpAddresses, " ")) - - res := new(DNSResource) - if err := c.send(ctx, http.MethodPost, "/dnsresources/", q, res); err != nil { - return nil, err - } - - return res, nil -} - -func (c *Client) DeleteDNSResources(ctx context.Context, id int) error { - - //q := url.Values{} - //q.Add("id", strconv.Itoa(id)) - - //res := new(DNSResource) - if err := c.send(ctx, http.MethodDelete, fmt.Sprintf("/dnsresources/%v/", id), nil, nil); err != nil { - return err - } - - return nil -} - -type UpdateDNSResourcesOptions struct { - ID int - IpAddresses []string -} - -func (c *Client) UpdateDNSResources(ctx context.Context, options UpdateDNSResourcesOptions) (*DNSResource, error) { - - q := url.Values{} - q.Add("ip_addresses", strings.Join(options.IpAddresses, " ")) - - res := new(DNSResource) - if err := c.send(ctx, http.MethodPut, fmt.Sprintf("/dnsresources/%v/", options.ID), q, res); err != nil { - return nil, err - } - - return res, nil -} diff --git a/pkg/maasclient/dns_test.go b/pkg/maasclient/dns_test.go deleted file mode 100644 index e6c6b42..0000000 --- a/pkg/maasclient/dns_test.go +++ /dev/null @@ -1,105 +0,0 @@ -package maasclient - -import ( - "context" - "github.com/stretchr/testify/assert" - "k8s.io/utils/pointer" - "os" - "testing" -) - -func TestGetDNSResources(t *testing.T) { - c := NewClient(os.Getenv("MAAS_ENDPOINT"), os.Getenv("MAAS_API_KEY")) - - ctx := context.Background() - - t.Run("no-options", func(t *testing.T) { - res, err := c.GetDNSResources(ctx, nil) - assert.Nil(t, err, "expecting nil error") - assert.NotNil(t, res, "expecting non-nil result") - - assert.Greater(t, len(res), 0, "expecting non-empty dns_resources") - - assert.NotZero(t, res[0].ID) - assert.NotEmpty(t, res[0].FQDN) - }) - - t.Run("invalid-search", func(t *testing.T) { - options := &GetDNSResourcesOptions{ - FQDN: pointer.StringPtr("bad-doesntexist.maas"), - } - res, err := c.GetDNSResources(ctx, options) - assert.Nil(t, err, "expecting nil error") - assert.NotNil(t, res, "expecting non-nil result") - assert.Empty(t, res) - - }) - - t.Run("get cluster1.maas", func(t *testing.T) { - options := &GetDNSResourcesOptions{ - FQDN: pointer.StringPtr("cluster1.maas"), - } - res, err := c.GetDNSResources(ctx, options) - assert.Nil(t, err, "expecting nil error") - assert.NotEmpty(t, res) - assert.NotZero(t, res[0].AddressTTL) - assert.NotEmpty(t, res[0].IpAddresses) - assert.NotEmpty(t, res[0].IpAddresses[0].IpAddress) - - // TODO create test DNS - - }) - - t.Run("create test-unit1.maas", func(t *testing.T) { - options := CreateDNSResourcesOptions{ - FQDN: "test-unit1.maas", - AddressTTL: "10", - IpAddresses: []string{}, - } - res, err := c.CreateDNSResources(ctx, options) - assert.Nil(t, err, "expecting nil error") - assert.NotNil(t, res) - assert.Equal(t, res.FQDN, "test-unit1.maas") - assert.Equal(t, *res.AddressTTL, 10) - assert.Empty(t, res.IpAddresses) - - err = c.DeleteDNSResources(ctx, res.ID) - assert.Nil(t, err, "expecting nil error") - - }) - - t.Run("create test-unit1.maas", func(t *testing.T) { - options := CreateDNSResourcesOptions{ - FQDN: "test-unit1.maas", - AddressTTL: "10", - IpAddresses: []string{}, - } - res, err := c.CreateDNSResources(ctx, options) - assert.Nil(t, err, "expecting nil error") - assert.NotNil(t, res) - - updateOptions := UpdateDNSResourcesOptions{ - ID: res.ID, - IpAddresses: []string{"1.2.3.4", "5.6.7.8"}, - } - res, err = c.UpdateDNSResources(ctx, updateOptions) - if err != nil { - t.Fatal("error", err) - } - assert.Equal(t, res.FQDN, "test-unit1.maas") - assert.Equal(t, *res.AddressTTL, 10) - assert.NotEmpty(t, res.IpAddresses) - - err = c.DeleteDNSResources(ctx, res.ID) - assert.Nil(t, err, "expecting nil error") - - }) - - //assert.Equal(t, 1, res.Count, "expecting 1 resource") - - //assert.Equal(t, 1, res.PagesCount, "expecting 1 PAGE found") - // - //assert.Equal(t, "integration_face_id", res.Faces[0].FaceID, "expecting correct face_id") - //assert.NotEmpty(t, res.Faces[0].FaceToken, "expecting non-empty face_token") - //assert.Greater(t, len(res.Faces[0].FaceImages), 0, "expecting non-empty face_images") -} diff --git a/pkg/maasclient/machine.go b/pkg/maasclient/machine.go deleted file mode 100644 index f96fe79..0000000 --- a/pkg/maasclient/machine.go +++ /dev/null @@ -1,144 +0,0 @@ -package maasclient - -import ( - "context" - "fmt" - "net/http" - "net/url" - "reflect" - "strconv" -) - -// Machine -type Machine struct { - //ID int `json:"id"` - SystemID string `json:"system_id"` - FQDN string `json:"fqdn"` - Zone `json:"zone"` - PowerState string `json:"power_state"` - Hostname string `json:"hostname"` - IpAddresses []string `json:"ip_addresses"` - State string `json:"status_name"` - OSSystem string `json:"osystem"` - DistroSeries string `json:"distro_series"` - SwapSize *int `json:"swap_size"` -} - -type Zone struct { - AvailabilityZone string `json:"name"` -} - -func (c *Client) GetMachine(ctx context.Context, systemID string) (*Machine, error) { - - // creates the zero value - res := new(Machine) - if err := c.send(ctx, http.MethodGet, fmt.Sprintf("/machines/%s/", systemID), nil, res); err != nil { - return nil, err - } - - return res, nil -} - -type AllocateMachineOptions struct { - SystemID *string - Name *string - AvailabilityZone *string - ResourcePool *string - MinCPU *int - MinMem *int -} - -func (c *Client) AllocateMachine(ctx context.Context, options *AllocateMachineOptions) (*Machine, error) { - // or you can create new url.Values struct and encode that like so - q := url.Values{} - q.Add("op", "allocate") - - if options != nil { - addParam(q, "zone", options.AvailabilityZone) - addParam(q, "system_id", options.SystemID) - addParam(q, "name", options.Name) - addParam(q, "cpu_count", options.MinCPU) - addParam(q, "mem", options.MinMem) - addParam(q, "pool", options.ResourcePool) - } - - res := new(Machine) - if err := c.send(ctx, http.MethodPost, "/machines/", q, res); err != nil { - return nil, err - } - - return res, nil -} - -func (c *Client) ReleaseMachine(ctx context.Context, systemID string) error { - q := url.Values{} - q.Add("op", "release") - - // creates the zero value - res := new(Machine) - if err := c.send(ctx, http.MethodPost, fmt.Sprintf("/machines/%s/", systemID), q, res); err != nil { - return err - } - - return nil -} - -type DeployMachineOptions struct { - SystemID string - OSSystem *string - DistroSeries *string - UserData *string -} - -func (c *Client) DeployMachine(ctx context.Context, options DeployMachineOptions) (*Machine, error) { - q := url.Values{} - q.Add("op", "deploy") - - addParam(q, "osystem", options.OSSystem) - addParam(q, "distro_series", options.DistroSeries) - addParam(q, "user_data", options.UserData) - - // creates the zero value - res := new(Machine) - if err := c.send(ctx, http.MethodPost, fmt.Sprintf("/machines/%s/", options.SystemID), q, res); err != nil { - return nil, err - } - - return res, nil -} - -type UpdateMachineOptions struct { - SystemID string - SwapSize *int - Hostname *string -} - -func (c *Client) UpdateMachine(ctx context.Context, options UpdateMachineOptions) (*Machine, error) { - - q := url.Values{} - addParam(q, "swap_size", options.SwapSize) - addParam(q, "hostname", options.Hostname) - - // creates the zero value - res := new(Machine) - if err := c.send(ctx, http.MethodPut, fmt.Sprintf("/machines/%s/", options.SystemID), q, res); err != nil { - return nil, err - } - - return res, nil -} - -func addParam(values url.Values, key string, value interface{}) { - if reflect.ValueOf(value).IsNil() { - return - } - - switch v := value.(type) { - case *int: - values.Add(key, strconv.Itoa(*v)) - case *string: - values.Add(key, *v) - default: - panic(fmt.Sprintf("Unexpected type %v", v)) - } -} diff --git a/pkg/maasclient/machine_test.go b/pkg/maasclient/machine_test.go deleted file mode 100644 index e00ae41..0000000 --- a/pkg/maasclient/machine_test.go +++ /dev/null @@ -1,140 +0,0 @@ -package maasclient - -import ( - "context" - "github.com/stretchr/testify/assert" - "k8s.io/utils/pointer" - "math/rand" - "os" - "testing" - "time" -) - -func TestMain(m *testing.M) { - rand.Seed(time.Now().UnixNano()) - code := m.Run() - os.Exit(code) -} - -func TestClient_GetMachine(t *testing.T) { - c := NewClient(os.Getenv("MAAS_ENDPOINT"), os.Getenv("MAAS_API_KEY")) - - ctx := context.Background() - res, err := c.GetMachine(ctx, "e37xxm") - - assert.Nil(t, err, "expecting nil error") - - assert.NotNil(t, res, "expecting non-nil result") - assert.NotEmpty(t, res.SystemID) - assert.NotEmpty(t, res.Hostname) - assert.Equal(t, res.State, "Deployed") - assert.NotEmpty(t, res.PowerState) - assert.Equal(t, res.AvailabilityZone, "az1") - - assert.NotEmpty(t, res.FQDN) - assert.NotEmpty(t, res.IpAddresses) - - assert.NotEmpty(t, res.OSSystem) - assert.NotEmpty(t, res.DistroSeries) - - assert.Zero(t, *res.SwapSize) - -} - -func TestClient_AllocateMachine(t *testing.T) { - c := NewClient(os.Getenv("MAAS_ENDPOINT"), os.Getenv("MAAS_API_KEY")) - - ctx := context.Background() - - releaseMachine := func(res *Machine) { - if res != nil { - err := c.ReleaseMachine(ctx, res.SystemID) - assert.Nil(t, err) - } - } - - t.Run("no-options", func(t *testing.T) { - res, err := c.AllocateMachine(ctx, nil) - - assert.Nil(t, err, "expecting nil error") - assert.NotNil(t, res) - - releaseMachine(res) - }) - - t.Run("bad-options", func(t *testing.T) { - res, err := c.AllocateMachine(ctx, &AllocateMachineOptions{SystemID: pointer.StringPtr("abc")}) - - assert.NotNil(t, err, "expecting error") - - releaseMachine(res) - }) - - t.Run("with-az", func(t *testing.T) { - res, err := c.AllocateMachine(ctx, &AllocateMachineOptions{AvailabilityZone: pointer.StringPtr("az1")}) - - assert.Nil(t, err, "expecting nil error") - assert.NotNil(t, res) - - releaseMachine(res) - }) - -} - -func TestClient_DeployMachine(t *testing.T) { - c := NewClient(os.Getenv("MAAS_ENDPOINT"), os.Getenv("MAAS_API_KEY")) - - ctx := context.Background() - - releaseMachine := func(res *Machine) { - if res != nil { - err := c.ReleaseMachine(ctx, res.SystemID) - assert.Nil(t, err) - } - } - - t.Run("simple", func(t *testing.T) { - res, err := c.AllocateMachine(ctx, nil) - if err != nil { - t.Fatal("Machine didn't allocate") - } - assert.NotNil(t, res) - assert.NotEmpty(t, res.SystemID) - - options := DeployMachineOptions{ - SystemID: res.SystemID, - OSSystem: pointer.StringPtr("custom"), - DistroSeries: pointer.StringPtr("spectro-u18-k11815"), - } - - res, err = c.DeployMachine(ctx, options) - assert.Nil(t, err, "expecting nil error") - assert.NotNil(t, res) - - assert.Equal(t, res.OSSystem, "custom") - assert.Equal(t, res.DistroSeries, "spectro-u18-k11815") - - // Give me a few seconds before clenaing up - time.Sleep(15 * time.Second) - - releaseMachine(res) - }) - -} - -func TestClient_UpdateMachine(t *testing.T) { - ctx := context.Background() - c := NewClient(os.Getenv("MAAS_ENDPOINT"), os.Getenv("MAAS_API_KEY")) - - swapSize := 0 - options := UpdateMachineOptions{ - SystemID: "e37xxm", - SwapSize: &swapSize, - } - - res, err := c.UpdateMachine(ctx, options) - assert.Nil(t, err) - assert.NotNil(t, res) - assert.Equal(t, *res.SwapSize, 0) - -} diff --git a/pkg/maasclient/oauth1/LICENSE b/pkg/maasclient/oauth1/LICENSE deleted file mode 100644 index 16bf5dd..0000000 --- a/pkg/maasclient/oauth1/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2019 Klaidas Urbanavicius - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. \ No newline at end of file diff --git a/pkg/maasclient/oauth1/README.md b/pkg/maasclient/oauth1/README.md deleted file mode 100644 index 3f3a8bf..0000000 --- a/pkg/maasclient/oauth1/README.md +++ /dev/null @@ -1,57 +0,0 @@ -# Go-OAuth1.0 -Golang lightweight package/ implementation example of OAuth1.0 Authentication Header/ Signature calculation (Twitter etc..) - -To quickly import the package into your project: -> ``` -> go get github.com/klaidas/go-oauth1 -> ``` - -  - -Example usage: -```Go -package main - -import ( - "fmt" - oauth1 "go-oauth1" - "net/http" -) - -func main() { - method := http.MethodPost - url := "https://api.twitter.com/1.1/statuses/update.json?include_entities=true" - - auth := oauth1.OAuth1{ - ConsumerKey: "xvz1evFS4wEEPTGEFPHBog", - ConsumerSecret: "kAcSOqF21Fu85e7zjz7ZN2U4ZRhfV3WpwPAoE3Z7kBw", - AccessToken: "370773112-GmHxMAgYyLbNEtIKZeRNFsMKPR9EyMZeS9weJAEb", - AccessSecret: "LswwdoUaIvS8ltyTt5jkRh4J50vUPVVHtR2YPi5kE", - } - - authHeader := auth.BuildOAuth1Header(method, url, map[string]string { - "include_entities": "true", - "status": "Hello Ladies + Gentlemen, a signed OAuth request!", - }) - - req, _ := http.NewRequest(method, url, nil) - req.Header.Set("Authorization", authHeader) - - if res, err := http.DefaultClient.Do(req); err == nil { - fmt.Println(res.StatusCode) - } -} -``` - -  - -- Simply import the package -- Create an OAuth1 Object with the information you have (In some cases, AccessSecret will be unknown, this is fine) -- Call BuildOAuth1Header to generate your Authorization Header for the request you're making - -  - -Output: -``` -OAuth oauth_consumer_key="xvz1evFS4wEEPTGEFPHBog",oauth_token="370773112-GmHxMAgYyLbNEtIKZeRNFsMKPR9EyMZeS9weJAEb",oauth_signature_method="HMAC-SHA1",oauth_timestamp="1318622958",oauth_nonce="kYjzVBB8Y0ZFabxSWbWovY3uYSQ2pTgmZeNu2VS4cg",oauth_version="1.0",oauth_signature="hCtSmYh%2BiHYCEqBWrE7C7hYmtUk%3D" -``` diff --git a/pkg/maasclient/oauth1/oauth1.go b/pkg/maasclient/oauth1/oauth1.go deleted file mode 100644 index 3cb2713..0000000 --- a/pkg/maasclient/oauth1/oauth1.go +++ /dev/null @@ -1,64 +0,0 @@ -package oauth1 - -import ( - "crypto/hmac" - "crypto/sha1" - "encoding/base64" - "math/rand" - "net/url" - "strconv" - "strings" - "time" -) - -type OAuth1 struct { - ConsumerKey string - ConsumerSecret string - AccessToken string - AccessSecret string -} - -// TODO add comment on-top about what is changed, and the header - -// Params being any key-value url query parameter pairs -func (auth OAuth1) BuildOAuth1Header(method, path string, params map[string]string) string { - vals := url.Values{} - vals.Add("oauth_nonce", generateNonce()) - vals.Add("oauth_consumer_key", auth.ConsumerKey) - vals.Add("oauth_signature_method", "HMAC-SHA1") - vals.Add("oauth_timestamp", strconv.Itoa(int(time.Now().Unix()))) - vals.Add("oauth_token", auth.AccessToken) - vals.Add("oauth_version", "1.0") - - for k, v := range params { - vals.Add(k, v) - } - // net/url package QueryEscape escapes " " into "+", this replaces it with the percentage encoding of " " - parameterString := strings.Replace(vals.Encode(), "+", "%20", -1) - - // Calculating Signature Base String and Signing Key - signatureBase := strings.ToUpper(method) + "&" + url.QueryEscape(strings.Split(path, "?")[0]) + "&" + url.QueryEscape(parameterString) - signingKey := url.QueryEscape(auth.ConsumerSecret) + "&" + url.QueryEscape(auth.AccessSecret) - signature := calculateSignature(signatureBase, signingKey) - - return "OAuth oauth_consumer_key=\"" + url.QueryEscape(vals.Get("oauth_consumer_key")) + "\", oauth_nonce=\"" + url.QueryEscape(vals.Get("oauth_nonce")) + - "\", oauth_signature=\"" + url.QueryEscape(signature) + "\", oauth_signature_method=\"" + url.QueryEscape(vals.Get("oauth_signature_method")) + - "\", oauth_timestamp=\"" + url.QueryEscape(vals.Get("oauth_timestamp")) + "\", oauth_token=\"" + url.QueryEscape(vals.Get("oauth_token")) + - "\", oauth_version=\"" + url.QueryEscape(vals.Get("oauth_version")) + "\"" -} - -func calculateSignature(base, key string) string { - hash := hmac.New(sha1.New, []byte(key)) - hash.Write([]byte(base)) - signature := hash.Sum(nil) - return base64.StdEncoding.EncodeToString(signature) -} - -func generateNonce() string { - const allowed = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" - b := make([]byte, 48) - for i := range b { - b[i] = allowed[rand.Intn(len(allowed))] - } - return string(b) -}