diff --git a/go.mod b/go.mod index 942a9326f..b9fdaedde 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,7 @@ require ( github.com/dgrijalva/jwt-go v3.2.1-0.20190620180102-5e25c22bd5d6+incompatible // indirect github.com/digitalocean/godo v1.30.0 github.com/dnsimple/dnsimple-go v0.31.0 - github.com/exoscale/egoscale v0.10.5 + github.com/exoscale/egoscale v0.23.0 github.com/go-acme/lego v2.7.2+incompatible github.com/gobwas/glob v0.2.4-0.20181002190808-e7a84e9525fe github.com/golang/protobuf v1.3.3 // indirect diff --git a/go.sum b/go.sum index c030e6485..e6522a514 100644 --- a/go.sum +++ b/go.sum @@ -69,8 +69,8 @@ github.com/dnsimple/dnsimple-go v0.31.0 h1:I1T+AxBQfhovyyfGSJ4CSUeH0iQejLArsUlhS github.com/dnsimple/dnsimple-go v0.31.0/go.mod h1:O5TJ0/U6r7AfT8niYNlmohpLbCSG+c71tQlGr9SeGrg= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/exoscale/egoscale v0.10.5 h1:pV1gDCsXPi9vfbZ1TIMz7mNGEDMiVHlQlbcJp1qxIaU= -github.com/exoscale/egoscale v0.10.5/go.mod h1:Ee3U4ZjSDpbbEc9VkQ/jttUU8USE8Nv7L3YzVi03Y1U= +github.com/exoscale/egoscale v0.23.0 h1:hoUDzrO8yNoobNdnrRvlRFjfg3Ng0vQTrv6bXRJu6z0= +github.com/exoscale/egoscale v0.23.0/go.mod h1:hRo78jkjkCDKpivQdRBEpNYF5+cVpCJCPDg2/r45KaY= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= github.com/go-acme/lego v2.7.2+incompatible h1:ThhpPBgf6oa9X/vRd0kEmWOsX7+vmYdckmGZSb+FEp0= @@ -80,6 +80,8 @@ github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LB github.com/go-test/deep v1.0.2-0.20181118220953-042da051cf31/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= github.com/gobwas/glob v0.2.4-0.20181002190808-e7a84e9525fe h1:zn8tqiUbec4wR94o7Qj3LZCAT6uGobhEgnDRg6isG5U= github.com/gobwas/glob v0.2.4-0.20181002190808-e7a84e9525fe/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= +github.com/gofrs/uuid v3.2.0+incompatible h1:y12jRkkFxsd7GpqdSZ+/KCs/fJbqpEXSGd4+jfEaewE= +github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= diff --git a/integrationTest/integration_test.go b/integrationTest/integration_test.go index 85948aebc..70de69fc8 100644 --- a/integrationTest/integration_test.go +++ b/integrationTest/integration_test.go @@ -457,7 +457,7 @@ func makeTests(t *testing.T) []*TestCase { tc("Change Weight", srv("_sip._tcp", 52, 62, 7, "foo.com."), srv("_sip._tcp", 15, 65, 75, "foo4.com.")), tc("Change Port", srv("_sip._tcp", 52, 62, 72, "foo.com."), srv("_sip._tcp", 15, 65, 75, "foo4.com.")), ) - if *providerToRun == "NAMEDOTCOM" || *providerToRun == "HEXONET" { + if *providerToRun == "NAMEDOTCOM" || *providerToRun == "HEXONET" || *providerToRun == "EXOSCALE" { t.Log("Skipping SRV Null Target test because provider does not support them") } else { tests = append(tests, tc("Null Target", srv("_sip._tcp", 52, 62, 72, "foo.com."), srv("_sip._tcp", 15, 65, 75, "."))) diff --git a/models/t_srv.go b/models/t_srv.go index 986b3249c..6672b7f65 100644 --- a/models/t_srv.go +++ b/models/t_srv.go @@ -61,7 +61,7 @@ func (rc *RecordConfig) SetTargetSRVPriorityString(priority uint16, s string) er func (rc *RecordConfig) SetTargetSRVString(s string) error { part := strings.Fields(s) if len(part) != 4 { - return fmt.Errorf("SRC value does not contain 4 fields: (%#v)", s) + return fmt.Errorf("SRV value does not contain 4 fields: (%#v)", s) } return rc.SetTargetSRVStrings(part[0], part[1], part[2], part[3]) } diff --git a/providers/exoscale/exoscaleProvider.go b/providers/exoscale/exoscaleProvider.go index a02927803..404fc1ef6 100644 --- a/providers/exoscale/exoscaleProvider.go +++ b/providers/exoscale/exoscaleProvider.go @@ -1,6 +1,7 @@ package exoscale import ( + "context" "encoding/json" "fmt" "strings" @@ -27,7 +28,7 @@ var features = providers.DocumentationNotes{ providers.CanUseAlias: providers.Can(), providers.CanUseCAA: providers.Can(), providers.CanUsePTR: providers.Can(), - providers.CanUseSRV: providers.Can(), + providers.CanUseSRV: providers.Can("SRV records with empty targets are not supported"), providers.CanUseTLSA: providers.Cannot(), providers.DocCreateDomains: providers.Cannot(), providers.DocDualHost: providers.Cannot("Exoscale does not allow sufficient control over the apex NS records"), @@ -41,9 +42,10 @@ func init() { // EnsureDomainExists returns an error if domain doesn't exist. func (c *exoscaleProvider) EnsureDomainExists(domain string) error { - _, err := c.client.GetDomain(domain) + ctx := context.Background() + _, err := c.client.GetDomain(ctx, domain) if err != nil { - _, err := c.client.CreateDomain(domain) + _, err := c.client.CreateDomain(ctx, domain) if err != nil { return err } @@ -57,7 +59,7 @@ func (c *exoscaleProvider) GetNameservers(domain string) ([]*models.Nameserver, } // GetZoneRecords gets the records of a zone and returns them in RecordConfig format. -func (client *exoscaleProvider) GetZoneRecords(domain string) (models.Records, error) { +func (c *exoscaleProvider) GetZoneRecords(domain string) (models.Records, error) { return nil, fmt.Errorf("not implemented") // This enables the get-zones subcommand. // Implement this by extracting the code from GetDomainCorrections into @@ -68,7 +70,8 @@ func (client *exoscaleProvider) GetZoneRecords(domain string) (models.Records, e func (c *exoscaleProvider) GetDomainCorrections(dc *models.DomainConfig) ([]*models.Correction, error) { dc.Punycode() - records, err := c.client.GetRecords(dc.Name) + ctx := context.Background() + records, err := c.client.GetRecords(ctx, dc.Name) if err != nil { return nil, err } @@ -100,11 +103,11 @@ func (c *exoscaleProvider) GetDomainCorrections(dc *models.DomainConfig) ([]*mod rec.SetTarget(r.Content) case "MX": if err := rec.SetTargetMX(uint16(r.Prio), r.Content); err != nil { - panic(fmt.Errorf("unparsable record received from dnsimple: %w", err)) + panic(fmt.Errorf("unparsable record received from exoscale: %w", err)) } default: if err := rec.PopulateFromString(r.RecordType, r.Content, dc.Name); err != nil { - panic(fmt.Errorf("unparsable record received from dnsimple: %w", err)) + panic(fmt.Errorf("unparsable record received from exoscale: %w", err)) } } existingRecords = append(existingRecords, rec) @@ -170,7 +173,8 @@ func (c *exoscaleProvider) createRecordFunc(rc *models.RecordConfig, domainName TTL: int(rc.TTL), Prio: int(rc.MxPreference), } - _, err := client.CreateRecord(domainName, record) + ctx := context.Background() + _, err := client.CreateRecord(ctx, domainName, record) if err != nil { return err } @@ -184,7 +188,8 @@ func (c *exoscaleProvider) deleteRecordFunc(recordID int64, domainName string) f return func() error { client := c.client - if err := client.DeleteRecord(domainName, recordID); err != nil { + ctx := context.Background() + if err := client.DeleteRecord(ctx, domainName, recordID); err != nil { return err } @@ -218,7 +223,8 @@ func (c *exoscaleProvider) updateRecordFunc(old *egoscale.DNSRecord, rc *models. ID: old.ID, } - _, err := client.UpdateRecord(domainName, record) + ctx := context.Background() + _, err := client.UpdateRecord(ctx, domainName, record) if err != nil { return err } diff --git a/providers/hexonet/hexonetProvider.go b/providers/hexonet/hexonetProvider.go index 7dbbba5a8..002e21c39 100644 --- a/providers/hexonet/hexonetProvider.go +++ b/providers/hexonet/hexonetProvider.go @@ -22,7 +22,7 @@ var features = providers.DocumentationNotes{ providers.CanUseCAA: providers.Can(), providers.CanUsePTR: providers.Can(), providers.CanUseRoute53Alias: providers.Cannot("Using ALIAS is possible through our extended DNS (X-DNS) service. Feel free to get in touch with us."), - providers.CanUseSRV: providers.Can(), + providers.CanUseSRV: providers.Can("SRV records with empty targets are not supported"), providers.CanUseTLSA: providers.Can(), providers.CanUseTXTMulti: providers.Can(), providers.CantUseNOPURGE: providers.Can(), diff --git a/vendor/github.com/exoscale/egoscale/.gitignore b/vendor/github.com/exoscale/egoscale/.gitignore index 1590d8c48..800fe1da7 100644 --- a/vendor/github.com/exoscale/egoscale/.gitignore +++ b/vendor/github.com/exoscale/egoscale/.gitignore @@ -1,6 +1,5 @@ .token -cloudstack.ini -listApis.json dist ops.asc -bash_completion +vendor +listApis.json \ No newline at end of file diff --git a/vendor/github.com/exoscale/egoscale/.golangci.yml b/vendor/github.com/exoscale/egoscale/.golangci.yml new file mode 100644 index 000000000..5ae58b40f --- /dev/null +++ b/vendor/github.com/exoscale/egoscale/.golangci.yml @@ -0,0 +1,28 @@ +linters-settings: + golint: + min-confidence: 0.3 + gocyclo: + min-complexity: 28 + goimports: + local-prefixes: github.com + +linters: + enable: + - deadcode + - dupl + - errcheck + - gocritic + - gocyclo + - goimports + - golint + - gosimple + - govet + - ineffassign + - megacheck + - nakedret + - scopelint + - staticcheck + - structcheck + - unused + - varcheck + disable-all: true diff --git a/vendor/github.com/exoscale/egoscale/.gometalinter.json b/vendor/github.com/exoscale/egoscale/.gometalinter.json deleted file mode 100644 index 71269e79c..000000000 --- a/vendor/github.com/exoscale/egoscale/.gometalinter.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "Disable": ["gocyclo", "goconst", "maligned"], - "Skip": ["vendor"] -} diff --git a/vendor/github.com/exoscale/egoscale/.goreleaser.yml b/vendor/github.com/exoscale/egoscale/.goreleaser.yml deleted file mode 100644 index 1f67bc3e6..000000000 --- a/vendor/github.com/exoscale/egoscale/.goreleaser.yml +++ /dev/null @@ -1,54 +0,0 @@ -builds: - - main: ./cmd/cs/ - binary: cs - env: - - CGO_ENABLED=0 - goos: - - windows - - darwin - - linux - - openbsd - - freebsd - - goarch: - - amd64 - - main: ./cmd/exo/ - binary: exo - env: - - CGO_ENABLED=0 - goos: - - windows - - darwin - - linux - - openbsd - goarch: - - amd64 - -sign: - cmd: gpg - args: ["-u", "ops@exoscale.ch", "--detach-sign", "${artifact}"] - artifacts: all - -archive: - format_overrides: - - goos: windows - format: zip - files: - - LICENSE - - CHANGELOG.md - - bash_completion - -release: - github: - owner: exoscale - name: egoscale - draft: true - -nfpm: - vendor: Exoscale - homepage: https://www.exoscale.com/ - description: Tools to manage (almost) everything at Exoscale from the command line. - license: Apache 2.0 - formats: - - deb - - rpm diff --git a/vendor/github.com/exoscale/egoscale/.travis.yml b/vendor/github.com/exoscale/egoscale/.travis.yml index 61e88bca8..41112905d 100644 --- a/vendor/github.com/exoscale/egoscale/.travis.yml +++ b/vendor/github.com/exoscale/egoscale/.travis.yml @@ -1,17 +1,20 @@ language: go -dist: trusty +dist: xenial sudo: required go: -- 1.7 -- 1.8 -- 1.9 -- "1.10" +- "1.7.x" +- "1.8.x" +- "1.9.x" +- "1.10.x" +- "1.11.x" +- "1.12.x" +- "1.13.x" - tip env: - - DEP_VERSION=0.5.0 HUGO_VERSION=0.45.1 GORELEASER_VERSION=0.82.0 NFPM_VERSION=0.9.3 + - GOLANGCI_LINT_VERSION=1.17.1 GO111MODULES=on cache: apt @@ -21,45 +24,28 @@ addons: packages: - rpm -install: | - curl -L -s https://github.com/golang/dep/releases/download/v${DEP_VERSION}/dep-linux-amd64 -o $GOPATH/bin/dep - chmod +x $GOPATH/bin/dep - wget https://github.com/goreleaser/goreleaser/releases/download/v${GORELEASER_VERSION}/goreleaser_amd64.deb - sudo dpkg -i goreleaser_amd64.deb - wget https://github.com/goreleaser/nfpm/releases/download/v${NFPM_VERSION}/nfpm_amd64.deb - sudo dpkg -i nfpm_amd64.deb - npm i codeclimate-test-reporter +install: + - curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s -- -b $GOPATH/bin v${GOLANGCI_LINT_VERSION} + - npm i codeclimate-test-reporter + - | + [ "$(echo "$TRAVIS_GO_VERSION" | awk -F. '{print $2}')" -ge "11" ] && go mod vendor || go get -u github.com/gofrs/uuid -script: | - go test -race -coverprofile=coverage.out -covermode=atomic . - npx codeclimate-test-reporter < coverage.out +before_script: + - curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter + - chmod +x ./cc-test-reporter + - ./cc-test-reporter before-build + +script: + - go test -race -coverprofile=c.out -covermode=atomic . + +after_script: + - ./cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT jobs: include: - - stage: goreleaser - go: "1.10" - if: type = push - script: | - cd cmd/cs - dep ensure -v -vendor-only - cd ../exo - dep ensure -v -vendor-only - cd ../.. - go run cmd/exo/completion/main.go - goreleaser --snapshot --skip-sign - - stage: gh-pages - go: "1.10" - if: branch = master AND type = push - script: | - cd website - sh prepare.sh - wget https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_${HUGO_VERSION}_Linux-64bit.deb - sudo dpkg -i hugo_${HUGO_VERSION}_Linux-64bit.deb - hugo - cd public - git init - git config user.name "TravisCI" - git config user.email "travis@travis-ci.org" - git add . - git commit -m "Deployed to github pages" - git push -f -q "https://${GITHUB_TOKEN}@github.com/${TRAVIS_REPO_SLUG}" master:gh-pages + - stage: golangci-lint + go: 1.12.x + if: type = pull_request + script: + - go get -u github.com/gofrs/uuid + - golangci-lint run . diff --git a/vendor/github.com/exoscale/egoscale/AUTHORS b/vendor/github.com/exoscale/egoscale/AUTHORS index ae4d8f83b..5c12a2a17 100644 --- a/vendor/github.com/exoscale/egoscale/AUTHORS +++ b/vendor/github.com/exoscale/egoscale/AUTHORS @@ -6,3 +6,4 @@ Sebastien Goasguen Yoan Blanc Stefano Marengo Pierre-Emmanuel Jacquier +Fabrizio Steiner diff --git a/vendor/github.com/exoscale/egoscale/CHANGELOG.md b/vendor/github.com/exoscale/egoscale/CHANGELOG.md index 13d9e94d3..f927f44a4 100644 --- a/vendor/github.com/exoscale/egoscale/CHANGELOG.md +++ b/vendor/github.com/exoscale/egoscale/CHANGELOG.md @@ -1,7 +1,211 @@ Changelog ========= -0.10.5 (unreleased) +0.23.0 +------ + +- change: Add `Resources` field to `APIKey` (#420) + +0.22.0 +------ + +- change: Remove all references to Network Offerings (#418) + +0.21.0 +------ + +- feature: add const `NotFound` 404 on type `ErrorCode` (#417) + +0.20.1 +------ + +- fix: update the `ListAPIKeysResponse` field (#415) + +0.20.0 +------ + +- feature: Add Instance pool implementation (#410) +- feature: Add IAM implementation (#411) + +0.19.0 +------ + +- feature: add field `Description` on type `IPAddress` (#413) +- change: add Json tag `omitempty` on field `TemplateFilter` in type `ListTemplates` (#412) + +0.18.1 +------ + +- change: make the "User-Agent" HTTP request header more informative and exposed + +0.18.0 +------ + +- feature: add method `DeepCopy` on type `AsyncJobResult` (#403) + +0.17.2 +------ + +- remove: remove the `IsFeatured` parameter from call `RegisterCustomTemplate` (#402) + +0.17.1 +------ + +- feature: add parameter `RescueProfile` to call `StartVirtualMachine` (#401) + +0.17.0 +------ + +- feature: add new call `RegisterCustomTemplate` (#400) +- feature: add new call `DeleteTemplate` (#399) + +0.16.0 +------ + +- feature: Add `Healthcheck*` parameters to call `UpdateIPAddress` +- change: Replace satori/go.uuid by gofrs/uuid + +0.15.0 +------ + +- change: prefix the healthcheck-related params with `Healthcheck` on call `AssociateIPAddress` +- EIP: the healthcheck should be a pointer +- ip addresses: Add the Healthcheck parameters +- readme: point to new lego org (#395) +- dns: user_id is not sent back (#394) + +0.14.3 +------ + +- fix: `AffinityGroup` lists virtual machines with `UUID` rather than string + +0.14.2 +------ + +- fix: `ListVirtualMachines` by `IDs` to accept `UUID` rather than string + +0.14.1 +------ + +- fix: `GetRunstatusPage` to always contain the subresources +- fix: `ListRunstatus*` to fetch all the subresources +- feature: `PaginateRunstatus*` used by list + +0.14.0 +------ + +- change: all DNS calls require a context +- fix: `CreateAffinityGroup` allows empty `name` + +0.13.3 +------ + +- fix: runstatus unmarshalling errors +- feature: `UUID` implements DeepCopy, DeepCopyInto +- change: export `BooleanResponse` + +0.13.2 +------ + +- feat: initial Runstatus API support +- feat: `admin` namespace containing `ListVirtualMachines` for admin usage + +0.13.1 +------ + +- feat: `Iso` support `ListIsos`, `AttachIso`, and `DetachIso` + +0.13.0 +------ + +- change: `Paginate` to accept `Listable` +- change: `ListCommand` is also `Listable` +- change: `client.Get` doesn't modify the given resource, returns a new one +- change: `Command` and `AsyncCommand` are fully public, thus extensible +- remove: `Gettable` + +0.12.5 +------ + +- fix: `AuthorizeSecurityGroupEgress` could return `authorizeSecurityGroupIngress` as name + +0.12.4 +------ + +- feat: `Snapshot` is `Listable` + +0.12.3 +------ + +- change: replace dep by Go modules +- change: remove domainid,domain,regionid,listall,isrecursive,... fields +- remove: `MigrateVirtualMachine`, `CreateUser`, `EnableAccount`, and other admin calls + +0.12.2 +------ + +- fix: `ListNics` has no virtualmachineid limitations anymore +- fix: `PCIDevice` ids are not UUIDs + +0.12.1 +------ + +- fix: `UpdateVMNicIP` is async + +0.12.0 +------ + +- feat: new VM state `Moving` +- feat: `UpdateNetwork` with `startip`, `endip`, `netmask` +- feat: `NetworkOffering` is `Listable` +- feat: when it fails parsing the body, it shows it +- fix: `Snapshot.State` is a string, rather than an scalar +- change: signature are now using the v3 version with expires by default + +0.11.6 +------ + +- fix: `Network.ListRequest` accepts a `Name` argument +- change: `SecurityGroup` and the rules aren't `Taggable` anymore + +0.11.5 +------ + +- feat: addition of `UpdateVMNicIP` +- fix: `UpdateVMAffinityGroup` expected response + +0.11.4 +------ + +*no changes in the core library* + +0.11.3 +------ + +*no changes in the core library* + +0.11.2 +------ + +- fix: empty list responses + +0.11.1 +------ + +- fix: `client.Sign` handles correctly the brackets (kudos to @stffabi) +- change: `client.Payload` returns a `url.Values` + +0.11.0 +------ + +- feat: `listOSCategories` and `OSCategory` type +- feat: `listApis` supports recursive response structures +- feat: `GetRecordsWithFilters` to list records with name or record_type filters +- fix: better `DNSErrorResponse` +- fix: `ListResourceLimits` type +- change: use UUID everywhere + +0.10.5 ------ - feat: `Client.Logger` to plug in any `*log.Logger` diff --git a/vendor/github.com/exoscale/egoscale/Dockerfile b/vendor/github.com/exoscale/egoscale/Dockerfile deleted file mode 100644 index a317320d3..000000000 --- a/vendor/github.com/exoscale/egoscale/Dockerfile +++ /dev/null @@ -1,48 +0,0 @@ -# -# First, export the ops.asc key locally. -# -# gpg --export-secret-key E458F9F85608DF5A22ECCD158B58C61D4FFE0C86 > ops.asc -# -# Build the container -# -# docker build -t egoscale . -# -# Prepare a snapshot release -# -# docker run -v $PWD:/go/src/github.com/exoscale/egoscale egoscale goreleaser --snapshot -# -# Publish egoscale exposing a valid GITHUB_TOKEN -# -# git tag -a v0.10 -# git push --tag -# docker run -v $PWD:/go/src/github.com/exoscale/egoscale -e GITHUB_TOKEN=... egoscale goreleaser -# -# -# ⚠ do not push this container anywhere ⚠ -# -FROM golang:1.10-stretch - -ARG DEBIAN_FRONTEND=noninteractive - -RUN go get -u github.com/golang/dep/cmd/dep \ - && go get -u -d github.com/goreleaser/goreleaser/... \ - && go get -u -d github.com/goreleaser/nfpm/... \ - && apt-get update -q \ - && apt-get upgrade -qy \ - && apt-get install -qy \ - rpm \ - && cd $GOPATH/src/github.com/goreleaser/nfpm \ - && dep ensure -v -vendor-only \ - && go install \ - && cd ../goreleaser \ - && dep ensure -v -vendor-only \ - && go install \ - && cd / - -ADD ops.asc ops.asc -RUN gpg --allow-secret-key-import --import ops.asc - -VOLUME /go/src/github.com/exoscale/egoscale -WORKDIR /go/src/github.com/exoscale/egoscale - -CMD ['goreleaser', '--snapshot'] diff --git a/vendor/github.com/exoscale/egoscale/Jenkinsfile b/vendor/github.com/exoscale/egoscale/Jenkinsfile deleted file mode 100644 index 62664eda6..000000000 --- a/vendor/github.com/exoscale/egoscale/Jenkinsfile +++ /dev/null @@ -1,90 +0,0 @@ -@Library('jenkins-pipeline') _ - -node { - cleanWs() - - repo = 'exoscale/egoscale' - - try { - dir('src') { - stage('SCM') { - checkout scm - } - stage('gofmt') { - gofmt(repo, "cs", "exo") - } - updateGithubCommitStatus('PENDING', "${env.WORKSPACE}/src") - stage('Build') { - parallel ( - "golint": { - golint(repo, "cmd/cs/...", "cmd/exo/...", "generate") - }, - "go test": { - test(repo) - }, - "go install": { - build(repo, "cs", "exo") - }, - ) - } - } - } catch (err) { - currentBuild.result = 'FAILURE' - throw err - } finally { - if (!currentBuild.result) { - currentBuild.result = 'SUCCESS' - } - updateGithubCommitStatus(currentBuild.result, "${env.WORKSPACE}/src") - cleanWs cleanWhenFailure: false - } -} - -def gofmt(repo, ...bins) { - docker.withRegistry('https://registry.internal.exoscale.ch') { - def image = docker.image('registry.internal.exoscale.ch/exoscale/golang:1.10') - image.pull() - image.inside("-u root --net=host -v ${env.WORKSPACE}/src:/go/src/github.com/${repo}") { - sh 'test `gofmt -s -d -e . | tee -a /dev/fd/2 | wc -l` -eq 0' - // let's not gofmt the dependencies - for (bin in bins) { - sh "cd /go/src/github.com/${repo}/cmd/${bin} && dep ensure -v -vendor-only" - } - } - } -} - -def golint(repo, ...extras) { - docker.withRegistry('https://registry.internal.exoscale.ch') { - def image = docker.image('registry.internal.exoscale.ch/exoscale/golang:1.10') - image.inside("-u root --net=host -v ${env.WORKSPACE}/src:/go/src/github.com/${repo}") { - sh "golint -set_exit_status -min_confidence 0.6 \$(go list github.com/${repo}/... | grep -v /vendor/)" - sh "go vet `go list github.com/${repo}/... | grep -v /vendor/`" - sh "cd /go/src/github.com/${repo} && gometalinter ." - for (extra in extras) { - sh "cd /go/src/github.com/${repo} && gometalinter ./${extra}" - } - } - } -} - -def test(repo) { - docker.withRegistry('https://registry.internal.exoscale.ch') { - def image = docker.image('registry.internal.exoscale.ch/exoscale/golang:1.10') - image.inside("-u root --net=host -v ${env.WORKSPACE}/src:/go/src/github.com/${repo}") { - sh "cd /go/src/github.com/${repo} && go test" - } - } -} - -def build(repo, ...bins) { - docker.withRegistry('https://registry.internal.exoscale.ch') { - def image = docker.image('registry.internal.exoscale.ch/exoscale/golang:1.10') - image.inside("-u root --net=host -v ${env.WORKSPACE}/src:/go/src/github.com/exoscale/egoscale") { - for (bin in bins) { - sh "go install github.com/${repo}/cmd/${bin}" - sh "test -e /go/bin/${bin}" - } - } - } -} diff --git a/vendor/github.com/exoscale/egoscale/README.md b/vendor/github.com/exoscale/egoscale/README.md index f587f1dfb..61e809d15 100644 --- a/vendor/github.com/exoscale/egoscale/README.md +++ b/vendor/github.com/exoscale/egoscale/README.md @@ -5,10 +5,20 @@ description: the Go library for Exoscale -[![Build Status](https://travis-ci.org/exoscale/egoscale.svg?branch=master)](https://travis-ci.org/exoscale/egoscale) [![Maintainability](https://api.codeclimate.com/v1/badges/fcab3b624b7d3ca96a9d/maintainability)](https://codeclimate.com/github/exoscale/egoscale/maintainability) [![Test Coverage](https://api.codeclimate.com/v1/badges/fcab3b624b7d3ca96a9d/test_coverage)](https://codeclimate.com/github/exoscale/egoscale/test_coverage) [![GoDoc](https://godoc.org/github.com/exoscale/egoscale?status.svg)](https://godoc.org/github.com/exoscale/egoscale) [![Go Report Card](https://goreportcard.com/badge/github.com/exoscale/egoscale)](https://goreportcard.com/report/github.com/exoscale/egoscale) +[![Build Status](https://travis-ci.com/exoscale/egoscale.svg?branch=master)](https://travis-ci.com/exoscale/egoscale) [![Maintainability](https://api.codeclimate.com/v1/badges/fcab3b624b7d3ca96a9d/maintainability)](https://codeclimate.com/github/exoscale/egoscale/maintainability) [![Test Coverage](https://api.codeclimate.com/v1/badges/fcab3b624b7d3ca96a9d/test_coverage)](https://codeclimate.com/github/exoscale/egoscale/test_coverage) [![GoDoc](https://godoc.org/github.com/exoscale/egoscale?status.svg)](https://godoc.org/github.com/exoscale/egoscale) [![Go Report Card](https://goreportcard.com/badge/github.com/exoscale/egoscale)](https://goreportcard.com/report/github.com/exoscale/egoscale) A wrapper for the [Exoscale public cloud](https://www.exoscale.com) API. +## Known users + +- [Exoscale CLI](https://github.com/exoscale/cli) +- [Exoscale Terraform provider](https://github.com/exoscale/terraform-provider-exoscale) +- [ExoIP](https://github.com/exoscale/exoip): IP Watchdog +- [Lego](https://github.com/go-acme/lego): Let's Encrypt and ACME library +- Kubernetes Incubator: [External DNS](https://github.com/kubernetes-incubator/external-dns) +- [Docker machine](https://docs.docker.com/machine/drivers/exoscale/) +- [etc.](https://godoc.org/github.com/exoscale/egoscale?importers) + ## License Licensed under the Apache License, Version 2.0 (the "License"); you diff --git a/vendor/github.com/exoscale/egoscale/accounts.go b/vendor/github.com/exoscale/egoscale/accounts.go index 88bdac4aa..9bcdec608 100644 --- a/vendor/github.com/exoscale/egoscale/accounts.go +++ b/vendor/github.com/exoscale/egoscale/accounts.go @@ -1,35 +1,15 @@ package egoscale -import "fmt" - -// AccountType represents the type of an Account -// -// http://docs.cloudstack.apache.org/projects/cloudstack-administration/en/4.8/accounts.html#accounts-users-and-domains -type AccountType int16 - -//go:generate stringer -type AccountType -const ( - // UserAccount represents a User - UserAccount AccountType = iota - // AdminAccount represents an Admin - AdminAccount - // DomainAdminAccount represents a Domain Admin - DomainAdminAccount -) - // Account provides the detailed account information type Account struct { AccountDetails map[string]string `json:"accountdetails,omitempty" doc:"details for the account"` - AccountType AccountType `json:"accounttype,omitempty" doc:"account type (admin, domain-admin, user)"` CPUAvailable string `json:"cpuavailable,omitempty" doc:"the total number of cpu cores available to be created for this account"` CPULimit string `json:"cpulimit,omitempty" doc:"the total number of cpu cores the account can own"` CPUTotal int64 `json:"cputotal,omitempty" doc:"the total number of cpu cores owned by account"` - DefaultZoneID string `json:"defaultzoneid,omitempty" doc:"the default zone of the account"` - Domain string `json:"domain,omitempty" doc:"name of the Domain the account belongs too"` - DomainID string `json:"domainid,omitempty" doc:"id of the Domain the account belongs too"` + DefaultZoneID *UUID `json:"defaultzoneid,omitempty" doc:"the default zone of the account"` EipLimit string `json:"eiplimit,omitempty" doc:"the total number of public elastic ip addresses this account can acquire"` Groups []string `json:"groups,omitempty" doc:"the list of acl groups that account belongs to"` - ID string `json:"id,omitempty" doc:"the id of the account"` + ID *UUID `json:"id,omitempty" doc:"the id of the account"` IPAvailable string `json:"ipavailable,omitempty" doc:"the total number of public ip addresses available for this account to acquire"` IPLimit string `json:"iplimit,omitempty" doc:"the total number of public ip addresses this account can acquire"` IPTotal int64 `json:"iptotal,omitempty" doc:"the total number of public ip addresses allocated for this account"` @@ -74,55 +54,23 @@ type Account struct { // ListRequest builds the ListAccountsGroups request func (a Account) ListRequest() (ListCommand, error) { return &ListAccounts{ - ID: a.ID, - DomainID: a.DomainID, - AccountType: a.AccountType, - State: a.State, + ID: a.ID, + State: a.State, }, nil } +//go:generate go run generate/main.go -interface=Listable ListAccounts + // ListAccounts represents a query to display the accounts type ListAccounts struct { - AccountType AccountType `json:"accounttype,omitempty" doc:"list accounts by account type. Valid account types are 1 (admin), 2 (domain-admin), and 0 (user)."` - DomainID string `json:"domainid,omitempty" doc:"list only resources belonging to the domain specified"` - ID string `json:"id,omitempty" doc:"list account by account ID"` - IsCleanUpRequired *bool `json:"iscleanuprequired,omitempty" doc:"list accounts by cleanuprequred attribute (values are true or false)"` - IsRecursive *bool `json:"isrecursive,omitempty" doc:"defaults to false, but if true, lists all resources from the parent specified by the domainId till leaves."` - Keyword string `json:"keyword,omitempty" doc:"List by keyword"` - ListAll *bool `json:"listall,omitempty" doc:"If set to false, list only resources belonging to the command's caller; if set to true - list resources that the caller is authorized to see. Default value is false"` - Name string `json:"name,omitempty" doc:"list account by account name"` - Page int `json:"page,omitempty"` - PageSize int `json:"pagesize,omitempty"` - State string `json:"state,omitempty" doc:"list accounts by state. Valid states are enabled, disabled, and locked."` - _ bool `name:"listAccounts" description:"Lists accounts and provides detailed account information for listed accounts"` -} - -func (ListAccounts) response() interface{} { - return new(ListAccountsResponse) -} - -// SetPage sets the current page -func (ls *ListAccounts) SetPage(page int) { - ls.Page = page -} - -// SetPageSize sets the page size -func (ls *ListAccounts) SetPageSize(pageSize int) { - ls.PageSize = pageSize -} - -func (ListAccounts) each(resp interface{}, callback IterateItemFunc) { - vms, ok := resp.(*ListAccountsResponse) - if !ok { - callback(nil, fmt.Errorf("wrong type. ListAccountsResponse expected, got %T", resp)) - return - } - - for i := range vms.Account { - if !callback(&vms.Account[i], nil) { - break - } - } + ID *UUID `json:"id,omitempty" doc:"List account by account ID"` + IsCleanUpRequired *bool `json:"iscleanuprequired,omitempty" doc:"list accounts by cleanuprequired attribute (values are true or false)"` + Keyword string `json:"keyword,omitempty" doc:"List by keyword"` + Name string `json:"name,omitempty" doc:"List account by account name"` + Page int `json:"page,omitempty"` + PageSize int `json:"pagesize,omitempty"` + State string `json:"state,omitempty" doc:"List accounts by state. Valid states are enabled, disabled, and locked."` + _ bool `name:"listAccounts" description:"Lists accounts and provides detailed account information for listed accounts"` } // ListAccountsResponse represents a list of accounts @@ -130,32 +78,3 @@ type ListAccountsResponse struct { Count int `json:"count"` Account []Account `json:"account"` } - -// EnableAccount represents the activation of an account -type EnableAccount struct { - Account string `json:"account,omitempty" doc:"Enables specified account."` - DomainID string `json:"domainid,omitempty" doc:"Enables specified account in this domain."` - ID string `json:"id,omitempty" doc:"Account id"` - _ bool `name:"enableAccount" description:"Enables an account"` -} - -func (EnableAccount) response() interface{} { - return new(Account) -} - -// DisableAccount (Async) represents the deactivation of an account -type DisableAccount struct { - Lock *bool `json:"lock" doc:"If true, only lock the account; else disable the account"` - Account string `json:"account,omitempty" doc:"Disables specified account."` - DomainID string `json:"domainid,omitempty" doc:"Disables specified account in this domain."` - ID string `json:"id,omitempty" doc:"Account id"` - _ bool `name:"disableAccount" description:"Disables an account"` -} - -func (DisableAccount) response() interface{} { - return new(AsyncJobResult) -} - -func (DisableAccount) asyncResponse() interface{} { - return new(Account) -} diff --git a/vendor/github.com/exoscale/egoscale/accounts_response.go b/vendor/github.com/exoscale/egoscale/accounts_response.go new file mode 100644 index 000000000..106daca32 --- /dev/null +++ b/vendor/github.com/exoscale/egoscale/accounts_response.go @@ -0,0 +1,43 @@ +// code generated; DO NOT EDIT. + +package egoscale + +import "fmt" + +// Response returns the struct to unmarshal +func (ListAccounts) Response() interface{} { + return new(ListAccountsResponse) +} + +// ListRequest returns itself +func (ls *ListAccounts) ListRequest() (ListCommand, error) { + if ls == nil { + return nil, fmt.Errorf("%T cannot be nil", ls) + } + return ls, nil +} + +// SetPage sets the current apge +func (ls *ListAccounts) SetPage(page int) { + ls.Page = page +} + +// SetPageSize sets the page size +func (ls *ListAccounts) SetPageSize(pageSize int) { + ls.PageSize = pageSize +} + +// Each triggers the callback for each, valid answer or any non 404 issue +func (ListAccounts) Each(resp interface{}, callback IterateItemFunc) { + items, ok := resp.(*ListAccountsResponse) + if !ok { + callback(nil, fmt.Errorf("wrong type, ListAccountsResponse was expected, got %T", resp)) + return + } + + for i := range items.Account { + if !callback(&items.Account[i], nil) { + break + } + } +} diff --git a/vendor/github.com/exoscale/egoscale/accounttype_string.go b/vendor/github.com/exoscale/egoscale/accounttype_string.go deleted file mode 100644 index 7d622a16c..000000000 --- a/vendor/github.com/exoscale/egoscale/accounttype_string.go +++ /dev/null @@ -1,16 +0,0 @@ -// Code generated by "stringer -type AccountType"; DO NOT EDIT. - -package egoscale - -import "strconv" - -const _AccountType_name = "UserAccountAdminAccountDomainAdminAccount" - -var _AccountType_index = [...]uint8{0, 11, 23, 41} - -func (i AccountType) String() string { - if i < 0 || i >= AccountType(len(_AccountType_index)-1) { - return "AccountType(" + strconv.FormatInt(int64(i), 10) + ")" - } - return _AccountType_name[_AccountType_index[i]:_AccountType_index[i+1]] -} diff --git a/vendor/github.com/exoscale/egoscale/addresses.go b/vendor/github.com/exoscale/egoscale/addresses.go index ebf47ee66..41e67a99d 100644 --- a/vendor/github.com/exoscale/egoscale/addresses.go +++ b/vendor/github.com/exoscale/egoscale/addresses.go @@ -6,37 +6,46 @@ import ( "net" ) +// Healthcheck represents an Healthcheck attached to an IP +type Healthcheck struct { + Interval int64 `json:"interval,omitempty" doc:"healthcheck definition: time in seconds to wait for each check. Default: 10, minimum: 5"` + Mode string `json:"mode,omitempty" doc:"healthcheck definition: healthcheck mode can be either 'tcp' or 'http'"` + Path string `json:"path,omitempty" doc:"healthcheck definition: the path against which the 'http' healthcheck will be performed. Required if mode is 'http', ignored otherwise."` + Port int64 `json:"port,omitempty" doc:"healthcheck definition: the port against which the healthcheck will be performed. Required if a 'mode' is provided."` + StrikesFail int64 `json:"strikes-fail,omitempty" doc:"healthcheck definition: number of times to retry before declaring the healthcheck 'dead'. Default: 3"` + StrikesOk int64 `json:"strikes-ok,omitempty" doc:"healthcheck definition: number of times to retry before declaring the healthcheck 'alive'. Default: 2"` + Timeout int64 `json:"timeout,omitempty" doc:"healthcheck definition: time in seconds to wait for each check. Default: 2, cannot be greater than interval."` +} + // IPAddress represents an IP Address type IPAddress struct { - Account string `json:"account,omitempty" doc:"the account the public IP address is associated with"` Allocated string `json:"allocated,omitempty" doc:"date the public IP address was acquired"` Associated string `json:"associated,omitempty" doc:"date the public IP address was associated"` - AssociatedNetworkID string `json:"associatednetworkid,omitempty" doc:"the ID of the Network associated with the IP address"` + AssociatedNetworkID *UUID `json:"associatednetworkid,omitempty" doc:"the ID of the Network associated with the IP address"` AssociatedNetworkName string `json:"associatednetworkname,omitempty" doc:"the name of the Network associated with the IP address"` - Domain string `json:"domain,omitempty" doc:"the domain the public IP address is associated with"` - DomainID string `json:"domainid,omitempty" doc:"the domain ID the public IP address is associated with"` - ForDisplay bool `json:"fordisplay,omitempty" doc:"is public ip for display to the regular user"` + Description string `json:"description,omitempty" doc:"The IP address description."` ForVirtualNetwork bool `json:"forvirtualnetwork,omitempty" doc:"the virtual network for the IP address"` - ID string `json:"id,omitempty" doc:"public IP address id"` + Healthcheck *Healthcheck `json:"healthcheck,omitempty" doc:"The IP healthcheck configuration"` + ID *UUID `json:"id,omitempty" doc:"public IP address id"` IPAddress net.IP `json:"ipaddress,omitempty" doc:"public IP address"` IsElastic bool `json:"iselastic,omitempty" doc:"is an elastic ip"` IsPortable bool `json:"isportable,omitempty" doc:"is public IP portable across the zones"` IsSourceNat bool `json:"issourcenat,omitempty" doc:"true if the IP address is a source nat address, false otherwise"` IsStaticNat *bool `json:"isstaticnat,omitempty" doc:"true if this ip is for static nat, false otherwise"` IsSystem bool `json:"issystem,omitempty" doc:"true if this ip is system ip (was allocated as a part of deployVm or createLbRule)"` - NetworkID string `json:"networkid,omitempty" doc:"the ID of the Network where ip belongs to"` - PhysicalNetworkID string `json:"physicalnetworkid,omitempty" doc:"the physical network this belongs to"` + NetworkID *UUID `json:"networkid,omitempty" doc:"the ID of the Network where ip belongs to"` + PhysicalNetworkID *UUID `json:"physicalnetworkid,omitempty" doc:"the physical network this belongs to"` Purpose string `json:"purpose,omitempty" doc:"purpose of the IP address. In Acton this value is not null for Ips with isSystem=true, and can have either StaticNat or LB value"` ReverseDNS []ReverseDNS `json:"reversedns,omitempty" doc:"the list of PTR record(s) associated with the ip address"` State string `json:"state,omitempty" doc:"State of the ip address. Can be: Allocatin, Allocated and Releasing"` Tags []ResourceTag `json:"tags,omitempty" doc:"the list of resource tags associated with ip address"` VirtualMachineDisplayName string `json:"virtualmachinedisplayname,omitempty" doc:"virtual machine display name the ip address is assigned to (not null only for static nat Ip)"` - VirtualMachineID string `json:"virtualmachineid,omitempty" doc:"virtual machine id the ip address is assigned to (not null only for static nat Ip)"` + VirtualMachineID *UUID `json:"virtualmachineid,omitempty" doc:"virtual machine id the ip address is assigned to (not null only for static nat Ip)"` VirtualMachineName string `json:"virtualmachinename,omitempty" doc:"virtual machine name the ip address is assigned to (not null only for static nat Ip)"` - VlanID string `json:"vlanid,omitempty" doc:"the ID of the VLAN associated with the IP address. This parameter is visible to ROOT admins only"` + VlanID *UUID `json:"vlanid,omitempty" doc:"the ID of the VLAN associated with the IP address. This parameter is visible to ROOT admins only"` VlanName string `json:"vlanname,omitempty" doc:"the VLAN associated with the IP address"` - VMIPAddress net.IP `json:"vmipaddress,omitempty" doc:"virutal machine (dnat) ip address (not null only for static nat Ip)"` - ZoneID string `json:"zoneid,omitempty" doc:"the ID of the zone the public IP address belongs to"` + VMIPAddress net.IP `json:"vmipaddress,omitempty" doc:"virtual machine (dnat) ip address (not null only for static nat Ip)"` + ZoneID *UUID `json:"zoneid,omitempty" doc:"the ID of the zone the public IP address belongs to"` ZoneName string `json:"zonename,omitempty" doc:"the name of the zone the public IP address belongs to"` } @@ -48,9 +57,7 @@ func (IPAddress) ResourceType() string { // ListRequest builds the ListAdresses request func (ipaddress IPAddress) ListRequest() (ListCommand, error) { req := &ListPublicIPAddresses{ - Account: ipaddress.Account, AssociatedNetworkID: ipaddress.AssociatedNetworkID, - DomainID: ipaddress.DomainID, ID: ipaddress.ID, IPAddress: ipaddress.IPAddress, PhysicalNetworkID: ipaddress.PhysicalNetworkID, @@ -63,9 +70,6 @@ func (ipaddress IPAddress) ListRequest() (ListCommand, error) { if ipaddress.IsSourceNat { req.IsSourceNat = &ipaddress.IsSourceNat } - if ipaddress.ForDisplay { - req.ForDisplay = &ipaddress.ForDisplay - } if ipaddress.ForVirtualNetwork { req.ForVirtualNetwork = &ipaddress.ForVirtualNetwork } @@ -75,7 +79,7 @@ func (ipaddress IPAddress) ListRequest() (ListCommand, error) { // Delete removes the resource func (ipaddress IPAddress) Delete(ctx context.Context, client *Client) error { - if ipaddress.ID == "" { + if ipaddress.ID == nil { return fmt.Errorf("an IPAddress may only be deleted using ID") } @@ -86,77 +90,88 @@ func (ipaddress IPAddress) Delete(ctx context.Context, client *Client) error { // AssociateIPAddress (Async) represents the IP creation type AssociateIPAddress struct { - Account string `json:"account,omitempty" doc:"the account to associate with this IP address"` - DomainID string `json:"domainid,omitempty" doc:"the ID of the domain to associate with this IP address"` - ForDisplay *bool `json:"fordisplay,omitempty" doc:"an optional field, whether to the display the ip to the end user or not"` - IsPortable *bool `json:"isportable,omitempty" doc:"should be set to true if public IP is required to be transferable across zones, if not specified defaults to false"` - NetworkdID string `json:"networkid,omitempty" doc:"The network this ip address should be associated to."` - RegionID int `json:"regionid,omitempty" doc:"region ID from where portable ip is to be associated."` - ZoneID string `json:"zoneid,omitempty" doc:"the ID of the availability zone you want to acquire an public IP address from"` - _ bool `name:"associateIpAddress" description:"Acquires and associates a public IP to an account."` + Description string `json:"description,omitempty" doc:"The IP address description."` + HealthcheckInterval int64 `json:"interval,omitempty" doc:"healthcheck definition: time in seconds to wait for each check. Default: 10, minimum: 5"` + HealthcheckMode string `json:"mode,omitempty" doc:"healthcheck definition: healthcheck mode can be either 'tcp' or 'http'"` + HealthcheckPath string `json:"path,omitempty" doc:"healthcheck definition: the path against which the 'http' healthcheck will be performed. Required if mode is 'http', ignored otherwise."` + HealthcheckPort int64 `json:"port,omitempty" doc:"healthcheck definition: the port against which the healthcheck will be performed. Required if a 'mode' is provided."` + HealthcheckStrikesFail int64 `json:"strikes-fail,omitempty" doc:"healthcheck definition: number of times to retry before declaring the healthcheck 'dead'. Default: 3"` + HealthcheckStrikesOk int64 `json:"strikes-ok,omitempty" doc:"healthcheck definition: number of times to retry before declaring the healthcheck 'alive'. Default: 2"` + HealthcheckTimeout int64 `json:"timeout,omitempty" doc:"healthcheck definition: time in seconds to wait for each check. Default: 2, cannot be greater than interval."` + ZoneID *UUID `json:"zoneid,omitempty" doc:"the ID of the availability zone you want to acquire a public IP address from"` + _ bool `name:"associateIpAddress" description:"Acquires and associates a public IP to an account."` } -func (AssociateIPAddress) response() interface{} { +// Response returns the struct to unmarshal +func (AssociateIPAddress) Response() interface{} { return new(AsyncJobResult) } -func (AssociateIPAddress) asyncResponse() interface{} { +// AsyncResponse returns the struct to unmarshal the async job +func (AssociateIPAddress) AsyncResponse() interface{} { return new(IPAddress) } // DisassociateIPAddress (Async) represents the IP deletion type DisassociateIPAddress struct { - ID string `json:"id" doc:"the id of the public ip address to disassociate"` - _ bool `name:"disassociateIpAddress" description:"Disassociates an ip address from the account."` + ID *UUID `json:"id" doc:"the id of the public ip address to disassociate"` + _ bool `name:"disassociateIpAddress" description:"Disassociates an ip address from the account."` } -func (DisassociateIPAddress) response() interface{} { +// Response returns the struct to unmarshal +func (DisassociateIPAddress) Response() interface{} { return new(AsyncJobResult) } -func (DisassociateIPAddress) asyncResponse() interface{} { - return new(booleanResponse) +// AsyncResponse returns the struct to unmarshal the async job +func (DisassociateIPAddress) AsyncResponse() interface{} { + return new(BooleanResponse) } // UpdateIPAddress (Async) represents the IP modification type UpdateIPAddress struct { - ID string `json:"id" doc:"the id of the public ip address to update"` - CustomID string `json:"customid,omitempty" doc:"an optional field, in case you want to set a custom id to the resource. Allowed to Root Admins only"` - ForDisplay *bool `json:"fordisplay,omitempty" doc:"an optional field, whether to the display the ip to the end user or not"` - _ bool `name:"updateIpAddress" description:"Updates an ip address"` + Description string `json:"description,omitempty" doc:"The IP address description."` + HealthcheckInterval int64 `json:"interval,omitempty" doc:"healthcheck definition: time in seconds to wait for each check. Default: 10, minimum: 5"` + HealthcheckMode string `json:"mode,omitempty" doc:"healthcheck definition: healthcheck mode can be either 'tcp' or 'http'"` + HealthcheckPath string `json:"path,omitempty" doc:"healthcheck definition: the path against which the 'http' healthcheck will be performed. Required if mode is 'http', ignored otherwise."` + HealthcheckPort int64 `json:"port,omitempty" doc:"healthcheck definition: the port against which the healthcheck will be performed. Required if a 'mode' is provided."` + HealthcheckStrikesFail int64 `json:"strikes-fail,omitempty" doc:"healthcheck definition: number of times to retry before declaring the healthcheck 'dead'. Default: 3"` + HealthcheckStrikesOk int64 `json:"strikes-ok,omitempty" doc:"healthcheck definition: number of times to retry before declaring the healthcheck 'alive'. Default: 2"` + HealthcheckTimeout int64 `json:"timeout,omitempty" doc:"healthcheck definition: time in seconds to wait for each check. Default: 2, cannot be greater than interval."` + ID *UUID `json:"id" doc:"the id of the public IP address to update"` + _ bool `name:"updateIpAddress" description:"Updates an IP address"` } -func (UpdateIPAddress) response() interface{} { +// Response returns the struct to unmarshal +func (UpdateIPAddress) Response() interface{} { return new(AsyncJobResult) } -func (UpdateIPAddress) asyncResponse() interface{} { +// AsyncResponse returns the struct to unmarshal the async job +func (UpdateIPAddress) AsyncResponse() interface{} { return new(IPAddress) } +//go:generate go run generate/main.go -interface=Listable ListPublicIPAddresses + // ListPublicIPAddresses represents a search for public IP addresses type ListPublicIPAddresses struct { - Account string `json:"account,omitempty" doc:"list resources by account. Must be used with the domainId parameter."` AllocatedOnly *bool `json:"allocatedonly,omitempty" doc:"limits search results to allocated public IP addresses"` - AssociatedNetworkID string `json:"associatednetworkid,omitempty" doc:"lists all public IP addresses associated to the network specified"` - DomainID string `json:"domainid,omitempty" doc:"list only resources belonging to the domain specified"` - ForDisplay *bool `json:"fordisplay,omitempty" doc:"list resources by display flag; only ROOT admin is eligible to pass this parameter"` + AssociatedNetworkID *UUID `json:"associatednetworkid,omitempty" doc:"lists all public IP addresses associated to the network specified"` ForLoadBalancing *bool `json:"forloadbalancing,omitempty" doc:"list only ips used for load balancing"` ForVirtualNetwork *bool `json:"forvirtualnetwork,omitempty" doc:"the virtual network for the IP address"` - ID string `json:"id,omitempty" doc:"lists ip address by id"` + ID *UUID `json:"id,omitempty" doc:"lists ip address by id"` IPAddress net.IP `json:"ipaddress,omitempty" doc:"lists the specified IP address"` IsElastic *bool `json:"iselastic,omitempty" doc:"list only elastic ip addresses"` - IsRecursive *bool `json:"isrecursive,omitempty" doc:"defaults to false, but if true, lists all resources from the parent specified by the domainId till leaves."` IsSourceNat *bool `json:"issourcenat,omitempty" doc:"list only source nat ip addresses"` IsStaticNat *bool `json:"isstaticnat,omitempty" doc:"list only static nat ip addresses"` Keyword string `json:"keyword,omitempty" doc:"List by keyword"` - ListAll *bool `json:"listall,omitempty" doc:"If set to false, list only resources belonging to the command's caller; if set to true - list resources that the caller is authorized to see. Default value is false"` Page int `json:"page,omitempty"` PageSize int `json:"pagesize,omitempty"` - PhysicalNetworkID string `json:"physicalnetworkid,omitempty" doc:"lists all public IP addresses by physical network id"` + PhysicalNetworkID *UUID `json:"physicalnetworkid,omitempty" doc:"lists all public IP addresses by physical network id"` Tags []ResourceTag `json:"tags,omitempty" doc:"List resources by tags (key/value pairs)"` - VlanID string `json:"vlanid,omitempty" doc:"lists all public IP addresses by VLAN ID"` - ZoneID string `json:"zoneid,omitempty" doc:"lists all public IP addresses by Zone ID"` + VlanID *UUID `json:"vlanid,omitempty" doc:"lists all public IP addresses by VLAN ID"` + ZoneID *UUID `json:"zoneid,omitempty" doc:"lists all public IP addresses by Zone ID"` _ bool `name:"listPublicIpAddresses" description:"Lists all public ip addresses"` } @@ -165,31 +180,3 @@ type ListPublicIPAddressesResponse struct { Count int `json:"count"` PublicIPAddress []IPAddress `json:"publicipaddress"` } - -func (ListPublicIPAddresses) response() interface{} { - return new(ListPublicIPAddressesResponse) -} - -// SetPage sets the current page -func (ls *ListPublicIPAddresses) SetPage(page int) { - ls.Page = page -} - -// SetPageSize sets the page size -func (ls *ListPublicIPAddresses) SetPageSize(pageSize int) { - ls.PageSize = pageSize -} - -func (ListPublicIPAddresses) each(resp interface{}, callback IterateItemFunc) { - ips, ok := resp.(*ListPublicIPAddressesResponse) - if !ok { - callback(nil, fmt.Errorf("wrong type. ListPublicIPAddressesResponse expected, got %T", resp)) - return - } - - for i := range ips.PublicIPAddress { - if !callback(&ips.PublicIPAddress[i], nil) { - break - } - } -} diff --git a/vendor/github.com/exoscale/egoscale/affinity_groups.go b/vendor/github.com/exoscale/egoscale/affinity_groups.go index 00e5981b6..ae909f6bf 100644 --- a/vendor/github.com/exoscale/egoscale/affinity_groups.go +++ b/vendor/github.com/exoscale/egoscale/affinity_groups.go @@ -6,22 +6,20 @@ import ( "net/url" ) -// AffinityGroup represents an (anti-)affinity group +// AffinityGroup represents an Affinity Group. // -// Affinity and Anti-Affinity groups provide a way to influence where VMs should run. +// Affinity and Anti-Affinity Groups provide a way to influence where VMs should run. // See: http://docs.cloudstack.apache.org/projects/cloudstack-administration/en/stable/virtual_machines.html#affinity-groups type AffinityGroup struct { - Account string `json:"account,omitempty" doc:"the account owning the affinity group"` - Description string `json:"description,omitempty" doc:"the description of the affinity group"` - Domain string `json:"domain,omitempty" doc:"the domain name of the affinity group"` - DomainID string `json:"domainid,omitempty" doc:"the domain ID of the affinity group"` - ID string `json:"id,omitempty" doc:"the ID of the affinity group"` - Name string `json:"name,omitempty" doc:"the name of the affinity group"` - Type string `json:"type,omitempty" doc:"the type of the affinity group"` - VirtualMachineIDs []string `json:"virtualmachineIds,omitempty" doc:"virtual machine Ids associated with this affinity group "` + Account string `json:"account,omitempty" doc:"the account owning the Affinity Group"` + Description string `json:"description,omitempty" doc:"the description of the Affinity Group"` + ID *UUID `json:"id,omitempty" doc:"the ID of the Affinity Group"` + Name string `json:"name,omitempty" doc:"the name of the Affinity Group"` + Type string `json:"type,omitempty" doc:"the type of the Affinity Group"` + VirtualMachineIDs []UUID `json:"virtualmachineIds,omitempty" doc:"virtual machine IDs associated with this Affinity Group"` } -// ListRequest builds the ListAffinityGroups request +// ListRequest builds the ListAffinityGroups request. func (ag AffinityGroup) ListRequest() (ListCommand, error) { return &ListAffinityGroups{ ID: ag.ID, @@ -29,18 +27,15 @@ func (ag AffinityGroup) ListRequest() (ListCommand, error) { }, nil } -// Delete removes the given Affinity Group +// Delete deletes the given Affinity Group. func (ag AffinityGroup) Delete(ctx context.Context, client *Client) error { - if ag.ID == "" && ag.Name == "" { + if ag.ID == nil && ag.Name == "" { return fmt.Errorf("an Affinity Group may only be deleted using ID or Name") } - req := &DeleteAffinityGroup{ - Account: ag.Account, - DomainID: ag.DomainID, - } + req := &DeleteAffinityGroup{} - if ag.ID != "" { + if ag.ID != nil { req.ID = ag.ID } else { req.Name = ag.Name @@ -49,133 +44,114 @@ func (ag AffinityGroup) Delete(ctx context.Context, client *Client) error { return client.BooleanRequestWithContext(ctx, req) } -// AffinityGroupType represent an affinity group type +// AffinityGroupType represent an Affinity Group type. type AffinityGroupType struct { - Type string `json:"type,omitempty" doc:"the type of the affinity group"` + Type string `json:"type,omitempty" doc:"the type of the Affinity Group"` } -// CreateAffinityGroup (Async) represents a new (anti-)affinity group +// CreateAffinityGroup (Async) represents a new Affinity Group. type CreateAffinityGroup struct { - Account string `json:"account,omitempty" doc:"an account for the affinity group. Must be used with domainId."` - Description string `json:"description,omitempty" doc:"optional description of the affinity group"` - DomainID string `json:"domainid,omitempty" doc:"domainId of the account owning the affinity group"` - Name string `json:"name" doc:"name of the affinity group"` - Type string `json:"type" doc:"Type of the affinity group from the available affinity/anti-affinity group types"` - _ bool `name:"createAffinityGroup" description:"Creates an affinity/anti-affinity group"` + Description string `json:"description,omitempty" doc:"Optional description of the Affinity Group"` + Name string `json:"name" doc:"Name of the Affinity Group"` + Type string `json:"type" doc:"Type of the Affinity Group from the available Affinity Group Group types"` + _ bool `name:"createAffinityGroup" description:"Creates an Affinity Group Group"` } -func (CreateAffinityGroup) response() interface{} { +func (req CreateAffinityGroup) onBeforeSend(params url.Values) error { + // Name must be set, but can be empty. + if req.Name == "" { + params.Set("name", "") + } + return nil +} + +// Response returns the struct to unmarshal. +func (CreateAffinityGroup) Response() interface{} { return new(AsyncJobResult) } -func (CreateAffinityGroup) asyncResponse() interface{} { +// AsyncResponse returns the struct to unmarshal the async job. +func (CreateAffinityGroup) AsyncResponse() interface{} { return new(AffinityGroup) } -// UpdateVMAffinityGroup (Async) represents a modification of a (anti-)affinity group +// UpdateVMAffinityGroup (Async) represents a modification of an Affinity Group. type UpdateVMAffinityGroup struct { - ID string `json:"id" doc:"The ID of the virtual machine"` - AffinityGroupIDs []string `json:"affinitygroupids,omitempty" doc:"comma separated list of affinity groups id that are going to be applied to the virtual machine. Should be passed only when vm is created from a zone with Basic Network support. Mutually exclusive with securitygroupnames parameter"` - AffinityGroupNames []string `json:"affinitygroupnames,omitempty" doc:"comma separated list of affinity groups names that are going to be applied to the virtual machine. Should be passed only when vm is created from a zone with Basic Network support. Mutually exclusive with securitygroupids parameter"` - _ bool `name:"updateVMAffinityGroup" description:"Updates the affinity/anti-affinity group associations of a virtual machine. The VM has to be stopped and restarted for the new properties to take effect."` + ID *UUID `json:"id" doc:"The ID of the virtual machine"` + AffinityGroupIDs []UUID `json:"affinitygroupids,omitempty" doc:"comma separated list of Affinity Groups id that are going to be applied to the virtual machine. Should be passed only when vm is created from a zone with Basic Network support. Mutually exclusive with securitygroupnames parameter"` + AffinityGroupNames []string `json:"affinitygroupnames,omitempty" doc:"comma separated list of Affinity Groups names that are going to be applied to the virtual machine. Should be passed only when vm is created from a zone with Basic Network support. Mutually exclusive with securitygroupids parameter"` + _ bool `name:"updateVMAffinityGroup" description:"Updates the Affinity Group Group associations of a virtual machine. The VM has to be stopped and restarted for the new properties to take effect."` } func (req UpdateVMAffinityGroup) onBeforeSend(params url.Values) error { - // Either AffinityGroupIDs or AffinityGroupNames must be set + // Either AffinityGroupIDs or AffinityGroupNames must be set. if len(req.AffinityGroupIDs) == 0 && len(req.AffinityGroupNames) == 0 { params.Set("affinitygroupids", "") } return nil } -func (UpdateVMAffinityGroup) response() interface{} { +// Response returns the struct to unmarshal. +func (UpdateVMAffinityGroup) Response() interface{} { return new(AsyncJobResult) } -func (UpdateVMAffinityGroup) asyncResponse() interface{} { +// AsyncResponse returns the struct to unmarshal the async job. +func (UpdateVMAffinityGroup) AsyncResponse() interface{} { return new(VirtualMachine) } -// DeleteAffinityGroup (Async) represents an (anti-)affinity group to be deleted +// DeleteAffinityGroup (Async) represents an Affinity Group to be deleted. type DeleteAffinityGroup struct { - Account string `json:"account,omitempty" doc:"the account of the affinity group. Must be specified with domain ID"` - DomainID string `json:"domainid,omitempty" doc:"the domain ID of account owning the affinity group"` - ID string `json:"id,omitempty" doc:"The ID of the affinity group. Mutually exclusive with name parameter"` - Name string `json:"name,omitempty" doc:"The name of the affinity group. Mutually exclusive with ID parameter"` - _ bool `name:"deleteAffinityGroup" description:"Deletes affinity group"` + ID *UUID `json:"id,omitempty" doc:"The ID of the Affinity Group. Mutually exclusive with name parameter"` + Name string `json:"name,omitempty" doc:"The name of the Affinity Group. Mutually exclusive with ID parameter"` + _ bool `name:"deleteAffinityGroup" description:"Deletes Affinity Group"` } -func (DeleteAffinityGroup) response() interface{} { +// Response returns the struct to unmarshal. +func (DeleteAffinityGroup) Response() interface{} { return new(AsyncJobResult) } -func (DeleteAffinityGroup) asyncResponse() interface{} { - return new(booleanResponse) +// AsyncResponse returns the struct to unmarshal the async job. +func (DeleteAffinityGroup) AsyncResponse() interface{} { + return new(BooleanResponse) } -// ListAffinityGroups represents an (anti-)affinity groups search +//go:generate go run generate/main.go -interface=Listable ListAffinityGroups + +// ListAffinityGroups represents an Affinity Groups search. type ListAffinityGroups struct { - Account string `json:"account,omitempty" doc:"list resources by account. Must be used with the domainId parameter."` - DomainID string `json:"domainid,omitempty" doc:"list only resources belonging to the domain specified"` - ID string `json:"id,omitempty" doc:"list the affinity group by the ID provided"` - IsRecursive *bool `json:"isrecursive,omitempty" doc:"defaults to false, but if true, lists all resources from the parent specified by the domainId till leaves."` + ID *UUID `json:"id,omitempty" doc:"List the Affinity Group by the ID provided"` Keyword string `json:"keyword,omitempty" doc:"List by keyword"` - ListAll *bool `json:"listall,omitempty" doc:"If set to false, list only resources belonging to the command's caller; if set to true - list resources that the caller is authorized to see. Default value is false"` - Name string `json:"name,omitempty" doc:"lists affinity groups by name"` + Name string `json:"name,omitempty" doc:"Lists Affinity Groups by name"` Page int `json:"page,omitempty"` PageSize int `json:"pagesize,omitempty"` - Type string `json:"type,omitempty" doc:"lists affinity groups by type"` - VirtualMachineID string `json:"virtualmachineid,omitempty" doc:"lists affinity groups by virtual machine ID"` - _ bool `name:"listAffinityGroups" description:"Lists affinity groups"` + Type string `json:"type,omitempty" doc:"Lists Affinity Groups by type"` + VirtualMachineID *UUID `json:"virtualmachineid,omitempty" doc:"Lists Affinity Groups by virtual machine ID"` + _ bool `name:"listAffinityGroups" description:"Lists Affinity Groups"` } -func (ListAffinityGroups) response() interface{} { - return new(ListAffinityGroupsResponse) -} - -// SetPage sets the current page -func (ls *ListAffinityGroups) SetPage(page int) { - ls.Page = page -} - -// SetPageSize sets the page size -func (ls *ListAffinityGroups) SetPageSize(pageSize int) { - ls.PageSize = pageSize -} - -func (ListAffinityGroups) each(resp interface{}, callback IterateItemFunc) { - vms, ok := resp.(*ListAffinityGroupsResponse) - if !ok { - callback(nil, fmt.Errorf("wrong type. ListAffinityGroupsResponse expected, got %T", resp)) - return - } - - for i := range vms.AffinityGroup { - if !callback(&vms.AffinityGroup[i], nil) { - break - } - } -} - -// ListAffinityGroupsResponse represents a list of (anti-)affinity groups +// ListAffinityGroupsResponse represents a list of Affinity Groups. type ListAffinityGroupsResponse struct { Count int `json:"count"` AffinityGroup []AffinityGroup `json:"affinitygroup"` } -// ListAffinityGroupTypes represents an (anti-)affinity groups search +// ListAffinityGroupTypes represents an Affinity Groups types search. type ListAffinityGroupTypes struct { Keyword string `json:"keyword,omitempty" doc:"List by keyword"` Page int `json:"page,omitempty"` PageSize int `json:"pagesize,omitempty"` - _ bool `name:"listAffinityGroupTypes" description:"Lists affinity group types available"` + _ bool `name:"listAffinityGroupTypes" description:"Lists Affinity Group types available"` } -func (ListAffinityGroupTypes) response() interface{} { +// Response returns the struct to unmarshal. +func (ListAffinityGroupTypes) Response() interface{} { return new(ListAffinityGroupTypesResponse) } -// ListAffinityGroupTypesResponse represents a list of (anti-)affinity group types +// ListAffinityGroupTypesResponse represents a list of Affinity Group types. type ListAffinityGroupTypesResponse struct { Count int `json:"count"` AffinityGroupType []AffinityGroupType `json:"affinitygrouptype"` diff --git a/vendor/github.com/exoscale/egoscale/affinitygroups_response.go b/vendor/github.com/exoscale/egoscale/affinitygroups_response.go new file mode 100644 index 000000000..606598887 --- /dev/null +++ b/vendor/github.com/exoscale/egoscale/affinitygroups_response.go @@ -0,0 +1,43 @@ +// code generated; DO NOT EDIT. + +package egoscale + +import "fmt" + +// Response returns the struct to unmarshal. +func (ListAffinityGroups) Response() interface{} { + return new(ListAffinityGroupsResponse) +} + +// ListRequest returns itself. +func (ls *ListAffinityGroups) ListRequest() (ListCommand, error) { + if ls == nil { + return nil, fmt.Errorf("%T cannot be nil", ls) + } + return ls, nil +} + +// SetPage sets the current page. +func (ls *ListAffinityGroups) SetPage(page int) { + ls.Page = page +} + +// SetPageSize sets the page size. +func (ls *ListAffinityGroups) SetPageSize(pageSize int) { + ls.PageSize = pageSize +} + +// Each triggers the callback for each, valid answer or any non 404 issue. +func (ListAffinityGroups) Each(resp interface{}, callback IterateItemFunc) { + items, ok := resp.(*ListAffinityGroupsResponse) + if !ok { + callback(nil, fmt.Errorf("wrong type, ListAffinityGroupsResponse was expected, got %T", resp)) + return + } + + for i := range items.AffinityGroup { + if !callback(&items.AffinityGroup[i], nil) { + break + } + } +} diff --git a/vendor/github.com/exoscale/egoscale/antiaffinity_groups.go b/vendor/github.com/exoscale/egoscale/antiaffinity_groups.go new file mode 100644 index 000000000..bc3d6928c --- /dev/null +++ b/vendor/github.com/exoscale/egoscale/antiaffinity_groups.go @@ -0,0 +1,103 @@ +package egoscale + +import ( + "context" + "fmt" + "net/url" +) + +// AntiAffinityGroup represents an Anti-Affinity Group. +type AntiAffinityGroup struct { + Account string `json:"account,omitempty" doc:"the account owning the Anti-Affinity Group"` + Description string `json:"description,omitempty" doc:"the description of the Anti-Affinity Group"` + ID *UUID `json:"id,omitempty" doc:"the ID of the Anti-Affinity Group"` + Name string `json:"name,omitempty" doc:"the name of the Anti-Affinity Group"` + Type string `json:"type,omitempty" doc:"the type of the Anti-Affinity Group"` + VirtualMachineIDs []UUID `json:"virtualmachineIds,omitempty" doc:"virtual machine IDs associated with this Anti-Affinity Group"` +} + +// ListRequest builds the ListAntiAffinityGroups request. +func (ag AntiAffinityGroup) ListRequest() (ListCommand, error) { + return &ListAffinityGroups{ + ID: ag.ID, + Name: ag.Name, + }, nil +} + +// Delete deletes the given Anti-Affinity Group. +func (ag AntiAffinityGroup) Delete(ctx context.Context, client *Client) error { + if ag.ID == nil && ag.Name == "" { + return fmt.Errorf("an Anti-Affinity Group may only be deleted using ID or Name") + } + + req := &DeleteAffinityGroup{} + + if ag.ID != nil { + req.ID = ag.ID + } else { + req.Name = ag.Name + } + + return client.BooleanRequestWithContext(ctx, req) +} + +// CreateAntiAffinityGroup represents an Anti-Affinity Group creation. +type CreateAntiAffinityGroup struct { + Name string `json:"name" doc:"Name of the Anti-Affinity Group"` + Description string `json:"description,omitempty" doc:"Optional description of the Anti-Affinity Group"` + _ bool `name:"createAntiAffinityGroup" description:"Creates an Anti-Affinity Group"` +} + +func (req CreateAntiAffinityGroup) onBeforeSend(params url.Values) error { + // Name must be set, but can be empty. + if req.Name == "" { + params.Set("name", "") + } + return nil +} + +// Response returns the struct to unmarshal. +func (CreateAntiAffinityGroup) Response() interface{} { + return new(AsyncJobResult) +} + +// AsyncResponse returns the struct to unmarshal the async job. +func (CreateAntiAffinityGroup) AsyncResponse() interface{} { + return new(AffinityGroup) +} + +//go:generate go run generate/main.go -interface=Listable ListAntiAffinityGroups + +// ListAntiAffinityGroups represents an Anti-Affinity Groups search. +type ListAntiAffinityGroups struct { + ID *UUID `json:"id,omitempty" doc:"List the Anti-Affinity Group by the ID provided"` + Keyword string `json:"keyword,omitempty" doc:"List by keyword"` + Name string `json:"name,omitempty" doc:"Lists Anti-Affinity Groups by name"` + Page int `json:"page,omitempty"` + PageSize int `json:"pagesize,omitempty"` + VirtualMachineID *UUID `json:"virtualmachineid,omitempty" doc:"Lists Anti-Affinity Groups by virtual machine ID"` + _ bool `name:"listAntiAffinityGroups" description:"Lists Anti-Affinity Groups"` +} + +// ListAntiAffinityGroupsResponse represents a list of Anti-Affinity Groups. +type ListAntiAffinityGroupsResponse struct { + Count int `json:"count"` + AntiAffinityGroup []AffinityGroup `json:"antiaffinitygroup"` +} + +// DeleteAntiAffinityGroup (Async) represents an Anti-Affinity Group to be deleted. +type DeleteAntiAffinityGroup struct { + ID *UUID `json:"id,omitempty" doc:"The ID of the Anti-Affinity Group. Mutually exclusive with name parameter"` + Name string `json:"name,omitempty" doc:"The name of the Anti-Affinity Group. Mutually exclusive with ID parameter"` + _ bool `name:"deleteAntiAffinityGroup" description:"Deletes Anti-Affinity Group"` +} + +// Response returns the struct to unmarshal. +func (DeleteAntiAffinityGroup) Response() interface{} { + return new(AsyncJobResult) +} + +// AsyncResponse returns the struct to unmarshal the async job. +func (DeleteAntiAffinityGroup) AsyncResponse() interface{} { + return new(BooleanResponse) +} diff --git a/vendor/github.com/exoscale/egoscale/antiaffinity_groups_response.go b/vendor/github.com/exoscale/egoscale/antiaffinity_groups_response.go new file mode 100644 index 000000000..153516be2 --- /dev/null +++ b/vendor/github.com/exoscale/egoscale/antiaffinity_groups_response.go @@ -0,0 +1,43 @@ +// code generated; DO NOT EDIT. + +package egoscale + +import "fmt" + +// Response returns the struct to unmarshal. +func (ListAntiAffinityGroups) Response() interface{} { + return new(ListAntiAffinityGroupsResponse) +} + +// ListRequest returns itself. +func (ls *ListAntiAffinityGroups) ListRequest() (ListCommand, error) { + if ls == nil { + return nil, fmt.Errorf("%T cannot be nil", ls) + } + return ls, nil +} + +// SetPage sets the current page. +func (ls *ListAntiAffinityGroups) SetPage(page int) { + ls.Page = page +} + +// SetPageSize sets the page size. +func (ls *ListAntiAffinityGroups) SetPageSize(pageSize int) { + ls.PageSize = pageSize +} + +// Each triggers the callback for each, valid answer or any non 404 issue. +func (ListAntiAffinityGroups) Each(resp interface{}, callback IterateItemFunc) { + items, ok := resp.(*ListAntiAffinityGroupsResponse) + if !ok { + callback(nil, fmt.Errorf("wrong type, ListAntiAffinityGroupsResponse was expected, got %T", resp)) + return + } + + for i := range items.AntiAffinityGroup { + if !callback(&items.AntiAffinityGroup[i], nil) { + break + } + } +} diff --git a/vendor/github.com/exoscale/egoscale/apis.go b/vendor/github.com/exoscale/egoscale/apis.go index f2a540bf6..098a03761 100644 --- a/vendor/github.com/exoscale/egoscale/apis.go +++ b/vendor/github.com/exoscale/egoscale/apis.go @@ -3,13 +3,13 @@ package egoscale // API represents an API service type API struct { Description string `json:"description,omitempty" doc:"description of the api"` - IsAsync bool `json:"isasync,omitempty" doc:"true if api is asynchronous"` + IsAsync bool `json:"isasync" doc:"true if api is asynchronous"` Name string `json:"name,omitempty" doc:"the name of the api command"` Related string `json:"related,omitempty" doc:"comma separated related apis"` Since string `json:"since,omitempty" doc:"version of CloudStack the api was introduced in"` Type string `json:"type,omitempty" doc:"response field type"` Params []APIParam `json:"params,omitempty" doc:"the list params the api accepts"` - Response []APIParam `json:"response,omitempty" doc:"api response fields"` + Response []APIField `json:"response,omitempty" doc:"api response fields"` } // APIParam represents an API parameter field @@ -18,14 +18,22 @@ type APIParam struct { Length int64 `json:"length"` Name string `json:"name"` Required bool `json:"required"` - Since string `json:"since"` + Since string `json:"since,omitempty"` Type string `json:"type"` } +// APIField represents an API response field +type APIField struct { + Description string `json:"description"` + Name string `json:"name"` + Response []APIField `json:"response,omitempty"` + Type string `json:"type"` +} + // ListAPIs represents a query to list the api type ListAPIs struct { Name string `json:"name,omitempty" doc:"API name"` - _ bool `name:"listApis" description:"lists all available apis on the server, provided by the Api Discovery plugin"` + _ bool `name:"listApis" description:"lists all available apis on the server"` } // ListAPIsResponse represents a list of API @@ -34,6 +42,7 @@ type ListAPIsResponse struct { API []API `json:"api"` } -func (*ListAPIs) response() interface{} { +// Response returns the struct to unmarshal +func (*ListAPIs) Response() interface{} { return new(ListAPIsResponse) } diff --git a/vendor/github.com/exoscale/egoscale/async_jobs.go b/vendor/github.com/exoscale/egoscale/async_jobs.go index 5c35debf9..ab4b52cff 100644 --- a/vendor/github.com/exoscale/egoscale/async_jobs.go +++ b/vendor/github.com/exoscale/egoscale/async_jobs.go @@ -7,20 +7,72 @@ import ( // AsyncJobResult represents an asynchronous job result type AsyncJobResult struct { - AccountID string `json:"accountid"` - Cmd string `json:"cmd"` - Created string `json:"created"` - JobInstanceID string `json:"jobinstanceid,omitempty"` - JobInstanceType string `json:"jobinstancetype,omitempty"` - JobProcStatus int `json:"jobprocstatus"` - JobResult *json.RawMessage `json:"jobresult"` - JobResultCode int `json:"jobresultcode"` - JobResultType string `json:"jobresulttype"` - JobStatus JobStatusType `json:"jobstatus"` - UserID string `json:"userid"` - JobID string `json:"jobid"` + AccountID *UUID `json:"accountid,omitempty" doc:"the account that executed the async command"` + Cmd string `json:"cmd,omitempty" doc:"the async command executed"` + Created string `json:"created,omitempty" doc:"the created date of the job"` + JobID *UUID `json:"jobid" doc:"extra field for the initial async call"` + JobInstanceID *UUID `json:"jobinstanceid,omitempty" doc:"the unique ID of the instance/entity object related to the job"` + JobInstanceType string `json:"jobinstancetype,omitempty" doc:"the instance/entity object related to the job"` + JobProcStatus int `json:"jobprocstatus,omitempty" doc:"the progress information of the PENDING job"` + JobResult *json.RawMessage `json:"jobresult,omitempty" doc:"the result reason"` + JobResultCode int `json:"jobresultcode,omitempty" doc:"the result code for the job"` + JobResultType string `json:"jobresulttype,omitempty" doc:"the result type"` + JobStatus JobStatusType `json:"jobstatus,omitempty" doc:"the current job status-should be 0 for PENDING"` + UserID *UUID `json:"userid,omitempty" doc:"the user that executed the async command"` } +// DeepCopy create a true copy of the receiver. +func (a *AsyncJobResult) DeepCopy() *AsyncJobResult { + if a == nil { + return nil + } + + return &AsyncJobResult{ + AccountID: a.AccountID.DeepCopy(), + Cmd: a.Cmd, + Created: a.Created, + JobID: a.JobID.DeepCopy(), + JobInstanceID: a.JobInstanceID.DeepCopy(), + JobInstanceType: a.JobInstanceType, + JobProcStatus: a.JobProcStatus, + JobResult: a.JobResult, + JobResultCode: a.JobResultCode, + JobResultType: a.JobResultType, + JobStatus: a.JobStatus, + UserID: a.UserID.DeepCopy(), + } +} + +// DeepCopyInto copies the receiver into out. +// +// In (a) must be non nil. out must be non nil +func (a *AsyncJobResult) DeepCopyInto(out *AsyncJobResult) { + *out = AsyncJobResult{ + AccountID: a.AccountID.DeepCopy(), + Cmd: a.Cmd, + Created: a.Created, + JobID: a.JobID.DeepCopy(), + JobInstanceID: a.JobInstanceID.DeepCopy(), + JobInstanceType: a.JobInstanceType, + JobProcStatus: a.JobProcStatus, + JobResult: a.JobResult, + JobResultCode: a.JobResultCode, + JobResultType: a.JobResultType, + JobStatus: a.JobStatus, + UserID: a.UserID.DeepCopy(), + } +} + +// ListRequest buils the (empty) ListAsyncJobs request +func (a AsyncJobResult) ListRequest() (ListCommand, error) { + req := &ListAsyncJobs{ + StartDate: a.Created, + } + + return req, nil +} + +// Error builds an error message from the result func (a AsyncJobResult) Error() error { r := new(ErrorResponse) if e := json.Unmarshal(*a.JobResult, r); e != nil { @@ -31,35 +83,30 @@ func (a AsyncJobResult) Error() error { // QueryAsyncJobResult represents a query to fetch the status of async job type QueryAsyncJobResult struct { - JobID string `json:"jobid" doc:"the ID of the asychronous job"` - _ bool `name:"queryAsyncJobResult" description:"Retrieves the current status of asynchronous job."` + JobID *UUID `json:"jobid" doc:"the ID of the asynchronous job"` + _ bool `name:"queryAsyncJobResult" description:"Retrieves the current status of asynchronous job."` } -func (QueryAsyncJobResult) response() interface{} { +// Response returns the struct to unmarshal +func (QueryAsyncJobResult) Response() interface{} { return new(AsyncJobResult) } +//go:generate go run generate/main.go -interface=Listable ListAsyncJobs + // ListAsyncJobs list the asynchronous jobs type ListAsyncJobs struct { - Account string `json:"account,omitempty" doc:"list resources by account. Must be used with the domainId parameter."` - DomainID string `json:"domainid,omitempty" doc:"list only resources belonging to the domain specified"` - IsRecursive *bool `json:"isrecursive,omitempty" doc:"defaults to false, but if true, lists all resources from the parent specified by the domainId till leaves."` - Keyword string `json:"keyword,omitempty" doc:"List by keyword"` - ListAll *bool `json:"listall,omitempty" doc:"If set to false, list only resources belonging to the command's caller; if set to true - list resources that the caller is authorized to see. Default value is false"` - Page int `json:"page,omitempty"` - PageSize int `json:"pagesize,omitempty"` - StartDate string `json:"startdate,omitempty" doc:"the start date of the async job"` - _ bool `name:"listAsyncJobs" description:"Lists all pending asynchronous jobs for the account."` + Keyword string `json:"keyword,omitempty" doc:"List by keyword"` + Page int `json:"page,omitempty"` + PageSize int `json:"pagesize,omitempty"` + StartDate string `json:"startdate,omitempty" doc:"the start date of the async job"` + _ bool `name:"listAsyncJobs" description:"Lists all pending asynchronous jobs for the account."` } // ListAsyncJobsResponse represents a list of job results type ListAsyncJobsResponse struct { - Count int `json:"count"` - AsyncJobs []AsyncJobResult `json:"asyncjobs"` -} - -func (ListAsyncJobs) response() interface{} { - return new(ListAsyncJobsResponse) + Count int `json:"count"` + AsyncJob []AsyncJobResult `json:"asyncjobs"` } // Result unmarshals the result of an AsyncJobResult into the given interface @@ -78,10 +125,6 @@ func (a AsyncJobResult) Result(i interface{}) error { return json.Unmarshal(*(a.JobResult), i) } - // more than one keys are list...response - if len(m) > 1 { - return json.Unmarshal(*(a.JobResult), i) - } // otherwise, pick the first key for k := range m { return json.Unmarshal(m[k], i) diff --git a/vendor/github.com/exoscale/egoscale/asyncjobs_response.go b/vendor/github.com/exoscale/egoscale/asyncjobs_response.go new file mode 100644 index 000000000..e4744e8bd --- /dev/null +++ b/vendor/github.com/exoscale/egoscale/asyncjobs_response.go @@ -0,0 +1,43 @@ +// code generated; DO NOT EDIT. + +package egoscale + +import "fmt" + +// Response returns the struct to unmarshal +func (ListAsyncJobs) Response() interface{} { + return new(ListAsyncJobsResponse) +} + +// ListRequest returns itself +func (ls *ListAsyncJobs) ListRequest() (ListCommand, error) { + if ls == nil { + return nil, fmt.Errorf("%T cannot be nil", ls) + } + return ls, nil +} + +// SetPage sets the current apge +func (ls *ListAsyncJobs) SetPage(page int) { + ls.Page = page +} + +// SetPageSize sets the page size +func (ls *ListAsyncJobs) SetPageSize(pageSize int) { + ls.PageSize = pageSize +} + +// Each triggers the callback for each, valid answer or any non 404 issue +func (ListAsyncJobs) Each(resp interface{}, callback IterateItemFunc) { + items, ok := resp.(*ListAsyncJobsResponse) + if !ok { + callback(nil, fmt.Errorf("wrong type, ListAsyncJobsResponse was expected, got %T", resp)) + return + } + + for i := range items.AsyncJob { + if !callback(&items.AsyncJob[i], nil) { + break + } + } +} diff --git a/vendor/github.com/exoscale/egoscale/cidr.go b/vendor/github.com/exoscale/egoscale/cidr.go index 743eaf916..74c054b71 100644 --- a/vendor/github.com/exoscale/egoscale/cidr.go +++ b/vendor/github.com/exoscale/egoscale/cidr.go @@ -1,6 +1,7 @@ package egoscale import ( + "bytes" "encoding/json" "fmt" "net" @@ -8,7 +9,7 @@ import ( // CIDR represents a nicely JSON serializable net.IPNet type CIDR struct { - *net.IPNet + net.IPNet } // UnmarshalJSON unmarshals the raw JSON into the MAC address @@ -21,13 +22,19 @@ func (cidr *CIDR) UnmarshalJSON(b []byte) error { if err != nil { return err } - cidr.IPNet = c.IPNet + *cidr = CIDR{c.IPNet} + return nil } // MarshalJSON converts the CIDR to a string representation func (cidr CIDR) MarshalJSON() ([]byte, error) { - return []byte(fmt.Sprintf("%q", cidr.IPNet)), nil + return []byte(fmt.Sprintf("%q", cidr)), nil +} + +// String returns the string representation of a CIDR +func (cidr CIDR) String() string { + return cidr.IPNet.String() } // ParseCIDR parses a CIDR from a string @@ -36,11 +43,11 @@ func ParseCIDR(s string) (*CIDR, error) { if err != nil { return nil, err } - return &CIDR{net}, nil + return &CIDR{*net}, nil } -// ForceParseCIDR forces parseCIDR or panics -func ForceParseCIDR(s string) *CIDR { +// MustParseCIDR forces parseCIDR or panics +func MustParseCIDR(s string) *CIDR { cidr, err := ParseCIDR(s) if err != nil { panic(err) @@ -48,3 +55,8 @@ func ForceParseCIDR(s string) *CIDR { return cidr } + +// Equal compare two CIDR +func (cidr CIDR) Equal(c CIDR) bool { + return (cidr.IPNet.IP.Equal(c.IPNet.IP) && bytes.Equal(cidr.IPNet.Mask, c.IPNet.Mask)) +} diff --git a/vendor/github.com/exoscale/egoscale/client.go b/vendor/github.com/exoscale/egoscale/client.go index ac0875d62..81c5f07b6 100644 --- a/vendor/github.com/exoscale/egoscale/client.go +++ b/vendor/github.com/exoscale/egoscale/client.go @@ -8,15 +8,24 @@ import ( "net/http" "net/http/httputil" "os" + "reflect" + "runtime" "strings" "time" ) -// Taggable represents a resource which can have tags attached +// UserAgent is the "User-Agent" HTTP request header added to outgoing HTTP requests. +var UserAgent = fmt.Sprintf("egoscale/%s (%s; %s/%s)", + Version, + runtime.Version(), + runtime.GOOS, + runtime.GOARCH) + +// Taggable represents a resource to which tags can be attached // // This is a helper to fill the resourcetype of a CreateTags call type Taggable interface { - // CloudStack resource type of the Taggable type + // ResourceType is the name of the Taggable type ResourceType() string } @@ -32,16 +41,11 @@ type Listable interface { ListRequest() (ListCommand, error) } -// Gettable represents an Interface that can be "Get" by the client -type Gettable interface { - Listable -} - -// Client represents the CloudStack API client +// Client represents the API client type Client struct { // HTTPClient holds the HTTP client HTTPClient *http.Client - // Endpoints is CloudStack API + // Endpoint is the HTTP URL Endpoint string // APIKey is the API identifier APIKey string @@ -51,13 +55,15 @@ type Client struct { PageSize int // Timeout represents the default timeout for the async requests Timeout time.Duration + // Expiration representation how long a signed payload may be used + Expiration time.Duration // RetryStrategy represents the waiting strategy for polling the async requests RetryStrategy RetryStrategyFunc // Logger contains any log, plug your own Logger *log.Logger } -// RetryStrategyFunc represents a how much time to wait between two calls to CloudStack +// RetryStrategyFunc represents a how much time to wait between two calls to the API type RetryStrategyFunc func(int64) time.Duration // IterateItemFunc represents the callback to iterate a list of results, if false stops @@ -66,11 +72,12 @@ type IterateItemFunc func(interface{}, error) bool // WaitAsyncJobResultFunc represents the callback to wait a results of an async request, if false stops type WaitAsyncJobResultFunc func(*AsyncJobResult, error) bool -// NewClient creates a CloudStack API client with default timeout (60) +// NewClient creates an API client with default timeout (60) // // Timeout is set to both the HTTP client and the client itself. func NewClient(endpoint, apiKey, apiSecret string) *Client { timeout := 60 * time.Second + expiration := 10 * time.Minute httpClient := &http.Client{ Transport: http.DefaultTransport, @@ -83,6 +90,7 @@ func NewClient(endpoint, apiKey, apiSecret string) *Client { apiSecret: apiSecret, PageSize: 50, Timeout: timeout, + Expiration: expiration, RetryStrategy: MonotonicRetryStrategyFunc(2), Logger: log.New(ioutil.Discard, "", 0), } @@ -96,44 +104,52 @@ func NewClient(endpoint, apiKey, apiSecret string) *Client { } // Get populates the given resource or fails -func (client *Client) Get(g Gettable) error { +func (client *Client) Get(ls Listable) (interface{}, error) { ctx, cancel := context.WithTimeout(context.Background(), client.Timeout) defer cancel() - return client.GetWithContext(ctx, g) + return client.GetWithContext(ctx, ls) } // GetWithContext populates the given resource or fails -func (client *Client) GetWithContext(ctx context.Context, g Gettable) error { - gs, err := client.ListWithContext(ctx, g) +func (client *Client) GetWithContext(ctx context.Context, ls Listable) (interface{}, error) { + gs, err := client.ListWithContext(ctx, ls) if err != nil { - return err + return nil, err } count := len(gs) if count != 1 { - req, err := g.ListRequest() + req, err := ls.ListRequest() if err != nil { - return err + return nil, err } - payload, err := client.Payload(req) + params, err := client.Payload(req) if err != nil { - return err + return nil, err } + // removing sensitive/useless informations + params.Del("expires") + params.Del("response") + params.Del("signature") + params.Del("signatureversion") + // formatting the query string nicely + payload := params.Encode() payload = strings.Replace(payload, "&", ", ", -1) if count == 0 { - return &ErrorResponse{ - ErrorCode: ParamError, - ErrorText: fmt.Sprintf("not found, query: %s", payload), + return nil, &ErrorResponse{ + CSErrorCode: ServerAPIException, + ErrorCode: ParamError, + ErrorText: fmt.Sprintf("not found, query: %s", payload), } } - return fmt.Errorf("more than one element found: %s", payload) + return nil, fmt.Errorf("more than one element found: %s", payload) } - return Copy(g, gs[0]) + return gs[0], nil } // Delete removes the given resource of fails @@ -158,18 +174,25 @@ func (client *Client) List(g Listable) ([]interface{}, error) { } // ListWithContext lists the given resources (and paginate till the end) -func (client *Client) ListWithContext(ctx context.Context, g Listable) ([]interface{}, error) { - s := make([]interface{}, 0) +func (client *Client) ListWithContext(ctx context.Context, g Listable) (s []interface{}, err error) { + s = make([]interface{}, 0) - if g == nil { - return s, fmt.Errorf("g Listable shouldn't be nil") + defer func() { + if e := recover(); e != nil { + if g == nil || reflect.ValueOf(g).IsNil() { + err = fmt.Errorf("g Listable shouldn't be nil, got %#v", g) + return + } + + panic(e) + } + }() + + req, e := g.ListRequest() + if e != nil { + err = e + return } - - req, err := g.ListRequest() - if err != nil { - return s, err - } - client.PaginateWithContext(ctx, req, func(item interface{}, e error) bool { if item != nil { s = append(s, item) @@ -179,7 +202,7 @@ func (client *Client) ListWithContext(ctx context.Context, g Listable) ([]interf return false }) - return s, err + return } // AsyncListWithContext lists the given resources (and paginate till the end) @@ -225,7 +248,6 @@ func (client *Client) AsyncListWithContext(ctx context.Context, g Listable) (<-c errChan <- err return } - client.PaginateWithContext(ctx, req, func(item interface{}, e error) bool { if item != nil { outChan <- item @@ -240,15 +262,21 @@ func (client *Client) AsyncListWithContext(ctx context.Context, g Listable) (<-c } // Paginate runs the ListCommand and paginates -func (client *Client) Paginate(req ListCommand, callback IterateItemFunc) { +func (client *Client) Paginate(g Listable, callback IterateItemFunc) { ctx, cancel := context.WithTimeout(context.Background(), client.Timeout) defer cancel() - client.PaginateWithContext(ctx, req, callback) + client.PaginateWithContext(ctx, g, callback) } // PaginateWithContext runs the ListCommand as long as the ctx is valid -func (client *Client) PaginateWithContext(ctx context.Context, req ListCommand, callback IterateItemFunc) { +func (client *Client) PaginateWithContext(ctx context.Context, g Listable, callback IterateItemFunc) { + req, err := g.ListRequest() + if err != nil { + callback(nil, err) + return + } + pageSize := client.PageSize page := 1 @@ -258,13 +286,18 @@ func (client *Client) PaginateWithContext(ctx context.Context, req ListCommand, req.SetPageSize(pageSize) resp, err := client.RequestWithContext(ctx, req) if err != nil { + // in case of 431, the response is knowingly empty + if errResponse, ok := err.(*ErrorResponse); ok && page == 1 && errResponse.ErrorCode == ParamError { + break + } + callback(nil, err) break } size := 0 didErr := false - req.each(resp, func(element interface{}, err error) bool { + req.Each(resp, func(element interface{}, err error) bool { // If the context was cancelled, kill it in flight if e := ctx.Err(); e != nil { element = nil @@ -288,10 +321,12 @@ func (client *Client) PaginateWithContext(ctx context.Context, req ListCommand, } } -// APIName returns the CloudStack name of the given command +// APIName returns the name of the given command func (client *Client) APIName(command Command) string { // This is due to a limitation of Go<=1.7 - if _, ok := command.(*AuthorizeSecurityGroupEgress); ok { + _, ok := command.(*AuthorizeSecurityGroupEgress) + _, okPtr := command.(AuthorizeSecurityGroupEgress) + if ok || okPtr { return "authorizeSecurityGroupEgress" } @@ -302,22 +337,22 @@ func (client *Client) APIName(command Command) string { return info.Name } -// APIDescription returns the description of the given CloudStack command +// APIDescription returns the description of the given command func (client *Client) APIDescription(command Command) string { info, err := info(command) if err != nil { - panic(err) + return "*missing description*" } return info.Description } // Response returns the response structure of the given command func (client *Client) Response(command Command) interface{} { - switch command.(type) { + switch c := command.(type) { case AsyncCommand: - return (command.(AsyncCommand)).asyncResponse() + return c.AsyncResponse() default: - return command.response() + return command.Response() } } diff --git a/vendor/github.com/exoscale/egoscale/copier.go b/vendor/github.com/exoscale/egoscale/copier.go deleted file mode 100644 index adeb981e7..000000000 --- a/vendor/github.com/exoscale/egoscale/copier.go +++ /dev/null @@ -1,37 +0,0 @@ -package egoscale - -import ( - "fmt" - "reflect" -) - -// Copy copies the value from from into to. The type of "from" must be convertible into the type of "to". -func Copy(to, from interface{}) error { - tt := reflect.TypeOf(to) - tv := reflect.ValueOf(to) - - ft := reflect.TypeOf(from) - fv := reflect.ValueOf(from) - - if tt.Kind() != reflect.Ptr { - return fmt.Errorf("must copy to a pointer, got %q", tt.Name()) - } - - tt = tt.Elem() - tv = tv.Elem() - - for { - if ft.ConvertibleTo(tt) { - break - } - if ft.Kind() == reflect.Ptr { - ft = ft.Elem() - fv = fv.Elem() - } else { - return fmt.Errorf("cannot convert %q into %q", tt.Name(), ft.Name()) - } - } - - tv.Set(fv.Convert(tt)) - return nil -} diff --git a/vendor/github.com/exoscale/egoscale/cserrorcode_string.go b/vendor/github.com/exoscale/egoscale/cserrorcode_string.go index 4711d5425..7bfb42100 100644 --- a/vendor/github.com/exoscale/egoscale/cserrorcode_string.go +++ b/vendor/github.com/exoscale/egoscale/cserrorcode_string.go @@ -4,6 +4,42 @@ package egoscale import "strconv" +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[CloudRuntimeException-4250] + _ = x[ExecutionException-4260] + _ = x[HypervisorVersionChangedException-4265] + _ = x[CloudException-4275] + _ = x[AccountLimitException-4280] + _ = x[AgentUnavailableException-4285] + _ = x[CloudAuthenticationException-4290] + _ = x[ConcurrentOperationException-4300] + _ = x[ConflictingNetworkSettingsException-4305] + _ = x[DiscoveredWithErrorException-4310] + _ = x[HAStateException-4315] + _ = x[InsufficientAddressCapacityException-4320] + _ = x[InsufficientCapacityException-4325] + _ = x[InsufficientNetworkCapacityException-4330] + _ = x[InsufficientServerCapacityException-4335] + _ = x[InsufficientStorageCapacityException-4340] + _ = x[InternalErrorException-4345] + _ = x[InvalidParameterValueException-4350] + _ = x[ManagementServerException-4355] + _ = x[NetworkRuleConflictException-4360] + _ = x[PermissionDeniedException-4365] + _ = x[ResourceAllocationException-4370] + _ = x[ResourceInUseException-4375] + _ = x[ResourceUnavailableException-4380] + _ = x[StorageUnavailableException-4385] + _ = x[UnsupportedServiceException-4390] + _ = x[VirtualMachineMigrationException-4395] + _ = x[AsyncCommandQueued-4540] + _ = x[RequestLimitException-4545] + _ = x[ServerAPIException-9999] +} + const _CSErrorCode_name = "CloudRuntimeExceptionExecutionExceptionHypervisorVersionChangedExceptionCloudExceptionAccountLimitExceptionAgentUnavailableExceptionCloudAuthenticationExceptionConcurrentOperationExceptionConflictingNetworkSettingsExceptionDiscoveredWithErrorExceptionHAStateExceptionInsufficientAddressCapacityExceptionInsufficientCapacityExceptionInsufficientNetworkCapacityExceptionInsufficientServerCapacityExceptionInsufficientStorageCapacityExceptionInternalErrorExceptionInvalidParameterValueExceptionManagementServerExceptionNetworkRuleConflictExceptionPermissionDeniedExceptionResourceAllocationExceptionResourceInUseExceptionResourceUnavailableExceptionStorageUnavailableExceptionUnsupportedServiceExceptionVirtualMachineMigrationExceptionAsyncCommandQueuedRequestLimitExceptionServerAPIException" var _CSErrorCode_map = map[CSErrorCode]string{ diff --git a/vendor/github.com/exoscale/egoscale/dns.go b/vendor/github.com/exoscale/egoscale/dns.go index e613d47a6..3d3af4078 100644 --- a/vendor/github.com/exoscale/egoscale/dns.go +++ b/vendor/github.com/exoscale/egoscale/dns.go @@ -1,10 +1,12 @@ package egoscale import ( + "context" "encoding/json" "fmt" "io/ioutil" "net/http" + "net/url" "strconv" "strings" ) @@ -12,9 +14,6 @@ import ( // DNSDomain represents a domain type DNSDomain struct { ID int64 `json:"id"` - AccountID int64 `json:"account_id,omitempty"` - UserID int64 `json:"user_id,omitempty"` - RegistrantID int64 `json:"registrant_id,omitempty"` Name string `json:"name"` UnicodeName string `json:"unicode_name"` Token string `json:"token"` @@ -73,13 +72,8 @@ type UpdateDNSRecordResponse struct { // DNSErrorResponse represents an error in the API type DNSErrorResponse struct { - Message string `json:"message,omitempty"` - Errors *DNSError `json:"errors"` -} - -// DNSError represents an error -type DNSError struct { - Name []string `json:"name"` + Message string `json:"message,omitempty"` + Errors map[string][]string `json:"errors"` } // Record represent record type @@ -119,14 +113,20 @@ const ( // Error formats the DNSerror into a string func (req *DNSErrorResponse) Error() string { - if req.Errors != nil { - return fmt.Sprintf("dns error: %s (%s)", req.Message, strings.Join(req.Errors.Name, ", ")) + if len(req.Errors) > 0 { + errs := []string{} + for name, ss := range req.Errors { + if len(ss) > 0 { + errs = append(errs, fmt.Sprintf("%s: %s", name, strings.Join(ss, ", "))) + } + } + return fmt.Sprintf("dns error: %s (%s)", req.Message, strings.Join(errs, "; ")) } return fmt.Sprintf("dns error: %s", req.Message) } // CreateDomain creates a DNS domain -func (client *Client) CreateDomain(name string) (*DNSDomain, error) { +func (client *Client) CreateDomain(ctx context.Context, name string) (*DNSDomain, error) { m, err := json.Marshal(DNSDomainResponse{ Domain: &DNSDomain{ Name: name, @@ -136,7 +136,7 @@ func (client *Client) CreateDomain(name string) (*DNSDomain, error) { return nil, err } - resp, err := client.dnsRequest("/v1/domains", string(m), "POST") + resp, err := client.dnsRequest(ctx, "/v1/domains", nil, string(m), "POST") if err != nil { return nil, err } @@ -150,8 +150,8 @@ func (client *Client) CreateDomain(name string) (*DNSDomain, error) { } // GetDomain gets a DNS domain -func (client *Client) GetDomain(name string) (*DNSDomain, error) { - resp, err := client.dnsRequest("/v1/domains/"+name, "", "GET") +func (client *Client) GetDomain(ctx context.Context, name string) (*DNSDomain, error) { + resp, err := client.dnsRequest(ctx, "/v1/domains/"+name, nil, "", "GET") if err != nil { return nil, err } @@ -165,8 +165,8 @@ func (client *Client) GetDomain(name string) (*DNSDomain, error) { } // GetDomains gets DNS domains -func (client *Client) GetDomains() ([]DNSDomain, error) { - resp, err := client.dnsRequest("/v1/domains", "", "GET") +func (client *Client) GetDomains(ctx context.Context) ([]DNSDomain, error) { + resp, err := client.dnsRequest(ctx, "/v1/domains", nil, "", "GET") if err != nil { return nil, err } @@ -184,15 +184,15 @@ func (client *Client) GetDomains() ([]DNSDomain, error) { } // DeleteDomain delets a DNS domain -func (client *Client) DeleteDomain(name string) error { - _, err := client.dnsRequest("/v1/domains/"+name, "", "DELETE") +func (client *Client) DeleteDomain(ctx context.Context, name string) error { + _, err := client.dnsRequest(ctx, "/v1/domains/"+name, nil, "", "DELETE") return err } // GetRecord returns a DNS record -func (client *Client) GetRecord(domain string, recordID int64) (*DNSRecord, error) { +func (client *Client) GetRecord(ctx context.Context, domain string, recordID int64) (*DNSRecord, error) { id := strconv.FormatInt(recordID, 10) - resp, err := client.dnsRequest("/v1/domains/"+domain+"/records/"+id, "", "GET") + resp, err := client.dnsRequest(ctx, "/v1/domains/"+domain+"/records/"+id, nil, "", "GET") if err != nil { return nil, err } @@ -206,8 +206,37 @@ func (client *Client) GetRecord(domain string, recordID int64) (*DNSRecord, erro } // GetRecords returns the DNS records -func (client *Client) GetRecords(name string) ([]DNSRecord, error) { - resp, err := client.dnsRequest("/v1/domains/"+name+"/records", "", "GET") +func (client *Client) GetRecords(ctx context.Context, domain string) ([]DNSRecord, error) { + resp, err := client.dnsRequest(ctx, "/v1/domains/"+domain+"/records", nil, "", "GET") + if err != nil { + return nil, err + } + + var r []DNSRecordResponse + if err = json.Unmarshal(resp, &r); err != nil { + return nil, err + } + + records := make([]DNSRecord, 0, len(r)) + for _, rec := range r { + records = append(records, rec.Record) + } + + return records, nil +} + +// GetRecordsWithFilters returns the DNS records (filters can be empty) +func (client *Client) GetRecordsWithFilters(ctx context.Context, domain, name, recordType string) ([]DNSRecord, error) { + + filters := url.Values{} + if name != "" { + filters.Add("name", name) + } + if recordType != "" { + filters.Add("record_type", recordType) + } + + resp, err := client.dnsRequest(ctx, "/v1/domains/"+domain+"/records", filters, "", "GET") if err != nil { return nil, err } @@ -226,7 +255,7 @@ func (client *Client) GetRecords(name string) ([]DNSRecord, error) { } // CreateRecord creates a DNS record -func (client *Client) CreateRecord(name string, rec DNSRecord) (*DNSRecord, error) { +func (client *Client) CreateRecord(ctx context.Context, name string, rec DNSRecord) (*DNSRecord, error) { body, err := json.Marshal(DNSRecordResponse{ Record: rec, }) @@ -234,7 +263,7 @@ func (client *Client) CreateRecord(name string, rec DNSRecord) (*DNSRecord, erro return nil, err } - resp, err := client.dnsRequest("/v1/domains/"+name+"/records", string(body), "POST") + resp, err := client.dnsRequest(ctx, "/v1/domains/"+name+"/records", nil, string(body), "POST") if err != nil { return nil, err } @@ -248,7 +277,7 @@ func (client *Client) CreateRecord(name string, rec DNSRecord) (*DNSRecord, erro } // UpdateRecord updates a DNS record -func (client *Client) UpdateRecord(name string, rec UpdateDNSRecord) (*DNSRecord, error) { +func (client *Client) UpdateRecord(ctx context.Context, name string, rec UpdateDNSRecord) (*DNSRecord, error) { body, err := json.Marshal(UpdateDNSRecordResponse{ Record: rec, }) @@ -257,7 +286,7 @@ func (client *Client) UpdateRecord(name string, rec UpdateDNSRecord) (*DNSRecord } id := strconv.FormatInt(rec.ID, 10) - resp, err := client.dnsRequest("/v1/domains/"+name+"/records/"+id, string(body), "PUT") + resp, err := client.dnsRequest(ctx, "/v1/domains/"+name+"/records/"+id, nil, string(body), "PUT") if err != nil { return nil, err } @@ -271,30 +300,43 @@ func (client *Client) UpdateRecord(name string, rec UpdateDNSRecord) (*DNSRecord } // DeleteRecord deletes a record -func (client *Client) DeleteRecord(name string, recordID int64) error { +func (client *Client) DeleteRecord(ctx context.Context, name string, recordID int64) error { id := strconv.FormatInt(recordID, 10) - _, err := client.dnsRequest("/v1/domains/"+name+"/records/"+id, "", "DELETE") + _, err := client.dnsRequest(ctx, "/v1/domains/"+name+"/records/"+id, nil, "", "DELETE") return err } -func (client *Client) dnsRequest(uri string, params string, method string) (json.RawMessage, error) { - url := client.Endpoint + uri - req, err := http.NewRequest(method, url, strings.NewReader(params)) +func (client *Client) dnsRequest(ctx context.Context, uri string, urlValues url.Values, params, method string) (json.RawMessage, error) { + rawURL := client.Endpoint + uri + url, err := url.Parse(rawURL) + if err != nil { + return nil, err + } + + q := url.Query() + for k, vs := range urlValues { + for _, v := range vs { + q.Add(k, v) + } + } + url.RawQuery = q.Encode() + + req, err := http.NewRequest(method, url.String(), strings.NewReader(params)) if err != nil { return nil, err } var hdr = make(http.Header) hdr.Add("X-DNS-TOKEN", client.APIKey+":"+client.apiSecret) - hdr.Add("User-Agent", fmt.Sprintf("exoscale/egoscale (%v)", Version)) + hdr.Add("User-Agent", UserAgent) hdr.Add("Accept", "application/json") if params != "" { hdr.Add("Content-Type", "application/json") } req.Header = hdr - resp, err := client.HTTPClient.Do(req) + resp, err := client.HTTPClient.Do(req.WithContext(ctx)) if err != nil { return nil, err } diff --git a/vendor/github.com/exoscale/egoscale/doc.go b/vendor/github.com/exoscale/egoscale/doc.go index 50030dcaf..ac2a1cd85 100644 --- a/vendor/github.com/exoscale/egoscale/doc.go +++ b/vendor/github.com/exoscale/egoscale/doc.go @@ -1,18 +1,18 @@ /* -Package egoscale is a mapping for with the CloudStack API (http://cloudstack.apache.org/api.html) from Go. It has been designed against the Exoscale (https://www.exoscale.com/) infrastructure but should fit other CloudStack services. +Package egoscale is a mapping for the Exoscale API (https://community.exoscale.com/api/compute/). Requests and Responses To build a request, construct the adequate struct. This library expects a pointer for efficiency reasons only. The response is a struct corresponding to the data at stake. E.g. DeployVirtualMachine gives a VirtualMachine, as a pointer as well to avoid big copies. -Then everything within the struct is not a pointer. Find below some examples of how egoscale may be used to interact with a CloudStack endpoint, especially Exoscale itself. If anything feels odd or unclear, please let us know: https://github.com/exoscale/egoscale/issues +Then everything within the struct is not a pointer. Find below some examples of how egoscale may be used. If anything feels odd or unclear, please let us know: https://github.com/exoscale/egoscale/issues req := &egoscale.DeployVirtualMachine{ Size: 10, - ServiceOfferingID: "...", - TemplateID: "...", - ZoneID: "...", + ServiceOfferingID: egoscale.MustParseUUID("..."), + TemplateID: egoscale.MustParseUUID("..."), + ZoneID: egoscale.MastParseUUID("..."), } fmt.Println("Deployment started") @@ -24,13 +24,13 @@ Then everything within the struct is not a pointer. Find below some examples of vm := resp.(*egoscale.VirtualMachine) fmt.Printf("Virtual Machine ID: %s\n", vm.ID) -This exemple deploys a virtual machine while controlling the job status as it goes. It enables a finer control over errors, e.g. HTTP timeout, and eventually a way to kill it of (from the client side). +This example deploys a virtual machine while controlling the job status as it goes. It enables a finer control over errors, e.g. HTTP timeout, and eventually a way to kill it of (from the client side). req := &egoscale.DeployVirtualMachine{ Size: 10, - ServiceOfferingID: "...", - TemplateID: "...", - ZoneID: "...", + ServiceOfferingID: egoscale.MustParseUUID("..."), + TemplateID: egoscale.MustParseUUID("..."), + ZoneID: egoscale.MustParseUUID("..."), } vm := &egoscale.VirtualMachine{} @@ -63,20 +63,20 @@ Debugging and traces As this library is mostly an HTTP client, you can reuse all the existing tools around it. - cs := egoscale.NewClient("https://api.exoscale.ch/compute", "EXO...", "...") + cs := egoscale.NewClient("https://api.exoscale.com/v1", "EXO...", "...") // sets a logger on stderr - cs.Logger = log.Newos.Stderr, "prefix", log.LstdFlags) + cs.Logger = log.New(os.Stderr, "prefix", log.LstdFlags) // activates the HTTP traces cs.TraceOn() -Nota bene: when running the tests or the egoscale library via another tool, e.g. the exo cli (or the cs cli), the environment variable EXOSCALE_TRACE=prefix does the above configuration for you. As a developer using egoscale as a library, you'll find it more convenient to plug your favorite io.Writer as it's Logger. +Nota bene: when running the tests or the egoscale library via another tool, e.g. the exo cli, the environment variable EXOSCALE_TRACE=prefix does the above configuration for you. As a developer using egoscale as a library, you'll find it more convenient to plug your favorite io.Writer as it's a Logger. APIs -All the available APIs on the server and provided by the API Discovery plugin +All the available APIs on the server and provided by the API Discovery plugin. - cs := egoscale.NewClient("https://api.exoscale.ch/compute", "EXO...", "...") + cs := egoscale.NewClient("https://api.exoscale.com/v1", "EXO...", "...") resp, err := cs.Request(&egoscale.ListAPIs{}) if err != nil { @@ -96,14 +96,17 @@ Security Groups provide a way to isolate traffic to VMs. Rules are added via the resp, err := cs.Request(&egoscale.CreateSecurityGroup{ Name: "Load balancer", - Description: "Opens HTTP/HTTPS ports from the outside world", + Description: "Open HTTP/HTTPS ports from the outside world", }) securityGroup := resp.(*egoscale.SecurityGroup) resp, err = cs.Request(&egoscale.AuthorizeSecurityGroupIngress{ Description: "SSH traffic", SecurityGroupID: securityGroup.ID, - CidrList: []string{"0.0.0.0/0"}, + CidrList: []CIDR{ + *egoscale.MustParseCIDR("0.0.0.0/0"), + *egoscale.MustParseCIDR("::/0"), + }, Protocol: "tcp", StartPort: 22, EndPort: 22, @@ -117,32 +120,32 @@ Security Groups provide a way to isolate traffic to VMs. Rules are added via the }) // ... -Security Group also implement the generic List, Get and Delete interfaces (Listable, Gettable and Deletable). +Security Group also implement the generic List, Get and Delete interfaces (Listable and Deletable). // List all Security Groups - sgs, err := cs.List(new(egoscale.SecurityGroup)) + sgs, _ := cs.List(&egoscale.SecurityGroup{}) for _, s := range sgs { sg := s.(egoscale.SecurityGroup) // ... } // Get a Security Group - sg := &egoscale.SecurityGroup{Name: "Load balancer"} - if err := cs.Get(sg); err != nil { + sgQuery := &egoscale.SecurityGroup{Name: "Load balancer"} + resp, err := cs.Get(sgQuery); err != nil { ... } - // The SecurityGroup struct has been loaded with the SecurityGroup informations + sg := resp.(*egoscale.SecurityGroup) if err := cs.Delete(sg); err != nil { ... } // The SecurityGroup has been deleted -See: http://docs.cloudstack.apache.org/projects/cloudstack-administration/en/stable/networking_and_traffic.html#security-groups +See: https://community.exoscale.com/documentation/compute/security-groups/ Zones -A Zone corresponds to a Data Center. You may list them. Zone implements the Listable interface, which let you perform a list in two different ways. The first exposes the underlying CloudStack request while the second one hide them and you only manipulate the structs of your interest. +A Zone corresponds to a Data Center. You may list them. Zone implements the Listable interface, which let you perform a list in two different ways. The first exposes the underlying request while the second one hide them and you only manipulate the structs of your interest. // Using ListZones request req := &egoscale.ListZones{} @@ -171,7 +174,7 @@ Elastic IPs An Elastic IP is a way to attach an IP address to many Virtual Machines. The API side of the story configures the external environment, like the routing. Some work is required within the machine to properly configure the interfaces. -See: http://docs.cloudstack.apache.org/projects/cloudstack-administration/en/latest/networking_and_traffic.html#about-elastic-ips +See: https://community.exoscale.com/documentation/compute/eip/ */ package egoscale diff --git a/vendor/github.com/exoscale/egoscale/errorcode_string.go b/vendor/github.com/exoscale/egoscale/errorcode_string.go index 19711257e..4b46b55bd 100644 --- a/vendor/github.com/exoscale/egoscale/errorcode_string.go +++ b/vendor/github.com/exoscale/egoscale/errorcode_string.go @@ -4,15 +4,37 @@ package egoscale import "strconv" +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[Unauthorized-401] + _ = x[NotFound-404] + _ = x[MethodNotAllowed-405] + _ = x[UnsupportedActionError-422] + _ = x[APILimitExceeded-429] + _ = x[MalformedParameterError-430] + _ = x[ParamError-431] + _ = x[InternalError-530] + _ = x[AccountError-531] + _ = x[AccountResourceLimitError-532] + _ = x[InsufficientCapacityError-533] + _ = x[ResourceUnavailableError-534] + _ = x[ResourceAllocationError-535] + _ = x[ResourceInUseError-536] + _ = x[NetworkRuleConflictError-537] +} + const ( _ErrorCode_name_0 = "Unauthorized" - _ErrorCode_name_1 = "MethodNotAllowed" + _ErrorCode_name_1 = "NotFoundMethodNotAllowed" _ErrorCode_name_2 = "UnsupportedActionError" _ErrorCode_name_3 = "APILimitExceededMalformedParameterErrorParamError" _ErrorCode_name_4 = "InternalErrorAccountErrorAccountResourceLimitErrorInsufficientCapacityErrorResourceUnavailableErrorResourceAllocationErrorResourceInUseErrorNetworkRuleConflictError" ) var ( + _ErrorCode_index_1 = [...]uint8{0, 8, 24} _ErrorCode_index_3 = [...]uint8{0, 16, 39, 49} _ErrorCode_index_4 = [...]uint8{0, 13, 25, 50, 75, 99, 122, 140, 164} ) @@ -21,8 +43,9 @@ func (i ErrorCode) String() string { switch { case i == 401: return _ErrorCode_name_0 - case i == 405: - return _ErrorCode_name_1 + case 404 <= i && i <= 405: + i -= 404 + return _ErrorCode_name_1[_ErrorCode_index_1[i]:_ErrorCode_index_1[i+1]] case i == 422: return _ErrorCode_name_2 case 429 <= i && i <= 431: diff --git a/vendor/github.com/exoscale/egoscale/events.go b/vendor/github.com/exoscale/egoscale/events.go index 60615b52c..c6adbfd69 100644 --- a/vendor/github.com/exoscale/egoscale/events.go +++ b/vendor/github.com/exoscale/egoscale/events.go @@ -5,38 +5,52 @@ type Event struct { Account string `json:"account,omitempty" doc:"the account name for the account that owns the object being acted on in the event (e.g. the owner of the virtual machine, ip address, or security group)"` Created string `json:"created,omitempty" doc:"the date the event was created"` Description string `json:"description,omitempty" doc:"a brief description of the event"` - Domain string `json:"domain,omitempty" doc:"the name of the account's domain"` - DomainID string `json:"domainid,omitempty" doc:"the id of the account's domain"` - ID string `json:"id,omitempty" doc:"the ID of the event"` + ID *UUID `json:"id" doc:"the ID of the event"` Level string `json:"level,omitempty" doc:"the event level (INFO, WARN, ERROR)"` - ParentID string `json:"parentid,omitempty" doc:"whether the event is parented"` + ParentID *UUID `json:"parentid,omitempty" doc:"whether the event is parented"` State string `json:"state,omitempty" doc:"the state of the event"` Type string `json:"type,omitempty" doc:"the type of the event (see event types)"` UserName string `json:"username,omitempty" doc:"the name of the user who performed the action (can be different from the account if an admin is performing an action for a user, e.g. starting/stopping a user's virtual machine)"` } +// ListRequest builds the ListEvents request +func (event Event) ListRequest() (ListCommand, error) { + req := &ListEvents{ + ID: event.ID, + Level: event.Level, + Type: event.Type, + } + + return req, nil +} + // EventType represent a type of event type EventType struct { Name string `json:"name,omitempty" doc:"Event Type"` } +// ListRequest builds the ListEventTypes request +func (EventType) ListRequest() (ListCommand, error) { + req := &ListEventTypes{} + + return req, nil +} + +//go:generate go run generate/main.go -interface=Listable ListEvents + // ListEvents list the events type ListEvents struct { - Account string `json:"account,omitempty" doc:"list resources by account. Must be used with the domainId parameter."` - DomainID string `json:"domainid,omitempty" doc:"list only resources belonging to the domain specified"` - Duration int `json:"duration,omitempty" doc:"the duration of the event"` - EndDate string `json:"enddate,omitempty" doc:"the end date range of the list you want to retrieve (use format \"yyyy-MM-dd\" or the new format \"yyyy-MM-dd HH:mm:ss\")"` - EntryTime int `json:"entrytime,omitempty" doc:"the time the event was entered"` - ID string `json:"id,omitempty" doc:"the ID of the event"` - IsRecursive *bool `json:"isrecursive,omitempty" doc:"defaults to false, but if true, lists all resources from the parent specified by the domainId till leaves." doc:"defaults to false, but if true, lists all resources from the parent specified by the domainId till leaves."` - Keyword string `json:"keyword,omitempty" doc:"List by keyword"` - Level string `json:"level,omitempty" doc:"the event level (INFO, WARN, ERROR)"` - ListAll *bool `json:"listall,omitempty" doc:"If set to false, list only resources belonging to the command's caller; if set to true - list resources that the caller is authorized to see. Default value is false"` - Page int `json:"page,omitempty" ` - PageSize int `json:"pagesize,omitempty"` - StartDate string `json:"startdate,omitempty" doc:"the start date range of the list you want to retrieve (use format \"yyyy-MM-dd\" or the new format \"yyyy-MM-dd HH:mm:ss\")"` - Type string `json:"type,omitempty" doc:"the event type (see event types)"` - _ bool `name:"listEvents" description:"A command to list events."` + Duration int `json:"duration,omitempty" doc:"the duration of the event"` + EndDate string `json:"enddate,omitempty" doc:"the end date range of the list you want to retrieve (use format \"yyyy-MM-dd\" or the new format \"yyyy-MM-dd HH:mm:ss\")"` + EntryTime int `json:"entrytime,omitempty" doc:"the time the event was entered"` + ID *UUID `json:"id,omitempty" doc:"the ID of the event"` + Keyword string `json:"keyword,omitempty" doc:"List by keyword"` + Level string `json:"level,omitempty" doc:"the event level (INFO, WARN, ERROR)"` + Page int `json:"page,omitempty"` + PageSize int `json:"pagesize,omitempty"` + StartDate string `json:"startdate,omitempty" doc:"the start date range of the list you want to retrieve (use format \"yyyy-MM-dd\" or the new format \"yyyy-MM-dd HH:mm:ss\")"` + Type string `json:"type,omitempty" doc:"the event type (see event types)"` + _ bool `name:"listEvents" description:"A command to list events."` } // ListEventsResponse represents a response of a list query @@ -45,13 +59,13 @@ type ListEventsResponse struct { Event []Event `json:"event"` } -func (ListEvents) response() interface{} { - return new(ListEventsResponse) -} +//go:generate go run generate/main.go -interface=Listable ListEventTypes // ListEventTypes list the event types type ListEventTypes struct { - _ bool `name:"listEventTypes" description:"List Event Types"` + Page int `json:"page,omitempty"` // fake + PageSize int `json:"pagesize,omitempty"` // fake + _ bool `name:"listEventTypes" description:"List Event Types"` } // ListEventTypesResponse represents a response of a list query @@ -60,7 +74,3 @@ type ListEventTypesResponse struct { EventType []EventType `json:"eventtype"` _ bool `name:"listEventTypes" description:"List Event Types"` } - -func (ListEventTypes) response() interface{} { - return new(ListEventTypesResponse) -} diff --git a/vendor/github.com/exoscale/egoscale/events_response.go b/vendor/github.com/exoscale/egoscale/events_response.go new file mode 100644 index 000000000..2af10cf45 --- /dev/null +++ b/vendor/github.com/exoscale/egoscale/events_response.go @@ -0,0 +1,43 @@ +// code generated; DO NOT EDIT. + +package egoscale + +import "fmt" + +// Response returns the struct to unmarshal +func (ListEvents) Response() interface{} { + return new(ListEventsResponse) +} + +// ListRequest returns itself +func (ls *ListEvents) ListRequest() (ListCommand, error) { + if ls == nil { + return nil, fmt.Errorf("%T cannot be nil", ls) + } + return ls, nil +} + +// SetPage sets the current apge +func (ls *ListEvents) SetPage(page int) { + ls.Page = page +} + +// SetPageSize sets the page size +func (ls *ListEvents) SetPageSize(pageSize int) { + ls.PageSize = pageSize +} + +// Each triggers the callback for each, valid answer or any non 404 issue +func (ListEvents) Each(resp interface{}, callback IterateItemFunc) { + items, ok := resp.(*ListEventsResponse) + if !ok { + callback(nil, fmt.Errorf("wrong type, ListEventsResponse was expected, got %T", resp)) + return + } + + for i := range items.Event { + if !callback(&items.Event[i], nil) { + break + } + } +} diff --git a/vendor/github.com/exoscale/egoscale/eventtypes_response.go b/vendor/github.com/exoscale/egoscale/eventtypes_response.go new file mode 100644 index 000000000..073d9648f --- /dev/null +++ b/vendor/github.com/exoscale/egoscale/eventtypes_response.go @@ -0,0 +1,43 @@ +// code generated; DO NOT EDIT. + +package egoscale + +import "fmt" + +// Response returns the struct to unmarshal +func (ListEventTypes) Response() interface{} { + return new(ListEventTypesResponse) +} + +// ListRequest returns itself +func (ls *ListEventTypes) ListRequest() (ListCommand, error) { + if ls == nil { + return nil, fmt.Errorf("%T cannot be nil", ls) + } + return ls, nil +} + +// SetPage sets the current apge +func (ls *ListEventTypes) SetPage(page int) { + ls.Page = page +} + +// SetPageSize sets the page size +func (ls *ListEventTypes) SetPageSize(pageSize int) { + ls.PageSize = pageSize +} + +// Each triggers the callback for each, valid answer or any non 404 issue +func (ListEventTypes) Each(resp interface{}, callback IterateItemFunc) { + items, ok := resp.(*ListEventTypesResponse) + if !ok { + callback(nil, fmt.Errorf("wrong type, ListEventTypesResponse was expected, got %T", resp)) + return + } + + for i := range items.EventType { + if !callback(&items.EventType[i], nil) { + break + } + } +} diff --git a/vendor/github.com/exoscale/egoscale/go.mod b/vendor/github.com/exoscale/egoscale/go.mod new file mode 100644 index 000000000..8e84ee4f0 --- /dev/null +++ b/vendor/github.com/exoscale/egoscale/go.mod @@ -0,0 +1,5 @@ +module github.com/exoscale/egoscale + +require github.com/gofrs/uuid v3.2.0+incompatible + +go 1.13 diff --git a/vendor/github.com/exoscale/egoscale/go.sum b/vendor/github.com/exoscale/egoscale/go.sum new file mode 100644 index 000000000..f27a0746d --- /dev/null +++ b/vendor/github.com/exoscale/egoscale/go.sum @@ -0,0 +1,2 @@ +github.com/gofrs/uuid v3.2.0+incompatible h1:y12jRkkFxsd7GpqdSZ+/KCs/fJbqpEXSGd4+jfEaewE= +github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= diff --git a/vendor/github.com/exoscale/egoscale/hosts.go b/vendor/github.com/exoscale/egoscale/hosts.go deleted file mode 100644 index 11f8a4bdf..000000000 --- a/vendor/github.com/exoscale/egoscale/hosts.go +++ /dev/null @@ -1,99 +0,0 @@ -package egoscale - -import ( - "net" -) - -// Host represents the Hypervisor -type Host struct { - Capabilities string `json:"capabilities,omitempty" doc:"capabilities of the host"` - ClusterID string `json:"clusterid,omitempty" doc:"the cluster ID of the host"` - ClusterName string `json:"clustername,omitempty" doc:"the cluster name of the host"` - ClusterType string `json:"clustertype,omitempty" doc:"the cluster type of the cluster that host belongs to"` - CPUAllocated int64 `json:"cpuallocated,omitempty" doc:"the amount of the host's CPU currently allocated"` - CPUNumber int `json:"cpunumber,omitempty" doc:"the CPU number of the host"` - CPUSockets int `json:"cpusockets,omitempty" doc:"the number of CPU sockets on the host"` - CPUSpeed int64 `json:"cpuspeed,omitempty" doc:"the CPU speed of the host"` - CPUUsed int64 `json:"cpuused,omitempty" doc:"the amount of the host's CPU currently used"` - CPUWithOverProvisioning int64 `json:"cpuwithoverprovisioning,omitempty" doc:"the amount of the host's CPU after applying the cpu.overprovisioning.factor"` - Created string `json:"created,omitempty" doc:"the date and time the host was created"` - Disconnected string `json:"disconnected,omitempty" doc:"true if the host is disconnected. False otherwise."` - DiskSizeAllocated int64 `json:"disksizeallocated,omitempty" doc:"the host's or host storage pool's currently allocated disk size"` - DiskSizeTotal int64 `json:"disksizetotal,omitempty" doc:"the total disk size of the host or host storage pool"` - DiskSizeUsed int64 `json:"disksizeused,omitempty" doc:"the host's or host storage pool's currently used disk size"` - DiskWithOverProvisioning int64 `json:"diskwithoverprovisioning,omitempty" doc:"the total disk size of the host or host storage pool with over provisioning factor"` - Events string `json:"events,omitempty" doc:"events available for the host"` - HAHost *bool `json:"hahost,omitempty" doc:"true if the host is Ha host (dedicated to vms started by HA process; false otherwise"` - HostTags string `json:"hosttags,omitempty" doc:"comma-separated list of tags for the host"` - Hypervisor string `json:"hypervisor,omitempty" doc:"the host hypervisor"` - HypervisorVersion string `json:"hypervisorversion,omitempty" doc:"the hypervisor version"` - ID string `json:"id,omitempty" doc:"the ID of the host"` - IPAddress net.IP `json:"ipaddress,omitempty" doc:"the IP address of the host"` - IsLocalstorageActive *bool `json:"islocalstorageactive,omitempty" doc:"true if local storage is active, false otherwise"` - LastPinged string `json:"lastpinged,omitempty" doc:"the date and time the host was last pinged"` - ManagementServerID string `json:"managementserverid,omitempty" doc:"the management server ID of the host"` - MemoryAllocated int64 `json:"memoryallocated,omitempty" doc:"the amount of VM's memory allocated onto the host"` - MemoryPhysical int64 `json:"memoryphysical,omitempty" doc:"the total physical memory of the host"` - MemoryReserved int64 `json:"memoryreserved,omitempty" doc:"the amount of the host's memory reserved"` - MemoryTotal int64 `json:"memorytotal,omitempty" doc:"the total memory of the host available (must be physical - reserved)"` - MemoryUsed int64 `json:"memoryused,omitempty" doc:"the amount of the host's memory used by running vm"` - Name string `json:"name,omitempty" doc:"the name of the host"` - NetworkKbsRead int64 `json:"networkkbsread,omitempty" doc:"the incoming network traffic on the host"` - NetworkKbsWrite int64 `json:"networkkbswrite,omitempty" doc:"the outgoing network traffic on the host"` - OSCategoryID string `json:"oscategoryid,omitempty" doc:"the OS category ID of the host"` - OSCategoryName string `json:"oscategoryname,omitempty" doc:"the OS category name of the host"` - PCIDevices []PCIDevice `json:"pcidevices,omitempty" doc:"PCI cards present in the host"` - PodID string `json:"podid,omitempty" doc:"the Pod ID of the host"` - PodName string `json:"podname,omitempty" doc:"the Pod name of the host"` - Removed string `json:"removed,omitempty" doc:"the date and time the host was removed"` - ResourceState string `json:"resourcestate,omitempty" doc:"the resource state of the host"` - State string `json:"state,omitempty" doc:"the state of the host"` - StorageID string `json:"storageid,omitempty" doc:"the host's storage pool id"` - Type string `json:"type,omitempty" doc:"the host type"` - Version string `json:"version,omitempty" doc:"the host version"` - ZoneID string `json:"zoneid,omitempty" doc:"the Zone ID of the host"` - ZoneName string `json:"zonename,omitempty" doc:"the Zone name of the host"` -} - -// ListHosts lists hosts -type ListHosts struct { - ClusterID string `json:"clusterid,omitempty" doc:"lists hosts existing in particular cluster"` - Details []string `json:"details,omitempty" doc:"comma separated list of host details requested, value can be a list of [ min, all, capacity, events, stats]"` - HAHost *bool `json:"hahost,omitempty" doc:"if true, list only hosts dedicated to HA"` - Hypervisor string `json:"hypervisor,omitempty" doc:"hypervisor type of host: KVM,Simulator"` - ID string `json:"id,omitempty" doc:"the id of the host"` - Keyword string `json:"keyword,omitempty" doc:"List by keyword"` - Name string `json:"name,omitempty" doc:"the name of the host"` - Page int `json:"page,omitempty"` - PageSize int `json:"pagesize,omitempty"` - PodID string `json:"podid,omitempty" doc:"the Pod ID for the host"` - ResourceState string `json:"resourcestate,omitempty" doc:"list hosts by resource state. Resource state represents current state determined by admin of host, value can be one of [Enabled, Disabled, Unmanaged, PrepareForMaintenance, ErrorInMaintenance, Maintenance, Error]"` - State string `json:"state,omitempty" doc:"the state of the host"` - Type string `json:"type,omitempty" doc:"the host type"` - ZoneID string `json:"zoneid,omitempty" doc:"the Zone ID for the host"` - _ bool `name:"listHosts" description:"Lists hosts."` -} - -func (ListHosts) response() interface{} { - return new(ListHostsResponse) -} - -// ListHostsResponse represents a list of hosts -type ListHostsResponse struct { - Count int `json:"count"` - Host []Host `json:"host"` -} - -// UpdateHost changes the resources state of a host -type UpdateHost struct { - Allocationstate string `json:"allocationstate,omitempty" doc:"Change resource state of host, valid values are [Enable, Disable]. Operation may failed if host in states not allowing Enable/Disable"` - HostTags []string `json:"hosttags,omitempty" doc:"list of tags to be added to the host"` - ID string `json:"id" doc:"the ID of the host to update"` - OSCategoryID string `json:"oscategoryid,omitempty" doc:"the id of Os category to update the host with"` - URL string `json:"url,omitempty" doc:"the new uri for the secondary storage: nfs://host/path"` - _ bool `name:"updateHost" description:"Updates a host."` -} - -func (UpdateHost) response() interface{} { - return new(Host) -} diff --git a/vendor/github.com/exoscale/egoscale/iam_apikey.go b/vendor/github.com/exoscale/egoscale/iam_apikey.go new file mode 100644 index 000000000..23cf2a934 --- /dev/null +++ b/vendor/github.com/exoscale/egoscale/iam_apikey.go @@ -0,0 +1,92 @@ +package egoscale + +// APIKeyType holds the type of the API key +type APIKeyType string + +const ( + // APIKeyTypeUnrestricted is unrestricted + APIKeyTypeUnrestricted APIKeyType = "unrestricted" + // APIKeyTypeRestricted is restricted + APIKeyTypeRestricted APIKeyType = "restricted" +) + +// APIKey represents an API key +type APIKey struct { + Name string `json:"name"` + Key string `json:"key"` + Secret string `json:"secret,omitempty"` + Operations []string `json:"operations,omitempty"` + Resources []string `json:"resources,omitempty"` + Type APIKeyType `json:"type"` +} + +// CreateAPIKey represents an API key creation +type CreateAPIKey struct { + Name string `json:"name"` + Operations string `json:"operations,omitempty"` + Resources string `json:"resources,omitempty"` + _ bool `name:"createApiKey" description:"Create an API key."` +} + +// Response returns the struct to unmarshal +func (CreateAPIKey) Response() interface{} { + return new(APIKey) +} + +// ListAPIKeys represents a search for API keys +type ListAPIKeys struct { + _ bool `name:"listApiKeys" description:"List API keys."` +} + +// ListAPIKeysResponse represents a list of API keys +type ListAPIKeysResponse struct { + Count int `json:"count"` + APIKeys []APIKey `json:"apikey"` +} + +// Response returns the struct to unmarshal +func (ListAPIKeys) Response() interface{} { + return new(ListAPIKeysResponse) +} + +// ListAPIKeyOperations represents a search for operations for the current API key +type ListAPIKeyOperations struct { + _ bool `name:"listApiKeyOperations" description:"List operations allowed for the current API key."` +} + +// ListAPIKeyOperationsResponse represents a list of operations for the current API key +type ListAPIKeyOperationsResponse struct { + Operations []string `json:"operations"` +} + +// Response returns the struct to unmarshal +func (ListAPIKeyOperations) Response() interface{} { + return new(ListAPIKeyOperationsResponse) +} + +// GetAPIKey get an API key +type GetAPIKey struct { + Key string `json:"key"` + _ bool `name:"getApiKey" description:"Get an API key."` +} + +// Response returns the struct to unmarshal +func (GetAPIKey) Response() interface{} { + return new(APIKey) +} + +// RevokeAPIKey represents a revocation of an API key +type RevokeAPIKey struct { + Key string `json:"key"` + _ bool `name:"revokeApiKey" description:"Revoke an API key."` +} + +// RevokeAPIKeyResponse represents the response to an API key revocation +type RevokeAPIKeyResponse struct { + Success bool `json:"success"` +} + +// Response returns the struct to unmarshal +func (RevokeAPIKey) Response() interface{} { + return new(RevokeAPIKeyResponse) +} diff --git a/vendor/github.com/exoscale/egoscale/instance_groups.go b/vendor/github.com/exoscale/egoscale/instance_groups.go new file mode 100644 index 000000000..52bffba9a --- /dev/null +++ b/vendor/github.com/exoscale/egoscale/instance_groups.go @@ -0,0 +1,71 @@ +package egoscale + +// InstanceGroup represents a group of VM +type InstanceGroup struct { + Account string `json:"account,omitempty" doc:"the account owning the instance group"` + Created string `json:"created,omitempty" doc:"time and date the instance group was created"` + ID *UUID `json:"id,omitempty" doc:"the id of the instance group"` + Name string `json:"name,omitempty" doc:"the name of the instance group"` +} + +// ListRequest builds the ListInstanceGroups request +func (ig InstanceGroup) ListRequest() (ListCommand, error) { + req := &ListInstanceGroups{ + ID: ig.ID, + Name: ig.Name, + } + + return req, nil +} + +// CreateInstanceGroup creates a VM group +type CreateInstanceGroup struct { + Name string `json:"name" doc:"the name of the instance group"` + _ bool `name:"createInstanceGroup" description:"Creates a vm group"` +} + +// Response returns the struct to unmarshal +func (CreateInstanceGroup) Response() interface{} { + return new(InstanceGroup) +} + +// UpdateInstanceGroup updates a VM group +type UpdateInstanceGroup struct { + ID *UUID `json:"id" doc:"Instance group ID"` + Name string `json:"name,omitempty" doc:"new instance group name"` + _ bool `name:"updateInstanceGroup" description:"Updates a vm group"` +} + +// Response returns the struct to unmarshal +func (UpdateInstanceGroup) Response() interface{} { + return new(InstanceGroup) +} + +// DeleteInstanceGroup deletes a VM group +type DeleteInstanceGroup struct { + ID *UUID `json:"id" doc:"the ID of the instance group"` + _ bool `name:"deleteInstanceGroup" description:"Deletes a vm group"` +} + +// Response returns the struct to unmarshal +func (DeleteInstanceGroup) Response() interface{} { + return new(BooleanResponse) +} + +//go:generate go run generate/main.go -interface=Listable ListInstanceGroups + +// ListInstanceGroups lists VM groups +type ListInstanceGroups struct { + ID *UUID `json:"id,omitempty" doc:"List instance groups by ID"` + Keyword string `json:"keyword,omitempty" doc:"List by keyword"` + Name string `json:"name,omitempty" doc:"List instance groups by name"` + Page int `json:"page,omitempty"` + PageSize int `json:"pagesize,omitempty"` + _ bool `name:"listInstanceGroups" description:"Lists vm groups"` +} + +// ListInstanceGroupsResponse represents a list of instance groups +type ListInstanceGroupsResponse struct { + Count int `json:"count"` + InstanceGroup []InstanceGroup `json:"instancegroup"` +} diff --git a/vendor/github.com/exoscale/egoscale/instance_pool.go b/vendor/github.com/exoscale/egoscale/instance_pool.go new file mode 100644 index 000000000..c6e4b6545 --- /dev/null +++ b/vendor/github.com/exoscale/egoscale/instance_pool.go @@ -0,0 +1,164 @@ +package egoscale + +// InstancePoolState represents the state of an instance pool. +type InstancePoolState string + +const ( + // InstancePoolCreating creating state. + InstancePoolCreating InstancePoolState = "creating" + // InstancePoolRunning running state. + InstancePoolRunning InstancePoolState = "running" + // InstancePoolDestroying destroying state. + InstancePoolDestroying InstancePoolState = "destroying" + // InstancePoolScalingUp scaling up state. + InstancePoolScalingUp InstancePoolState = "scaling-up" + // InstancePoolScalingDown scaling down state. + InstancePoolScalingDown InstancePoolState = "scaling-down" +) + +// InstancePool represents an instance pool. +type InstancePool struct { + ID *UUID `json:"id"` + Name string `json:"name"` + Description string `json:"description"` + ServiceOfferingID *UUID `json:"serviceofferingid"` + TemplateID *UUID `json:"templateid"` + ZoneID *UUID `json:"zoneid"` + SecurityGroupIDs []UUID `json:"securitygroupids"` + NetworkIDs []UUID `json:"networkids"` + KeyPair string `json:"keypair"` + UserData string `json:"userdata"` + Size int `json:"size"` + RootDiskSize int `json:"rootdisksize"` + State InstancePoolState `json:"state"` + VirtualMachines []VirtualMachine `json:"virtualmachines"` +} + +// CreateInstancePool represents an instance pool creation API request. +type CreateInstancePool struct { + Name string `json:"name"` + Description string `json:"description,omitempty"` + ServiceOfferingID *UUID `json:"serviceofferingid"` + TemplateID *UUID `json:"templateid"` + ZoneID *UUID `json:"zoneid"` + SecurityGroupIDs []UUID `json:"securitygroupids,omitempty"` + NetworkIDs []UUID `json:"networkids,omitempty"` + KeyPair string `json:"keypair,omitempty"` + UserData string `json:"userdata,omitempty"` + Size int `json:"size"` + RootDiskSize int `json:"rootdisksize,omitempty"` + _ bool `name:"createInstancePool" description:"Create an Instance Pool"` +} + +// CreateInstancePoolResponse represents an instance pool creation API response. +type CreateInstancePoolResponse struct { + ID *UUID `json:"id"` + Name string `json:"name"` + Description string `json:"description"` + ServiceOfferingID *UUID `json:"serviceofferingid"` + TemplateID *UUID `json:"templateid"` + ZoneID *UUID `json:"zoneid"` + SecurityGroupIDs []UUID `json:"securitygroupids"` + NetworkIDs []UUID `json:"networkids"` + KeyPair string `json:"keypair"` + UserData string `json:"userdata"` + Size int64 `json:"size"` + RootDiskSize int `json:"rootdisksize"` + State InstancePoolState `json:"state"` +} + +// Response returns an empty structure to unmarshal an instance pool creation API response into. +func (CreateInstancePool) Response() interface{} { + return new(CreateInstancePoolResponse) +} + +// UpdateInstancePool represents an instance pool update API request. +type UpdateInstancePool struct { + ID *UUID `json:"id"` + ZoneID *UUID `json:"zoneid"` + Name string `json:"name,omitempty"` + Description string `json:"description,omitempty"` + TemplateID *UUID `json:"templateid,omitempty"` + UserData string `json:"userdata,omitempty"` + _ bool `name:"updateInstancePool" description:"Update an Instance Pool"` +} + +// UpdateInstancePoolResponse represents an instance pool update API response. +type UpdateInstancePoolResponse struct { + Success bool `json:"success"` +} + +// Response returns an empty structure to unmarshal an instance pool update API response into. +func (UpdateInstancePool) Response() interface{} { + return new(UpdateInstancePoolResponse) +} + +// ScaleInstancePool represents an instance pool scaling API request. +type ScaleInstancePool struct { + ID *UUID `json:"id"` + ZoneID *UUID `json:"zoneid"` + Size int `json:"size"` + _ bool `name:"scaleInstancePool" description:"Scale an Instance Pool"` +} + +// ScaleInstancePoolResponse represents an instance pool scaling API response. +type ScaleInstancePoolResponse struct { + Success bool `json:"success"` +} + +// Response returns an empty structure to unmarshal an instance pool scaling API response into. +func (ScaleInstancePool) Response() interface{} { + return new(ScaleInstancePoolResponse) +} + +// DestroyInstancePool represents an instance pool destruction API request. +type DestroyInstancePool struct { + ID *UUID `json:"id"` + ZoneID *UUID `json:"zoneid"` + _ bool `name:"destroyInstancePool" description:"Destroy an Instance Pool"` +} + +// DestroyInstancePoolResponse represents an instance pool destruction API response. +type DestroyInstancePoolResponse struct { + Success bool `json:"success"` +} + +// Response returns an empty structure to unmarshal an instance pool destruction API response into. +func (DestroyInstancePool) Response() interface{} { + return new(DestroyInstancePoolResponse) +} + +// GetInstancePool retrieves an instance pool's details. +type GetInstancePool struct { + ID *UUID `json:"id"` + ZoneID *UUID `json:"zoneid"` + _ bool `name:"getInstancePool" description:"Get an Instance Pool"` +} + +// GetInstancePoolResponse get instance pool API response. +type GetInstancePoolResponse struct { + Count int + InstancePools []InstancePool `json:"instancepool"` +} + +// Response returns an empty structure to unmarshal an instance pool get API response into. +func (GetInstancePool) Response() interface{} { + return new(GetInstancePoolResponse) +} + +// ListInstancePools represents a list instance pool API request. +type ListInstancePools struct { + ZoneID *UUID `json:"zoneid"` + _ bool `name:"listInstancePools" description:"List Instance Pools"` +} + +// ListInstancePoolsResponse represents a list instance pool API response. +type ListInstancePoolsResponse struct { + Count int + InstancePools []InstancePool `json:"instancepool"` +} + +// Response returns an empty structure to unmarshal an instance pool list API response into. +func (ListInstancePools) Response() interface{} { + return new(ListInstancePoolsResponse) +} diff --git a/vendor/github.com/exoscale/egoscale/instancegroups_response.go b/vendor/github.com/exoscale/egoscale/instancegroups_response.go new file mode 100644 index 000000000..90fc1dbac --- /dev/null +++ b/vendor/github.com/exoscale/egoscale/instancegroups_response.go @@ -0,0 +1,43 @@ +// code generated; DO NOT EDIT. + +package egoscale + +import "fmt" + +// Response returns the struct to unmarshal +func (ListInstanceGroups) Response() interface{} { + return new(ListInstanceGroupsResponse) +} + +// ListRequest returns itself +func (ls *ListInstanceGroups) ListRequest() (ListCommand, error) { + if ls == nil { + return nil, fmt.Errorf("%T cannot be nil", ls) + } + return ls, nil +} + +// SetPage sets the current apge +func (ls *ListInstanceGroups) SetPage(page int) { + ls.Page = page +} + +// SetPageSize sets the page size +func (ls *ListInstanceGroups) SetPageSize(pageSize int) { + ls.PageSize = pageSize +} + +// Each triggers the callback for each, valid answer or any non 404 issue +func (ListInstanceGroups) Each(resp interface{}, callback IterateItemFunc) { + items, ok := resp.(*ListInstanceGroupsResponse) + if !ok { + callback(nil, fmt.Errorf("wrong type, ListInstanceGroupsResponse was expected, got %T", resp)) + return + } + + for i := range items.InstanceGroup { + if !callback(&items.InstanceGroup[i], nil) { + break + } + } +} diff --git a/vendor/github.com/exoscale/egoscale/isos.go b/vendor/github.com/exoscale/egoscale/isos.go new file mode 100644 index 000000000..d9a0ace82 --- /dev/null +++ b/vendor/github.com/exoscale/egoscale/isos.go @@ -0,0 +1,94 @@ +package egoscale + +// ISO represents an attachable ISO disc +type ISO Template + +// ResourceType returns the type of the resource +func (ISO) ResourceType() string { + return "ISO" +} + +// ListRequest produces the ListIsos command. +func (iso ISO) ListRequest() (ListCommand, error) { + req := &ListISOs{ + ID: iso.ID, + Name: iso.Name, + ZoneID: iso.ZoneID, + } + if iso.Bootable { + *req.Bootable = true + } + if iso.IsFeatured { + req.IsoFilter = "featured" + } + if iso.IsPublic { + *req.IsPublic = true + } + if iso.IsReady { + *req.IsReady = true + } + + for i := range iso.Tags { + req.Tags = append(req.Tags, iso.Tags[i]) + } + + return req, nil +} + +//go:generate go run generate/main.go -interface=Listable ListISOs + +// ListISOs represents the list all available ISO files request +type ListISOs struct { + _ bool `name:"listIsos" description:"Lists all available ISO files."` + Bootable *bool `json:"bootable,omitempty" doc:"True if the ISO is bootable, false otherwise"` + ID *UUID `json:"id,omitempty" doc:"List ISO by id"` + IsoFilter string `json:"isofilter,omitempty" doc:"Possible values are \"featured\", \"self\", \"selfexecutable\",\"sharedexecutable\",\"executable\", and \"community\". * featured : templates that have been marked as featured and public. * self : templates that have been registered or created by the calling user. * selfexecutable : same as self, but only returns templates that can be used to deploy a new VM. * sharedexecutable : templates ready to be deployed that have been granted to the calling user by another user. * executable : templates that are owned by the calling user, or public templates, that can be used to deploy a VM. * community : templates that have been marked as public but not featured. * all : all templates (only usable by admins)."` + IsPublic *bool `json:"ispublic,omitempty" doc:"True if the ISO is publicly available to all users, false otherwise."` + IsReady *bool `json:"isready,omitempty" doc:"True if this ISO is ready to be deployed"` + Keyword string `json:"keyword,omitempty" doc:"List by keyword"` + Name string `json:"name,omitempty" doc:"List all isos by name"` + Page int `json:"page,omitempty"` + PageSize int `json:"pagesize,omitempty"` + ShowRemoved *bool `json:"showremoved,omitempty" doc:"Show removed ISOs as well"` + Tags []ResourceTag `json:"tags,omitempty" doc:"List resources by tags (key/value pairs)"` + ZoneID *UUID `json:"zoneid,omitempty" doc:"The ID of the zone"` +} + +// ListISOsResponse represents a list of ISO files +type ListISOsResponse struct { + Count int `json:"count"` + ISO []ISO `json:"iso"` +} + +// AttachISO represents the request to attach an ISO to a virtual machine. +type AttachISO struct { + _ bool `name:"attachIso" description:"Attaches an ISO to a virtual machine."` + ID *UUID `json:"id" doc:"the ID of the ISO file"` + VirtualMachineID *UUID `json:"virtualmachineid" doc:"the ID of the virtual machine"` +} + +// Response returns the struct to unmarshal +func (AttachISO) Response() interface{} { + return new(AsyncJobResult) +} + +// AsyncResponse returns the struct to unmarshal the async job +func (AttachISO) AsyncResponse() interface{} { + return new(VirtualMachine) +} + +// DetachISO represents the request to detach an ISO to a virtual machine. +type DetachISO struct { + _ bool `name:"detachIso" description:"Detaches any ISO file (if any) currently attached to a virtual machine."` + VirtualMachineID *UUID `json:"virtualmachineid" doc:"The ID of the virtual machine"` +} + +// Response returns the struct to unmarshal +func (DetachISO) Response() interface{} { + return new(AsyncJobResult) +} + +// AsyncResponse returns the struct to unmarshal the async job +func (DetachISO) AsyncResponse() interface{} { + return new(VirtualMachine) +} diff --git a/vendor/github.com/exoscale/egoscale/isos_response.go b/vendor/github.com/exoscale/egoscale/isos_response.go new file mode 100644 index 000000000..2faa45a88 --- /dev/null +++ b/vendor/github.com/exoscale/egoscale/isos_response.go @@ -0,0 +1,43 @@ +// code generated; DO NOT EDIT. + +package egoscale + +import "fmt" + +// Response returns the struct to unmarshal +func (ListISOs) Response() interface{} { + return new(ListISOsResponse) +} + +// ListRequest returns itself +func (ls *ListISOs) ListRequest() (ListCommand, error) { + if ls == nil { + return nil, fmt.Errorf("%T cannot be nil", ls) + } + return ls, nil +} + +// SetPage sets the current apge +func (ls *ListISOs) SetPage(page int) { + ls.Page = page +} + +// SetPageSize sets the page size +func (ls *ListISOs) SetPageSize(pageSize int) { + ls.PageSize = pageSize +} + +// Each triggers the callback for each, valid answer or any non 404 issue +func (ListISOs) Each(resp interface{}, callback IterateItemFunc) { + items, ok := resp.(*ListISOsResponse) + if !ok { + callback(nil, fmt.Errorf("wrong type, ListISOsResponse was expected, got %T", resp)) + return + } + + for i := range items.ISO { + if !callback(&items.ISO[i], nil) { + break + } + } +} diff --git a/vendor/github.com/exoscale/egoscale/jobstatustype_string.go b/vendor/github.com/exoscale/egoscale/jobstatustype_string.go index 298561608..12401c454 100644 --- a/vendor/github.com/exoscale/egoscale/jobstatustype_string.go +++ b/vendor/github.com/exoscale/egoscale/jobstatustype_string.go @@ -4,6 +4,15 @@ package egoscale import "strconv" +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[Pending-0] + _ = x[Success-1] + _ = x[Failure-2] +} + const _JobStatusType_name = "PendingSuccessFailure" var _JobStatusType_index = [...]uint8{0, 7, 14, 21} diff --git a/vendor/github.com/exoscale/egoscale/limits.go b/vendor/github.com/exoscale/egoscale/limits.go deleted file mode 100644 index d61c38447..000000000 --- a/vendor/github.com/exoscale/egoscale/limits.go +++ /dev/null @@ -1,140 +0,0 @@ -package egoscale - -// https://github.com/apache/cloudstack/blob/master/api/src/main/java/com/cloud/configuration/Resource.java - -// ResourceTypeName represents the name of a resource type (for limits) -type ResourceTypeName string - -const ( - // VirtualMachineTypeName is the resource type name of a VM - VirtualMachineTypeName ResourceTypeName = "user_vm" - // IPAddressTypeName is the resource type name of an IP address - IPAddressTypeName ResourceTypeName = "public_ip" - // VolumeTypeName is the resource type name of a volume - VolumeTypeName ResourceTypeName = "volume" - // SnapshotTypeName is the resource type name of a snapshot - SnapshotTypeName ResourceTypeName = "snapshot" - // TemplateTypeName is the resource type name of a template - TemplateTypeName ResourceTypeName = "template" - // ProjectTypeName is the resource type name of a project - ProjectTypeName ResourceTypeName = "project" - // NetworkTypeName is the resource type name of a network - NetworkTypeName ResourceTypeName = "network" - // VPCTypeName is the resource type name of a VPC - VPCTypeName ResourceTypeName = "vpc" - // CPUTypeName is the resource type name of a CPU - CPUTypeName ResourceTypeName = "cpu" - // MemoryTypeName is the resource type name of Memory - MemoryTypeName ResourceTypeName = "memory" - // PrimaryStorageTypeName is the resource type name of primary storage - PrimaryStorageTypeName ResourceTypeName = "primary_storage" - // SecondaryStorageTypeName is the resource type name of secondary storage - SecondaryStorageTypeName ResourceTypeName = "secondary_storage" -) - -// ResourceType represents the ID of a resource type (for limits) -type ResourceType int64 - -//go:generate stringer -type=ResourceType -const ( - // VirtualMachineType is the resource type ID of a VM - VirtualMachineType ResourceType = iota - // IPAddressType is the resource type ID of an IP address - IPAddressType - // VolumeType is the resource type ID of a volume - VolumeType - // SnapshotType is the resource type ID of a snapshot - SnapshotType - // TemplateType is the resource type ID of a template - TemplateType - // ProjectType is the resource type ID of a project - ProjectType - // NetworkType is the resource type ID of a network - NetworkType - // VPCType is the resource type ID of a VPC - VPCType - // CPUType is the resource type ID of a CPU - CPUType - // MemoryType is the resource type ID of Memory - MemoryType - // PrimaryStorageType is the resource type ID of primary storage - PrimaryStorageType - // SecondaryStorageType is the resource type ID of secondary storage - SecondaryStorageType -) - -// ResourceLimit represents the limit on a particular resource -type ResourceLimit struct { - Account string `json:"account,omitempty" doc:"the account of the resource limit"` - Domain string `json:"domain,omitempty" doc:"the domain name of the resource limit"` - DomainID string `json:"domainid,omitempty" doc:"the domain ID of the resource limit"` - Max int64 `json:"max,omitempty" doc:"the maximum number of the resource. A -1 means the resource currently has no limit."` - ResourceType ResourceType `json:"resourcetype,omitempty" doc:"resource type. Values include 0, 1, 2, 3, 4, 6, 7, 8, 9, 10, 11. See the resourceType parameter for more information on these values."` - ResourceTypeName ResourceTypeName `json:"resourcetypename,omitempty" doc:"resource type name. Values include user_vm, public_ip, volume, snapshot, template, project, network, vpc, cpu, memory, primary_storage, secondary_storage."` -} - -// APILimit represents the limit count -type APILimit struct { - Account string `json:"account,omitempty" doc:"the account name of the api remaining count"` - Accountid string `json:"accountid,omitempty" doc:"the account uuid of the api remaining count"` - APIAllowed int `json:"apiAllowed,omitempty" doc:"currently allowed number of apis"` - APIIssued int `json:"apiIssued,omitempty" doc:"number of api already issued"` - ExpireAfter int64 `json:"expireAfter,omitempty" doc:"seconds left to reset counters"` -} - -// ListResourceLimits lists the resource limits -type ListResourceLimits struct { - Account string `json:"account,omitempty" doc:"list resources by account. Must be used with the domainId parameter."` - DomainID string `json:"domainid,omitempty" doc:"list only resources belonging to the domain specified"` - ID int64 `json:"id,omitempty" doc:"Lists resource limits by ID."` - IsRecursive *bool `json:"isrecursive,omitempty" doc:"defaults to false, but if true, lists all resources from the parent specified by the domainId till leaves."` - Keyword string `json:"keyword,omitempty" doc:"List by keyword"` - ListAll *bool `json:"listall,omitempty" doc:"If set to false, list only resources belonging to the command's caller; if set to true - list resources that the caller is authorized to see. Default value is false"` - Page int `json:"page,omitempty"` - PageSize int `json:"pagesize,omitempty"` - ResourceType ResourceType `json:"resourcetype,omitempty" doc:"Type of resource. Values are 0, 1, 2, 3, 4, 6, 7, 8, 9, 10 and 11. 0 - Instance. Number of instances a user can create. 1 - IP. Number of public IP addresses an account can own. 2 - Volume. Number of disk volumes an account can own. 3 - Snapshot. Number of snapshots an account can own. 4 - Template. Number of templates an account can register/create. 5 - Project. Number of projects an account can own. 6 - Network. Number of networks an account can own. 7 - VPC. Number of VPC an account can own. 8 - CPU. Number of CPU an account can allocate for his resources. 9 - Memory. Amount of RAM an account can allocate for his resources. 10 - PrimaryStorage. Total primary storage space (in GiB) a user can use. 11 - SecondaryStorage. Total secondary storage space (in GiB) a user can use. 12 - Elastic IP. Number of public elastic IP addresses an account can own. 13 - SMTP. If the account is allowed SMTP outbound traffic."` - ResourceTypeName ResourceTypeName `json:"resourcetypename,omitempty" doc:"Type of resource (wins over resourceType if both are provided). Values are: user_vm - Instance. Number of instances a user can create. public_ip - IP. Number of public IP addresses an account can own. volume - Volume. Number of disk volumes an account can own. snapshot - Snapshot. Number of snapshots an account can own. template - Template. Number of templates an account can register/create. project - Project. Number of projects an account can own. network - Network. Number of networks an account can own. vpc - VPC. Number of VPC an account can own. cpu - CPU. Number of CPU an account can allocate for his resources. memory - Memory. Amount of RAM an account can allocate for his resources. primary_storage - PrimaryStorage. Total primary storage space (in GiB) a user can use. secondary_storage - SecondaryStorage. Total secondary storage space (in GiB) a user can use. public_elastic_ip - IP. Number of public elastic IP addresses an account can own. smtp - SG. If the account is allowed SMTP outbound traffic."` - _ bool `name:"listResourceLimits" description:"Lists resource limits."` -} - -// ListResourceLimitsResponse represents a list of resource limits -type ListResourceLimitsResponse struct { - Count int `json:"count"` - ResourceLimit []ResourceLimit `json:"resourcelimit"` -} - -func (ListResourceLimits) response() interface{} { - return new(ListResourceLimitsResponse) -} - -// UpdateResourceLimit updates the resource limit -type UpdateResourceLimit struct { - Account string `json:"account,omitempty" doc:"Update resource for a specified account. Must be used with the domainId parameter."` - DomainID string `json:"domainid,omitempty" doc:"Update resource limits for all accounts in specified domain. If used with the account parameter, updates resource limits for a specified account in specified domain."` - Max int64 `json:"max,omitempty" doc:"Maximum resource limit."` - ResourceType ResourceType `json:"resourcetype" doc:"Type of resource to update. Values are 0, 1, 2, 3, 4, 6, 7, 8, 9, 10 and 11. 0 - Instance. Number of instances a user can create. 1 - IP. Number of public IP addresses a user can own. 2 - Volume. Number of disk volumes a user can create. 3 - Snapshot. Number of snapshots a user can create. 4 - Template. Number of templates that a user can register/create. 6 - Network. Number of guest network a user can create. 7 - VPC. Number of VPC a user can create. 8 - CPU. Total number of CPU cores a user can use. 9 - Memory. Total Memory (in MB) a user can use. 10 - PrimaryStorage. Total primary storage space (in GiB) a user can use. 11 - SecondaryStorage. Total secondary storage space (in GiB) a user can use."` - _ bool `name:"updateResourceLimit" description:"Updates resource limits for an account or domain."` -} - -// UpdateResourceLimitResponse represents an updated resource limit -type UpdateResourceLimitResponse struct { - ResourceLimit ResourceLimit `json:"resourcelimit"` -} - -func (UpdateResourceLimit) response() interface{} { - return new(UpdateResourceLimitResponse) -} - -// GetAPILimit gets API limit count for the caller -type GetAPILimit struct { - _ bool `name:"getApiLimit" description:"Get API limit count for the caller"` -} - -// GetAPILimitResponse represents the limits towards the API call -type GetAPILimitResponse struct { - APILimit APILimit `json:"apilimit"` -} - -func (GetAPILimit) response() interface{} { - return new(GetAPILimitResponse) -} diff --git a/vendor/github.com/exoscale/egoscale/macaddress.go b/vendor/github.com/exoscale/egoscale/macaddress.go index 458fbb6df..3c1dcaea4 100644 --- a/vendor/github.com/exoscale/egoscale/macaddress.go +++ b/vendor/github.com/exoscale/egoscale/macaddress.go @@ -53,8 +53,8 @@ func ParseMAC(s string) (MACAddress, error) { return (MACAddress)(hw), err } -// ForceParseMAC acts like ParseMAC but panics if in case of an error -func ForceParseMAC(s string) MACAddress { +// MustParseMAC acts like ParseMAC but panics if in case of an error +func MustParseMAC(s string) MACAddress { mac, err := ParseMAC(s) if err != nil { panic(err) diff --git a/vendor/github.com/exoscale/egoscale/network_offerings.go b/vendor/github.com/exoscale/egoscale/network_offerings.go deleted file mode 100644 index 6879d19b2..000000000 --- a/vendor/github.com/exoscale/egoscale/network_offerings.go +++ /dev/null @@ -1,77 +0,0 @@ -package egoscale - -// NetworkOffering corresponds to the Compute Offerings -type NetworkOffering struct { - Availability string `json:"availability,omitempty" doc:"availability of the network offering"` - ConserveMode bool `json:"conservemode,omitempty" doc:"true if network offering is ip conserve mode enabled"` - Created string `json:"created,omitempty" doc:"the date this network offering was created"` - Details map[string]string `json:"details,omitempty" doc:"additional key/value details tied with network offering"` - DisplayText string `json:"displaytext,omitempty" doc:"an alternate display text of the network offering."` - EgressDefaultPolicy bool `json:"egressdefaultpolicy,omitempty" doc:"true if guest network default egress policy is allow; false if default egress policy is deny"` - GuestIPType string `json:"guestiptype,omitempty" doc:"guest type of the network offering, can be Shared or Isolated"` - ID string `json:"id,omitempty" doc:"the id of the network offering"` - IsDefault bool `json:"isdefault,omitempty" doc:"true if network offering is default, false otherwise"` - IsPersistent bool `json:"ispersistent,omitempty" doc:"true if network offering supports persistent networks, false otherwise"` - MaxConnections int `json:"maxconnections,omitempty" doc:"maximum number of concurrents connections to be handled by lb"` - Name string `json:"name,omitempty" doc:"the name of the network offering"` - NetworkRate int `json:"networkrate,omitempty" doc:"data transfer rate in megabits per second allowed."` - Service []Service `json:"service,omitempty" doc:"the list of supported services"` - ServiceOfferingID string `json:"serviceofferingid,omitempty" doc:"the ID of the service offering used by virtual router provider"` - SpecifyIPRanges bool `json:"specifyipranges,omitempty" doc:"true if network offering supports specifying ip ranges, false otherwise"` - SpecifyVlan bool `json:"specifyvlan,omitempty" doc:"true if network offering supports vlans, false otherwise"` - State string `json:"state,omitempty" doc:"state of the network offering. Can be Disabled/Enabled/Inactive"` - SupportsStrechedL2Subnet bool `json:"supportsstrechedl2subnet,omitempty" doc:"true if network offering supports network that span multiple zones"` - Tags string `json:"tags,omitempty" doc:"the tags for the network offering"` - TrafficType string `json:"traffictype,omitempty" doc:"the traffic type for the network offering, supported types are Public, Management, Control, Guest, Vlan or Storage."` -} - -// ListNetworkOfferings represents a query for network offerings -type ListNetworkOfferings struct { - Availability string `json:"availability,omitempty" doc:"the availability of network offering. Default value is Required"` - DisplayText string `json:"displaytext,omitempty" doc:"list network offerings by display text"` - GuestIPType string `json:"guestiptype,omitempty" doc:"list network offerings by guest type: Shared or Isolated"` - ID string `json:"id,omitempty" doc:"list network offerings by id"` - IsDefault *bool `json:"isdefault,omitempty" doc:"true if need to list only default network offerings. Default value is false"` - IsTagged *bool `json:"istagged,omitempty" doc:"true if offering has tags specified"` - Keyword string `json:"keyword,omitempty" doc:"List by keyword"` - Name string `json:"name,omitempty" doc:"list network offerings by name"` - NetworkID string `json:"networkid,omitempty" doc:"the ID of the network. Pass this in if you want to see the available network offering that a network can be changed to."` - Page int `json:"page,omitempty"` - PageSize int `json:"pagesize,omitempty"` - SourceNATSupported *bool `json:"sourcenatsupported,omitempty" doc:"true if need to list only netwok offerings where source nat is supported, false otherwise"` - SpecifyIPRanges *bool `json:"specifyipranges,omitempty" doc:"true if need to list only network offerings which support specifying ip ranges"` - SpecifyVlan *bool `json:"specifyvlan,omitempty" doc:"the tags for the network offering."` - State string `json:"state,omitempty" doc:"list network offerings by state"` - SupportedServices []Service `json:"supportedservices,omitempty" doc:"list network offerings supporting certain services"` - Tags string `json:"tags,omitempty" doc:"list network offerings by tags"` - TrafficType string `json:"traffictype,omitempty" doc:"list by traffic type"` - ZoneID string `json:"zoneid,omitempty" doc:"list netowrk offerings available for network creation in specific zone"` - _ bool `name:"listNetworkOfferings" description:"Lists all available network offerings."` -} - -// ListNetworkOfferingsResponse represents a list of service offerings -type ListNetworkOfferingsResponse struct { - Count int `json:"count"` - NetworkOffering []NetworkOffering `json:"networkoffering"` -} - -func (ListNetworkOfferings) response() interface{} { - return new(ListNetworkOfferingsResponse) -} - -// UpdateNetworkOffering represents a modification of a network offering -type UpdateNetworkOffering struct { - Availability string `json:"availability,omitempty" doc:"the availability of network offering. Default value is Required for Guest Virtual network offering; Optional for Guest Direct network offering"` - DisplayText string `json:"displaytext,omitempty" doc:"the display text of the network offering"` - ID string `json:"id,omitempty" doc:"the id of the network offering"` - KeepAliveEnabled *bool `json:"keepaliveenabled,omitempty" doc:"if true keepalive will be turned on in the loadbalancer. At the time of writing this has only an effect on haproxy; the mode http and httpclose options are unset in the haproxy conf file."` - MaxConnections int `json:"maxconnections,omitempty" doc:"maximum number of concurrent connections supported by the network offering"` - Name string `json:"name,omitempty" doc:"the name of the network offering"` - SortKey int `json:"sortkey,omitempty" doc:"sort key of the network offering, integer"` - State string `json:"state,omitempty" doc:"update state for the network offering"` - _ bool `name:"updateNetworkOffering" description:"Updates a network offering."` -} - -func (UpdateNetworkOffering) response() interface{} { - return new(NetworkOffering) -} diff --git a/vendor/github.com/exoscale/egoscale/networks.go b/vendor/github.com/exoscale/egoscale/networks.go index 59fdec9ee..6a6e1d81f 100644 --- a/vendor/github.com/exoscale/egoscale/networks.go +++ b/vendor/github.com/exoscale/egoscale/networks.go @@ -1,7 +1,6 @@ package egoscale import ( - "fmt" "net" "net/url" ) @@ -10,59 +9,52 @@ import ( // // See: http://docs.cloudstack.apache.org/projects/cloudstack-administration/en/latest/networking_and_traffic.html type Network struct { - Account string `json:"account,omitempty" doc:"the owner of the network"` - AccountID string `json:"accountid,omitempty" doc:"the owner ID of the network"` - BroadcastDomainType string `json:"broadcastdomaintype,omitempty" doc:"Broadcast domain type of the network"` - BroadcastURI string `json:"broadcasturi,omitempty" doc:"broadcast uri of the network."` - CanUseForDeploy bool `json:"canusefordeploy,omitempty" doc:"list networks available for vm deployment"` - CIDR *CIDR `json:"cidr,omitempty" doc:"Cloudstack managed address space, all CloudStack managed VMs get IP address from CIDR"` - DisplayNetwork bool `json:"displaynetwork,omitempty" doc:"an optional field, whether to the display the network to the end user or not."` - DisplayText string `json:"displaytext,omitempty" doc:"the displaytext of the network"` - DNS1 net.IP `json:"dns1,omitempty" doc:"the first DNS for the network"` - DNS2 net.IP `json:"dns2,omitempty" doc:"the second DNS for the network"` - Domain string `json:"domain,omitempty" doc:"the domain name of the network owner"` - DomainID string `json:"domainid,omitempty" doc:"the domain id of the network owner"` - Gateway net.IP `json:"gateway,omitempty" doc:"the network's gateway"` - ID string `json:"id,omitempty" doc:"the id of the network"` - IP6CIDR *CIDR `json:"ip6cidr,omitempty" doc:"the cidr of IPv6 network"` - IP6Gateway net.IP `json:"ip6gateway,omitempty" doc:"the gateway of IPv6 network"` - IsDefault bool `json:"isdefault,omitempty" doc:"true if network is default, false otherwise"` - IsPersistent bool `json:"ispersistent,omitempty" doc:"list networks that are persistent"` - IsSystem bool `json:"issystem,omitempty" doc:"true if network is system, false otherwise"` - Name string `json:"name,omitempty" doc:"the name of the network"` - Netmask net.IP `json:"netmask,omitempty" doc:"the network's netmask"` - NetworkCIDR *CIDR `json:"networkcidr,omitempty" doc:"the network CIDR of the guest network configured with IP reservation. It is the summation of CIDR and RESERVED_IP_RANGE"` - NetworkDomain string `json:"networkdomain,omitempty" doc:"the network domain"` - NetworkOfferingAvailability string `json:"networkofferingavailability,omitempty" doc:"availability of the network offering the network is created from"` - NetworkOfferingConserveMode bool `json:"networkofferingconservemode,omitempty" doc:"true if network offering is ip conserve mode enabled"` - NetworkOfferingDisplayText string `json:"networkofferingdisplaytext,omitempty" doc:"display text of the network offering the network is created from"` - NetworkOfferingID string `json:"networkofferingid,omitempty" doc:"network offering id the network is created from"` - NetworkOfferingName string `json:"networkofferingname,omitempty" doc:"name of the network offering the network is created from"` - PhysicalNetworkID string `json:"physicalnetworkid,omitempty" doc:"the physical network id"` - Related string `json:"related,omitempty" doc:"related to what other network configuration"` - ReservedIPRange string `json:"reservediprange,omitempty" doc:"the network's IP range not to be used by CloudStack guest VMs and can be used for non CloudStack purposes"` - RestartRequired bool `json:"restartrequired,omitempty" doc:"true network requires restart"` - Service []Service `json:"service,omitempty" doc:"the list of services"` - SpecifyIPRanges bool `json:"specifyipranges,omitempty" doc:"true if network supports specifying ip ranges, false otherwise"` - State string `json:"state,omitempty" doc:"state of the network"` - StrechedL2Subnet bool `json:"strechedl2subnet,omitempty" doc:"true if network can span multiple zones"` - SubdomainAccess bool `json:"subdomainaccess,omitempty" doc:"true if users from subdomains can access the domain level network"` - Tags []ResourceTag `json:"tags,omitempty" doc:"the list of resource tags associated with network"` - TrafficType string `json:"traffictype,omitempty" doc:"the traffic type of the network"` - Type string `json:"type,omitempty" doc:"the type of the network"` - Vlan string `json:"vlan,omitemtpy" doc:"The vlan of the network. This parameter is visible to ROOT admins only"` - ZoneID string `json:"zoneid,omitempty" doc:"zone id of the network"` - ZoneName string `json:"zonename,omitempty" doc:"the name of the zone the network belongs to"` - ZonesNetworkSpans []Zone `json:"zonesnetworkspans,omitempty" doc:"If a network is enabled for 'streched l2 subnet' then represents zones on which network currently spans"` + Account string `json:"account,omitempty" doc:"the owner of the network"` + AccountID *UUID `json:"accountid,omitempty" doc:"the owner ID of the network"` + BroadcastDomainType string `json:"broadcastdomaintype,omitempty" doc:"Broadcast domain type of the network"` + BroadcastURI string `json:"broadcasturi,omitempty" doc:"broadcast uri of the network."` + CanUseForDeploy bool `json:"canusefordeploy,omitempty" doc:"list networks available for vm deployment"` + CIDR *CIDR `json:"cidr,omitempty" doc:"Cloudstack managed address space, all CloudStack managed VMs get IP address from CIDR"` + DisplayText string `json:"displaytext,omitempty" doc:"the displaytext of the network"` + DNS1 net.IP `json:"dns1,omitempty" doc:"the first DNS for the network"` + DNS2 net.IP `json:"dns2,omitempty" doc:"the second DNS for the network"` + EndIP net.IP `json:"endip,omitempty" doc:"the ending IP address in the network IP range. Required for managed networks."` + Gateway net.IP `json:"gateway,omitempty" doc:"the network's gateway"` + ID *UUID `json:"id,omitempty" doc:"the id of the network"` + IP6CIDR *CIDR `json:"ip6cidr,omitempty" doc:"the cidr of IPv6 network"` + IP6Gateway net.IP `json:"ip6gateway,omitempty" doc:"the gateway of IPv6 network"` + IsDefault bool `json:"isdefault,omitempty" doc:"true if network is default, false otherwise"` + IsPersistent bool `json:"ispersistent,omitempty" doc:"list networks that are persistent"` + IsSystem bool `json:"issystem,omitempty" doc:"true if network is system, false otherwise"` + Name string `json:"name,omitempty" doc:"the name of the network"` + Netmask net.IP `json:"netmask,omitempty" doc:"the network's netmask"` + NetworkCIDR *CIDR `json:"networkcidr,omitempty" doc:"the network CIDR of the guest network configured with IP reservation. It is the summation of CIDR and RESERVED_IP_RANGE"` + NetworkDomain string `json:"networkdomain,omitempty" doc:"the network domain"` + PhysicalNetworkID *UUID `json:"physicalnetworkid,omitempty" doc:"the physical network id"` + Related string `json:"related,omitempty" doc:"related to what other network configuration"` + ReservedIPRange string `json:"reservediprange,omitempty" doc:"the network's IP range not to be used by CloudStack guest VMs and can be used for non CloudStack purposes"` + RestartRequired bool `json:"restartrequired,omitempty" doc:"true network requires restart"` + Service []Service `json:"service,omitempty" doc:"the list of services"` + SpecifyIPRanges bool `json:"specifyipranges,omitempty" doc:"true if network supports specifying ip ranges, false otherwise"` + StartIP net.IP `json:"startip,omitempty" doc:"the beginning IP address in the network IP range. Required for managed networks."` + State string `json:"state,omitempty" doc:"state of the network"` + StrechedL2Subnet bool `json:"strechedl2subnet,omitempty" doc:"true if network can span multiple zones"` + SubdomainAccess bool `json:"subdomainaccess,omitempty" doc:"true if users from subdomains can access the domain level network"` + Tags []ResourceTag `json:"tags,omitempty" doc:"the list of resource tags associated with network"` + TrafficType string `json:"traffictype,omitempty" doc:"the traffic type of the network"` + Type string `json:"type,omitempty" doc:"the type of the network"` + Vlan string `json:"vlan,omitemtpy" doc:"The vlan of the network. This parameter is visible to ROOT admins only"` + ZoneID *UUID `json:"zoneid,omitempty" doc:"zone id of the network"` + ZoneName string `json:"zonename,omitempty" doc:"the name of the zone the network belongs to"` + ZonesNetworkSpans []Zone `json:"zonesnetworkspans,omitempty" doc:"If a network is enabled for 'streched l2 subnet' then represents zones on which network currently spans"` } // ListRequest builds the ListNetworks request func (network Network) ListRequest() (ListCommand, error) { //TODO add tags support req := &ListNetworks{ - Account: network.Account, - DomainID: network.DomainID, ID: network.ID, + Keyword: network.Name, // this is a hack as listNetworks doesn't support to search by name. PhysicalNetworkID: network.PhysicalNetworkID, TrafficType: network.TrafficType, Type: network.Type, @@ -101,39 +93,35 @@ type ServiceCapability struct { // ServiceProvider represents the provider of the service type ServiceProvider struct { CanEnableIndividualService bool `json:"canenableindividualservice"` - DestinationPhysicalNetworkID string `json:"destinationphysicalnetworkid"` - ID string `json:"id"` + DestinationPhysicalNetworkID *UUID `json:"destinationphysicalnetworkid"` + ID *UUID `json:"id"` Name string `json:"name"` - PhysicalNetworkID string `json:"physicalnetworkid"` + PhysicalNetworkID *UUID `json:"physicalnetworkid"` ServiceList []string `json:"servicelist,omitempty"` } // CreateNetwork creates a network type CreateNetwork struct { - Account string `json:"account,omitempty" doc:"account who will own the network"` - DisplayNetwork *bool `json:"displaynetwork,omitempty" doc:"an optional field, whether to the display the network to the end user or not."` DisplayText string `json:"displaytext,omitempty" doc:"the display text of the network"` // This field is required but might be empty - DomainID string `json:"domainid,omitempty" doc:"domain ID of the account owning a network"` - EndIP net.IP `json:"endip,omitempty" doc:"the ending IP address in the network IP range. If not specified, will be defaulted to startIP"` + EndIP net.IP `json:"endip,omitempty" doc:"the ending IP address in the network IP range. Required for managed networks."` EndIpv6 net.IP `json:"endipv6,omitempty" doc:"the ending IPv6 address in the IPv6 network range"` Gateway net.IP `json:"gateway,omitempty" doc:"the gateway of the network. Required for Shared networks and Isolated networks when it belongs to VPC"` IP6CIDR *CIDR `json:"ip6cidr,omitempty" doc:"the CIDR of IPv6 network, must be at least /64"` IP6Gateway net.IP `json:"ip6gateway,omitempty" doc:"the gateway of the IPv6 network. Required for Shared networks and Isolated networks when it belongs to VPC"` IsolatedPVlan string `json:"isolatedpvlan,omitempty" doc:"the isolated private vlan for this network"` Name string `json:"name,omitempty" doc:"the name of the network"` // This field is required but might be empty - Netmask net.IP `json:"netmask,omitempty" doc:"the netmask of the network. Required for Shared networks and Isolated networks when it belongs to VPC"` + Netmask net.IP `json:"netmask,omitempty" doc:"the netmask of the network. Required for managed networks."` NetworkDomain string `json:"networkdomain,omitempty" doc:"network domain"` - NetworkOfferingID string `json:"networkofferingid" doc:"the network offering id"` - PhysicalNetworkID string `json:"physicalnetworkid,omitempty" doc:"the Physical Network ID the network belongs to"` - StartIP net.IP `json:"startip,omitempty" doc:"the beginning IP address in the network IP range"` + PhysicalNetworkID *UUID `json:"physicalnetworkid,omitempty" doc:"the Physical Network ID the network belongs to"` + StartIP net.IP `json:"startip,omitempty" doc:"the beginning IP address in the network IP range. Required for managed networks."` StartIpv6 net.IP `json:"startipv6,omitempty" doc:"the beginning IPv6 address in the IPv6 network range"` - SubdomainAccess *bool `json:"subdomainaccess,omitempty" doc:"Defines whether to allow subdomains to use networks dedicated to their parent domain(s). Should be used with aclType=Domain, defaulted to allow.subdomain.network.access global config if not specified"` Vlan string `json:"vlan,omitempty" doc:"the ID or VID of the network"` - ZoneID string `json:"zoneid" doc:"the Zone ID for the network"` + ZoneID *UUID `json:"zoneid" doc:"the Zone ID for the network"` _ bool `name:"createNetwork" description:"Creates a network"` } -func (CreateNetwork) response() interface{} { +// Response returns the struct to unmarshal +func (CreateNetwork) Response() interface{} { return new(Network) } @@ -150,77 +138,80 @@ func (req CreateNetwork) onBeforeSend(params url.Values) error { // UpdateNetwork (Async) updates a network type UpdateNetwork struct { - ID string `json:"id" doc:"the ID of the network"` - ChangeCidr *bool `json:"changecidr,omitempty" doc:"Force update even if cidr type is different"` - CustomID string `json:"customid,omitempty" doc:"an optional field, in case you want to set a custom id to the resource. Allowed to Root Admins only"` - DisplayNetwork *bool `json:"displaynetwork,omitempty" doc:"an optional field, whether to the display the network to the end user or not."` - DisplayText string `json:"displaytext,omitempty" doc:"the new display text for the network"` - GuestVMCidr string `json:"guestvmcidr,omitempty" doc:"CIDR for Guest VMs,Cloudstack allocates IPs to Guest VMs only from this CIDR"` - Name string `json:"name,omitempty" doc:"the new name for the network"` - NetworkDomain string `json:"networkdomain,omitempty" doc:"network domain"` - NetworkOfferingID string `json:"networkofferingid,omitempty" doc:"network offering ID"` - _ bool `name:"updateNetwork" description:"Updates a network"` + _ bool `name:"updateNetwork" description:"Updates a network"` + ChangeCIDR *bool `json:"changecidr,omitempty" doc:"Force update even if cidr type is different"` + DisplayText string `json:"displaytext,omitempty" doc:"the new display text for the network"` + EndIP net.IP `json:"endip,omitempty" doc:"the ending IP address in the network IP range. Required for managed networks."` + GuestVMCIDR *CIDR `json:"guestvmcidr,omitempty" doc:"CIDR for Guest VMs,Cloudstack allocates IPs to Guest VMs only from this CIDR"` + ID *UUID `json:"id" doc:"the ID of the network"` + Name string `json:"name,omitempty" doc:"the new name for the network"` + Netmask net.IP `json:"netmask,omitempty" doc:"the netmask of the network. Required for managed networks."` + NetworkDomain string `json:"networkdomain,omitempty" doc:"network domain"` + StartIP net.IP `json:"startip,omitempty" doc:"the beginning IP address in the network IP range. Required for managed networks."` } -func (UpdateNetwork) response() interface{} { +// Response returns the struct to unmarshal +func (UpdateNetwork) Response() interface{} { return new(AsyncJobResult) } -func (UpdateNetwork) asyncResponse() interface{} { +// AsyncResponse returns the struct to unmarshal the async job +func (UpdateNetwork) AsyncResponse() interface{} { return new(Network) } // RestartNetwork (Async) updates a network type RestartNetwork struct { - ID string `json:"id" doc:"The id of the network to restart."` - Cleanup *bool `json:"cleanup,omitempty" doc:"If cleanup old network elements"` - _ bool `name:"restartNetwork" description:"Restarts the network; includes 1) restarting network elements - virtual routers, dhcp servers 2) reapplying all public ips 3) reapplying loadBalancing/portForwarding rules"` + ID *UUID `json:"id" doc:"The id of the network to restart."` + Cleanup *bool `json:"cleanup,omitempty" doc:"If cleanup old network elements"` + _ bool `name:"restartNetwork" description:"Restarts the network; includes 1) restarting network elements - virtual routers, dhcp servers 2) reapplying all public ips 3) reapplying loadBalancing/portForwarding rules"` } -func (RestartNetwork) response() interface{} { +// Response returns the struct to unmarshal +func (RestartNetwork) Response() interface{} { return new(AsyncJobResult) } -func (RestartNetwork) asyncResponse() interface{} { +// AsyncResponse returns the struct to unmarshal the async job +func (RestartNetwork) AsyncResponse() interface{} { return new(Network) } // DeleteNetwork deletes a network type DeleteNetwork struct { - ID string `json:"id" doc:"the ID of the network"` - Forced *bool `json:"forced,omitempty" doc:"Force delete a network. Network will be marked as 'Destroy' even when commands to shutdown and cleanup to the backend fails."` - _ bool `name:"deleteNetwork" description:"Deletes a network"` + ID *UUID `json:"id" doc:"the ID of the network"` + Forced *bool `json:"forced,omitempty" doc:"Force delete a network. Network will be marked as 'Destroy' even when commands to shutdown and cleanup to the backend fails."` + _ bool `name:"deleteNetwork" description:"Deletes a network"` } -func (DeleteNetwork) response() interface{} { +// Response returns the struct to unmarshal +func (DeleteNetwork) Response() interface{} { return new(AsyncJobResult) } -func (DeleteNetwork) asyncResponse() interface{} { - return new(booleanResponse) +// AsyncResponse returns the struct to unmarshal the async job +func (DeleteNetwork) AsyncResponse() interface{} { + return new(BooleanResponse) } +//go:generate go run generate/main.go -interface=Listable ListNetworks + // ListNetworks represents a query to a network type ListNetworks struct { - Account string `json:"account,omitempty" doc:"list resources by account. Must be used with the domainId parameter."` - CanUseForDeploy *bool `json:"canusefordeploy,omitempty" doc:"list networks available for vm deployment"` - DisplayNetwork *bool `json:"displaynetwork,omitempty" doc:"list resources by display flag; only ROOT admin is eligible to pass this parameter"` - DomainID string `json:"domainid,omitempty" doc:"list only resources belonging to the domain specified"` - ID string `json:"id,omitempty" doc:"list networks by id"` - IsRecursive *bool `json:"isrecursive,omitempty" doc:"defaults to false, but if true, lists all resources from the parent specified by the domainId till leaves."` - IsSystem *bool `json:"issystem,omitempty" doc:"true if network is system, false otherwise"` + CanUseForDeploy *bool `json:"canusefordeploy,omitempty" doc:"List networks available for vm deployment"` + ID *UUID `json:"id,omitempty" doc:"List networks by id"` + IsSystem *bool `json:"issystem,omitempty" doc:"true If network is system, false otherwise"` Keyword string `json:"keyword,omitempty" doc:"List by keyword"` - ListAll *bool `json:"listall,omitempty" doc:"If set to false, list only resources belonging to the command's caller; if set to true - list resources that the caller is authorized to see. Default value is false"` Page int `json:"page,omitempty"` PageSize int `json:"pagesize,omitempty"` - PhysicalNetworkID string `json:"physicalnetworkid,omitempty" doc:"list networks by physical network id"` - RestartRequired *bool `json:"restartrequired,omitempty" doc:"list networks by restartRequired"` - SpecifyIPRanges *bool `json:"specifyipranges,omitempty" doc:"true if need to list only networks which support specifying ip ranges"` - SupportedServices []Service `json:"supportedservices,omitempty" doc:"list networks supporting certain services"` + PhysicalNetworkID *UUID `json:"physicalnetworkid,omitempty" doc:"List networks by physical network id"` + RestartRequired *bool `json:"restartrequired,omitempty" doc:"List networks by restartRequired"` + SpecifyIPRanges *bool `json:"specifyipranges,omitempty" doc:"True if need to list only networks which support specifying ip ranges"` + SupportedServices []Service `json:"supportedservices,omitempty" doc:"List networks supporting certain services"` Tags []ResourceTag `json:"tags,omitempty" doc:"List resources by tags (key/value pairs)"` - TrafficType string `json:"traffictype,omitempty" doc:"type of the traffic"` - Type string `json:"type,omitempty" doc:"the type of the network. Supported values are: Isolated and Shared"` - ZoneID string `json:"zoneid,omitempty" doc:"the Zone ID of the network"` + TrafficType string `json:"traffictype,omitempty" doc:"Type of the traffic"` + Type string `json:"type,omitempty" doc:"The type of the network. Supported values are: Isolated and Shared"` + ZoneID *UUID `json:"zoneid,omitempty" doc:"The Zone ID of the network"` _ bool `name:"listNetworks" description:"Lists all available networks."` } @@ -229,31 +220,3 @@ type ListNetworksResponse struct { Count int `json:"count"` Network []Network `json:"network"` } - -func (ListNetworks) response() interface{} { - return new(ListNetworksResponse) -} - -// SetPage sets the current page -func (listNetwork *ListNetworks) SetPage(page int) { - listNetwork.Page = page -} - -// SetPageSize sets the page size -func (listNetwork *ListNetworks) SetPageSize(pageSize int) { - listNetwork.PageSize = pageSize -} - -func (ListNetworks) each(resp interface{}, callback IterateItemFunc) { - networks, ok := resp.(*ListNetworksResponse) - if !ok { - callback(nil, fmt.Errorf("type error: ListNetworksResponse expected, got %T", resp)) - return - } - - for i := range networks.Network { - if !callback(&networks.Network[i], nil) { - break - } - } -} diff --git a/vendor/github.com/exoscale/egoscale/networks_response.go b/vendor/github.com/exoscale/egoscale/networks_response.go new file mode 100644 index 000000000..058890624 --- /dev/null +++ b/vendor/github.com/exoscale/egoscale/networks_response.go @@ -0,0 +1,43 @@ +// code generated; DO NOT EDIT. + +package egoscale + +import "fmt" + +// Response returns the struct to unmarshal +func (ListNetworks) Response() interface{} { + return new(ListNetworksResponse) +} + +// ListRequest returns itself +func (ls *ListNetworks) ListRequest() (ListCommand, error) { + if ls == nil { + return nil, fmt.Errorf("%T cannot be nil", ls) + } + return ls, nil +} + +// SetPage sets the current apge +func (ls *ListNetworks) SetPage(page int) { + ls.Page = page +} + +// SetPageSize sets the page size +func (ls *ListNetworks) SetPageSize(pageSize int) { + ls.PageSize = pageSize +} + +// Each triggers the callback for each, valid answer or any non 404 issue +func (ListNetworks) Each(resp interface{}, callback IterateItemFunc) { + items, ok := resp.(*ListNetworksResponse) + if !ok { + callback(nil, fmt.Errorf("wrong type, ListNetworksResponse was expected, got %T", resp)) + return + } + + for i := range items.Network { + if !callback(&items.Network[i], nil) { + break + } + } +} diff --git a/vendor/github.com/exoscale/egoscale/nics.go b/vendor/github.com/exoscale/egoscale/nics.go index 996945a44..755e70395 100644 --- a/vendor/github.com/exoscale/egoscale/nics.go +++ b/vendor/github.com/exoscale/egoscale/nics.go @@ -1,7 +1,6 @@ package egoscale import ( - "errors" "net" ) @@ -10,9 +9,9 @@ import ( // See: http://docs.cloudstack.apache.org/projects/cloudstack-administration/en/latest/networking_and_traffic.html#configuring-multiple-ip-addresses-on-a-single-nic type Nic struct { BroadcastURI string `json:"broadcasturi,omitempty" doc:"the broadcast uri of the nic"` - DeviceID string `json:"deviceid,omitempty" doc:"device id for the network when plugged into the virtual machine"` + DeviceID *UUID `json:"deviceid,omitempty" doc:"device id for the network when plugged into the virtual machine"` Gateway net.IP `json:"gateway,omitempty" doc:"the gateway of the nic"` - ID string `json:"id,omitempty" doc:"the ID of the nic"` + ID *UUID `json:"id,omitempty" doc:"the ID of the nic"` IP6Address net.IP `json:"ip6address,omitempty" doc:"the IPv6 address of network"` IP6CIDR *CIDR `json:"ip6cidr,omitempty" doc:"the cidr of IPv6 network"` IP6Gateway net.IP `json:"ip6gateway,omitempty" doc:"the gateway of IPv6 network"` @@ -21,21 +20,17 @@ type Nic struct { IsolationURI string `json:"isolationuri,omitempty" doc:"the isolation uri of the nic"` MACAddress MACAddress `json:"macaddress,omitempty" doc:"true if nic is default, false otherwise"` Netmask net.IP `json:"netmask,omitempty" doc:"the netmask of the nic"` - NetworkID string `json:"networkid,omitempty" doc:"the ID of the corresponding network"` + NetworkID *UUID `json:"networkid,omitempty" doc:"the ID of the corresponding network"` NetworkName string `json:"networkname,omitempty" doc:"the name of the corresponding network"` ReverseDNS []ReverseDNS `json:"reversedns,omitempty" doc:"the list of PTR record(s) associated with the virtual machine"` SecondaryIP []NicSecondaryIP `json:"secondaryip,omitempty" doc:"the Secondary ipv4 addr of nic"` TrafficType string `json:"traffictype,omitempty" doc:"the traffic type of the nic"` Type string `json:"type,omitempty" doc:"the type of the nic"` - VirtualMachineID string `json:"virtualmachineid,omitempty" doc:"Id of the vm to which the nic belongs"` + VirtualMachineID *UUID `json:"virtualmachineid,omitempty" doc:"Id of the vm to which the nic belongs"` } // ListRequest build a ListNics request from the given Nic func (nic Nic) ListRequest() (ListCommand, error) { - if nic.VirtualMachineID == "" { - return nil, errors.New("command ListNics requires the VirtualMachineID field to be set") - } - req := &ListNics{ VirtualMachineID: nic.VirtualMachineID, NicID: nic.ID, @@ -47,22 +42,23 @@ func (nic Nic) ListRequest() (ListCommand, error) { // NicSecondaryIP represents a link between NicID and IPAddress type NicSecondaryIP struct { - ID string `json:"id,omitempty" doc:"the ID of the secondary private IP addr"` + ID *UUID `json:"id,omitempty" doc:"the ID of the secondary private IP addr"` IPAddress net.IP `json:"ipaddress,omitempty" doc:"Secondary IP address"` - NetworkID string `json:"networkid,omitempty" doc:"the ID of the network"` - NicID string `json:"nicid,omitempty" doc:"the ID of the nic"` - VirtualMachineID string `json:"virtualmachineid,omitempty" doc:"the ID of the vm"` + NetworkID *UUID `json:"networkid,omitempty" doc:"the ID of the network"` + NicID *UUID `json:"nicid,omitempty" doc:"the ID of the nic"` + VirtualMachineID *UUID `json:"virtualmachineid,omitempty" doc:"the ID of the vm"` } +//go:generate go run generate/main.go -interface=Listable ListNics + // ListNics represents the NIC search type ListNics struct { - ForDisplay bool `json:"fordisplay,omitempty" doc:"list resources by display flag; only ROOT admin is eligible to pass this parameter"` Keyword string `json:"keyword,omitempty" doc:"List by keyword"` - NetworkID string `json:"networkid,omitempty" doc:"list nic of the specific vm's network"` - NicID string `json:"nicid,omitempty" doc:"the ID of the nic to to list IPs"` + NetworkID *UUID `json:"networkid,omitempty" doc:"list nic of the specific vm's network"` + NicID *UUID `json:"nicid,omitempty" doc:"the ID of the nic to to list IPs"` Page int `json:"page,omitempty"` PageSize int `json:"pagesize,omitempty"` - VirtualMachineID string `json:"virtualmachineid" doc:"the ID of the vm"` + VirtualMachineID *UUID `json:"virtualmachineid,omitempty" doc:"the ID of the vm"` _ bool `name:"listNics" description:"list the vm nics IP to NIC"` } @@ -72,70 +68,53 @@ type ListNicsResponse struct { Nic []Nic `json:"nic"` } -func (ListNics) response() interface{} { - return new(ListNicsResponse) -} - -// SetPage sets the current page -func (ls *ListNics) SetPage(page int) { - ls.Page = page -} - -// SetPageSize sets the page size -func (ls *ListNics) SetPageSize(pageSize int) { - ls.PageSize = pageSize -} - -func (ListNics) each(resp interface{}, callback IterateItemFunc) { - nics := resp.(*ListNicsResponse) - for i := range nics.Nic { - if !callback(&(nics.Nic[i]), nil) { - break - } - } -} - // AddIPToNic (Async) represents the assignation of a secondary IP type AddIPToNic struct { - NicID string `json:"nicid" doc:"the ID of the nic to which you want to assign private IP"` + NicID *UUID `json:"nicid" doc:"the ID of the nic to which you want to assign private IP"` IPAddress net.IP `json:"ipaddress,omitempty" doc:"Secondary IP Address"` _ bool `name:"addIpToNic" description:"Assigns secondary IP to NIC"` } -func (AddIPToNic) response() interface{} { +// Response returns the struct to unmarshal +func (AddIPToNic) Response() interface{} { return new(AsyncJobResult) } -func (AddIPToNic) asyncResponse() interface{} { +// AsyncResponse returns the struct to unmarshal the async job +func (AddIPToNic) AsyncResponse() interface{} { return new(NicSecondaryIP) } // RemoveIPFromNic (Async) represents a deletion request type RemoveIPFromNic struct { - ID string `json:"id" doc:"the ID of the secondary ip address to nic"` - _ bool `name:"removeIpFromNic" description:"Removes secondary IP from the NIC."` + ID *UUID `json:"id" doc:"the ID of the secondary ip address to nic"` + _ bool `name:"removeIpFromNic" description:"Removes secondary IP from the NIC."` } -func (RemoveIPFromNic) response() interface{} { +// Response returns the struct to unmarshal +func (RemoveIPFromNic) Response() interface{} { return new(AsyncJobResult) } -func (RemoveIPFromNic) asyncResponse() interface{} { - return new(booleanResponse) +// AsyncResponse returns the struct to unmarshal the async job +func (RemoveIPFromNic) AsyncResponse() interface{} { + return new(BooleanResponse) } // ActivateIP6 (Async) activates the IP6 on the given NIC // -// Exoscale specific API: https://community.exoscale.ch/api/compute/#activateip6_GET +// Exoscale specific API: https://community.exoscale.com/api/compute/#activateip6_GET type ActivateIP6 struct { - NicID string `json:"nicid" doc:"the ID of the nic to which you want to assign the IPv6"` - _ bool `name:"activateIp6" description:"Activate the IPv6 on the VM's nic"` + NicID *UUID `json:"nicid" doc:"the ID of the nic to which you want to assign the IPv6"` + _ bool `name:"activateIp6" description:"Activate the IPv6 on the VM's nic"` } -func (ActivateIP6) response() interface{} { +// Response returns the struct to unmarshal +func (ActivateIP6) Response() interface{} { return new(AsyncJobResult) } -func (ActivateIP6) asyncResponse() interface{} { +// AsyncResponse returns the struct to unmarshal the async job +func (ActivateIP6) AsyncResponse() interface{} { return new(Nic) } diff --git a/vendor/github.com/exoscale/egoscale/nics_response.go b/vendor/github.com/exoscale/egoscale/nics_response.go new file mode 100644 index 000000000..dcf960915 --- /dev/null +++ b/vendor/github.com/exoscale/egoscale/nics_response.go @@ -0,0 +1,43 @@ +// code generated; DO NOT EDIT. + +package egoscale + +import "fmt" + +// Response returns the struct to unmarshal +func (ListNics) Response() interface{} { + return new(ListNicsResponse) +} + +// ListRequest returns itself +func (ls *ListNics) ListRequest() (ListCommand, error) { + if ls == nil { + return nil, fmt.Errorf("%T cannot be nil", ls) + } + return ls, nil +} + +// SetPage sets the current apge +func (ls *ListNics) SetPage(page int) { + ls.Page = page +} + +// SetPageSize sets the page size +func (ls *ListNics) SetPageSize(pageSize int) { + ls.PageSize = pageSize +} + +// Each triggers the callback for each, valid answer or any non 404 issue +func (ListNics) Each(resp interface{}, callback IterateItemFunc) { + items, ok := resp.(*ListNicsResponse) + if !ok { + callback(nil, fmt.Errorf("wrong type, ListNicsResponse was expected, got %T", resp)) + return + } + + for i := range items.Nic { + if !callback(&items.Nic[i], nil) { + break + } + } +} diff --git a/vendor/github.com/exoscale/egoscale/oscategories_response.go b/vendor/github.com/exoscale/egoscale/oscategories_response.go new file mode 100644 index 000000000..985f875df --- /dev/null +++ b/vendor/github.com/exoscale/egoscale/oscategories_response.go @@ -0,0 +1,43 @@ +// code generated; DO NOT EDIT. + +package egoscale + +import "fmt" + +// Response returns the struct to unmarshal +func (ListOSCategories) Response() interface{} { + return new(ListOSCategoriesResponse) +} + +// ListRequest returns itself +func (ls *ListOSCategories) ListRequest() (ListCommand, error) { + if ls == nil { + return nil, fmt.Errorf("%T cannot be nil", ls) + } + return ls, nil +} + +// SetPage sets the current apge +func (ls *ListOSCategories) SetPage(page int) { + ls.Page = page +} + +// SetPageSize sets the page size +func (ls *ListOSCategories) SetPageSize(pageSize int) { + ls.PageSize = pageSize +} + +// Each triggers the callback for each, valid answer or any non 404 issue +func (ListOSCategories) Each(resp interface{}, callback IterateItemFunc) { + items, ok := resp.(*ListOSCategoriesResponse) + if !ok { + callback(nil, fmt.Errorf("wrong type, ListOSCategoriesResponse was expected, got %T", resp)) + return + } + + for i := range items.OSCategory { + if !callback(&items.OSCategory[i], nil) { + break + } + } +} diff --git a/vendor/github.com/exoscale/egoscale/publicipaddresses_response.go b/vendor/github.com/exoscale/egoscale/publicipaddresses_response.go new file mode 100644 index 000000000..2ee92bd7a --- /dev/null +++ b/vendor/github.com/exoscale/egoscale/publicipaddresses_response.go @@ -0,0 +1,43 @@ +// code generated; DO NOT EDIT. + +package egoscale + +import "fmt" + +// Response returns the struct to unmarshal +func (ListPublicIPAddresses) Response() interface{} { + return new(ListPublicIPAddressesResponse) +} + +// ListRequest returns itself +func (ls *ListPublicIPAddresses) ListRequest() (ListCommand, error) { + if ls == nil { + return nil, fmt.Errorf("%T cannot be nil", ls) + } + return ls, nil +} + +// SetPage sets the current apge +func (ls *ListPublicIPAddresses) SetPage(page int) { + ls.Page = page +} + +// SetPageSize sets the page size +func (ls *ListPublicIPAddresses) SetPageSize(pageSize int) { + ls.PageSize = pageSize +} + +// Each triggers the callback for each, valid answer or any non 404 issue +func (ListPublicIPAddresses) Each(resp interface{}, callback IterateItemFunc) { + items, ok := resp.(*ListPublicIPAddressesResponse) + if !ok { + callback(nil, fmt.Errorf("wrong type, ListPublicIPAddressesResponse was expected, got %T", resp)) + return + } + + for i := range items.PublicIPAddress { + if !callback(&items.PublicIPAddress[i], nil) { + break + } + } +} diff --git a/vendor/github.com/exoscale/egoscale/record_string.go b/vendor/github.com/exoscale/egoscale/record_string.go index b84303bb7..71285c696 100644 --- a/vendor/github.com/exoscale/egoscale/record_string.go +++ b/vendor/github.com/exoscale/egoscale/record_string.go @@ -4,6 +4,26 @@ package egoscale import "strconv" +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[A-0] + _ = x[AAAA-1] + _ = x[ALIAS-2] + _ = x[CNAME-3] + _ = x[HINFO-4] + _ = x[MX-5] + _ = x[NAPTR-6] + _ = x[NS-7] + _ = x[POOL-8] + _ = x[SPF-9] + _ = x[SRV-10] + _ = x[SSHFP-11] + _ = x[TXT-12] + _ = x[URL-13] +} + const _Record_name = "AAAAAALIASCNAMEHINFOMXNAPTRNSPOOLSPFSRVSSHFPTXTURL" var _Record_index = [...]uint8{0, 1, 5, 10, 15, 20, 22, 27, 29, 33, 36, 39, 44, 47, 50} diff --git a/vendor/github.com/exoscale/egoscale/request.go b/vendor/github.com/exoscale/egoscale/request.go index adf24fced..079c626c0 100644 --- a/vendor/github.com/exoscale/egoscale/request.go +++ b/vendor/github.com/exoscale/egoscale/request.go @@ -24,7 +24,7 @@ func (e ErrorResponse) Error() string { } // Error formats a CloudStack job response into a standard error -func (e booleanResponse) Error() error { +func (e BooleanResponse) Error() error { if !e.Success { return fmt.Errorf("API error: %s", e.DisplayText) } @@ -32,7 +32,20 @@ func (e booleanResponse) Error() error { return nil } -func (client *Client) parseResponse(resp *http.Response, key string) (json.RawMessage, error) { +func responseKey(key string) (string, bool) { + // XXX: addIpToNic, activateIp6, restorevmresponse are kind of special + var responseKeys = map[string]string{ + "addiptonicresponse": "addiptovmnicresponse", + "activateip6response": "activateip6nicresponse", + "restorevirtualmachineresponse": "restorevmresponse", + "updatevmaffinitygroupresponse": "updatevirtualmachineresponse", + } + + k, ok := responseKeys[key] + return k, ok +} + +func (client *Client) parseResponse(resp *http.Response, apiName string) (json.RawMessage, error) { b, err := ioutil.ReadAll(resp.Body) if err != nil { return nil, err @@ -43,14 +56,24 @@ func (client *Client) parseResponse(resp *http.Response, key string) (json.RawMe return nil, err } + key := fmt.Sprintf("%sresponse", strings.ToLower(apiName)) response, ok := m[key] if !ok { if resp.StatusCode >= 400 { response, ok = m["errorresponse"] } + if !ok { - for k := range m { - return nil, fmt.Errorf("malformed JSON response, %q was expected, got %q", key, k) + // try again with the special keys + value, ok := responseKey(key) + if ok { + key = value + } + + response, ok = m[key] + + if !ok { + return nil, fmt.Errorf("malformed JSON response %d, %q was expected.\n%s", resp.StatusCode, key, b) } } } @@ -68,7 +91,8 @@ func (client *Client) parseResponse(resp *http.Response, key string) (json.RawMe return nil, err } - if len(n) > 1 { + // list response may contain only one key + if len(n) > 1 || strings.HasPrefix(key, "list") { return response, nil } @@ -90,7 +114,7 @@ func (client *Client) parseResponse(resp *http.Response, key string) (json.RawMe func (client *Client) asyncRequest(ctx context.Context, asyncCommand AsyncCommand) (interface{}, error) { var err error - resp := asyncCommand.asyncResponse() + resp := asyncCommand.AsyncResponse() client.AsyncRequestWithContext( ctx, asyncCommand, @@ -99,7 +123,7 @@ func (client *Client) asyncRequest(ctx context.Context, asyncCommand AsyncComman err = e return false } - if j.JobStatus == Success { + if j.JobStatus != Pending { if r := j.Result(resp); r != nil { err = r } @@ -118,8 +142,8 @@ func (client *Client) SyncRequestWithContext(ctx context.Context, command Comman return nil, err } - response := command.response() - b, ok := response.(*booleanResponse) + response := command.Response() + b, ok := response.(*BooleanResponse) if ok { m := make(map[string]interface{}) if errUnmarshal := json.Unmarshal(body, &m); errUnmarshal != nil { @@ -157,7 +181,7 @@ func (client *Client) BooleanRequest(command Command) error { return err } - if b, ok := resp.(*booleanResponse); ok { + if b, ok := resp.(*BooleanResponse); ok { return b.Error() } @@ -171,7 +195,7 @@ func (client *Client) BooleanRequestWithContext(ctx context.Context, command Com return err } - if b, ok := resp.(*booleanResponse); ok { + if b, ok := resp.(*BooleanResponse); ok { return b.Error() } @@ -188,9 +212,9 @@ func (client *Client) Request(command Command) (interface{}, error) { // RequestWithContext preforms a command with a context func (client *Client) RequestWithContext(ctx context.Context, command Command) (interface{}, error) { - switch command.(type) { + switch c := command.(type) { case AsyncCommand: - return client.asyncRequest(ctx, command.(AsyncCommand)) + return client.asyncRequest(ctx, c) default: return client.SyncRequestWithContext(ctx, command) } @@ -227,7 +251,7 @@ func (client *Client) AsyncRequestWithContext(ctx context.Context, asyncCommand } // Successful response - if jobResult.JobID == "" || jobResult.JobStatus != Pending { + if jobResult.JobID == nil || jobResult.JobStatus != Pending { callback(jobResult, nil) // without a JobID, the next requests will only fail return @@ -249,82 +273,63 @@ func (client *Client) AsyncRequestWithContext(ctx context.Context, asyncCommand } } - if result.JobStatus == Failure { - if !callback(nil, result.Error()) { - return - } - } else { - if !callback(result, nil) { - return - } + if !callback(result, nil) { + return } } } -// Payload builds the HTTP request from the given command -func (client *Client) Payload(command Command) (string, error) { - params := url.Values{} - err := prepareValues("", params, command) +// Payload builds the HTTP request params from the given command +func (client *Client) Payload(command Command) (url.Values, error) { + params, err := prepareValues("", command) if err != nil { - return "", err + return nil, err } if hookReq, ok := command.(onBeforeHook); ok { if err := hookReq.onBeforeSend(params); err != nil { - return "", err + return params, err } } params.Set("apikey", client.APIKey) params.Set("command", client.APIName(command)) params.Set("response", "json") - // This code is borrowed from net/url/url.go - // The way it's encoded by net/url doesn't match - // how CloudStack work. - var buf bytes.Buffer - keys := make([]string, 0, len(params)) - for k := range params { - keys = append(keys, k) + if params.Get("expires") == "" && client.Expiration >= 0 { + params.Set("signatureversion", "3") + params.Set("expires", time.Now().Add(client.Expiration).Local().Format("2006-01-02T15:04:05-0700")) } - sort.Strings(keys) - for _, k := range keys { - prefix := csEncode(k) + "=" - for _, v := range params[k] { - if buf.Len() > 0 { - buf.WriteByte('&') - } - buf.WriteString(prefix) - buf.WriteString(csEncode(v)) - } - } - - return buf.String(), nil + return params, nil } -// Sign signs the HTTP request and return it -func (client *Client) Sign(query string) (string, error) { +// Sign signs the HTTP request and returns the signature as as base64 encoding +func (client *Client) Sign(params url.Values) (string, error) { + query := encodeValues(params) + query = strings.ToLower(query) mac := hmac.New(sha1.New, []byte(client.apiSecret)) - _, err := mac.Write([]byte(strings.ToLower(query))) + _, err := mac.Write([]byte(query)) if err != nil { return "", err } - signature := csEncode(base64.StdEncoding.EncodeToString(mac.Sum(nil))) - return fmt.Sprintf("%s&signature=%s", csQuotePlus(query), signature), nil + signature := base64.StdEncoding.EncodeToString(mac.Sum(nil)) + return signature, nil } // request makes a Request while being close to the metal func (client *Client) request(ctx context.Context, command Command) (json.RawMessage, error) { - payload, err := client.Payload(command) + params, err := client.Payload(command) if err != nil { return nil, err } - query, err := client.Sign(payload) + signature, err := client.Sign(params) if err != nil { return nil, err } + params.Add("signature", signature) method := "GET" + query := params.Encode() url := fmt.Sprintf("%s?%s", client.Endpoint, query) var body io.Reader @@ -340,7 +345,7 @@ func (client *Client) request(ctx context.Context, command Command) (json.RawMes return nil, err } request = request.WithContext(ctx) - request.Header.Add("User-Agent", fmt.Sprintf("exoscale/egoscale (%v)", Version)) + request.Header.Add("User-Agent", UserAgent) if method == "POST" { request.Header.Add("Content-Type", "application/x-www-form-urlencoded") @@ -359,19 +364,42 @@ func (client *Client) request(ctx context.Context, command Command) (json.RawMes return nil, fmt.Errorf(`body content-type response expected "application/json", got %q`, contentType) } - apiName := client.APIName(command) - key := fmt.Sprintf("%sresponse", strings.ToLower(apiName)) - // XXX: addIpToNic, activateIp6 are kind of special - if key == "addiptonicresponse" { - key = "addiptovmnicresponse" - } else if key == "activateip6response" { - key = "activateip6nicresponse" - } - - text, err := client.parseResponse(resp, key) + text, err := client.parseResponse(resp, client.APIName(command)) if err != nil { return nil, err } return text, nil } + +func encodeValues(params url.Values) string { + // This code is borrowed from net/url/url.go + // The way it's encoded by net/url doesn't match + // how CloudStack works to determine the signature. + // + // CloudStack only encodes the values of the query parameters + // and furthermore doesn't use '+' for whitespaces. Therefore + // after encoding the values all '+' are replaced with '%20'. + if params == nil { + return "" + } + + var buf bytes.Buffer + keys := make([]string, 0, len(params)) + for k := range params { + keys = append(keys, k) + } + + sort.Strings(keys) + for _, k := range keys { + prefix := k + "=" + for _, v := range params[k] { + if buf.Len() > 0 { + buf.WriteByte('&') + } + buf.WriteString(prefix) + buf.WriteString(csEncode(v)) + } + } + return buf.String() +} diff --git a/vendor/github.com/exoscale/egoscale/request_type.go b/vendor/github.com/exoscale/egoscale/request_type.go index 974a4f9ee..6775cde69 100644 --- a/vendor/github.com/exoscale/egoscale/request_type.go +++ b/vendor/github.com/exoscale/egoscale/request_type.go @@ -4,27 +4,27 @@ import ( "net/url" ) -// Command represents a CloudStack request +// Command represents a generic request type Command interface { - response() interface{} + Response() interface{} } -// AsyncCommand represents a async CloudStack request +// AsyncCommand represents a async request type AsyncCommand interface { Command - // Response interface to Unmarshal the JSON into - asyncResponse() interface{} + AsyncResponse() interface{} } -// ListCommand represents a CloudStack list request +// ListCommand represents a listing request type ListCommand interface { + Listable Command // SetPage defines the current pages SetPage(int) // SetPageSize defines the size of the page SetPageSize(int) - // each reads the data from the response and feeds channels, and returns true if we are on the last page - each(interface{}, IterateItemFunc) + // Each reads the data from the response and feeds channels, and returns true if we are on the last page + Each(interface{}, IterateItemFunc) } // onBeforeHook represents an action to be done on the params before sending them @@ -57,13 +57,15 @@ const ( // ErrorCode represents the CloudStack ApiErrorCode enum // -// See: https://github.com/apache/cloudstack/blob/master/api/src/org/apache/cloudstack/api/ApiErrorCode.java +// See: https://github.com/apache/cloudstack/blob/master/api/src/main/java/org/apache/cloudstack/api/ApiErrorCode.java type ErrorCode int //go:generate stringer -type ErrorCode const ( // Unauthorized represents ... (TODO) Unauthorized ErrorCode = 401 + // NotFound represents ... (TODO) + NotFound ErrorCode = 404 // MethodNotAllowed represents ... (TODO) MethodNotAllowed ErrorCode = 405 // UnsupportedActionError represents ... (TODO) @@ -162,7 +164,7 @@ const ( ServerAPIException CSErrorCode = 9999 ) -// ErrorResponse represents the standard error response from CloudStack +// ErrorResponse represents the standard error response type ErrorResponse struct { CSErrorCode CSErrorCode `json:"cserrorcode"` ErrorCode ErrorCode `json:"errorcode"` @@ -177,8 +179,8 @@ type UUIDItem struct { UUID string `json:"uuid"` } -// booleanResponse represents a boolean response (usually after a deletion) -type booleanResponse struct { +// BooleanResponse represents a boolean response (usually after a deletion) +type BooleanResponse struct { DisplayText string `json:"displaytext,omitempty"` Success bool `json:"success"` } diff --git a/vendor/github.com/exoscale/egoscale/resource_limits.go b/vendor/github.com/exoscale/egoscale/resource_limits.go new file mode 100644 index 000000000..56011dc66 --- /dev/null +++ b/vendor/github.com/exoscale/egoscale/resource_limits.go @@ -0,0 +1,100 @@ +package egoscale + +// https://github.com/apache/cloudstack/blob/master/api/src/main/java/com/cloud/configuration/Resource.java + +// ResourceTypeName represents the name of a resource type (for limits) +type ResourceTypeName string + +const ( + // VirtualMachineTypeName is the resource type name of a VM + VirtualMachineTypeName ResourceTypeName = "user_vm" + // IPAddressTypeName is the resource type name of an IP address + IPAddressTypeName ResourceTypeName = "public_ip" + // VolumeTypeName is the resource type name of a volume + VolumeTypeName ResourceTypeName = "volume" + // SnapshotTypeName is the resource type name of a snapshot + SnapshotTypeName ResourceTypeName = "snapshot" + // TemplateTypeName is the resource type name of a template + TemplateTypeName ResourceTypeName = "template" + // ProjectTypeName is the resource type name of a project + ProjectTypeName ResourceTypeName = "project" + // NetworkTypeName is the resource type name of a network + NetworkTypeName ResourceTypeName = "network" + // VPCTypeName is the resource type name of a VPC + VPCTypeName ResourceTypeName = "vpc" + // CPUTypeName is the resource type name of a CPU + CPUTypeName ResourceTypeName = "cpu" + // MemoryTypeName is the resource type name of Memory + MemoryTypeName ResourceTypeName = "memory" + // PrimaryStorageTypeName is the resource type name of primary storage + PrimaryStorageTypeName ResourceTypeName = "primary_storage" + // SecondaryStorageTypeName is the resource type name of secondary storage + SecondaryStorageTypeName ResourceTypeName = "secondary_storage" +) + +// ResourceType represents the ID of a resource type (for limits) +type ResourceType string + +const ( + // VirtualMachineType is the resource type ID of a VM + VirtualMachineType ResourceType = "0" + // IPAddressType is the resource type ID of an IP address + IPAddressType ResourceType = "1" + // VolumeType is the resource type ID of a volume + VolumeType ResourceType = "2" + // SnapshotType is the resource type ID of a snapshot + SnapshotType ResourceType = "3" + // TemplateType is the resource type ID of a template + TemplateType ResourceType = "4" + // ProjectType is the resource type ID of a project + ProjectType ResourceType = "5" + // NetworkType is the resource type ID of a network + NetworkType ResourceType = "6" + // VPCType is the resource type ID of a VPC + VPCType ResourceType = "7" + // CPUType is the resource type ID of a CPU + CPUType ResourceType = "8" + // MemoryType is the resource type ID of Memory + MemoryType ResourceType = "9" + // PrimaryStorageType is the resource type ID of primary storage + PrimaryStorageType ResourceType = "10" + // SecondaryStorageType is the resource type ID of secondary storage + SecondaryStorageType ResourceType = "11" +) + +// ResourceLimit represents the limit on a particular resource +type ResourceLimit struct { + Max int64 `json:"max,omitempty" doc:"the maximum number of the resource. A -1 means the resource currently has no limit."` + ResourceType ResourceType `json:"resourcetype,omitempty" doc:"resource type. Values include 0, 1, 2, 3, 4, 6, 7, 8, 9, 10, 11. See the resourceType parameter for more information on these values."` + ResourceTypeName string `json:"resourcetypename,omitempty" doc:"resource type name. Values include user_vm, public_ip, volume, snapshot, template, network, cpu, memory, primary_storage, secondary_storage."` +} + +// ListRequest builds the ListResourceLimits request +func (limit ResourceLimit) ListRequest() (ListCommand, error) { + req := &ListResourceLimits{ + ResourceType: limit.ResourceType, + ResourceTypeName: limit.ResourceTypeName, + } + + return req, nil +} + +//go:generate go run generate/main.go -interface=Listable ListResourceLimits + +// ListResourceLimits lists the resource limits +type ListResourceLimits struct { + ID int64 `json:"id,omitempty" doc:"Lists resource limits by ID."` + Keyword string `json:"keyword,omitempty" doc:"List by keyword"` + Page int `json:"page,omitempty"` + PageSize int `json:"pagesize,omitempty"` + ResourceType ResourceType `json:"resourcetype,omitempty" doc:"Type of resource. Values are 0, 1, 2, 3, 4, 6, 8, 9, 10, 11, 12, and 13. 0 - Instance. Number of instances a user can create. 1 - IP. Number of public IP addresses an account can own. 2 - Volume. Number of disk volumes an account can own. 3 - Snapshot. Number of snapshots an account can own. 4 - Template. Number of templates an account can register/create. 6 - Network. Number of networks an account can own. 8 - CPU. Number of CPU an account can allocate for his resources. 9 - Memory. Amount of RAM an account can allocate for his resources. 10 - PrimaryStorage. Total primary storage space (in GiB) a user can use. 11 - SecondaryStorage. Total secondary storage space (in GiB) a user can use. 12 - Elastic IP. Number of public elastic IP addresses an account can own. 13 - SMTP. If the account is allowed SMTP outbound traffic."` + ResourceTypeName string `json:"resourcetypename,omitempty" doc:"Type of resource (wins over resourceType if both are provided). Values are: user_vm - Instance. Number of instances a user can create. public_ip - IP. Number of public IP addresses an account can own. volume - Volume. Number of disk volumes an account can own. snapshot - Snapshot. Number of snapshots an account can own. template - Template. Number of templates an account can register/create. network - Network. Number of networks an account can own. cpu - CPU. Number of CPU an account can allocate for his resources. memory - Memory. Amount of RAM an account can allocate for his resources. primary_storage - PrimaryStorage. Total primary storage space (in GiB) a user can use. secondary_storage - SecondaryStorage. Total secondary storage space (in GiB) a user can use. public_elastic_ip - IP. Number of public elastic IP addresses an account can own. smtp - SG. If the account is allowed SMTP outbound traffic."` + + _ bool `name:"listResourceLimits" description:"Lists resource limits."` +} + +// ListResourceLimitsResponse represents a list of resource limits +type ListResourceLimitsResponse struct { + Count int `json:"count"` + ResourceLimit []ResourceLimit `json:"resourcelimit"` +} diff --git a/vendor/github.com/exoscale/egoscale/resource_metadata.go b/vendor/github.com/exoscale/egoscale/resource_metadata.go index b2d12efcb..52c5ee8b0 100644 --- a/vendor/github.com/exoscale/egoscale/resource_metadata.go +++ b/vendor/github.com/exoscale/egoscale/resource_metadata.go @@ -1,19 +1,36 @@ package egoscale +import "fmt" + +// ResourceDetail represents extra details +type ResourceDetail ResourceTag + +// ListRequest builds the ListResourceDetails request +func (detail ResourceDetail) ListRequest() (ListCommand, error) { + if detail.ResourceType == "" { + return nil, fmt.Errorf("the resourcetype parameter is required") + } + + req := &ListResourceDetails{ + ResourceType: detail.ResourceType, + ResourceID: detail.ResourceID, + } + + return req, nil +} + +//go:generate go run generate/main.go -interface=Listable ListResourceDetails + // ListResourceDetails lists the resource tag(s) (but different from listTags...) type ListResourceDetails struct { ResourceType string `json:"resourcetype" doc:"list by resource type"` - Account string `json:"account,omitempty" doc:"list resources by account. Must be used with the domainId parameter."` - DomainID string `json:"domainid,omitempty" doc:"list only resources belonging to the domain specified"` ForDisplay bool `json:"fordisplay,omitempty" doc:"if set to true, only details marked with display=true, are returned. False by default"` Key string `json:"key,omitempty" doc:"list by key"` Keyword string `json:"keyword,omitempty" doc:"List by keyword"` - ListAll bool `json:"listall,omitempty" doc:"If set to false, list only resources belonging to the command's caller; if set to true - list resources that the caller is authorized to see. Default value is false"` Page int `json:"page,omitempty"` PageSize int `json:"pagesize,omitempty"` - ResourceID string `json:"resourceid,omitempty" doc:"list by resource id"` + ResourceID *UUID `json:"resourceid,omitempty" doc:"list by resource id"` Value string `json:"value,omitempty" doc:"list by key, value. Needs to be passed only along with key"` - IsRecursive bool `json:"isrecursive,omitempty" doc:"defaults to false, but if true, lists all resources from the parent specified by the domainId till leaves."` _ bool `name:"listResourceDetails" description:"List resource detail(s)"` } @@ -22,15 +39,3 @@ type ListResourceDetailsResponse struct { Count int `json:"count"` ResourceDetail []ResourceTag `json:"resourcedetail"` } - -func (*ListResourceDetails) name() string { - return "listResourceDetails" -} - -func (*ListResourceDetails) description() string { - return "List resource detail(s)" -} - -func (*ListResourceDetails) response() interface{} { - return new(ListResourceDetailsResponse) -} diff --git a/vendor/github.com/exoscale/egoscale/resourcedetails_response.go b/vendor/github.com/exoscale/egoscale/resourcedetails_response.go new file mode 100644 index 000000000..2a08cd825 --- /dev/null +++ b/vendor/github.com/exoscale/egoscale/resourcedetails_response.go @@ -0,0 +1,43 @@ +// code generated; DO NOT EDIT. + +package egoscale + +import "fmt" + +// Response returns the struct to unmarshal +func (ListResourceDetails) Response() interface{} { + return new(ListResourceDetailsResponse) +} + +// ListRequest returns itself +func (ls *ListResourceDetails) ListRequest() (ListCommand, error) { + if ls == nil { + return nil, fmt.Errorf("%T cannot be nil", ls) + } + return ls, nil +} + +// SetPage sets the current apge +func (ls *ListResourceDetails) SetPage(page int) { + ls.Page = page +} + +// SetPageSize sets the page size +func (ls *ListResourceDetails) SetPageSize(pageSize int) { + ls.PageSize = pageSize +} + +// Each triggers the callback for each, valid answer or any non 404 issue +func (ListResourceDetails) Each(resp interface{}, callback IterateItemFunc) { + items, ok := resp.(*ListResourceDetailsResponse) + if !ok { + callback(nil, fmt.Errorf("wrong type, ListResourceDetailsResponse was expected, got %T", resp)) + return + } + + for i := range items.ResourceDetail { + if !callback(&items.ResourceDetail[i], nil) { + break + } + } +} diff --git a/vendor/github.com/exoscale/egoscale/resourcelimits_response.go b/vendor/github.com/exoscale/egoscale/resourcelimits_response.go new file mode 100644 index 000000000..656febfc9 --- /dev/null +++ b/vendor/github.com/exoscale/egoscale/resourcelimits_response.go @@ -0,0 +1,43 @@ +// code generated; DO NOT EDIT. + +package egoscale + +import "fmt" + +// Response returns the struct to unmarshal +func (ListResourceLimits) Response() interface{} { + return new(ListResourceLimitsResponse) +} + +// ListRequest returns itself +func (ls *ListResourceLimits) ListRequest() (ListCommand, error) { + if ls == nil { + return nil, fmt.Errorf("%T cannot be nil", ls) + } + return ls, nil +} + +// SetPage sets the current apge +func (ls *ListResourceLimits) SetPage(page int) { + ls.Page = page +} + +// SetPageSize sets the page size +func (ls *ListResourceLimits) SetPageSize(pageSize int) { + ls.PageSize = pageSize +} + +// Each triggers the callback for each, valid answer or any non 404 issue +func (ListResourceLimits) Each(resp interface{}, callback IterateItemFunc) { + items, ok := resp.(*ListResourceLimitsResponse) + if !ok { + callback(nil, fmt.Errorf("wrong type, ListResourceLimitsResponse was expected, got %T", resp)) + return + } + + for i := range items.ResourceLimit { + if !callback(&items.ResourceLimit[i], nil) { + break + } + } +} diff --git a/vendor/github.com/exoscale/egoscale/resourcetype_string.go b/vendor/github.com/exoscale/egoscale/resourcetype_string.go deleted file mode 100644 index dce3d2ce2..000000000 --- a/vendor/github.com/exoscale/egoscale/resourcetype_string.go +++ /dev/null @@ -1,16 +0,0 @@ -// Code generated by "stringer -type=ResourceType"; DO NOT EDIT. - -package egoscale - -import "strconv" - -const _ResourceType_name = "VirtualMachineTypeIPAddressTypeVolumeTypeSnapshotTypeTemplateTypeProjectTypeNetworkTypeVPCTypeCPUTypeMemoryTypePrimaryStorageTypeSecondaryStorageType" - -var _ResourceType_index = [...]uint8{0, 18, 31, 41, 53, 65, 76, 87, 94, 101, 111, 129, 149} - -func (i ResourceType) String() string { - if i < 0 || i >= ResourceType(len(_ResourceType_index)-1) { - return "ResourceType(" + strconv.FormatInt(int64(i), 10) + ")" - } - return _ResourceType_name[_ResourceType_index[i]:_ResourceType_index[i+1]] -} diff --git a/vendor/github.com/exoscale/egoscale/reversedns.go b/vendor/github.com/exoscale/egoscale/reversedns.go index 916e3b995..e8bd124ce 100644 --- a/vendor/github.com/exoscale/egoscale/reversedns.go +++ b/vendor/github.com/exoscale/egoscale/reversedns.go @@ -9,69 +9,75 @@ type ReverseDNS struct { DomainName string `json:"domainname,omitempty" doc:"the domain name of the PTR record"` IP6Address net.IP `json:"ip6address,omitempty" doc:"the IPv6 address linked with the PTR record (mutually exclusive with ipaddress)"` IPAddress net.IP `json:"ipaddress,omitempty" doc:"the IPv4 address linked with the PTR record (mutually exclusive with ip6address)"` - NicID string `json:"nicid,omitempty" doc:"the virtual machine default NIC ID"` - PublicIPID string `json:"publicipid,omitempty" doc:"the public IP address ID"` - VirtualMachineID string `json:"virtualmachineid,omitempty" doc:"the virtual machine ID"` + NicID *UUID `json:"nicid,omitempty" doc:"the virtual machine default NIC ID"` + PublicIPID *UUID `json:"publicipid,omitempty" doc:"the public IP address ID"` + VirtualMachineID *UUID `json:"virtualmachineid,omitempty" doc:"the virtual machine ID"` } // DeleteReverseDNSFromPublicIPAddress is a command to create/delete the PTR record of a public IP address type DeleteReverseDNSFromPublicIPAddress struct { - ID string `json:"id,omitempty" doc:"the ID of the public IP address"` - _ bool `name:"deleteReverseDnsFromPublicIpAddress" description:"delete the PTR DNS record from the public IP address"` + ID *UUID `json:"id,omitempty" doc:"the ID of the public IP address"` + _ bool `name:"deleteReverseDnsFromPublicIpAddress" description:"delete the PTR DNS record from the public IP address"` } -func (*DeleteReverseDNSFromPublicIPAddress) response() interface{} { - return new(booleanResponse) +// Response returns the struct to unmarshal +func (*DeleteReverseDNSFromPublicIPAddress) Response() interface{} { + return new(BooleanResponse) } // DeleteReverseDNSFromVirtualMachine is a command to create/delete the PTR record(s) of a virtual machine type DeleteReverseDNSFromVirtualMachine struct { - ID string `json:"id,omitempty" doc:"the ID of the virtual machine"` - _ bool `name:"deleteReverseDnsFromVirtualMachine" description:"Delete the PTR DNS record(s) from the virtual machine"` + ID *UUID `json:"id,omitempty" doc:"the ID of the virtual machine"` + _ bool `name:"deleteReverseDnsFromVirtualMachine" description:"Delete the PTR DNS record(s) from the virtual machine"` } -func (*DeleteReverseDNSFromVirtualMachine) response() interface{} { - return new(booleanResponse) +// Response returns the struct to unmarshal +func (*DeleteReverseDNSFromVirtualMachine) Response() interface{} { + return new(BooleanResponse) } // QueryReverseDNSForPublicIPAddress is a command to create/query the PTR record of a public IP address type QueryReverseDNSForPublicIPAddress struct { - ID string `json:"id,omitempty" doc:"the ID of the public IP address"` - _ bool `name:"queryReverseDnsForPublicIpAddress" description:"Query the PTR DNS record for the public IP address"` + ID *UUID `json:"id,omitempty" doc:"the ID of the public IP address"` + _ bool `name:"queryReverseDnsForPublicIpAddress" description:"Query the PTR DNS record for the public IP address"` } -func (*QueryReverseDNSForPublicIPAddress) response() interface{} { +// Response returns the struct to unmarshal +func (*QueryReverseDNSForPublicIPAddress) Response() interface{} { return new(IPAddress) } // QueryReverseDNSForVirtualMachine is a command to create/query the PTR record(s) of a virtual machine type QueryReverseDNSForVirtualMachine struct { - ID string `json:"id,omitempty" doc:"the ID of the virtual machine"` - _ bool `name:"queryReverseDnsForVirtualMachine" description:"Query the PTR DNS record(s) for the virtual machine"` + ID *UUID `json:"id,omitempty" doc:"the ID of the virtual machine"` + _ bool `name:"queryReverseDnsForVirtualMachine" description:"Query the PTR DNS record(s) for the virtual machine"` } -func (*QueryReverseDNSForVirtualMachine) response() interface{} { +// Response returns the struct to unmarshal +func (*QueryReverseDNSForVirtualMachine) Response() interface{} { return new(VirtualMachine) } // UpdateReverseDNSForPublicIPAddress is a command to create/update the PTR record of a public IP address type UpdateReverseDNSForPublicIPAddress struct { DomainName string `json:"domainname,omitempty" doc:"the domain name for the PTR record. It must have a valid TLD"` - ID string `json:"id,omitempty" doc:"the ID of the public IP address"` + ID *UUID `json:"id,omitempty" doc:"the ID of the public IP address"` _ bool `name:"updateReverseDnsForPublicIpAddress" description:"Update/create the PTR DNS record for the public IP address"` } -func (*UpdateReverseDNSForPublicIPAddress) response() interface{} { +// Response returns the struct to unmarshal +func (*UpdateReverseDNSForPublicIPAddress) Response() interface{} { return new(IPAddress) } // UpdateReverseDNSForVirtualMachine is a command to create/update the PTR record(s) of a virtual machine type UpdateReverseDNSForVirtualMachine struct { DomainName string `json:"domainname,omitempty" doc:"the domain name for the PTR record(s). It must have a valid TLD"` - ID string `json:"id,omitempty" doc:"the ID of the virtual machine"` + ID *UUID `json:"id,omitempty" doc:"the ID of the virtual machine"` _ bool `name:"updateReverseDnsForVirtualMachine" description:"Update/create the PTR DNS record(s) for the virtual machine"` } -func (*UpdateReverseDNSForVirtualMachine) response() interface{} { +// Response returns the struct to unmarshal +func (*UpdateReverseDNSForVirtualMachine) Response() interface{} { return new(VirtualMachine) } diff --git a/vendor/github.com/exoscale/egoscale/runstatus.go b/vendor/github.com/exoscale/egoscale/runstatus.go new file mode 100644 index 000000000..48905962e --- /dev/null +++ b/vendor/github.com/exoscale/egoscale/runstatus.go @@ -0,0 +1,131 @@ +package egoscale + +import ( + "context" + "crypto/hmac" + "crypto/sha256" + "encoding/hex" + "encoding/json" + "fmt" + "io/ioutil" + "net/http" + "net/url" + "strings" + "time" +) + +// RunstatusValidationErrorResponse represents an error in the API +type RunstatusValidationErrorResponse map[string][]string + +// RunstatusErrorResponse represents the default errors +type RunstatusErrorResponse struct { + Detail string `json:"detail"` +} + +// runstatusPagesURL is the only URL that cannot be guessed +const runstatusPagesURL = "/pages" + +// Error formats the DNSerror into a string +func (req RunstatusErrorResponse) Error() string { + return fmt.Sprintf("Runstatus error: %s", req.Detail) +} + +// Error formats the DNSerror into a string +func (req RunstatusValidationErrorResponse) Error() string { + if len(req) > 0 { + errs := []string{} + for name, ss := range req { + if len(ss) > 0 { + errs = append(errs, fmt.Sprintf("%s: %s", name, strings.Join(ss, ", "))) + } + } + return fmt.Sprintf("Runstatus error: %s", strings.Join(errs, "; ")) + } + return fmt.Sprintf("Runstatus error") +} + +func (client *Client) runstatusRequest(ctx context.Context, uri string, structParam interface{}, method string) (json.RawMessage, error) { + reqURL, err := url.Parse(uri) + if err != nil { + return nil, err + } + if reqURL.Scheme == "" { + return nil, fmt.Errorf("only absolute URI are considered valid, got %q", uri) + } + + var params string + if structParam != nil { + m, err := json.Marshal(structParam) + if err != nil { + return nil, err + } + params = string(m) + } + + req, err := http.NewRequest(method, reqURL.String(), strings.NewReader(params)) + if err != nil { + return nil, err + } + + time := time.Now().Local().Format("2006-01-02T15:04:05-0700") + + payload := fmt.Sprintf("%s%s%s", req.URL.String(), time, params) + + mac := hmac.New(sha256.New, []byte(client.apiSecret)) + _, err = mac.Write([]byte(payload)) + if err != nil { + return nil, err + } + signature := hex.EncodeToString(mac.Sum(nil)) + + var hdr = make(http.Header) + + hdr.Add("Authorization", fmt.Sprintf("Exoscale-HMAC-SHA256 %s:%s", client.APIKey, signature)) + hdr.Add("Exoscale-Date", time) + hdr.Add("User-Agent", UserAgent) + hdr.Add("Accept", "application/json") + if params != "" { + hdr.Add("Content-Type", "application/json") + } + req.Header = hdr + + req = req.WithContext(ctx) + + resp, err := client.HTTPClient.Do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() // nolint: errcheck + + if resp.StatusCode == 204 { + if method != "DELETE" { + return nil, fmt.Errorf("only DELETE is expected to produce 204, was %q", method) + } + return nil, nil + } + + contentType := resp.Header.Get("content-type") + if !strings.Contains(contentType, "application/json") { + return nil, fmt.Errorf(`response %d content-type expected to be "application/json", got %q`, resp.StatusCode, contentType) + } + + b, err := ioutil.ReadAll(resp.Body) + if err != nil { + return nil, err + } + + if resp.StatusCode >= 400 { + rerr := new(RunstatusValidationErrorResponse) + if err := json.Unmarshal(b, rerr); err == nil { + return nil, rerr + } + rverr := new(RunstatusErrorResponse) + if err := json.Unmarshal(b, rverr); err != nil { + return nil, err + } + + return nil, rverr + } + + return b, nil +} diff --git a/vendor/github.com/exoscale/egoscale/runstatus_event.go b/vendor/github.com/exoscale/egoscale/runstatus_event.go new file mode 100644 index 000000000..2c698788b --- /dev/null +++ b/vendor/github.com/exoscale/egoscale/runstatus_event.go @@ -0,0 +1,37 @@ +package egoscale + +import ( + "context" + "fmt" + "time" +) + +//RunstatusEvent is a runstatus event +type RunstatusEvent struct { + Created *time.Time `json:"created,omitempty"` + State string `json:"state,omitempty"` + Status string `json:"status"` + Text string `json:"text"` +} + +// UpdateRunstatusIncident create runstatus incident event +// Events can be updates or final message with status completed. +func (client *Client) UpdateRunstatusIncident(ctx context.Context, incident RunstatusIncident, event RunstatusEvent) error { + if incident.EventsURL == "" { + return fmt.Errorf("empty Events URL for %#v", incident) + } + + _, err := client.runstatusRequest(ctx, incident.EventsURL, event, "POST") + return err +} + +// UpdateRunstatusMaintenance adds a event to a maintenance. +// Events can be updates or final message with status completed. +func (client *Client) UpdateRunstatusMaintenance(ctx context.Context, maintenance RunstatusMaintenance, event RunstatusEvent) error { + if maintenance.EventsURL == "" { + return fmt.Errorf("empty Events URL for %#v", maintenance) + } + + _, err := client.runstatusRequest(ctx, maintenance.EventsURL, event, "POST") + return err +} diff --git a/vendor/github.com/exoscale/egoscale/runstatus_incident.go b/vendor/github.com/exoscale/egoscale/runstatus_incident.go new file mode 100644 index 000000000..82613e5d6 --- /dev/null +++ b/vendor/github.com/exoscale/egoscale/runstatus_incident.go @@ -0,0 +1,176 @@ +package egoscale + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "time" +) + +//RunstatusIncident is a runstatus incident +type RunstatusIncident struct { + EndDate *time.Time `json:"end_date,omitempty"` + Events []RunstatusEvent `json:"events,omitempty"` + EventsURL string `json:"events_url,omitempty"` + ID int `json:"id,omitempty"` + PageURL string `json:"page_url,omitempty"` // fake field + PostMortem string `json:"post_mortem,omitempty"` + RealTime bool `json:"real_time,omitempty"` + Services []string `json:"services"` + StartDate *time.Time `json:"start_date,omitempty"` + State string `json:"state"` + Status string `json:"status"` + StatusText string `json:"status_text"` + Title string `json:"title"` + URL string `json:"url,omitempty"` +} + +// Match returns true if the other incident has got similarities with itself +func (incident RunstatusIncident) Match(other RunstatusIncident) bool { + if other.Title != "" && incident.Title == other.Title { + return true + } + + if other.ID > 0 && incident.ID == other.ID { + return true + } + + return false +} + +//RunstatusIncidentList is a list of incident +type RunstatusIncidentList struct { + Next string `json:"next"` + Previous string `json:"previous"` + Incidents []RunstatusIncident `json:"results"` +} + +// GetRunstatusIncident retrieves the details of a specific incident. +func (client *Client) GetRunstatusIncident(ctx context.Context, incident RunstatusIncident) (*RunstatusIncident, error) { + if incident.URL != "" { + return client.getRunstatusIncident(ctx, incident.URL) + } + + if incident.PageURL == "" { + return nil, fmt.Errorf("empty Page URL for %#v", incident) + } + + page, err := client.getRunstatusPage(ctx, incident.PageURL) + if err != nil { + return nil, err + } + + for i := range page.Incidents { + j := &page.Incidents[i] + if j.Match(incident) { + return j, nil + } + } + + return nil, errors.New("incident not found") +} + +func (client *Client) getRunstatusIncident(ctx context.Context, incidentURL string) (*RunstatusIncident, error) { + resp, err := client.runstatusRequest(ctx, incidentURL, nil, "GET") + if err != nil { + return nil, err + } + + i := new(RunstatusIncident) + if err := json.Unmarshal(resp, i); err != nil { + return nil, err + } + return i, nil +} + +// ListRunstatusIncidents lists the incidents for a specific page. +func (client *Client) ListRunstatusIncidents(ctx context.Context, page RunstatusPage) ([]RunstatusIncident, error) { + if page.IncidentsURL == "" { + return nil, fmt.Errorf("empty Incidents URL for %#v", page) + } + + results := make([]RunstatusIncident, 0) + + var err error + client.PaginateRunstatusIncidents(ctx, page, func(incident *RunstatusIncident, e error) bool { + if e != nil { + err = e + return false + } + + results = append(results, *incident) + return true + }) + + return results, err +} + +// PaginateRunstatusIncidents paginate Incidents +func (client *Client) PaginateRunstatusIncidents(ctx context.Context, page RunstatusPage, callback func(*RunstatusIncident, error) bool) { + if page.IncidentsURL == "" { + callback(nil, fmt.Errorf("empty Incidents URL for %#v", page)) + return + } + + incidentsURL := page.IncidentsURL + for incidentsURL != "" { + resp, err := client.runstatusRequest(ctx, incidentsURL, nil, "GET") + if err != nil { + callback(nil, err) + return + } + + var is *RunstatusIncidentList + if err := json.Unmarshal(resp, &is); err != nil { + callback(nil, err) + return + } + + for i := range is.Incidents { + if cont := callback(&is.Incidents[i], nil); !cont { + return + } + } + + incidentsURL = is.Next + } +} + +// CreateRunstatusIncident create runstatus incident +func (client *Client) CreateRunstatusIncident(ctx context.Context, incident RunstatusIncident) (*RunstatusIncident, error) { + if incident.PageURL == "" { + return nil, fmt.Errorf("empty Page URL for %#v", incident) + } + + page, err := client.getRunstatusPage(ctx, incident.PageURL) + if err != nil { + return nil, err + } + + if page.IncidentsURL == "" { + return nil, fmt.Errorf("empty Incidents URL for %#v", page) + } + + resp, err := client.runstatusRequest(ctx, page.IncidentsURL, incident, "POST") + if err != nil { + return nil, err + } + + i := &RunstatusIncident{} + if err := json.Unmarshal(resp, &i); err != nil { + return nil, err + } + + return i, nil +} + +// DeleteRunstatusIncident delete runstatus incident +func (client *Client) DeleteRunstatusIncident(ctx context.Context, incident RunstatusIncident) error { + if incident.URL == "" { + return fmt.Errorf("empty URL for %#v", incident) + } + + _, err := client.runstatusRequest(ctx, incident.URL, nil, "DELETE") + return err +} diff --git a/vendor/github.com/exoscale/egoscale/runstatus_maintenance.go b/vendor/github.com/exoscale/egoscale/runstatus_maintenance.go new file mode 100644 index 000000000..07372466c --- /dev/null +++ b/vendor/github.com/exoscale/egoscale/runstatus_maintenance.go @@ -0,0 +1,209 @@ +package egoscale + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "log" + "net/url" + "path" + "strconv" + "time" +) + +// RunstatusMaintenance is a runstatus maintenance +type RunstatusMaintenance struct { + Created *time.Time `json:"created,omitempty"` + Description string `json:"description,omitempty"` + EndDate *time.Time `json:"end_date"` + Events []RunstatusEvent `json:"events,omitempty"` + EventsURL string `json:"events_url,omitempty"` + ID int `json:"id,omitempty"` // missing field + PageURL string `json:"page_url,omitempty"` // fake field + RealTime bool `json:"real_time,omitempty"` + Services []string `json:"services"` + StartDate *time.Time `json:"start_date"` + Status string `json:"status"` + Title string `json:"title"` + URL string `json:"url,omitempty"` +} + +// Match returns true if the other maintenance has got similarities with itself +func (maintenance RunstatusMaintenance) Match(other RunstatusMaintenance) bool { + if other.Title != "" && maintenance.Title == other.Title { + return true + } + + if other.ID > 0 && maintenance.ID == other.ID { + return true + } + + return false +} + +// FakeID fills up the ID field as it's currently missing +func (maintenance *RunstatusMaintenance) FakeID() error { + if maintenance.ID > 0 { + return nil + } + + if maintenance.URL == "" { + return fmt.Errorf("empty URL for %#v", maintenance) + } + + u, err := url.Parse(maintenance.URL) + if err != nil { + return err + } + + s := path.Base(u.Path) + id, err := strconv.Atoi(s) + if err != nil { + return err + } + maintenance.ID = id + return nil +} + +// RunstatusMaintenanceList is a list of incident +type RunstatusMaintenanceList struct { + Next string `json:"next"` + Previous string `json:"previous"` + Maintenances []RunstatusMaintenance `json:"results"` +} + +// GetRunstatusMaintenance retrieves the details of a specific maintenance. +func (client *Client) GetRunstatusMaintenance(ctx context.Context, maintenance RunstatusMaintenance) (*RunstatusMaintenance, error) { + if maintenance.URL != "" { + return client.getRunstatusMaintenance(ctx, maintenance.URL) + } + + if maintenance.PageURL == "" { + return nil, fmt.Errorf("empty Page URL for %#v", maintenance) + } + + page, err := client.getRunstatusPage(ctx, maintenance.PageURL) + if err != nil { + return nil, err + } + + for i := range page.Maintenances { + m := &page.Maintenances[i] + if m.Match(maintenance) { + if err := m.FakeID(); err != nil { + log.Printf("bad fake ID for %#v, %s", m, err) + } + return m, nil + } + } + + return nil, errors.New("maintenance not found") +} + +func (client *Client) getRunstatusMaintenance(ctx context.Context, maintenanceURL string) (*RunstatusMaintenance, error) { + resp, err := client.runstatusRequest(ctx, maintenanceURL, nil, "GET") + if err != nil { + return nil, err + } + + m := new(RunstatusMaintenance) + if err := json.Unmarshal(resp, m); err != nil { + return nil, err + } + return m, nil +} + +// ListRunstatusMaintenances returns the list of maintenances for the page. +func (client *Client) ListRunstatusMaintenances(ctx context.Context, page RunstatusPage) ([]RunstatusMaintenance, error) { + if page.MaintenancesURL == "" { + return nil, fmt.Errorf("empty Maintenances URL for %#v", page) + } + + results := make([]RunstatusMaintenance, 0) + + var err error + client.PaginateRunstatusMaintenances(ctx, page, func(maintenance *RunstatusMaintenance, e error) bool { + if e != nil { + err = e + return false + } + + results = append(results, *maintenance) + return true + }) + + return results, err +} + +// PaginateRunstatusMaintenances paginate Maintenances +func (client *Client) PaginateRunstatusMaintenances(ctx context.Context, page RunstatusPage, callback func(*RunstatusMaintenance, error) bool) { // nolint: dupl + if page.MaintenancesURL == "" { + callback(nil, fmt.Errorf("empty Maintenances URL for %#v", page)) + return + } + + maintenancesURL := page.MaintenancesURL + for maintenancesURL != "" { + resp, err := client.runstatusRequest(ctx, maintenancesURL, nil, "GET") + if err != nil { + callback(nil, err) + return + } + + var ms *RunstatusMaintenanceList + if err := json.Unmarshal(resp, &ms); err != nil { + callback(nil, err) + return + } + + for i := range ms.Maintenances { + if err := ms.Maintenances[i].FakeID(); err != nil { + log.Printf("bad fake ID for %#v, %s", ms.Maintenances[i], err) + } + if cont := callback(&ms.Maintenances[i], nil); !cont { + return + } + } + + maintenancesURL = ms.Next + } +} + +// CreateRunstatusMaintenance create runstatus Maintenance +func (client *Client) CreateRunstatusMaintenance(ctx context.Context, maintenance RunstatusMaintenance) (*RunstatusMaintenance, error) { + if maintenance.PageURL == "" { + return nil, fmt.Errorf("empty Page URL for %#v", maintenance) + } + + page, err := client.getRunstatusPage(ctx, maintenance.PageURL) + if err != nil { + return nil, err + } + + resp, err := client.runstatusRequest(ctx, page.MaintenancesURL, maintenance, "POST") + if err != nil { + return nil, err + } + + m := &RunstatusMaintenance{} + if err := json.Unmarshal(resp, &m); err != nil { + return nil, err + } + + if err := m.FakeID(); err != nil { + log.Printf("bad fake ID for %#v, %s", m, err) + } + + return m, nil +} + +// DeleteRunstatusMaintenance delete runstatus Maintenance +func (client *Client) DeleteRunstatusMaintenance(ctx context.Context, maintenance RunstatusMaintenance) error { + if maintenance.URL == "" { + return fmt.Errorf("empty URL for %#v", maintenance) + } + + _, err := client.runstatusRequest(ctx, maintenance.URL, nil, "DELETE") + return err +} diff --git a/vendor/github.com/exoscale/egoscale/runstatus_page.go b/vendor/github.com/exoscale/egoscale/runstatus_page.go new file mode 100644 index 000000000..19ab942c1 --- /dev/null +++ b/vendor/github.com/exoscale/egoscale/runstatus_page.go @@ -0,0 +1,169 @@ +package egoscale + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "log" + "time" +) + +// RunstatusPage runstatus page +type RunstatusPage struct { + Created *time.Time `json:"created,omitempty"` + DarkTheme bool `json:"dark_theme,omitempty"` + Domain string `json:"domain,omitempty"` + GradientEnd string `json:"gradient_end,omitempty"` + GradientStart string `json:"gradient_start,omitempty"` + HeaderBackground string `json:"header_background,omitempty"` + ID int `json:"id,omitempty"` + Incidents []RunstatusIncident `json:"incidents,omitempty"` + IncidentsURL string `json:"incidents_url,omitempty"` + Logo string `json:"logo,omitempty"` + Maintenances []RunstatusMaintenance `json:"maintenances,omitempty"` + MaintenancesURL string `json:"maintenances_url,omitempty"` + Name string `json:"name"` //fake field (used to post a new runstatus page) + OkText string `json:"ok_text,omitempty"` + Plan string `json:"plan,omitempty"` + PublicURL string `json:"public_url,omitempty"` + Services []RunstatusService `json:"services,omitempty"` + ServicesURL string `json:"services_url,omitempty"` + State string `json:"state,omitempty"` + Subdomain string `json:"subdomain"` + SupportEmail string `json:"support_email,omitempty"` + TimeZone string `json:"time_zone,omitempty"` + Title string `json:"title,omitempty"` + TitleColor string `json:"title_color,omitempty"` + TwitterUsername string `json:"twitter_username,omitempty"` + URL string `json:"url,omitempty"` +} + +// Match returns true if the other page has got similarities with itself +func (page RunstatusPage) Match(other RunstatusPage) bool { + if other.Subdomain != "" && page.Subdomain == other.Subdomain { + return true + } + + if other.ID > 0 && page.ID == other.ID { + return true + } + + return false +} + +// RunstatusPageList runstatus page list +type RunstatusPageList struct { + Next string `json:"next"` + Previous string `json:"previous"` + Pages []RunstatusPage `json:"results"` +} + +// CreateRunstatusPage create runstatus page +func (client *Client) CreateRunstatusPage(ctx context.Context, page RunstatusPage) (*RunstatusPage, error) { + resp, err := client.runstatusRequest(ctx, client.Endpoint+runstatusPagesURL, page, "POST") + if err != nil { + return nil, err + } + + var p *RunstatusPage + if err := json.Unmarshal(resp, &p); err != nil { + return nil, err + } + + return p, nil +} + +// DeleteRunstatusPage delete runstatus page +func (client *Client) DeleteRunstatusPage(ctx context.Context, page RunstatusPage) error { + if page.URL == "" { + return fmt.Errorf("empty URL for %#v", page) + } + _, err := client.runstatusRequest(ctx, page.URL, nil, "DELETE") + return err +} + +// GetRunstatusPage fetches the runstatus page +func (client *Client) GetRunstatusPage(ctx context.Context, page RunstatusPage) (*RunstatusPage, error) { + if page.URL != "" { + return client.getRunstatusPage(ctx, page.URL) + } + + ps, err := client.ListRunstatusPages(ctx) + if err != nil { + return nil, err + } + + for i := range ps { + if ps[i].Match(page) { + return client.getRunstatusPage(ctx, ps[i].URL) + } + } + + return nil, errors.New("page not found") +} + +func (client *Client) getRunstatusPage(ctx context.Context, pageURL string) (*RunstatusPage, error) { + resp, err := client.runstatusRequest(ctx, pageURL, nil, "GET") + if err != nil { + return nil, err + } + + p := new(RunstatusPage) + if err := json.Unmarshal(resp, p); err != nil { + return nil, err + } + + // NOTE: fix the missing IDs + for i := range p.Maintenances { + if err := p.Maintenances[i].FakeID(); err != nil { + log.Printf("bad fake ID for %#v, %s", p.Maintenances[i], err) + } + } + for i := range p.Services { + if err := p.Services[i].FakeID(); err != nil { + log.Printf("bad fake ID for %#v, %s", p.Services[i], err) + } + } + + return p, nil +} + +// ListRunstatusPages list all the runstatus pages +func (client *Client) ListRunstatusPages(ctx context.Context) ([]RunstatusPage, error) { + resp, err := client.runstatusRequest(ctx, client.Endpoint+runstatusPagesURL, nil, "GET") + if err != nil { + return nil, err + } + + var p *RunstatusPageList + if err := json.Unmarshal(resp, &p); err != nil { + return nil, err + } + + return p.Pages, nil +} + +//PaginateRunstatusPages paginate on runstatus pages +func (client *Client) PaginateRunstatusPages(ctx context.Context, callback func(pages []RunstatusPage, e error) bool) { + pageURL := client.Endpoint + runstatusPagesURL + for pageURL != "" { + resp, err := client.runstatusRequest(ctx, pageURL, nil, "GET") + if err != nil { + callback(nil, err) + return + } + + var p *RunstatusPageList + if err := json.Unmarshal(resp, &p); err != nil { + callback(nil, err) + return + } + + if ok := callback(p.Pages, nil); ok { + return + } + + pageURL = p.Next + } +} diff --git a/vendor/github.com/exoscale/egoscale/runstatus_service.go b/vendor/github.com/exoscale/egoscale/runstatus_service.go new file mode 100644 index 000000000..764eeea5b --- /dev/null +++ b/vendor/github.com/exoscale/egoscale/runstatus_service.go @@ -0,0 +1,202 @@ +package egoscale + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "log" + "net/url" + "path" + "strconv" +) + +// RunstatusService is a runstatus service +type RunstatusService struct { + ID int `json:"id"` // missing field + Name string `json:"name"` + PageURL string `json:"page_url,omitempty"` // fake field + State string `json:"state,omitempty"` + URL string `json:"url,omitempty"` +} + +// FakeID fills up the ID field as it's currently missing +func (service *RunstatusService) FakeID() error { + if service.ID > 0 { + return nil + } + + if service.URL == "" { + return fmt.Errorf("empty URL for %#v", service) + } + + u, err := url.Parse(service.URL) + if err != nil { + return err + } + + s := path.Base(u.Path) + id, err := strconv.Atoi(s) + if err != nil { + return err + } + service.ID = id + return nil +} + +// Match returns true if the other service has got similarities with itself +func (service RunstatusService) Match(other RunstatusService) bool { + if other.Name != "" && service.Name == other.Name { + return true + } + + if other.ID > 0 && service.ID == other.ID { + return true + } + + return false +} + +// RunstatusServiceList service list +type RunstatusServiceList struct { + Next string `json:"next"` + Previous string `json:"previous"` + Services []RunstatusService `json:"results"` +} + +// DeleteRunstatusService delete runstatus service +func (client *Client) DeleteRunstatusService(ctx context.Context, service RunstatusService) error { + if service.URL == "" { + return fmt.Errorf("empty URL for %#v", service) + } + + _, err := client.runstatusRequest(ctx, service.URL, nil, "DELETE") + return err +} + +// CreateRunstatusService create runstatus service +func (client *Client) CreateRunstatusService(ctx context.Context, service RunstatusService) (*RunstatusService, error) { + if service.PageURL == "" { + return nil, fmt.Errorf("empty Page URL for %#v", service) + } + + page, err := client.GetRunstatusPage(ctx, RunstatusPage{URL: service.PageURL}) + if err != nil { + return nil, err + } + + resp, err := client.runstatusRequest(ctx, page.ServicesURL, service, "POST") + if err != nil { + return nil, err + } + + s := &RunstatusService{} + if err := json.Unmarshal(resp, s); err != nil { + return nil, err + } + + return s, nil +} + +// GetRunstatusService displays service detail. +func (client *Client) GetRunstatusService(ctx context.Context, service RunstatusService) (*RunstatusService, error) { + if service.URL != "" { + return client.getRunstatusService(ctx, service.URL) + } + + if service.PageURL == "" { + return nil, fmt.Errorf("empty Page URL in %#v", service) + } + + page, err := client.getRunstatusPage(ctx, service.PageURL) + if err != nil { + return nil, err + } + + for i := range page.Services { + s := &page.Services[i] + if s.Match(service) { + if err := s.FakeID(); err != nil { + log.Printf("bad fake ID for %#v, %s", s, err) + } + return s, nil + } + } + + return nil, errors.New("service not found") +} + +func (client *Client) getRunstatusService(ctx context.Context, serviceURL string) (*RunstatusService, error) { + resp, err := client.runstatusRequest(ctx, serviceURL, nil, "GET") + if err != nil { + return nil, err + } + + s := &RunstatusService{} + if err := json.Unmarshal(resp, &s); err != nil { + return nil, err + } + + if err := s.FakeID(); err != nil { + log.Printf("bad fake ID for %#v, %s", s, err) + } + + return s, nil +} + +// ListRunstatusServices displays the list of services. +func (client *Client) ListRunstatusServices(ctx context.Context, page RunstatusPage) ([]RunstatusService, error) { + if page.ServicesURL == "" { + return nil, fmt.Errorf("empty Services URL for %#v", page) + } + + results := make([]RunstatusService, 0) + + var err error + client.PaginateRunstatusServices(ctx, page, func(service *RunstatusService, e error) bool { + if e != nil { + err = e + return false + } + + results = append(results, *service) + return true + }) + + return results, err +} + +// PaginateRunstatusServices paginates Services +func (client *Client) PaginateRunstatusServices(ctx context.Context, page RunstatusPage, callback func(*RunstatusService, error) bool) { // nolint: dupl + if page.ServicesURL == "" { + callback(nil, fmt.Errorf("empty Services URL for %#v", page)) + return + } + + servicesURL := page.ServicesURL + for servicesURL != "" { + resp, err := client.runstatusRequest(ctx, servicesURL, nil, "GET") + if err != nil { + callback(nil, err) + return + } + + var ss *RunstatusServiceList + if err := json.Unmarshal(resp, &ss); err != nil { + callback(nil, err) + return + } + + for i := range ss.Services { + if err := ss.Services[i].FakeID(); err != nil { + log.Printf("bad fake ID for %#v, %s", ss.Services[i], err) + } + + if cont := callback(&ss.Services[i], nil); !cont { + return + } + } + + servicesURL = ss.Next + } +} diff --git a/vendor/github.com/exoscale/egoscale/security_groups.go b/vendor/github.com/exoscale/egoscale/security_groups.go index 5caf83bd9..a11e53a4f 100644 --- a/vendor/github.com/exoscale/egoscale/security_groups.go +++ b/vendor/github.com/exoscale/egoscale/security_groups.go @@ -12,34 +12,22 @@ import ( type SecurityGroup struct { Account string `json:"account,omitempty" doc:"the account owning the security group"` Description string `json:"description,omitempty" doc:"the description of the security group"` - Domain string `json:"domain,omitempty" doc:"the domain name of the security group"` - DomainID string `json:"domainid,omitempty" doc:"the domain ID of the security group"` EgressRule []EgressRule `json:"egressrule,omitempty" doc:"the list of egress rules associated with the security group"` - ID string `json:"id,omitempty" doc:"the ID of the security group"` + ID *UUID `json:"id" doc:"the ID of the security group"` IngressRule []IngressRule `json:"ingressrule,omitempty" doc:"the list of ingress rules associated with the security group"` Name string `json:"name,omitempty" doc:"the name of the security group"` - Tags []ResourceTag `json:"tags,omitempty" doc:"the list of resource tags associated with the rule"` -} - -// ResourceType returns the type of the resource -func (SecurityGroup) ResourceType() string { - return "SecurityGroup" } // UserSecurityGroup converts a SecurityGroup to a UserSecurityGroup func (sg SecurityGroup) UserSecurityGroup() UserSecurityGroup { return UserSecurityGroup{ - Account: sg.Account, - Group: sg.Name, + Group: sg.Name, } } // ListRequest builds the ListSecurityGroups request func (sg SecurityGroup) ListRequest() (ListCommand, error) { - //TODO add tags req := &ListSecurityGroups{ - Account: sg.Account, - DomainID: sg.DomainID, ID: sg.ID, SecurityGroupName: sg.Name, } @@ -49,16 +37,13 @@ func (sg SecurityGroup) ListRequest() (ListCommand, error) { // Delete deletes the given Security Group func (sg SecurityGroup) Delete(ctx context.Context, client *Client) error { - if sg.ID == "" && sg.Name == "" { + if sg.ID == nil && sg.Name == "" { return fmt.Errorf("a SecurityGroup may only be deleted using ID or Name") } - req := &DeleteSecurityGroup{ - Account: sg.Account, - DomainID: sg.DomainID, - } + req := &DeleteSecurityGroup{} - if sg.ID != "" { + if sg.ID != nil { req.ID = sg.ID } else { req.Name = sg.Name @@ -68,15 +53,15 @@ func (sg SecurityGroup) Delete(ctx context.Context, client *Client) error { } // RuleByID returns IngressRule or EgressRule by a rule ID -func (sg SecurityGroup) RuleByID(ruleID string) (*IngressRule, *EgressRule) { +func (sg SecurityGroup) RuleByID(ruleID UUID) (*IngressRule, *EgressRule) { for i, in := range sg.IngressRule { - if ruleID == in.RuleID { + if in.RuleID.Equal(ruleID) { return &sg.IngressRule[i], nil } } for i, out := range sg.EgressRule { - if ruleID == out.RuleID { + if out.RuleID.Equal(ruleID) { return nil, &sg.EgressRule[i] } } @@ -86,19 +71,15 @@ func (sg SecurityGroup) RuleByID(ruleID string) (*IngressRule, *EgressRule) { // IngressRule represents the ingress rule type IngressRule struct { - Account string `json:"account,omitempty" doc:"account owning the security group rule"` - CIDR *CIDR `json:"cidr,omitempty" doc:"the CIDR notation for the base IP address of the security group rule"` - Description string `json:"description,omitempty" doc:"description of the security group rule"` - EndPort uint16 `json:"endport,omitempty" doc:"the ending port of the security group rule "` - IcmpCode uint8 `json:"icmpcode,omitempty" doc:"the code for the ICMP message response"` - IcmpType uint8 `json:"icmptype,omitempty" doc:"the type of the ICMP message response"` - Protocol string `json:"protocol,omitempty" doc:"the protocol of the security group rule"` - RuleID string `json:"ruleid,omitempty" doc:"the id of the security group rule"` - SecurityGroupID string `json:"securitygroupid,omitempty"` - SecurityGroupName string `json:"securitygroupname,omitempty" doc:"security group name"` - StartPort uint16 `json:"startport,omitempty" doc:"the starting port of the security group rule"` - Tags []ResourceTag `json:"tags,omitempty" doc:"the list of resource tags associated with the rule"` - UserSecurityGroupList []UserSecurityGroup `json:"usersecuritygrouplist,omitempty"` + CIDR *CIDR `json:"cidr,omitempty" doc:"the CIDR notation for the base IP address of the security group rule"` + Description string `json:"description,omitempty" doc:"description of the security group rule"` + EndPort uint16 `json:"endport,omitempty" doc:"the ending port of the security group rule "` + IcmpCode uint8 `json:"icmpcode,omitempty" doc:"the code for the ICMP message response"` + IcmpType uint8 `json:"icmptype,omitempty" doc:"the type of the ICMP message response"` + Protocol string `json:"protocol,omitempty" doc:"the protocol of the security group rule"` + RuleID *UUID `json:"ruleid" doc:"the id of the security group rule"` + SecurityGroupName string `json:"securitygroupname,omitempty" doc:"security group name"` + StartPort uint16 `json:"startport,omitempty" doc:"the starting port of the security group rule"` } // EgressRule represents the ingress rule @@ -106,8 +87,7 @@ type EgressRule IngressRule // UserSecurityGroup represents the traffic of another security group type UserSecurityGroup struct { - Group string `json:"group,omitempty"` - Account string `json:"account,omitempty"` + Group string `json:"group,omitempty"` } // String gives the UserSecurityGroup name @@ -118,51 +98,49 @@ func (usg UserSecurityGroup) String() string { // CreateSecurityGroup represents a security group creation type CreateSecurityGroup struct { Name string `json:"name" doc:"name of the security group"` - Account string `json:"account,omitempty" doc:"an optional account for the security group. Must be used with domainId."` Description string `json:"description,omitempty" doc:"the description of the security group"` - DomainID string `json:"domainid,omitempty" doc:"an optional domainId for the security group. If the account parameter is used, domainId must also be used."` _ bool `name:"createSecurityGroup" description:"Creates a security group"` } -func (CreateSecurityGroup) response() interface{} { +// Response returns the struct to unmarshal +func (CreateSecurityGroup) Response() interface{} { return new(SecurityGroup) } // DeleteSecurityGroup represents a security group deletion type DeleteSecurityGroup struct { - Account string `json:"account,omitempty" doc:"the account of the security group. Must be specified with domain ID"` - DomainID string `json:"domainid,omitempty" doc:"the domain ID of account owning the security group"` - ID string `json:"id,omitempty" doc:"The ID of the security group. Mutually exclusive with name parameter"` - Name string `json:"name,omitempty" doc:"The ID of the security group. Mutually exclusive with id parameter"` - _ bool `name:"deleteSecurityGroup" description:"Deletes security group"` + ID *UUID `json:"id,omitempty" doc:"The ID of the security group. Mutually exclusive with name parameter"` + Name string `json:"name,omitempty" doc:"The ID of the security group. Mutually exclusive with id parameter"` + _ bool `name:"deleteSecurityGroup" description:"Deletes security group"` } -func (DeleteSecurityGroup) response() interface{} { - return new(booleanResponse) +// Response returns the struct to unmarshal +func (DeleteSecurityGroup) Response() interface{} { + return new(BooleanResponse) } // AuthorizeSecurityGroupIngress (Async) represents the ingress rule creation type AuthorizeSecurityGroupIngress struct { - Account string `json:"account,omitempty" doc:"an optional account for the security group. Must be used with domainId."` CIDRList []CIDR `json:"cidrlist,omitempty" doc:"the cidr list associated"` Description string `json:"description,omitempty" doc:"the description of the ingress/egress rule"` - DomainID string `json:"domainid,omitempty" doc:"an optional domainid for the security group. If the account parameter is used, domainid must also be used."` - EndPort uint16 `json:"endport,omitempty" doc:"end port for this ingress rule"` + EndPort uint16 `json:"endport,omitempty" doc:"end port for this ingress/egress rule"` IcmpCode uint8 `json:"icmpcode,omitempty" doc:"error code for this icmp message"` IcmpType uint8 `json:"icmptype,omitempty" doc:"type of the icmp message being sent"` - Protocol string `json:"protocol,omitempty" doc:"TCP is default. UDP, ICMP, ICMPv6, AH, ESP, GRE are the other supported protocols"` - SecurityGroupID string `json:"securitygroupid,omitempty" doc:"The ID of the security group. Mutually exclusive with securitygroupname parameter"` + Protocol string `json:"protocol,omitempty" doc:"TCP is default. UDP, ICMP, ICMPv6, AH, ESP, GRE, IPIP are the other supported protocols"` + SecurityGroupID *UUID `json:"securitygroupid,omitempty" doc:"The ID of the security group. Mutually exclusive with securitygroupname parameter"` SecurityGroupName string `json:"securitygroupname,omitempty" doc:"The name of the security group. Mutually exclusive with securitygroupid parameter"` - StartPort uint16 `json:"startport,omitempty" doc:"start port for this ingress rule"` + StartPort uint16 `json:"startport,omitempty" doc:"start port for this ingress/egress rule"` UserSecurityGroupList []UserSecurityGroup `json:"usersecuritygrouplist,omitempty" doc:"user to security group mapping"` - _ bool `name:"authorizeSecurityGroupIngress" description:"Authorizes a particular ingress/egress rule for this security group"` + _ bool `name:"authorizeSecurityGroupIngress" description:"Authorize a particular ingress/egress rule for this security group"` } -func (AuthorizeSecurityGroupIngress) response() interface{} { +// Response returns the struct to unmarshal +func (AuthorizeSecurityGroupIngress) Response() interface{} { return new(AsyncJobResult) } -func (AuthorizeSecurityGroupIngress) asyncResponse() interface{} { +// AsyncResponse returns the struct to unmarshal the async job +func (AuthorizeSecurityGroupIngress) AsyncResponse() interface{} { return new(SecurityGroup) } @@ -182,11 +160,13 @@ func (req AuthorizeSecurityGroupIngress) onBeforeSend(params url.Values) error { // AuthorizeSecurityGroupEgress (Async) represents the egress rule creation type AuthorizeSecurityGroupEgress AuthorizeSecurityGroupIngress -func (AuthorizeSecurityGroupEgress) response() interface{} { +// Response returns the struct to unmarshal +func (AuthorizeSecurityGroupEgress) Response() interface{} { return new(AsyncJobResult) } -func (AuthorizeSecurityGroupEgress) asyncResponse() interface{} { +// AsyncResponse returns the struct to unmarshal the async job +func (AuthorizeSecurityGroupEgress) AsyncResponse() interface{} { return new(SecurityGroup) } @@ -196,45 +176,47 @@ func (req AuthorizeSecurityGroupEgress) onBeforeSend(params url.Values) error { // RevokeSecurityGroupIngress (Async) represents the ingress/egress rule deletion type RevokeSecurityGroupIngress struct { - ID string `json:"id" doc:"The ID of the ingress rule"` - _ bool `name:"revokeSecurityGroupIngress" description:"Deletes a particular ingress rule from this security group"` + ID *UUID `json:"id" doc:"The ID of the ingress rule"` + _ bool `name:"revokeSecurityGroupIngress" description:"Deletes a particular ingress rule from this security group"` } -func (RevokeSecurityGroupIngress) response() interface{} { +// Response returns the struct to unmarshal +func (RevokeSecurityGroupIngress) Response() interface{} { return new(AsyncJobResult) } -func (RevokeSecurityGroupIngress) asyncResponse() interface{} { - return new(booleanResponse) + +// AsyncResponse returns the struct to unmarshal the async job +func (RevokeSecurityGroupIngress) AsyncResponse() interface{} { + return new(BooleanResponse) } // RevokeSecurityGroupEgress (Async) represents the ingress/egress rule deletion type RevokeSecurityGroupEgress struct { - ID string `json:"id" doc:"The ID of the egress rule"` - _ bool `name:"revokeSecurityGroupEgress" description:"Deletes a particular egress rule from this security group"` + ID *UUID `json:"id" doc:"The ID of the egress rule"` + _ bool `name:"revokeSecurityGroupEgress" description:"Deletes a particular egress rule from this security group"` } -func (RevokeSecurityGroupEgress) response() interface{} { +// Response returns the struct to unmarshal +func (RevokeSecurityGroupEgress) Response() interface{} { return new(AsyncJobResult) } -func (RevokeSecurityGroupEgress) asyncResponse() interface{} { - return new(booleanResponse) +// AsyncResponse returns the struct to unmarshal the async job +func (RevokeSecurityGroupEgress) AsyncResponse() interface{} { + return new(BooleanResponse) } +//go:generate go run generate/main.go -interface=Listable ListSecurityGroups + // ListSecurityGroups represents a search for security groups type ListSecurityGroups struct { - Account string `json:"account,omitempty" doc:"list resources by account. Must be used with the domainId parameter."` - DomainID string `json:"domainid,omitempty" doc:"list only resources belonging to the domain specified"` - ID string `json:"id,omitempty" doc:"list the security group by the id provided"` - IsRecursive *bool `json:"isrecursive,omitempty" doc:"defaults to false, but if true, lists all resources from the parent specified by the domainId till leaves."` - Keyword string `json:"keyword,omitempty" doc:"List by keyword"` - ListAll *bool `json:"listall,omitempty" doc:"If set to false, list only resources belonging to the command's caller; if set to true - list resources that the caller is authorized to see. Default value is false"` - Page int `json:"page,omitempty"` - PageSize int `json:"pagesize,omitempty"` - SecurityGroupName string `json:"securitygroupname,omitempty" doc:"lists security groups by name"` - Tags []ResourceTag `json:"tags,omitempty" doc:"List resources by tags (key/value pairs)"` - VirtualMachineID string `json:"virtualmachineid,omitempty" doc:"lists security groups by virtual machine id"` - _ bool `name:"listSecurityGroups" description:"Lists security groups"` + ID *UUID `json:"id,omitempty" doc:"list the security group by the id provided"` + Keyword string `json:"keyword,omitempty" doc:"List by keyword"` + Page int `json:"page,omitempty"` + PageSize int `json:"pagesize,omitempty"` + SecurityGroupName string `json:"securitygroupname,omitempty" doc:"lists security groups by name"` + VirtualMachineID *UUID `json:"virtualmachineid,omitempty" doc:"lists security groups by virtual machine id"` + _ bool `name:"listSecurityGroups" description:"Lists security groups"` } // ListSecurityGroupsResponse represents a list of security groups @@ -242,31 +224,3 @@ type ListSecurityGroupsResponse struct { Count int `json:"count"` SecurityGroup []SecurityGroup `json:"securitygroup"` } - -func (ListSecurityGroups) response() interface{} { - return new(ListSecurityGroupsResponse) -} - -// SetPage sets the current page -func (lsg *ListSecurityGroups) SetPage(page int) { - lsg.Page = page -} - -// SetPageSize sets the page size -func (lsg *ListSecurityGroups) SetPageSize(pageSize int) { - lsg.PageSize = pageSize -} - -func (ListSecurityGroups) each(resp interface{}, callback IterateItemFunc) { - sgs, ok := resp.(*ListSecurityGroupsResponse) - if !ok { - callback(nil, fmt.Errorf("wrong type. ListSecurityGroupsResponse expected, got %T", resp)) - return - } - - for i := range sgs.SecurityGroup { - if !callback(&sgs.SecurityGroup[i], nil) { - break - } - } -} diff --git a/vendor/github.com/exoscale/egoscale/securitygroups_response.go b/vendor/github.com/exoscale/egoscale/securitygroups_response.go new file mode 100644 index 000000000..ff08f333c --- /dev/null +++ b/vendor/github.com/exoscale/egoscale/securitygroups_response.go @@ -0,0 +1,43 @@ +// code generated; DO NOT EDIT. + +package egoscale + +import "fmt" + +// Response returns the struct to unmarshal +func (ListSecurityGroups) Response() interface{} { + return new(ListSecurityGroupsResponse) +} + +// ListRequest returns itself +func (ls *ListSecurityGroups) ListRequest() (ListCommand, error) { + if ls == nil { + return nil, fmt.Errorf("%T cannot be nil", ls) + } + return ls, nil +} + +// SetPage sets the current apge +func (ls *ListSecurityGroups) SetPage(page int) { + ls.Page = page +} + +// SetPageSize sets the page size +func (ls *ListSecurityGroups) SetPageSize(pageSize int) { + ls.PageSize = pageSize +} + +// Each triggers the callback for each, valid answer or any non 404 issue +func (ListSecurityGroups) Each(resp interface{}, callback IterateItemFunc) { + items, ok := resp.(*ListSecurityGroupsResponse) + if !ok { + callback(nil, fmt.Errorf("wrong type, ListSecurityGroupsResponse was expected, got %T", resp)) + return + } + + for i := range items.SecurityGroup { + if !callback(&items.SecurityGroup[i], nil) { + break + } + } +} diff --git a/vendor/github.com/exoscale/egoscale/serialization.go b/vendor/github.com/exoscale/egoscale/serialization.go index fc2124125..255dd4554 100644 --- a/vendor/github.com/exoscale/egoscale/serialization.go +++ b/vendor/github.com/exoscale/egoscale/serialization.go @@ -13,8 +13,8 @@ import ( func csQuotePlus(s string) string { s = strings.Replace(s, "+", "%20", -1) - s = strings.Replace(s, "%5B", "[", -1) - s = strings.Replace(s, "%5D", "]", -1) + // This line is used to safeguard the "*" when producing the signature + s = strings.Replace(s, "%2A", "*", -1) return s } @@ -56,7 +56,9 @@ func info(command interface{}) (*CommandInfo, error) { // prepareValues uses a command to build a POST request // // command is not a Command so it's easier to Test -func prepareValues(prefix string, params url.Values, command interface{}) error { +func prepareValues(prefix string, command interface{}) (url.Values, error) { + params := url.Values{} + value := reflect.ValueOf(command) typeof := reflect.TypeOf(command) @@ -68,7 +70,7 @@ func prepareValues(prefix string, params url.Values, command interface{}) error // Checking for nil commands if !value.IsValid() { - return fmt.Errorf("cannot serialize the invalid value %#v", command) + return nil, fmt.Errorf("cannot serialize the invalid value %#v", command) } for i := 0; i < typeof.NumField(); i++ { @@ -79,219 +81,165 @@ func prepareValues(prefix string, params url.Values, command interface{}) error val := value.Field(i) tag := field.Tag + + var err error + var name string + var value interface{} + if json, ok := tag.Lookup("json"); ok { n, required := ExtractJSONTag(field.Name, json) - name := prefix + n + name = prefix + n switch val.Kind() { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - v := val.Int() - if v == 0 { - if required { - return fmt.Errorf("%s.%s (%v) is required, got 0", typeof.Name(), n, val.Kind()) - } - } else { - params.Set(name, strconv.FormatInt(v, 10)) - } + value, err = prepareInt(val.Int(), required) + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: - v := val.Uint() - if v == 0 { - if required { - return fmt.Errorf("%s.%s (%v) is required, got 0", typeof.Name(), n, val.Kind()) - } - } else { - params.Set(name, strconv.FormatUint(v, 10)) - } + value, err = prepareUint(val.Uint(), required) + case reflect.Float32, reflect.Float64: - v := val.Float() - if v == 0 { - if required { - return fmt.Errorf("%s.%s (%v) is required, got 0", typeof.Name(), n, val.Kind()) - } - } else { - params.Set(name, strconv.FormatFloat(v, 'f', -1, 64)) - } + value, err = prepareFloat(val.Float(), required) + case reflect.String: - v := val.String() - if v == "" { - if required { - return fmt.Errorf("%s.%s (%v) is required, got \"\"", typeof.Name(), n, val.Kind()) - } - } else { - params.Set(name, v) - } + value, err = prepareString(val.String(), required) + case reflect.Bool: - v := val.Bool() - if !v { - if required { - params.Set(name, "false") - } - } else { - params.Set(name, "true") - } - case reflect.Ptr: - if val.IsNil() { - if required { - return fmt.Errorf("%s.%s (%v) is required, got tempty ptr", typeof.Name(), n, val.Kind()) - } - } else { - switch field.Type.Elem().Kind() { - case reflect.Bool: - params.Set(name, strconv.FormatBool(val.Elem().Bool())) - case reflect.Struct: - i := val.Interface() - s, ok := i.(fmt.Stringer) - if !ok { - return fmt.Errorf("%s.%s (%v) is not a Stringer", typeof.Name(), field.Name, val.Kind()) - } - if s != nil && s.String() == "" { - if required { - return fmt.Errorf("%s.%s (%v) is required, got empty value", typeof.Name(), field.Name, val.Kind()) - } - } else { - params.Set(n, s.String()) - } - default: - log.Printf("[SKIP] %s.%s (%v) not supported", typeof.Name(), n, field.Type.Elem().Kind()) - } - } - case reflect.Slice: - switch field.Type.Elem().Kind() { - case reflect.Uint8: - switch field.Type { - case reflect.TypeOf(net.IPv4zero): - ip := (net.IP)(val.Bytes()) - if ip == nil || ip.Equal(net.IPv4zero) { - if required { - return fmt.Errorf("%s.%s (%v) is required, got zero IPv4 address", typeof.Name(), n, val.Kind()) - } - } else { - params.Set(name, ip.String()) - } - case reflect.TypeOf(MAC48(0, 0, 0, 0, 0, 0)): - mac := val.Interface().(MACAddress) - s := mac.String() - if s == "" { - if required { - return fmt.Errorf("%s.%s (%v) is required, got empty MAC address", typeof.Name(), field.Name, val.Kind()) - } - } else { - params.Set(name, s) - } - default: - if val.Len() == 0 { - if required { - return fmt.Errorf("%s.%s (%v) is required, got empty slice", typeof.Name(), n, val.Kind()) - } - } else { - v := val.Bytes() - params.Set(name, base64.StdEncoding.EncodeToString(v)) - } - } - case reflect.String: - { - if val.Len() == 0 { - if required { - return fmt.Errorf("%s.%s (%v) is required, got empty slice", typeof.Name(), n, val.Kind()) - } - } else { - elems := make([]string, 0, val.Len()) - for i := 0; i < val.Len(); i++ { - // XXX what if the value contains a comma? Double encode? - s := val.Index(i).String() - elems = append(elems, s) - } - params.Set(name, strings.Join(elems, ",")) - } - } - default: - switch field.Type.Elem() { - case reflect.TypeOf(CIDR{}): - if val.Len() == 0 { - if required { - return fmt.Errorf("%s.%s (%v) is required, got empty slice", typeof.Name(), n, val.Kind()) - } - } else { - value := reflect.ValueOf(val.Interface()) - ss := make([]string, val.Len()) - for i := 0; i < value.Len(); i++ { - v := value.Index(i).Interface() - s, ok := v.(fmt.Stringer) - if !ok { - return fmt.Errorf("not a String, %T", v) - } - ss[i] = s.String() - } - params.Set(name, strings.Join(ss, ",")) - } - default: - if val.Len() == 0 { - if required { - return fmt.Errorf("%s.%s (%v) is required, got empty slice", typeof.Name(), n, val.Kind()) - } - } else { - err := prepareList(name, params, val.Interface()) - if err != nil { - return err - } - } - } - } + value, err = prepareBool(val.Bool(), required) + case reflect.Map: if val.Len() == 0 { if required { - return fmt.Errorf("%s.%s (%v) is required, got empty map", typeof.Name(), field.Name, val.Kind()) + err = fmt.Errorf("field is required, got empty map") } } else { - err := prepareMap(name, params, val.Interface()) - if err != nil { - return err - } + value, err = prepareMap(name, val.Interface()) } + + case reflect.Ptr: + value, err = preparePtr(field.Type.Elem().Kind(), val, required) + + case reflect.Slice: + value, err = prepareSlice(name, field.Type, val, required) + case reflect.Struct: - i := val.Interface() - s, ok := i.(fmt.Stringer) - if !ok { - return fmt.Errorf("%s.%s (%v) is not a Stringer", typeof.Name(), field.Name, val.Kind()) - } - if s != nil && s.String() == "" { - if required { - return fmt.Errorf("%s.%s (%v) is required, got empty value", typeof.Name(), field.Name, val.Kind()) - } - } else { - params.Set(n, s.String()) - } + value, err = prepareStruct(val.Interface(), required) + default: if required { - return fmt.Errorf("unsupported type %s.%s (%v)", typeof.Name(), n, val.Kind()) + err = fmt.Errorf("unsupported type") } - fmt.Printf("%s\n", val.Kind()) } } else { - log.Printf("[SKIP] %s.%s no json label found", typeof.Name(), field.Name) + switch val.Kind() { + case reflect.Struct: + value, err = prepareEmbedStruct(val.Interface()) + default: + log.Printf("[SKIP] %s.%s no json label found", typeof.Name(), field.Name) + } + } + + if err != nil { + return nil, fmt.Errorf("%s.%s (%v) %s", typeof.Name(), field.Name, val.Kind(), err) + } + + switch v := value.(type) { + case *string: + if name != "" && v != nil { + params.Set(name, *v) + } + case url.Values: + for k, xs := range v { + for _, x := range xs { + params.Add(k, x) + } + } } } - return nil + return params, nil } -func prepareList(prefix string, params url.Values, slice interface{}) error { +func prepareInt(v int64, required bool) (*string, error) { + if v == 0 { + if required { + return nil, fmt.Errorf("field is required, got %d", v) + } + return nil, nil + } + value := strconv.FormatInt(v, 10) + return &value, nil +} + +func prepareUint(v uint64, required bool) (*string, error) { + if v == 0 { + if required { + return nil, fmt.Errorf("field is required, got %d", v) + } + return nil, nil + } + + value := strconv.FormatUint(v, 10) + return &value, nil +} + +func prepareFloat(v float64, required bool) (*string, error) { + if v == 0 { + if required { + return nil, fmt.Errorf("field is required, got %f", v) + } + return nil, nil + } + value := strconv.FormatFloat(v, 'f', -1, 64) + return &value, nil +} + +func prepareString(v string, required bool) (*string, error) { + if v == "" { + if required { + return nil, fmt.Errorf("field is required, got %q", v) + } + return nil, nil + } + return &v, nil +} + +func prepareBool(v bool, required bool) (*string, error) { + value := strconv.FormatBool(v) + if !v { + if required { + return &value, nil + } + return nil, nil + } + + return &value, nil +} + +func prepareList(prefix string, slice interface{}) (url.Values, error) { + params := url.Values{} value := reflect.ValueOf(slice) for i := 0; i < value.Len(); i++ { - err := prepareValues(fmt.Sprintf("%s[%d].", prefix, i), params, value.Index(i).Interface()) + ps, err := prepareValues(fmt.Sprintf("%s[%d].", prefix, i), value.Index(i).Interface()) if err != nil { - return err + return nil, err + } + + for k, xs := range ps { + for _, x := range xs { + params.Add(k, x) + } } } - return nil + return params, nil } -func prepareMap(prefix string, params url.Values, m interface{}) error { - value := reflect.ValueOf(m) +func prepareMap(prefix string, m interface{}) (url.Values, error) { + value := url.Values{} + v := reflect.ValueOf(m) - for i, key := range value.MapKeys() { + for i, key := range v.MapKeys() { var keyName string var keyValue string @@ -299,19 +247,143 @@ func prepareMap(prefix string, params url.Values, m interface{}) error { case reflect.String: keyName = key.String() default: - return fmt.Errorf("only map[string]string are supported (XXX)") + return value, fmt.Errorf("only map[string]string are supported (XXX)") } - val := value.MapIndex(key) + val := v.MapIndex(key) switch val.Kind() { case reflect.String: keyValue = val.String() default: - return fmt.Errorf("only map[string]string are supported (XXX)") + return value, fmt.Errorf("only map[string]string are supported (XXX)") } - params.Set(fmt.Sprintf("%s[%d].%s", prefix, i, keyName), keyValue) + + value.Set(fmt.Sprintf("%s[%d].%s", prefix, i, keyName), keyValue) } - return nil + + return value, nil +} + +func preparePtr(kind reflect.Kind, val reflect.Value, required bool) (*string, error) { + if val.IsNil() { + if required { + return nil, fmt.Errorf("field is required, got empty ptr") + } + return nil, nil + } + + switch kind { + case reflect.Bool: + return prepareBool(val.Elem().Bool(), true) + case reflect.Struct: + return prepareStruct(val.Interface(), required) + default: + return nil, fmt.Errorf("kind %v is not supported as a ptr", kind) + } +} + +func prepareSlice(name string, fieldType reflect.Type, val reflect.Value, required bool) (interface{}, error) { + switch fieldType.Elem().Kind() { + case reflect.Uint8: + switch fieldType { + case reflect.TypeOf(net.IPv4zero): + ip := (net.IP)(val.Bytes()) + if ip == nil || ip.Equal(net.IP{}) { + if required { + return nil, fmt.Errorf("field is required, got zero IPv4 address") + } + } else { + value := ip.String() + return &value, nil + } + + case reflect.TypeOf(MAC48(0, 0, 0, 0, 0, 0)): + mac := val.Interface().(MACAddress) + s := mac.String() + if s == "" { + if required { + return nil, fmt.Errorf("field is required, got empty MAC address") + } + } else { + return &s, nil + } + default: + if val.Len() == 0 { + if required { + return nil, fmt.Errorf("field is required, got empty slice") + } + } else { + value := base64.StdEncoding.EncodeToString(val.Bytes()) + return &value, nil + } + } + case reflect.String: + if val.Len() == 0 { + if required { + return nil, fmt.Errorf("field is required, got empty slice") + } + } else { + elems := make([]string, 0, val.Len()) + for i := 0; i < val.Len(); i++ { + // XXX what if the value contains a comma? Double encode? + s := val.Index(i).String() + elems = append(elems, s) + } + value := strings.Join(elems, ",") + return &value, nil + } + default: + switch fieldType.Elem() { + case reflect.TypeOf(CIDR{}), reflect.TypeOf(UUID{}): + if val.Len() == 0 { + if required { + return nil, fmt.Errorf("field is required, got empty slice") + } + } else { + v := reflect.ValueOf(val.Interface()) + ss := make([]string, val.Len()) + for i := 0; i < v.Len(); i++ { + e := v.Index(i).Interface() + s, ok := e.(fmt.Stringer) + if !ok { + return nil, fmt.Errorf("not a String, %T", e) + } + ss[i] = s.String() + } + value := strings.Join(ss, ",") + return &value, nil + } + default: + if val.Len() == 0 { + if required { + return nil, fmt.Errorf("field is required, got empty slice") + } + } else { + return prepareList(name, val.Interface()) + } + } + } + + return nil, nil +} + +func prepareStruct(i interface{}, required bool) (*string, error) { + s, ok := i.(fmt.Stringer) + if !ok { + return nil, fmt.Errorf("struct field not a Stringer") + } + + if s == nil { + if required { + return nil, fmt.Errorf("field is required, got %#v", s) + } + } + + return prepareString(s.String(), required) +} + +func prepareEmbedStruct(i interface{}) (url.Values, error) { + return prepareValues("", i) } // ExtractJSONTag returns the variable name or defaultName as well as if the field is required (!omitempty) diff --git a/vendor/github.com/exoscale/egoscale/service_offerings.go b/vendor/github.com/exoscale/egoscale/service_offerings.go index 2d2e44597..8d3551467 100644 --- a/vendor/github.com/exoscale/egoscale/service_offerings.go +++ b/vendor/github.com/exoscale/egoscale/service_offerings.go @@ -1,9 +1,5 @@ package egoscale -import ( - "fmt" -) - // ServiceOffering corresponds to the Compute Offerings // // A service offering correspond to some hardware features (CPU, RAM). @@ -21,11 +17,9 @@ type ServiceOffering struct { DiskIopsReadRate int64 `json:"diskIopsReadRate,omitempty" doc:"io requests read rate of the service offering"` DiskIopsWriteRate int64 `json:"diskIopsWriteRate,omitempty" doc:"io requests write rate of the service offering"` Displaytext string `json:"displaytext,omitempty" doc:"an alternate display text of the service offering."` - Domain string `json:"domain,omitempty" doc:"Domain name for the offering"` - DomainID string `json:"domainid,omitempty" doc:"the domain id of the service offering"` HostTags string `json:"hosttags,omitempty" doc:"the host tag for the service offering"` HypervisorSnapshotReserve int `json:"hypervisorsnapshotreserve,omitempty" doc:"Hypervisor snapshot reserve space as a percent of a volume (for managed storage using Xen or VMware)"` - ID string `json:"id,omitempty" doc:"the id of the service offering"` + ID *UUID `json:"id" doc:"the id of the service offering"` IsCustomized bool `json:"iscustomized,omitempty" doc:"is true if the offering is customized"` IsCustomizedIops bool `json:"iscustomizediops,omitempty" doc:"true if disk offering uses custom iops, false otherwise"` IsSystem bool `json:"issystem,omitempty" doc:"is this a system vm offering"` @@ -49,8 +43,6 @@ func (so ServiceOffering) ListRequest() (ListCommand, error) { // Restricted cannot be applied here because it really has three states req := &ListServiceOfferings{ ID: so.ID, - DomainID: so.DomainID, - IsSystem: &so.IsSystem, Name: so.Name, SystemVMType: so.SystemVMType, } @@ -62,10 +54,11 @@ func (so ServiceOffering) ListRequest() (ListCommand, error) { return req, nil } +//go:generate go run generate/main.go -interface=Listable ListServiceOfferings + // ListServiceOfferings represents a query for service offerings type ListServiceOfferings struct { - DomainID string `json:"domainid,omitempty" doc:"the ID of the domain associated with the service offering"` - ID string `json:"id,omitempty" doc:"ID of the service offering"` + ID *UUID `json:"id,omitempty" doc:"ID of the service offering"` IsSystem *bool `json:"issystem,omitempty" doc:"is this a system vm offering"` Keyword string `json:"keyword,omitempty" doc:"List by keyword"` Name string `json:"name,omitempty" doc:"name of the service offering"` @@ -73,7 +66,7 @@ type ListServiceOfferings struct { PageSize int `json:"pagesize,omitempty"` Restricted *bool `json:"restricted,omitempty" doc:"filter by the restriction flag: true to list only the restricted service offerings, false to list non-restricted service offerings, or nothing for all."` SystemVMType string `json:"systemvmtype,omitempty" doc:"the system VM type. Possible types are \"consoleproxy\", \"secondarystoragevm\" or \"domainrouter\"."` - VirtualMachineID string `json:"virtualmachineid,omitempty" doc:"the ID of the virtual machine. Pass this in if you want to see the available service offering that a virtual machine can be changed to."` + VirtualMachineID *UUID `json:"virtualmachineid,omitempty" doc:"the ID of the virtual machine. Pass this in if you want to see the available service offering that a virtual machine can be changed to."` _ bool `name:"listServiceOfferings" description:"Lists all available service offerings."` } @@ -82,31 +75,3 @@ type ListServiceOfferingsResponse struct { Count int `json:"count"` ServiceOffering []ServiceOffering `json:"serviceoffering"` } - -func (ListServiceOfferings) response() interface{} { - return new(ListServiceOfferingsResponse) -} - -// SetPage sets the current page -func (lso *ListServiceOfferings) SetPage(page int) { - lso.Page = page -} - -// SetPageSize sets the page size -func (lso *ListServiceOfferings) SetPageSize(pageSize int) { - lso.PageSize = pageSize -} - -func (ListServiceOfferings) each(resp interface{}, callback IterateItemFunc) { - sos, ok := resp.(*ListServiceOfferingsResponse) - if !ok { - callback(nil, fmt.Errorf("wrong type. ListServiceOfferingsResponse expected, got %T", resp)) - return - } - - for i := range sos.ServiceOffering { - if !callback(&sos.ServiceOffering[i], nil) { - break - } - } -} diff --git a/vendor/github.com/exoscale/egoscale/serviceofferings_response.go b/vendor/github.com/exoscale/egoscale/serviceofferings_response.go new file mode 100644 index 000000000..a01d4aaf4 --- /dev/null +++ b/vendor/github.com/exoscale/egoscale/serviceofferings_response.go @@ -0,0 +1,43 @@ +// code generated; DO NOT EDIT. + +package egoscale + +import "fmt" + +// Response returns the struct to unmarshal +func (ListServiceOfferings) Response() interface{} { + return new(ListServiceOfferingsResponse) +} + +// ListRequest returns itself +func (ls *ListServiceOfferings) ListRequest() (ListCommand, error) { + if ls == nil { + return nil, fmt.Errorf("%T cannot be nil", ls) + } + return ls, nil +} + +// SetPage sets the current apge +func (ls *ListServiceOfferings) SetPage(page int) { + ls.Page = page +} + +// SetPageSize sets the page size +func (ls *ListServiceOfferings) SetPageSize(pageSize int) { + ls.PageSize = pageSize +} + +// Each triggers the callback for each, valid answer or any non 404 issue +func (ListServiceOfferings) Each(resp interface{}, callback IterateItemFunc) { + items, ok := resp.(*ListServiceOfferingsResponse) + if !ok { + callback(nil, fmt.Errorf("wrong type, ListServiceOfferingsResponse was expected, got %T", resp)) + return + } + + for i := range items.ServiceOffering { + if !callback(&items.ServiceOffering[i], nil) { + break + } + } +} diff --git a/vendor/github.com/exoscale/egoscale/snapshots.go b/vendor/github.com/exoscale/egoscale/snapshots.go index 769f0b40e..191f4a0f7 100644 --- a/vendor/github.com/exoscale/egoscale/snapshots.go +++ b/vendor/github.com/exoscale/egoscale/snapshots.go @@ -3,50 +3,47 @@ package egoscale // SnapshotState represents the Snapshot.State enum // // See: https://github.com/apache/cloudstack/blob/master/api/src/main/java/com/cloud/storage/Snapshot.java -type SnapshotState int +type SnapshotState string -//go:generate stringer -type SnapshotState const ( // Allocated ... (TODO) - Allocated SnapshotState = iota + Allocated SnapshotState = "Allocated" // Creating ... (TODO) - Creating + Creating SnapshotState = "Creating" // CreatedOnPrimary ... (TODO) - CreatedOnPrimary + CreatedOnPrimary SnapshotState = "CreatedOnPrimary" // BackingUp ... (TODO) - BackingUp + BackingUp SnapshotState = "BackingUp" // BackedUp ... (TODO) - BackedUp + BackedUp SnapshotState = "BackedUp" // Copying ... (TODO) - Copying + Copying SnapshotState = "Copying" // Destroying ... (TODO) - Destroying + Destroying SnapshotState = "Destroying" // Destroyed ... (TODO) - Destroyed - // Error ... (TODO) - Error + Destroyed SnapshotState = "Destroyed" + // Error is a state where the user can't see the snapshot while the snapshot may still exist on the storage + Error SnapshotState = "Error" ) // Snapshot represents a volume snapshot type Snapshot struct { Account string `json:"account,omitempty" doc:"the account associated with the snapshot"` - AccountID string `json:"accountid,omitempty" doc:"the account ID associated with the snapshot"` + AccountID *UUID `json:"accountid,omitempty" doc:"the account ID associated with the snapshot"` Created string `json:"created,omitempty" doc:"the date the snapshot was created"` - Domain string `json:"domain,omitempty" doc:"the domain name of the snapshot's account"` - DomainID string `json:"domainid,omitempty" doc:"the domain ID of the snapshot's account"` - ID string `json:"id,omitempty" doc:"ID of the snapshot"` + ID *UUID `json:"id,omitempty" doc:"ID of the snapshot"` IntervalType string `json:"intervaltype,omitempty" doc:"valid types are hourly, daily, weekly, monthy, template, and none."` Name string `json:"name,omitempty" doc:"name of the snapshot"` PhysicalSize int64 `json:"physicalsize,omitempty" doc:"physical size of the snapshot on image store"` Revertable *bool `json:"revertable,omitempty" doc:"indicates whether the underlying storage supports reverting the volume to this snapshot"` Size int64 `json:"size,omitempty" doc:"the size of original volume"` SnapshotType string `json:"snapshottype,omitempty" doc:"the type of the snapshot"` - State SnapshotState `json:"state,omitempty" doc:"the state of the snapshot. BackedUp means that snapshot is ready to be used; Creating - the snapshot is being allocated on the primary storage; BackingUp - the snapshot is being backed up on secondary storage"` + State string `json:"state,omitempty" doc:"the state of the snapshot. BackedUp means that snapshot is ready to be used; Creating - the snapshot is being allocated on the primary storage; BackingUp - the snapshot is being backed up on secondary storage"` Tags []ResourceTag `json:"tags,omitempty" doc:"the list of resource tags associated with snapshot"` - VolumeID string `json:"volumeid,omitempty" doc:"ID of the disk volume"` + VolumeID *UUID `json:"volumeid,omitempty" doc:"ID of the disk volume"` VolumeName string `json:"volumename,omitempty" doc:"name of the disk volume"` VolumeType string `json:"volumetype,omitempty" doc:"type of the disk volume"` - ZoneID string `json:"zoneid,omitempty" doc:"id of the availability zone"` + ZoneID *UUID `json:"zoneid,omitempty" doc:"id of the availability zone"` } // ResourceType returns the type of the resource @@ -56,37 +53,50 @@ func (Snapshot) ResourceType() string { // CreateSnapshot (Async) creates an instant snapshot of a volume type CreateSnapshot struct { - VolumeID string `json:"volumeid" doc:"The ID of the disk volume"` - Account string `json:"account,omitempty" doc:"The account of the snapshot. The account parameter must be used with the domainId parameter."` - DomainID string `json:"domainid,omitempty" doc:"The domain ID of the snapshot. If used with the account parameter, specifies a domain for the account associated with the disk volume."` - QuiesceVM *bool `json:"quiescevm,omitempty" doc:"quiesce vm if true"` - _ bool `name:"createSnapshot" description:"Creates an instant snapshot of a volume."` + VolumeID *UUID `json:"volumeid" doc:"The ID of the disk volume"` + QuiesceVM *bool `json:"quiescevm,omitempty" doc:"quiesce vm if true"` + _ bool `name:"createSnapshot" description:"Creates an instant snapshot of a volume."` } -func (CreateSnapshot) response() interface{} { +// Response returns the struct to unmarshal +func (CreateSnapshot) Response() interface{} { return new(AsyncJobResult) } -func (CreateSnapshot) asyncResponse() interface{} { +// AsyncResponse returns the struct to unmarshal the async job +func (CreateSnapshot) AsyncResponse() interface{} { return new(Snapshot) } +// ListRequest builds the ListSnapshot request +func (ss Snapshot) ListRequest() (ListCommand, error) { + // Restricted cannot be applied here because it really has three states + req := &ListSnapshots{ + ID: ss.ID, + Name: ss.Name, + VolumeID: ss.VolumeID, + SnapshotType: ss.SnapshotType, + ZoneID: ss.ZoneID, + // TODO: tags + } + + return req, nil +} + +//go:generate go run generate/main.go -interface=Listable ListSnapshots + // ListSnapshots lists the volume snapshots type ListSnapshots struct { - Account string `json:"account,omitempty" doc:"list resources by account. Must be used with the domainId parameter."` - DomainID string `json:"domainid,omitempty" doc:"list only resources belonging to the domain specified"` - ID string `json:"id,omitempty" doc:"lists snapshot by snapshot ID"` + ID *UUID `json:"id,omitempty" doc:"lists snapshot by snapshot ID"` IntervalType string `json:"intervaltype,omitempty" doc:"valid values are HOURLY, DAILY, WEEKLY, and MONTHLY."` - IsRecursive *bool `json:"isrecursive,omitempty" doc:"defaults to false, but if true, lists all resources from the parent specified by the domainId till leaves."` Keyword string `json:"keyword,omitempty" doc:"List by keyword"` - ListAll *bool `json:"listall,omitempty" doc:"If set to false, list only resources belonging to the command's caller; if set to true - list resources that the caller is authorized to see. Default value is false"` Name string `json:"name,omitempty" doc:"lists snapshot by snapshot name"` Page int `json:"page,omitempty"` PageSize int `json:"pagesize,omitempty"` SnapshotType string `json:"snapshottype,omitempty" doc:"valid values are MANUAL or RECURRING."` Tags []ResourceTag `json:"tags,omitempty" doc:"List resources by tags (key/value pairs)"` - VolumeID string `json:"volumeid,omitempty" doc:"the ID of the disk volume"` - ZoneID string `json:"zoneid,omitempty" doc:"list snapshots by zone id"` + VolumeID *UUID `json:"volumeid,omitempty" doc:"the ID of the disk volume"` + ZoneID *UUID `json:"zoneid,omitempty" doc:"list snapshots by zone id"` _ bool `name:"listSnapshots" description:"Lists all available snapshots for the account."` } @@ -96,34 +106,34 @@ type ListSnapshotsResponse struct { Snapshot []Snapshot `json:"snapshot"` } -func (ListSnapshots) response() interface{} { - return new(ListSnapshotsResponse) -} - // DeleteSnapshot (Async) deletes a snapshot of a disk volume type DeleteSnapshot struct { - ID string `json:"id" doc:"The ID of the snapshot"` - _ bool `name:"deleteSnapshot" description:"Deletes a snapshot of a disk volume."` + ID *UUID `json:"id" doc:"The ID of the snapshot"` + _ bool `name:"deleteSnapshot" description:"Deletes a snapshot of a disk volume."` } -func (DeleteSnapshot) response() interface{} { +// Response returns the struct to unmarshal +func (DeleteSnapshot) Response() interface{} { return new(AsyncJobResult) } -func (DeleteSnapshot) asyncResponse() interface{} { - return new(booleanResponse) +// AsyncResponse returns the struct to unmarshal the async job +func (DeleteSnapshot) AsyncResponse() interface{} { + return new(BooleanResponse) } // RevertSnapshot (Async) reverts a volume snapshot type RevertSnapshot struct { - ID string `json:"id" doc:"The ID of the snapshot"` - _ bool `name:"revertSnapshot" description:"revert a volume snapshot."` + ID *UUID `json:"id" doc:"The ID of the snapshot"` + _ bool `name:"revertSnapshot" description:"revert a volume snapshot."` } -func (RevertSnapshot) response() interface{} { +// Response returns the struct to unmarshal +func (RevertSnapshot) Response() interface{} { return new(AsyncJobResult) } -func (RevertSnapshot) asyncResponse() interface{} { - return new(booleanResponse) +// AsyncResponse returns the struct to unmarshal the async job +func (RevertSnapshot) AsyncResponse() interface{} { + return new(BooleanResponse) } diff --git a/vendor/github.com/exoscale/egoscale/snapshots_response.go b/vendor/github.com/exoscale/egoscale/snapshots_response.go new file mode 100644 index 000000000..2ca9cff5a --- /dev/null +++ b/vendor/github.com/exoscale/egoscale/snapshots_response.go @@ -0,0 +1,43 @@ +// code generated; DO NOT EDIT. + +package egoscale + +import "fmt" + +// Response returns the struct to unmarshal +func (ListSnapshots) Response() interface{} { + return new(ListSnapshotsResponse) +} + +// ListRequest returns itself +func (ls *ListSnapshots) ListRequest() (ListCommand, error) { + if ls == nil { + return nil, fmt.Errorf("%T cannot be nil", ls) + } + return ls, nil +} + +// SetPage sets the current apge +func (ls *ListSnapshots) SetPage(page int) { + ls.Page = page +} + +// SetPageSize sets the page size +func (ls *ListSnapshots) SetPageSize(pageSize int) { + ls.PageSize = pageSize +} + +// Each triggers the callback for each, valid answer or any non 404 issue +func (ListSnapshots) Each(resp interface{}, callback IterateItemFunc) { + items, ok := resp.(*ListSnapshotsResponse) + if !ok { + callback(nil, fmt.Errorf("wrong type, ListSnapshotsResponse was expected, got %T", resp)) + return + } + + for i := range items.Snapshot { + if !callback(&items.Snapshot[i], nil) { + break + } + } +} diff --git a/vendor/github.com/exoscale/egoscale/snapshotstate_string.go b/vendor/github.com/exoscale/egoscale/snapshotstate_string.go deleted file mode 100644 index a7119dca0..000000000 --- a/vendor/github.com/exoscale/egoscale/snapshotstate_string.go +++ /dev/null @@ -1,16 +0,0 @@ -// Code generated by "stringer -type SnapshotState"; DO NOT EDIT. - -package egoscale - -import "strconv" - -const _SnapshotState_name = "AllocatedCreatingCreatedOnPrimaryBackingUpBackedUpCopyingDestroyingDestroyedError" - -var _SnapshotState_index = [...]uint8{0, 9, 17, 33, 42, 50, 57, 67, 76, 81} - -func (i SnapshotState) String() string { - if i < 0 || i >= SnapshotState(len(_SnapshotState_index)-1) { - return "SnapshotState(" + strconv.FormatInt(int64(i), 10) + ")" - } - return _SnapshotState_name[_SnapshotState_index[i]:_SnapshotState_index[i+1]] -} diff --git a/vendor/github.com/exoscale/egoscale/ssh_keypairs.go b/vendor/github.com/exoscale/egoscale/ssh_keypairs.go index 04924f1f5..9f2bedca0 100644 --- a/vendor/github.com/exoscale/egoscale/ssh_keypairs.go +++ b/vendor/github.com/exoscale/egoscale/ssh_keypairs.go @@ -9,11 +9,9 @@ import ( // // See: http://docs.cloudstack.apache.org/projects/cloudstack-administration/en/stable/virtual_machines.html#creating-the-ssh-keypair type SSHKeyPair struct { - Account string `json:"account,omitempty"` // must be used with a Domain ID - DomainID string `json:"domainid,omitempty"` - Fingerprint string `json:"fingerprint,omitempty"` - Name string `json:"name,omitempty"` - PrivateKey string `json:"privatekey,omitempty"` + Fingerprint string `json:"fingerprint,omitempty" doc:"Fingerprint of the public key"` + Name string `json:"name,omitempty" doc:"Name of the keypair"` + PrivateKey string `json:"privatekey,omitempty" doc:"Private key"` } // Delete removes the given SSH key, by Name @@ -23,17 +21,13 @@ func (ssh SSHKeyPair) Delete(ctx context.Context, client *Client) error { } return client.BooleanRequestWithContext(ctx, &DeleteSSHKeyPair{ - Name: ssh.Name, - Account: ssh.Account, - DomainID: ssh.DomainID, + Name: ssh.Name, }) } // ListRequest builds the ListSSHKeyPairs request func (ssh SSHKeyPair) ListRequest() (ListCommand, error) { req := &ListSSHKeyPairs{ - Account: ssh.Account, - DomainID: ssh.DomainID, Fingerprint: ssh.Fingerprint, Name: ssh.Name, } @@ -43,49 +37,44 @@ func (ssh SSHKeyPair) ListRequest() (ListCommand, error) { // CreateSSHKeyPair represents a new keypair to be created type CreateSSHKeyPair struct { - Name string `json:"name" doc:"Name of the keypair"` - Account string `json:"account,omitempty" doc:"an optional account for the ssh key. Must be used with domainId."` - DomainID string `json:"domainid,omitempty" doc:"an optional domainId for the ssh key. If the account parameter is used, domainId must also be used."` - _ bool `name:"createSSHKeyPair" description:"Create a new keypair and returns the private key"` + Name string `json:"name" doc:"Name of the keypair"` + _ bool `name:"createSSHKeyPair" description:"Create a new keypair and returns the private key"` } -func (CreateSSHKeyPair) response() interface{} { +// Response returns the struct to unmarshal +func (CreateSSHKeyPair) Response() interface{} { return new(SSHKeyPair) } // DeleteSSHKeyPair represents a new keypair to be created type DeleteSSHKeyPair struct { - Name string `json:"name" doc:"Name of the keypair"` - Account string `json:"account,omitempty" doc:"the account associated with the keypair. Must be used with the domainId parameter."` - DomainID string `json:"domainid,omitempty" doc:"the domain ID associated with the keypair"` - _ bool `name:"deleteSSHKeyPair" description:"Deletes a keypair by name"` + Name string `json:"name" doc:"Name of the keypair"` + _ bool `name:"deleteSSHKeyPair" description:"Deletes a keypair by name"` } -func (DeleteSSHKeyPair) response() interface{} { - return new(booleanResponse) +// Response returns the struct to unmarshal +func (DeleteSSHKeyPair) Response() interface{} { + return new(BooleanResponse) } // RegisterSSHKeyPair represents a new registration of a public key in a keypair type RegisterSSHKeyPair struct { Name string `json:"name" doc:"Name of the keypair"` PublicKey string `json:"publickey" doc:"Public key material of the keypair"` - Account string `json:"account,omitempty" doc:"an optional account for the ssh key. Must be used with domainId."` - DomainID string `json:"domainid,omitempty" doc:"an optional domainId for the ssh key. If the account parameter is used, domainId must also be used."` _ bool `name:"registerSSHKeyPair" description:"Register a public key in a keypair under a certain name"` } -func (RegisterSSHKeyPair) response() interface{} { +// Response returns the struct to unmarshal +func (RegisterSSHKeyPair) Response() interface{} { return new(SSHKeyPair) } +//go:generate go run generate/main.go -interface=Listable ListSSHKeyPairs + // ListSSHKeyPairs represents a query for a list of SSH KeyPairs type ListSSHKeyPairs struct { - Account string `json:"account,omitempty" doc:"list resources by account. Must be used with the domainId parameter."` - DomainID string `json:"domainid,omitempty" doc:"list only resources belonging to the domain specified"` Fingerprint string `json:"fingerprint,omitempty" doc:"A public key fingerprint to look for"` - IsRecursive *bool `json:"isrecursive,omitempty" doc:"defaults to false, but if true, lists all resources from the parent specified by the domainId till leaves."` Keyword string `json:"keyword,omitempty" doc:"List by keyword"` - ListAll *bool `json:"listall,omitempty" doc:"If set to false, list only resources belonging to the command's caller; if set to true - list resources that the caller is authorized to see. Default value is false"` Name string `json:"name,omitempty" doc:"A key pair name to look for"` Page int `json:"page,omitempty"` PageSize int `json:"pagesize,omitempty"` @@ -98,47 +87,19 @@ type ListSSHKeyPairsResponse struct { SSHKeyPair []SSHKeyPair `json:"sshkeypair"` } -func (ListSSHKeyPairs) response() interface{} { - return new(ListSSHKeyPairsResponse) -} - -// SetPage sets the current page -func (ls *ListSSHKeyPairs) SetPage(page int) { - ls.Page = page -} - -// SetPageSize sets the page size -func (ls *ListSSHKeyPairs) SetPageSize(pageSize int) { - ls.PageSize = pageSize -} - -func (ListSSHKeyPairs) each(resp interface{}, callback IterateItemFunc) { - sshs, ok := resp.(*ListSSHKeyPairsResponse) - if !ok { - callback(nil, fmt.Errorf("wrong type. ListSSHKeyPairsResponse expected, got %T", resp)) - return - } - - for i := range sshs.SSHKeyPair { - if !callback(&sshs.SSHKeyPair[i], nil) { - break - } - } -} - // ResetSSHKeyForVirtualMachine (Async) represents a change for the key pairs type ResetSSHKeyForVirtualMachine struct { - ID string `json:"id" doc:"The ID of the virtual machine"` - KeyPair string `json:"keypair" doc:"name of the ssh key pair used to login to the virtual machine"` - Account string `json:"account,omitempty" doc:"an optional account for the ssh key. Must be used with domainId."` - DomainID string `json:"domainid,omitempty" doc:"an optional domainId for the virtual machine. If the account parameter is used, domainId must also be used."` - _ bool `name:"resetSSHKeyForVirtualMachine" description:"Resets the SSH Key for virtual machine. The virtual machine must be in a \"Stopped\" state."` + ID *UUID `json:"id" doc:"The ID of the virtual machine"` + KeyPair string `json:"keypair" doc:"Name of the ssh key pair used to login to the virtual machine"` + _ bool `name:"resetSSHKeyForVirtualMachine" description:"Resets the SSH Key for virtual machine. The virtual machine must be in a \"Stopped\" state."` } -func (ResetSSHKeyForVirtualMachine) response() interface{} { +// Response returns the struct to unmarshal +func (ResetSSHKeyForVirtualMachine) Response() interface{} { return new(AsyncJobResult) } -func (ResetSSHKeyForVirtualMachine) asyncResponse() interface{} { +// AsyncResponse returns the struct to unmarshal the async job +func (ResetSSHKeyForVirtualMachine) AsyncResponse() interface{} { return new(VirtualMachine) } diff --git a/vendor/github.com/exoscale/egoscale/sshkeypairs_response.go b/vendor/github.com/exoscale/egoscale/sshkeypairs_response.go new file mode 100644 index 000000000..31c471df2 --- /dev/null +++ b/vendor/github.com/exoscale/egoscale/sshkeypairs_response.go @@ -0,0 +1,43 @@ +// code generated; DO NOT EDIT. + +package egoscale + +import "fmt" + +// Response returns the struct to unmarshal +func (ListSSHKeyPairs) Response() interface{} { + return new(ListSSHKeyPairsResponse) +} + +// ListRequest returns itself +func (ls *ListSSHKeyPairs) ListRequest() (ListCommand, error) { + if ls == nil { + return nil, fmt.Errorf("%T cannot be nil", ls) + } + return ls, nil +} + +// SetPage sets the current apge +func (ls *ListSSHKeyPairs) SetPage(page int) { + ls.Page = page +} + +// SetPageSize sets the page size +func (ls *ListSSHKeyPairs) SetPageSize(pageSize int) { + ls.PageSize = pageSize +} + +// Each triggers the callback for each, valid answer or any non 404 issue +func (ListSSHKeyPairs) Each(resp interface{}, callback IterateItemFunc) { + items, ok := resp.(*ListSSHKeyPairsResponse) + if !ok { + callback(nil, fmt.Errorf("wrong type, ListSSHKeyPairsResponse was expected, got %T", resp)) + return + } + + for i := range items.SSHKeyPair { + if !callback(&items.SSHKeyPair[i], nil) { + break + } + } +} diff --git a/vendor/github.com/exoscale/egoscale/tags.go b/vendor/github.com/exoscale/egoscale/tags.go index e17e67cbf..56e014850 100644 --- a/vendor/github.com/exoscale/egoscale/tags.go +++ b/vendor/github.com/exoscale/egoscale/tags.go @@ -2,63 +2,76 @@ package egoscale // ResourceTag is a tag associated with a resource // -// http://docs.cloudstack.apache.org/projects/cloudstack-administration/en/4.9/management.html +// https://community.exoscale.com/documentation/compute/instance-tags/ type ResourceTag struct { Account string `json:"account,omitempty" doc:"the account associated with the tag"` Customer string `json:"customer,omitempty" doc:"customer associated with the tag"` - Domain string `json:"domain,omitempty" doc:"the domain associated with the tag"` - DomainID string `json:"domainid,omitempty" doc:"the ID of the domain associated with the tag"` Key string `json:"key,omitempty" doc:"tag key name"` - ResourceID string `json:"resourceid,omitempty" doc:"id of the resource"` + ResourceID *UUID `json:"resourceid,omitempty" doc:"id of the resource"` ResourceType string `json:"resourcetype,omitempty" doc:"resource type"` Value string `json:"value,omitempty" doc:"tag value"` } +// ListRequest builds the ListZones request +func (tag ResourceTag) ListRequest() (ListCommand, error) { + req := &ListTags{ + Customer: tag.Customer, + Key: tag.Key, + ResourceID: tag.ResourceID, + ResourceType: tag.ResourceType, + Value: tag.Value, + } + + return req, nil +} + // CreateTags (Async) creates resource tag(s) type CreateTags struct { - ResourceIDs []string `json:"resourceids" doc:"list of resources to create the tags for"` + ResourceIDs []UUID `json:"resourceids" doc:"list of resources to create the tags for"` ResourceType string `json:"resourcetype" doc:"type of the resource"` Tags []ResourceTag `json:"tags" doc:"Map of tags (key/value pairs)"` Customer string `json:"customer,omitempty" doc:"identifies client specific tag. When the value is not null, the tag can't be used by cloudStack code internally"` _ bool `name:"createTags" description:"Creates resource tag(s)"` } -func (CreateTags) response() interface{} { +// Response returns the struct to unmarshal +func (CreateTags) Response() interface{} { return new(AsyncJobResult) } -func (CreateTags) asyncResponse() interface{} { - return new(booleanResponse) +// AsyncResponse returns the struct to unmarshal the async job +func (CreateTags) AsyncResponse() interface{} { + return new(BooleanResponse) } // DeleteTags (Async) deletes the resource tag(s) type DeleteTags struct { - ResourceIDs []string `json:"resourceids" doc:"Delete tags for resource id(s)"` + ResourceIDs []UUID `json:"resourceids" doc:"Delete tags for resource id(s)"` ResourceType string `json:"resourcetype" doc:"Delete tag by resource type"` Tags []ResourceTag `json:"tags,omitempty" doc:"Delete tags matching key/value pairs"` _ bool `name:"deleteTags" description:"Deleting resource tag(s)"` } -func (DeleteTags) response() interface{} { +// Response returns the struct to unmarshal +func (DeleteTags) Response() interface{} { return new(AsyncJobResult) } -func (DeleteTags) asyncResponse() interface{} { - return new(booleanResponse) +// AsyncResponse returns the struct to unmarshal the async job +func (DeleteTags) AsyncResponse() interface{} { + return new(BooleanResponse) } +//go:generate go run generate/main.go -interface=Listable ListTags + // ListTags list resource tag(s) type ListTags struct { - Account string `json:"account,omitempty" doc:"list resources by account. Must be used with the domainId parameter."` Customer string `json:"customer,omitempty" doc:"list by customer name"` - DomainID string `json:"domainid,omitempty" doc:"list only resources belonging to the domain specified"` - IsRecursive *bool `json:"isrecursive,omitempty" doc:"defaults to false, but if true, lists all resources from the parent specified by the domainId till leaves."` Key string `json:"key,omitempty" doc:"list by key"` Keyword string `json:"keyword,omitempty" doc:"List by keyword"` - ListAll *bool `json:"listall,omitempty" doc:"If set to false, list only resources belonging to the command's caller; if set to true - list resources that the caller is authorized to see. Default value is false"` Page int `json:"page,omitempty"` PageSize int `json:"pagesize,omitempty"` - ResourceID string `json:"resourceid,omitempty" doc:"list by resource id"` + ResourceID *UUID `json:"resourceid,omitempty" doc:"list by resource id"` ResourceType string `json:"resourcetype,omitempty" doc:"list by resource type"` Value string `json:"value,omitempty" doc:"list by value"` _ bool `name:"listTags" description:"List resource tag(s)"` @@ -69,7 +82,3 @@ type ListTagsResponse struct { Count int `json:"count"` Tag []ResourceTag `json:"tag"` } - -func (ListTags) response() interface{} { - return new(ListTagsResponse) -} diff --git a/vendor/github.com/exoscale/egoscale/tags_response.go b/vendor/github.com/exoscale/egoscale/tags_response.go new file mode 100644 index 000000000..870ef49a8 --- /dev/null +++ b/vendor/github.com/exoscale/egoscale/tags_response.go @@ -0,0 +1,43 @@ +// code generated; DO NOT EDIT. + +package egoscale + +import "fmt" + +// Response returns the struct to unmarshal +func (ListTags) Response() interface{} { + return new(ListTagsResponse) +} + +// ListRequest returns itself +func (ls *ListTags) ListRequest() (ListCommand, error) { + if ls == nil { + return nil, fmt.Errorf("%T cannot be nil", ls) + } + return ls, nil +} + +// SetPage sets the current apge +func (ls *ListTags) SetPage(page int) { + ls.Page = page +} + +// SetPageSize sets the page size +func (ls *ListTags) SetPageSize(pageSize int) { + ls.PageSize = pageSize +} + +// Each triggers the callback for each, valid answer or any non 404 issue +func (ListTags) Each(resp interface{}, callback IterateItemFunc) { + items, ok := resp.(*ListTagsResponse) + if !ok { + callback(nil, fmt.Errorf("wrong type, ListTagsResponse was expected, got %T", resp)) + return + } + + for i := range items.Tag { + if !callback(&items.Tag[i], nil) { + break + } + } +} diff --git a/vendor/github.com/exoscale/egoscale/templates.go b/vendor/github.com/exoscale/egoscale/templates.go index f5ed0cc3a..c31c5ce79 100644 --- a/vendor/github.com/exoscale/egoscale/templates.go +++ b/vendor/github.com/exoscale/egoscale/templates.go @@ -1,40 +1,34 @@ package egoscale -import ( - "fmt" -) - -// Template represents a machine to be deployed -// -// See: http://docs.cloudstack.apache.org/projects/cloudstack-administration/en/latest/templates.html +// Template represents a machine to be deployed. type Template struct { Account string `json:"account,omitempty" doc:"the account name to which the template belongs"` - AccountID string `json:"accountid,omitempty" doc:"the account id to which the template belongs"` + AccountID *UUID `json:"accountid,omitempty" doc:"the account id to which the template belongs"` Bootable bool `json:"bootable,omitempty" doc:"true if the ISO is bootable, false otherwise"` Checksum string `json:"checksum,omitempty" doc:"checksum of the template"` Created string `json:"created,omitempty" doc:"the date this template was created"` CrossZones bool `json:"crossZones,omitempty" doc:"true if the template is managed across all Zones, false otherwise"` Details map[string]string `json:"details,omitempty" doc:"additional key/value details tied with template"` DisplayText string `json:"displaytext,omitempty" doc:"the template display text"` - Domain string `json:"domain,omitempty" doc:"the name of the domain to which the template belongs"` - DomainID string `json:"domainid,omitempty" doc:"the ID of the domain to which the template belongs"` Format string `json:"format,omitempty" doc:"the format of the template."` - HostID string `json:"hostid,omitempty" doc:"the ID of the secondary storage host for the template"` + HostID *UUID `json:"hostid,omitempty" doc:"the ID of the secondary storage host for the template"` HostName string `json:"hostname,omitempty" doc:"the name of the secondary storage host for the template"` - Hypervisor string `json:"hypervisor,omitempty" doc:"the hypervisor on which the template runs"` - ID string `json:"id,omitempty" doc:"the template ID"` + Hypervisor string `json:"hypervisor,omitempty" doc:"the target hypervisor for the template"` + ID *UUID `json:"id,omitempty" doc:"the template ID"` IsDynamicallyScalable bool `json:"isdynamicallyscalable,omitempty" doc:"true if template contains XS/VMWare tools inorder to support dynamic scaling of VM cpu/memory"` IsExtractable bool `json:"isextractable,omitempty" doc:"true if the template is extractable, false otherwise"` IsFeatured bool `json:"isfeatured,omitempty" doc:"true if this template is a featured template, false otherwise"` IsPublic bool `json:"ispublic,omitempty" doc:"true if this template is a public template, false otherwise"` IsReady bool `json:"isready,omitempty" doc:"true if the template is ready to be deployed from, false otherwise."` Name string `json:"name,omitempty" doc:"the template name"` - OsTypeID string `json:"ostypeid,omitempty" doc:"the ID of the OS type for this template."` - OsTypeName string `json:"ostypename,omitempty" doc:"the name of the OS type for this template."` + OsCategoryID *UUID `json:"oscategoryid,omitempty" doc:"the ID of the OS category for this template"` + OsCategoryName string `json:"oscategoryname,omitempty" doc:"the name of the OS category for this template"` + OsTypeID *UUID `json:"ostypeid,omitempty" doc:"the ID of the OS type for this template"` + OsTypeName string `json:"ostypename,omitempty" doc:"the name of the OS type for this template"` PasswordEnabled bool `json:"passwordenabled,omitempty" doc:"true if the reset password feature is enabled, false otherwise"` Removed string `json:"removed,omitempty" doc:"the date this template was removed"` Size int64 `json:"size,omitempty" doc:"the size of the template"` - SourceTemplateID string `json:"sourcetemplateid,omitempty" doc:"the template ID of the parent template if present"` + SourceTemplateID *UUID `json:"sourcetemplateid,omitempty" doc:"the template ID of the parent template if present"` SSHKeyEnabled bool `json:"sshkeyenabled,omitempty" doc:"true if template is sshkey enabled, false otherwise"` Status string `json:"status,omitempty" doc:"the status of the template"` Tags []ResourceTag `json:"tags,omitempty" doc:"the list of resource tags associated with tempate"` @@ -42,7 +36,7 @@ type Template struct { TemplateTag string `json:"templatetag,omitempty" doc:"the tag of this template"` TemplateType string `json:"templatetype,omitempty" doc:"the type of the template"` URL string `json:"url,omitempty" doc:"Original URL of the template where it was downloaded"` - ZoneID string `json:"zoneid,omitempty" doc:"the ID of the zone for this template"` + ZoneID *UUID `json:"zoneid,omitempty" doc:"the ID of the zone for this template"` ZoneName string `json:"zonename,omitempty" doc:"the name of the zone for this template"` } @@ -52,42 +46,39 @@ func (Template) ResourceType() string { } // ListRequest builds the ListTemplates request -func (temp Template) ListRequest() (ListCommand, error) { +func (template Template) ListRequest() (ListCommand, error) { req := &ListTemplates{ - Name: temp.Name, - Account: temp.Account, - DomainID: temp.DomainID, - ID: temp.ID, - ZoneID: temp.ZoneID, - Hypervisor: temp.Hypervisor, - //TODO Tags + ID: template.ID, + Name: template.Name, + ZoneID: template.ZoneID, } - if temp.IsFeatured { + if template.IsFeatured { req.TemplateFilter = "featured" } - if temp.Removed != "" { + if template.Removed != "" { *req.ShowRemoved = true } + for i := range template.Tags { + req.Tags = append(req.Tags, template.Tags[i]) + } + return req, nil } +//go:generate go run generate/main.go -interface=Listable ListTemplates + // ListTemplates represents a template query filter type ListTemplates struct { - TemplateFilter string `json:"templatefilter" doc:"possible values are \"featured\", \"self\", \"selfexecutable\",\"sharedexecutable\",\"executable\", and \"community\". * featured : templates that have been marked as featured and public. * self : templates that have been registered or created by the calling user. * selfexecutable : same as self, but only returns templates that can be used to deploy a new VM. * sharedexecutable : templates ready to be deployed that have been granted to the calling user by another user. * executable : templates that are owned by the calling user, or public templates, that can be used to deploy a VM. * community : templates that have been marked as public but not featured. * all : all templates (only usable by admins)."` - Account string `json:"account,omitempty" doc:"list resources by account. Must be used with the domainId parameter."` - DomainID string `json:"domainid,omitempty" doc:"list only resources belonging to the domain specified"` - Hypervisor string `json:"hypervisor,omitempty" doc:"the hypervisor for which to restrict the search"` - ID string `json:"id,omitempty" doc:"the template ID"` - IsRecursive *bool `json:"isrecursive,omitempty" doc:"defaults to false, but if true, lists all resources from the parent specified by the domainId till leaves."` + TemplateFilter string `json:"templatefilter,omitempty" doc:"Possible values are \"featured\", \"self\", \"selfexecutable\",\"sharedexecutable\",\"executable\", and \"community\". * featured : templates that have been marked as featured and public. * self : templates that have been registered or created by the calling user. * selfexecutable : same as self, but only returns templates that can be used to deploy a new VM. * sharedexecutable : templates ready to be deployed that have been granted to the calling user by another user. * executable : templates that are owned by the calling user, or public templates, that can be used to deploy a VM. * community : templates that have been marked as public but not featured."` + ID *UUID `json:"id,omitempty" doc:"the template ID"` Keyword string `json:"keyword,omitempty" doc:"List by keyword"` - ListAll *bool `json:"listall,omitempty" doc:"If set to false, list only resources belonging to the command's caller; if set to true - list resources that the caller is authorized to see. Default value is false"` Name string `json:"name,omitempty" doc:"the template name"` Page int `json:"page,omitempty"` PageSize int `json:"pagesize,omitempty"` - ShowRemoved *bool `json:"showremoved,omitempty" doc:"show removed templates as well"` + ShowRemoved *bool `json:"showremoved,omitempty" doc:"Show removed templates as well"` Tags []ResourceTag `json:"tags,omitempty" doc:"List resources by tags (key/value pairs)"` - ZoneID string `json:"zoneid,omitempty" doc:"list templates by zoneId"` + ZoneID *UUID `json:"zoneid,omitempty" doc:"list templates by zoneid"` _ bool `name:"listTemplates" description:"List all public, private, and privileged templates."` } @@ -97,159 +88,76 @@ type ListTemplatesResponse struct { Template []Template `json:"template"` } -func (ListTemplates) response() interface{} { - return new(ListTemplatesResponse) +// OSCategory represents an OS category +type OSCategory struct { + ID *UUID `json:"id,omitempty" doc:"the ID of the OS category"` + Name string `json:"name,omitempty" doc:"the name of the OS category"` } -func (ListTemplates) each(resp interface{}, callback IterateItemFunc) { - temps, ok := resp.(*ListTemplatesResponse) - if !ok { - callback(nil, fmt.Errorf("wrong type. ListTemplatesResponse expected, got %T", resp)) - return +// ListRequest builds the ListOSCategories request +func (osCat OSCategory) ListRequest() (ListCommand, error) { + req := &ListOSCategories{ + Name: osCat.Name, + ID: osCat.ID, } - for i := range temps.Template { - if !callback(&temps.Template[i], nil) { - break - } - } + return req, nil } -// SetPage sets the current page -func (ls *ListTemplates) SetPage(page int) { - ls.Page = page +//go:generate go run generate/main.go -interface=Listable ListOSCategories + +// ListOSCategories lists the OS categories +type ListOSCategories struct { + ID *UUID `json:"id,omitempty" doc:"list Os category by id"` + Keyword string `json:"keyword,omitempty" doc:"List by keyword"` + Name string `json:"name,omitempty" doc:"list os category by name"` + Page int `json:"page,omitempty"` + PageSize int `json:"pagesize,omitempty"` + _ bool `name:"listOsCategories" description:"Lists all supported OS categories for this cloud."` } -// SetPageSize sets the page size -func (ls *ListTemplates) SetPageSize(pageSize int) { - ls.PageSize = pageSize +// ListOSCategoriesResponse represents a list of OS categories +type ListOSCategoriesResponse struct { + Count int `json:"count"` + OSCategory []OSCategory `json:"oscategory"` } -// CreateTemplate (Async) represents a template creation -type CreateTemplate struct { - Bits int `json:"bits,omitempty" doc:"32 or 64 bit"` - Details map[string]string `json:"details,omitempty" doc:"Template details in key/value pairs."` - DisplayText string `json:"displaytext" doc:"the display text of the template. This is usually used for display purposes."` - IsDynamicallyScalable *bool `json:"isdynamicallyscalable,omitempty" doc:"true if template contains XS/VMWare tools inorder to support dynamic scaling of VM cpu/memory"` - IsFeatured *bool `json:"isfeatured,omitempty" doc:"true if this template is a featured template, false otherwise"` - IsPublic *bool `json:"ispublic,omitempty" doc:"true if this template is a public template, false otherwise"` - Name string `json:"name" doc:"the name of the template"` - OsTypeID string `json:"ostypeid" doc:"the ID of the OS Type that best represents the OS of this template."` - PasswordEnabled *bool `json:"passwordenabled,omitempty" doc:"true if the template supports the password reset feature; default is false"` - RequiresHVM *bool `json:"requireshvm,omitempty" doc:"true if the template requres HVM, false otherwise"` - SnapshotID string `json:"snapshotid,omitempty" doc:"the ID of the snapshot the template is being created from. Either this parameter, or volumeId has to be passed in"` - TemplateTag string `json:"templatetag,omitempty" doc:"the tag for this template."` - URL string `json:"url,omitempty" doc:"Optional, only for baremetal hypervisor. The directory name where template stored on CIFS server"` - VirtualMachineID string `json:"virtualmachineid,omitempty" doc:"Optional, VM ID. If this presents, it is going to create a baremetal template for VM this ID refers to. This is only for VM whose hypervisor type is BareMetal"` - VolumeID string `json:"volumeid,omitempty" doc:"the ID of the disk volume the template is being created from. Either this parameter, or snapshotId has to be passed in"` - _ bool `name:"createTemplate" description:"Creates a template of a virtual machine. The virtual machine must be in a STOPPED state. A template created from this command is automatically designated as a private template visible to the account that created it."` -} - -func (CreateTemplate) response() interface{} { - return new(AsyncJobResult) -} - -func (CreateTemplate) asyncResponse() interface{} { - return new(Template) -} - -// CopyTemplate (Async) represents a template copy -type CopyTemplate struct { - DestZoneID string `json:"destzoneid" doc:"ID of the zone the template is being copied to."` - ID string `json:"id" doc:"Template ID."` - SourceZoneID string `json:"sourcezoneid,omitempty" doc:"ID of the zone the template is currently hosted on. If not specified and template is cross-zone, then we will sync this template to region wide image store."` - _ bool `name:"copyTemplate" description:"Copies a template from one zone to another."` -} - -func (CopyTemplate) response() interface{} { - return new(AsyncJobResult) -} - -func (CopyTemplate) asyncResponse() interface{} { - return new(Template) -} - -// UpdateTemplate represents a template change -type UpdateTemplate struct { - Bootable *bool `json:"bootable,omitempty" doc:"true if image is bootable, false otherwise"` - Details map[string]string `json:"details,omitempty" doc:"Details in key/value pairs."` - DisplayText string `json:"displaytext,omitempty" doc:"the display text of the image"` - Format string `json:"format,omitempty" doc:"the format for the image"` - ID string `json:"id" doc:"the ID of the image file"` - IsDynamicallyScalable *bool `json:"isdynamicallyscalable,omitempty" doc:"true if template/ISO contains XS/VMWare tools inorder to support dynamic scaling of VM cpu/memory"` - IsRouting *bool `json:"isrouting,omitempty" doc:"true if the template type is routing i.e., if template is used to deploy router"` - Name string `json:"name,omitempty" doc:"the name of the image file"` - OsTypeID string `json:"ostypeid,omitempty" doc:"the ID of the OS type that best represents the OS of this image."` - PasswordEnabled *bool `json:"passwordenabled,omitempty" doc:"true if the image supports the password reset feature; default is false"` - SortKey int `json:"sortkey,omitempty" doc:"sort key of the template, integer"` - _ bool `name:"updateTemplate" description:"Updates attributes of a template."` -} - -func (UpdateTemplate) response() interface{} { - return new(AsyncJobResult) -} - -func (UpdateTemplate) asyncResponse() interface{} { - return new(Template) -} - -// DeleteTemplate (Async) represents the deletion of a template +// DeleteTemplate deletes a template by ID type DeleteTemplate struct { - ID string `json:"id" doc:"the ID of the template"` - ZoneID string `json:"zoneid,omitempty" doc:"the ID of zone of the template"` - _ bool `name:"deleteTemplate" description:"Deletes a template from the system. All virtual machines using the deleted template will not be affected."` + _ bool `name:"deleteTemplate" description:"Deletes a template"` + ID *UUID `json:"id" doc:"the ID of the template"` } -func (DeleteTemplate) response() interface{} { +// Response returns the struct to unmarshal +func (DeleteTemplate) Response() interface{} { return new(AsyncJobResult) } -func (DeleteTemplate) asyncResponse() interface{} { - return new(booleanResponse) +// AsyncResponse returns the struct to unmarshal the async job +func (DeleteTemplate) AsyncResponse() interface{} { + return new(BooleanResponse) } -// PrepareTemplate represents a template preparation -type PrepareTemplate struct { - TemplateID string `json:"templateid" doc:"template ID of the template to be prepared in primary storage(s)."` - ZoneID string `json:"zoneid" doc:"zone ID of the template to be prepared in primary storage(s)."` - _ bool `name:"prepareTemplate" description:"load template into primary storage"` +// RegisterCustomTemplate registers a new template +type RegisterCustomTemplate struct { + _ bool `name:"registerCustomTemplate" description:"Register a new template."` + Checksum string `json:"checksum" doc:"the MD5 checksum value of this template"` + Details map[string]string `json:"details,omitempty" doc:"Template details in key/value pairs"` + Displaytext string `json:"displaytext" doc:"the display text of the template"` + Name string `json:"name" doc:"the name of the template"` + PasswordEnabled *bool `json:"passwordenabled,omitempty" doc:"true if the template supports the password reset feature; default is false"` + SSHKeyEnabled *bool `json:"sshkeyenabled,omitempty" doc:"true if the template supports the sshkey upload feature; default is false"` + TemplateTag string `json:"templatetag,omitempty" doc:"the tag for this template"` + URL string `json:"url" doc:"the URL of where the template is hosted"` + ZoneID *UUID `json:"zoneid" doc:"the ID of the zone the template is to be hosted on"` } -func (PrepareTemplate) response() interface{} { +// Response returns the struct to unmarshal +func (RegisterCustomTemplate) Response() interface{} { return new(AsyncJobResult) } -func (PrepareTemplate) asyncResponse() interface{} { - return new(Template) -} - -// RegisterTemplate represents a template registration -type RegisterTemplate struct { - Account string `json:"account,omitempty" doc:"an optional accountName. Must be used with domainId."` - Bits int `json:"bits,omitempty" doc:"32 or 64 bits support. 64 by default"` - Checksum string `json:"checksum,omitempty" doc:"the MD5 checksum value of this template"` - Details map[string]string `json:"details,omitempty" doc:"Template details in key/value pairs."` - DisplayText string `json:"displaytext" doc:"the display text of the template. This is usually used for display purposes."` - DomainID string `json:"domainid,omitempty" doc:"an optional domainId. If the account parameter is used, domainId must also be used."` - Format string `json:"format" doc:"the format for the template. Possible values include QCOW2, RAW, and VHD."` - Hypervisor string `json:"hypervisor" doc:"the target hypervisor for the template"` - IsDynamicallyScalable *bool `json:"isdynamicallyscalable,omitempty" doc:"true if template contains XS/VMWare tools inorder to support dynamic scaling of VM cpu/memory"` - IsExtractable *bool `json:"isextractable,omitempty" doc:"true if the template or its derivatives are extractable; default is false"` - IsFeatured *bool `json:"isfeatured,omitempty" doc:"true if this template is a featured template, false otherwise"` - IsPublic *bool `json:"ispublic,omitempty" doc:"true if the template is available to all accounts; default is true"` - IsRouting *bool `json:"isrouting,omitempty" doc:"true if the template type is routing i.e., if template is used to deploy router"` - IsSystem *bool `json:"issystem,omitempty" doc:"true if the template type is system i.e., if template is used to deploy system VM"` - Name string `json:"name" doc:"the name of the template"` - OsTypeID string `json:"ostypeid" doc:"the ID of the OS Type that best represents the OS of this template."` - PasswordEnabled *bool `json:"passwordenabled,omitempty" doc:"true if the template supports the password reset feature; default is false"` - RequiresHVM *bool `json:"requireshvm,omitempty" doc:"true if this template requires HVM"` - SSHKeyEnabled *bool `json:"sshkeyenabled,omitempty" doc:"true if the template supports the sshkey upload feature; default is false"` - TemplateTag string `json:"templatetag,omitempty" doc:"the tag for this template."` - URL string `json:"url" doc:"the URL of where the template is hosted. Possible URL include http:// and https://"` - ZoneID string `json:"zoneid" doc:"the ID of the zone the template is to be hosted on"` - _ bool `name:"registerTemplate" description:"Registers an existing template into the CloudStack cloud."` -} - -func (RegisterTemplate) response() interface{} { - return new(Template) +// AsyncResponse returns the struct to unmarshal the async job +func (RegisterCustomTemplate) AsyncResponse() interface{} { + return new([]Template) } diff --git a/vendor/github.com/exoscale/egoscale/templates_response.go b/vendor/github.com/exoscale/egoscale/templates_response.go new file mode 100644 index 000000000..b9d61b546 --- /dev/null +++ b/vendor/github.com/exoscale/egoscale/templates_response.go @@ -0,0 +1,43 @@ +// code generated; DO NOT EDIT. + +package egoscale + +import "fmt" + +// Response returns the struct to unmarshal +func (ListTemplates) Response() interface{} { + return new(ListTemplatesResponse) +} + +// ListRequest returns itself +func (ls *ListTemplates) ListRequest() (ListCommand, error) { + if ls == nil { + return nil, fmt.Errorf("%T cannot be nil", ls) + } + return ls, nil +} + +// SetPage sets the current apge +func (ls *ListTemplates) SetPage(page int) { + ls.Page = page +} + +// SetPageSize sets the page size +func (ls *ListTemplates) SetPageSize(pageSize int) { + ls.PageSize = pageSize +} + +// Each triggers the callback for each, valid answer or any non 404 issue +func (ListTemplates) Each(resp interface{}, callback IterateItemFunc) { + items, ok := resp.(*ListTemplatesResponse) + if !ok { + callback(nil, fmt.Errorf("wrong type, ListTemplatesResponse was expected, got %T", resp)) + return + } + + for i := range items.Template { + if !callback(&items.Template[i], nil) { + break + } + } +} diff --git a/vendor/github.com/exoscale/egoscale/users.go b/vendor/github.com/exoscale/egoscale/users.go index f3ee68b72..71078a97b 100644 --- a/vendor/github.com/exoscale/egoscale/users.go +++ b/vendor/github.com/exoscale/egoscale/users.go @@ -2,90 +2,58 @@ package egoscale // User represents a User type User struct { - APIKey string `json:"apikey,omitempty" doc:"the api key of the user"` - Account string `json:"account,omitempty" doc:"the account name of the user"` - AccountID string `json:"accountid,omitempty" doc:"the account ID of the user"` - AccountType int16 `json:"accounttype,omitempty" doc:"the account type of the user"` - Created string `json:"created,omitempty" doc:"the date and time the user account was created"` - Domain string `json:"domain,omitempty" doc:"the domain name of the user"` - DomainID string `json:"domainid,omitempty" doc:"the domain ID of the user"` - Email string `json:"email,omitempty" doc:"the user email address"` - FirstName string `json:"firstname,omitempty" doc:"the user firstname"` - ID string `json:"id,omitempty" doc:"the user ID"` - IsCallerChildDomain bool `json:"iscallerchilddomain,omitempty" doc:"the boolean value representing if the updating target is in caller's child domain"` - IsDefault bool `json:"isdefault,omitempty" doc:"true if user is default, false otherwise"` - LastName string `json:"lastname,omitempty" doc:"the user lastname"` - RoleID string `json:"roleid,omitempty" doc:"the ID of the role"` - RoleName string `json:"rolename,omitempty" doc:"the name of the role"` - RoleType string `json:"roletype,omitempty" doc:"the type of the role"` - SecretKey string `json:"secretkey,omitempty" doc:"the secret key of the user"` - State string `json:"state,omitempty" doc:"the user state"` - Timezone string `json:"timezone,omitempty" doc:"the timezone user was created in"` - UserName string `json:"username,omitempty" doc:"the user name"` + APIKey string `json:"apikey,omitempty" doc:"the api key of the user"` + Account string `json:"account,omitempty" doc:"the account name of the user"` + AccountID *UUID `json:"accountid,omitempty" doc:"the account ID of the user"` + Created string `json:"created,omitempty" doc:"the date and time the user account was created"` + Email string `json:"email,omitempty" doc:"the user email address"` + FirstName string `json:"firstname,omitempty" doc:"the user firstname"` + ID *UUID `json:"id,omitempty" doc:"the user ID"` + IsDefault bool `json:"isdefault,omitempty" doc:"true if user is default, false otherwise"` + LastName string `json:"lastname,omitempty" doc:"the user lastname"` + RoleID *UUID `json:"roleid,omitempty" doc:"the ID of the role"` + RoleName string `json:"rolename,omitempty" doc:"the name of the role"` + RoleType string `json:"roletype,omitempty" doc:"the type of the role"` + SecretKey string `json:"secretkey,omitempty" doc:"the secret key of the user"` + State string `json:"state,omitempty" doc:"the user state"` + Timezone string `json:"timezone,omitempty" doc:"the timezone user was created in"` + UserName string `json:"username,omitempty" doc:"the user name"` +} + +// ListRequest builds the ListUsers request +func (user User) ListRequest() (ListCommand, error) { + req := &ListUsers{ + ID: user.ID, + UserName: user.UserName, + } + + return req, nil } // RegisterUserKeys registers a new set of key of the given user // // NB: only the APIKey and SecretKey will be filled type RegisterUserKeys struct { - ID string `json:"id" doc:"User id"` - _ bool `name:"registerUserKeys" description:"This command allows a user to register for the developer API, returning a secret key and an API key. This request is made through the integration API port, so it is a privileged command and must be made on behalf of a user. It is up to the implementer just how the username and password are entered, and then how that translates to an integration API request. Both secret key and API key should be returned to the user"` + ID *UUID `json:"id" doc:"User id"` + _ bool `name:"registerUserKeys" description:"This command allows a user to register for the developer API, returning a secret key and an API key. This request is made through the integration API port, so it is a privileged command and must be made on behalf of a user. It is up to the implementer just how the username and password are entered, and then how that translates to an integration API request. Both secret key and API key should be returned to the user"` } -func (RegisterUserKeys) response() interface{} { +// Response returns the struct to unmarshal +func (RegisterUserKeys) Response() interface{} { return new(User) } -// CreateUser represents the creation of a User -type CreateUser struct { - Account string `json:"account" doc:"Creates the user under the specified account. If no account is specified, the username will be used as the account name."` - Email string `json:"email" doc:"email"` - FirstName string `json:"firstname" doc:"firstname"` - LastName string `json:"lastname" doc:"lastname"` - Password string `json:"password" doc:"Clear text password (Default hashed to SHA256SALT). If you wish to use any other hashing algorithm, you would need to write a custom authentication adapter See Docs section."` - UserName string `json:"username" doc:"Unique username."` - DomainID string `json:"domainid,omitempty" doc:"Creates the user under the specified domain. Has to be accompanied with the account parameter"` - Timezone string `json:"timezone,omitempty" doc:"Specifies a timezone for this command. For more information on the timezone parameter, see Time Zone Format."` - UserID string `json:"userid,omitempty" doc:"User UUID, required for adding account from external provisioning system"` - _ bool `name:"createUser" description:"Creates a user for an account that already exists"` -} - -func (CreateUser) response() interface{} { - return new(User) -} - -// UpdateUser represents the modification of a User -type UpdateUser struct { - ID string `json:"id" doc:"User uuid"` - Email string `json:"email,omitempty" doc:"email"` - FirstName string `json:"firstname,omitempty" doc:"first name"` - LastName string `json:"lastname,omitempty" doc:"last name"` - Password string `json:"password,omitempty" doc:"Clear text password (default hashed to SHA256SALT). If you wish to use any other hashing algorithm, you would need to write a custom authentication adapter"` - Timezone string `json:"timezone,omitempty" doc:"Specifies a timezone for this command. For more information on the timezone parameter, see Time Zone Format."` - UserAPIKey string `json:"userapikey,omitempty" doc:"The API key for the user. Must be specified with userSecretKey"` - UserName string `json:"username,omitempty" doc:"Unique username"` - UserSecretKey string `json:"usersecretkey,omitempty" doc:"The secret key for the user. Must be specified with userApiKey"` - _ bool `name:"updateUser" description:"Updates a user account"` -} - -func (UpdateUser) response() interface{} { - return new(User) -} +//go:generate go run generate/main.go -interface=Listable ListUsers // ListUsers represents the search for Users type ListUsers struct { - Account string `json:"account,omitempty" doc:"list resources by account. Must be used with the domainId parameter."` - AccountType int64 `json:"accounttype,omitempty" doc:"List users by account type. Valid types include admin, domain-admin, read-only-admin, or user."` - DomainID string `json:"domainid,omitempty" doc:"list only resources belonging to the domain specified"` - ID string `json:"id,omitempty" doc:"List user by ID."` - IsRecursive bool `json:"isrecursive,omitempty" doc:"defaults to false, but if true, lists all resources from the parent specified by the domainId till leaves."` - Keyword string `json:"keyword,omitempty" doc:"List by keyword"` - ListAll bool `json:"listall,omitempty" doc:"If set to false, list only resources belonging to the command's caller; if set to true - list resources that the caller is authorized to see. Default value is false"` - Page int `json:"page,omitempty"` - PageSize int `json:"pagesize,omitempty"` - State string `json:"state,omitempty" doc:"List users by state of the user account."` - Username string `json:"username,omitempty" doc:"List user by the username"` - _ bool `name:"listUsers" description:"Lists user accounts"` + ID *UUID `json:"id,omitempty" doc:"List user by ID."` + Keyword string `json:"keyword,omitempty" doc:"List by keyword"` + Page int `json:"page,omitempty"` + PageSize int `json:"pagesize,omitempty"` + State string `json:"state,omitempty" doc:"List users by state of the user account."` + UserName string `json:"username,omitempty" doc:"List user by the username"` + _ bool `name:"listUsers" description:"Lists user accounts"` } // ListUsersResponse represents a list of users @@ -93,17 +61,3 @@ type ListUsersResponse struct { Count int `json:"count"` User []User `json:"user"` } - -func (ListUsers) response() interface{} { - return new(ListUsersResponse) -} - -// DeleteUser deletes a user for an account -type DeleteUser struct { - ID string `json:"id" doc:"id of the user to be deleted"` - _ bool `name:"deleteUser" description:"Deletes a user for an account"` -} - -func (DeleteUser) response() interface{} { - return new(booleanResponse) -} diff --git a/vendor/github.com/exoscale/egoscale/users_response.go b/vendor/github.com/exoscale/egoscale/users_response.go new file mode 100644 index 000000000..4bd4bf473 --- /dev/null +++ b/vendor/github.com/exoscale/egoscale/users_response.go @@ -0,0 +1,43 @@ +// code generated; DO NOT EDIT. + +package egoscale + +import "fmt" + +// Response returns the struct to unmarshal +func (ListUsers) Response() interface{} { + return new(ListUsersResponse) +} + +// ListRequest returns itself +func (ls *ListUsers) ListRequest() (ListCommand, error) { + if ls == nil { + return nil, fmt.Errorf("%T cannot be nil", ls) + } + return ls, nil +} + +// SetPage sets the current apge +func (ls *ListUsers) SetPage(page int) { + ls.Page = page +} + +// SetPageSize sets the page size +func (ls *ListUsers) SetPageSize(pageSize int) { + ls.PageSize = pageSize +} + +// Each triggers the callback for each, valid answer or any non 404 issue +func (ListUsers) Each(resp interface{}, callback IterateItemFunc) { + items, ok := resp.(*ListUsersResponse) + if !ok { + callback(nil, fmt.Errorf("wrong type, ListUsersResponse was expected, got %T", resp)) + return + } + + for i := range items.User { + if !callback(&items.User[i], nil) { + break + } + } +} diff --git a/vendor/github.com/exoscale/egoscale/uuid.go b/vendor/github.com/exoscale/egoscale/uuid.go new file mode 100644 index 000000000..dd8be1557 --- /dev/null +++ b/vendor/github.com/exoscale/egoscale/uuid.go @@ -0,0 +1,79 @@ +package egoscale + +import ( + "encoding/json" + "fmt" + + uuid "github.com/gofrs/uuid" +) + +// UUID holds a UUID v4 +type UUID struct { + uuid.UUID +} + +// DeepCopy create a true copy of the receiver. +func (u *UUID) DeepCopy() *UUID { + if u == nil { + return nil + } + + out := [uuid.Size]byte{} + copy(out[:], u.Bytes()) + + return &UUID{ + (uuid.UUID)(out), + } +} + +// DeepCopyInto copies the receiver into out. +// +// In must be non nil. +func (u *UUID) DeepCopyInto(out *UUID) { + o := [uuid.Size]byte{} + copy(o[:], u.Bytes()) + + out.UUID = (uuid.UUID)(o) +} + +// Equal returns true if itself is equal to other. +func (u UUID) Equal(other UUID) bool { + return u == other +} + +// UnmarshalJSON unmarshals the raw JSON into the UUID. +func (u *UUID) UnmarshalJSON(b []byte) error { + var s string + if err := json.Unmarshal(b, &s); err != nil { + return err + } + + new, err := ParseUUID(s) + if err == nil { + u.UUID = new.UUID + } + return err +} + +// MarshalJSON converts the UUID to a string representation. +func (u UUID) MarshalJSON() ([]byte, error) { + return []byte(fmt.Sprintf("%q", u.String())), nil +} + +// ParseUUID parses a string into a UUID. +func ParseUUID(s string) (*UUID, error) { + u, err := uuid.FromString(s) + if err != nil { + return nil, err + } + return &UUID{u}, nil +} + +// MustParseUUID acts like ParseUUID but panic in case of a failure. +func MustParseUUID(s string) *UUID { + u, e := ParseUUID(s) + if e != nil { + panic(e) + } + return u +} diff --git a/vendor/github.com/exoscale/egoscale/version.go b/vendor/github.com/exoscale/egoscale/version.go index 3ad44bb90..51eff5e30 100644 --- a/vendor/github.com/exoscale/egoscale/version.go +++ b/vendor/github.com/exoscale/egoscale/version.go @@ -1,4 +1,4 @@ package egoscale // Version of the library -const Version = "0.10.5" +const Version = "0.23.0" diff --git a/vendor/github.com/exoscale/egoscale/virtual_machines.go b/vendor/github.com/exoscale/egoscale/virtual_machines.go index e473ed1a0..da6ce65c5 100644 --- a/vendor/github.com/exoscale/egoscale/virtual_machines.go +++ b/vendor/github.com/exoscale/egoscale/virtual_machines.go @@ -11,71 +11,96 @@ import ( "net/url" ) +// VirtualMachineState holds the state of the instance +// +// https://github.com/apache/cloudstack/blob/master/api/src/main/java/com/cloud/vm/VirtualMachine.java +type VirtualMachineState string + +const ( + // VirtualMachineStarting VM is being started. At this state, you should find host id filled which means it's being started on that host + VirtualMachineStarting VirtualMachineState = "Starting" + // VirtualMachineRunning VM is running. host id has the host that it is running on + VirtualMachineRunning VirtualMachineState = "Running" + // VirtualMachineStopping VM is being stopped. host id has the host that it is being stopped on + VirtualMachineStopping VirtualMachineState = "Stopping" + // VirtualMachineStopped VM is stopped. host id should be null + VirtualMachineStopped VirtualMachineState = "Stopped" + // VirtualMachineDestroyed VM is marked for destroy + VirtualMachineDestroyed VirtualMachineState = "Destroyed" + // VirtualMachineExpunging "VM is being expunged + VirtualMachineExpunging VirtualMachineState = "Expunging" + // VirtualMachineMigrating VM is being live migrated. host id holds destination host, last host id holds source host + VirtualMachineMigrating VirtualMachineState = "Migrating" + // VirtualMachineMoving VM is being migrated offline (volume is being moved). + VirtualMachineMoving VirtualMachineState = "Moving" + // VirtualMachineError VM is in error + VirtualMachineError VirtualMachineState = "Error" + // VirtualMachineUnknown VM state is unknown + VirtualMachineUnknown VirtualMachineState = "Unknown" + // VirtualMachineShutdowned VM is shutdowned from inside + VirtualMachineShutdowned VirtualMachineState = "Shutdowned" +) + // VirtualMachine represents a virtual machine // // See: http://docs.cloudstack.apache.org/projects/cloudstack-administration/en/stable/virtual_machines.html type VirtualMachine struct { - Account string `json:"account,omitempty" doc:"the account associated with the virtual machine"` - AccountID string `json:"accountid,omitempty" doc:"the account ID associated with the virtual machine"` - AffinityGroup []AffinityGroup `json:"affinitygroup,omitempty" doc:"list of affinity groups associated with the virtual machine"` - ClusterID string `json:"clusterid,omitempty" doc:"the ID of the vm's cluster"` - ClusterName string `json:"clustername,omitempty" doc:"the name of the vm's cluster"` - CPUNumber int `json:"cpunumber,omitempty" doc:"the number of cpu this virtual machine is running with"` - CPUSpeed int `json:"cpuspeed,omitempty" doc:"the speed of each cpu"` - CPUUsed string `json:"cpuused,omitempty" doc:"the amount of the vm's CPU currently used"` - Created string `json:"created,omitempty" doc:"the date when this virtual machine was created"` - Details map[string]string `json:"details,omitempty" doc:"Vm details in key/value pairs."` - DiskIoRead int64 `json:"diskioread,omitempty" doc:"the read (io) of disk on the vm"` - DiskIoWrite int64 `json:"diskiowrite,omitempty" doc:"the write (io) of disk on the vm"` - DiskKbsRead int64 `json:"diskkbsread,omitempty" doc:"the read (bytes) of disk on the vm"` - DiskKbsWrite int64 `json:"diskkbswrite,omitempty" doc:"the write (bytes) of disk on the vm"` - DiskOfferingID string `json:"diskofferingid,omitempty" doc:"the ID of the disk offering of the virtual machine"` - DiskOfferingName string `json:"diskofferingname,omitempty" doc:"the name of the disk offering of the virtual machine"` - DisplayName string `json:"displayname,omitempty" doc:"user generated name. The name of the virtual machine is returned if no displayname exists."` - DisplayVM bool `json:"displayvm,omitempty" doc:"an optional field whether to the display the vm to the end user or not."` - Domain string `json:"domain,omitempty" doc:"the name of the domain in which the virtual machine exists"` - DomainID string `json:"domainid,omitempty" doc:"the ID of the domain in which the virtual machine exists"` - ForVirtualNetwork bool `json:"forvirtualnetwork,omitempty" doc:"the virtual network for the service offering"` - Group string `json:"group,omitempty" doc:"the group name of the virtual machine"` - GroupID string `json:"groupid,omitempty" doc:"the group ID of the virtual machine"` - HAEnable bool `json:"haenable,omitempty" doc:"true if high-availability is enabled, false otherwise"` - HostID string `json:"hostid,omitempty" doc:"the ID of the host for the virtual machine"` - HostName string `json:"hostname,omitempty" doc:"the name of the host for the virtual machine"` - Hypervisor string `json:"hypervisor,omitempty" doc:"the hypervisor on which the template runs"` - ID string `json:"id,omitempty" doc:"the ID of the virtual machine"` - InstanceName string `json:"instancename,omitempty" doc:"instance name of the user vm; this parameter is returned to the ROOT admin only"` - IsDynamicallyScalable bool `json:"isdynamicallyscalable,omitempty" doc:"true if vm contains XS/VMWare tools inorder to support dynamic scaling of VM cpu/memory."` - IsoDisplayText string `json:"isodisplaytext,omitempty" doc:"an alternate display text of the ISO attached to the virtual machine"` - IsoID string `json:"isoid,omitempty" doc:"the ID of the ISO attached to the virtual machine"` - IsoName string `json:"isoname,omitempty" doc:"the name of the ISO attached to the virtual machine"` - KeyPair string `json:"keypair,omitempty" doc:"ssh key-pair"` - Memory int `json:"memory,omitempty" doc:"the memory allocated for the virtual machine"` - Name string `json:"name,omitempty" doc:"the name of the virtual machine"` - NetworkKbsRead int64 `json:"networkkbsread,omitempty" doc:"the incoming network traffic on the vm"` - NetworkKbsWrite int64 `json:"networkkbswrite,omitempty" doc:"the outgoing network traffic on the host"` - Nic []Nic `json:"nic,omitempty" doc:"the list of nics associated with vm"` - OsCategoryID string `json:"oscategoryid,omitempty" doc:"Os category ID of the virtual machine"` - OsCategoryName string `json:"oscategoryname,omitempty" doc:"Os category name of the virtual machine"` - Password string `json:"password,omitempty" doc:"the password (if exists) of the virtual machine"` - PasswordEnabled bool `json:"passwordenabled,omitempty" doc:"true if the password rest feature is enabled, false otherwise"` - PCIDevices []PCIDevice `json:"pcidevices,omitempty" doc:"list of PCI devices"` - PodID string `json:"podid,omitempty" doc:"the ID of the vm's pod"` - PodName string `json:"podname,omitempty" doc:"the name of the vm's pod"` - PublicIP string `json:"publicip,omitempty" doc:"public IP address id associated with vm via Static nat rule"` - PublicIPID string `json:"publicipid,omitempty" doc:"public IP address id associated with vm via Static nat rule"` - RootDeviceID int64 `json:"rootdeviceid,omitempty" doc:"device ID of the root volume"` - RootDeviceType string `json:"rootdevicetype,omitempty" doc:"device type of the root volume"` - SecurityGroup []SecurityGroup `json:"securitygroup,omitempty" doc:"list of security groups associated with the virtual machine"` - ServiceOfferingID string `json:"serviceofferingid,omitempty" doc:"the ID of the service offering of the virtual machine"` - ServiceOfferingName string `json:"serviceofferingname,omitempty" doc:"the name of the service offering of the virtual machine"` - ServiceState string `json:"servicestate,omitempty" doc:"State of the Service from LB rule"` - State string `json:"state,omitempty" doc:"the state of the virtual machine"` - Tags []ResourceTag `json:"tags,omitempty" doc:"the list of resource tags associated with vm"` - TemplateDisplayText string `json:"templatedisplaytext,omitempty" doc:"an alternate display text of the template for the virtual machine"` - TemplateID string `json:"templateid,omitempty" doc:"the ID of the template for the virtual machine. A -1 is returned if the virtual machine was created from an ISO file."` - TemplateName string `json:"templatename,omitempty" doc:"the name of the template for the virtual machine"` - ZoneID string `json:"zoneid,omitempty" doc:"the ID of the availablility zone for the virtual machine"` - ZoneName string `json:"zonename,omitempty" doc:"the name of the availability zone for the virtual machine"` + Account string `json:"account,omitempty" doc:"the account associated with the virtual machine"` + AccountID *UUID `json:"accountid,omitempty" doc:"the account ID associated with the virtual machine"` + AffinityGroup []AffinityGroup `json:"affinitygroup,omitempty" doc:"list of affinity groups associated with the virtual machine"` + ClusterID *UUID `json:"clusterid,omitempty" doc:"the ID of the vm's cluster"` + ClusterName string `json:"clustername,omitempty" doc:"the name of the vm's cluster"` + CPUNumber int `json:"cpunumber,omitempty" doc:"the number of cpu this virtual machine is running with"` + CPUSpeed int `json:"cpuspeed,omitempty" doc:"the speed of each cpu"` + CPUUsed string `json:"cpuused,omitempty" doc:"the amount of the vm's CPU currently used"` + Created string `json:"created,omitempty" doc:"the date when this virtual machine was created"` + Details map[string]string `json:"details,omitempty" doc:"Vm details in key/value pairs."` + DiskIoRead int64 `json:"diskioread,omitempty" doc:"the read (io) of disk on the vm"` + DiskIoWrite int64 `json:"diskiowrite,omitempty" doc:"the write (io) of disk on the vm"` + DiskKbsRead int64 `json:"diskkbsread,omitempty" doc:"the read (bytes) of disk on the vm"` + DiskKbsWrite int64 `json:"diskkbswrite,omitempty" doc:"the write (bytes) of disk on the vm"` + DiskOfferingID *UUID `json:"diskofferingid,omitempty" doc:"the ID of the disk offering of the virtual machine"` + DiskOfferingName string `json:"diskofferingname,omitempty" doc:"the name of the disk offering of the virtual machine"` + DisplayName string `json:"displayname,omitempty" doc:"user generated name. The name of the virtual machine is returned if no displayname exists."` + ForVirtualNetwork bool `json:"forvirtualnetwork,omitempty" doc:"the virtual network for the service offering"` + Group string `json:"group,omitempty" doc:"the group name of the virtual machine"` + GroupID *UUID `json:"groupid,omitempty" doc:"the group ID of the virtual machine"` + HAEnable bool `json:"haenable,omitempty" doc:"true if high-availability is enabled, false otherwise"` + HostName string `json:"hostname,omitempty" doc:"the name of the host for the virtual machine"` + ID *UUID `json:"id,omitempty" doc:"the ID of the virtual machine"` + InstanceName string `json:"instancename,omitempty" doc:"instance name of the user vm; this parameter is returned to the ROOT admin only"` + IsoDisplayText string `json:"isodisplaytext,omitempty" doc:"an alternate display text of the ISO attached to the virtual machine"` + IsoID *UUID `json:"isoid,omitempty" doc:"the ID of the ISO attached to the virtual machine"` + IsoName string `json:"isoname,omitempty" doc:"the name of the ISO attached to the virtual machine"` + KeyPair string `json:"keypair,omitempty" doc:"ssh key-pair"` + Memory int `json:"memory,omitempty" doc:"the memory allocated for the virtual machine"` + Name string `json:"name,omitempty" doc:"the name of the virtual machine"` + NetworkKbsRead int64 `json:"networkkbsread,omitempty" doc:"the incoming network traffic on the vm"` + NetworkKbsWrite int64 `json:"networkkbswrite,omitempty" doc:"the outgoing network traffic on the host"` + Nic []Nic `json:"nic,omitempty" doc:"the list of nics associated with vm"` + OSCategoryID *UUID `json:"oscategoryid,omitempty" doc:"Os category ID of the virtual machine"` + OSCategoryName string `json:"oscategoryname,omitempty" doc:"Os category name of the virtual machine"` + OSTypeID *UUID `json:"ostypeid,omitempty" doc:"OS type id of the vm"` + Password string `json:"password,omitempty" doc:"the password (if exists) of the virtual machine"` + PasswordEnabled bool `json:"passwordenabled,omitempty" doc:"true if the password rest feature is enabled, false otherwise"` + PCIDevices []PCIDevice `json:"pcidevices,omitempty" doc:"list of PCI devices"` + PodID *UUID `json:"podid,omitempty" doc:"the ID of the vm's pod"` + PodName string `json:"podname,omitempty" doc:"the name of the vm's pod"` + PublicIP string `json:"publicip,omitempty" doc:"public IP address id associated with vm via Static nat rule"` + PublicIPID *UUID `json:"publicipid,omitempty" doc:"public IP address id associated with vm via Static nat rule"` + RootDeviceID int64 `json:"rootdeviceid,omitempty" doc:"device ID of the root volume"` + RootDeviceType string `json:"rootdevicetype,omitempty" doc:"device type of the root volume"` + SecurityGroup []SecurityGroup `json:"securitygroup,omitempty" doc:"list of security groups associated with the virtual machine"` + ServiceOfferingID *UUID `json:"serviceofferingid,omitempty" doc:"the ID of the service offering of the virtual machine"` + ServiceOfferingName string `json:"serviceofferingname,omitempty" doc:"the name of the service offering of the virtual machine"` + ServiceState string `json:"servicestate,omitempty" doc:"State of the Service from LB rule"` + State string `json:"state,omitempty" doc:"the state of the virtual machine"` + Tags []ResourceTag `json:"tags,omitempty" doc:"the list of resource tags associated with vm"` + TemplateDisplayText string `json:"templatedisplaytext,omitempty" doc:"an alternate display text of the template for the virtual machine"` + TemplateID *UUID `json:"templateid,omitempty" doc:"the ID of the template for the virtual machine. A -1 is returned if the virtual machine was created from an ISO file."` + TemplateName string `json:"templatename,omitempty" doc:"the name of the template for the virtual machine"` + ZoneID *UUID `json:"zoneid,omitempty" doc:"the ID of the availablility zone for the virtual machine"` + ZoneName string `json:"zonename,omitempty" doc:"the name of the availability zone for the virtual machine"` } // ResourceType returns the type of the resource @@ -94,11 +119,9 @@ func (vm VirtualMachine) Delete(ctx context.Context, client *Client) error { // ListRequest builds the ListVirtualMachines request func (vm VirtualMachine) ListRequest() (ListCommand, error) { - // XXX: AffinityGroupID, SecurityGroupID, Tags + // XXX: AffinityGroupID, SecurityGroupID req := &ListVirtualMachines{ - Account: vm.Account, - DomainID: vm.DomainID, GroupID: vm.GroupID, ID: vm.ID, Name: vm.Name, @@ -112,14 +135,18 @@ func (vm VirtualMachine) ListRequest() (ListCommand, error) { req.IPAddress = nic.IPAddress } + for i := range vm.Tags { + req.Tags = append(req.Tags, vm.Tags[i]) + } + return req, nil } // DefaultNic returns the default nic func (vm VirtualMachine) DefaultNic() *Nic { - for _, nic := range vm.Nic { + for i, nic := range vm.Nic { if nic.IsDefault { - return &nic + return &vm.Nic[i] } } @@ -143,8 +170,9 @@ func (vm VirtualMachine) NicsByType(nicType string) []Nic { for _, nic := range vm.Nic { if nic.Type == nicType { // XXX The API forgets to specify it - nic.VirtualMachineID = vm.ID - nics = append(nics, nic) + n := nic + n.VirtualMachineID = vm.ID + nics = append(nics, n) } } return nics @@ -153,22 +181,24 @@ func (vm VirtualMachine) NicsByType(nicType string) []Nic { // NicByNetworkID returns the corresponding interface based on the given NetworkID // // A VM cannot be connected twice to a same network. -func (vm VirtualMachine) NicByNetworkID(networkID string) *Nic { +func (vm VirtualMachine) NicByNetworkID(networkID UUID) *Nic { for _, nic := range vm.Nic { - if nic.NetworkID == networkID { - nic.VirtualMachineID = vm.ID - return &nic + if nic.NetworkID.Equal(networkID) { + n := nic + n.VirtualMachineID = vm.ID + return &n } } return nil } // NicByID returns the corresponding interface base on its ID -func (vm VirtualMachine) NicByID(nicID string) *Nic { +func (vm VirtualMachine) NicByID(nicID UUID) *Nic { for _, nic := range vm.Nic { - if nic.ID == nicID { - nic.VirtualMachineID = vm.ID - return &nic + if nic.ID.Equal(nicID) { + n := nic + n.VirtualMachineID = vm.ID + return &n } } @@ -177,9 +207,9 @@ func (vm VirtualMachine) NicByID(nicID string) *Nic { // IPToNetwork represents a mapping between ip and networks type IPToNetwork struct { - IP string `json:"ip,omitempty"` - Ipv6 string `json:"ipv6,omitempty"` - NetworkID string `json:"networkid,omitempty"` + IP net.IP `json:"ip,omitempty"` + Ipv6 net.IP `json:"ipv6,omitempty"` + NetworkID *UUID `json:"networkid,omitempty"` } // PCIDevice represents a PCI card present in the host @@ -201,8 +231,8 @@ type Password struct { // VirtualMachineUserData represents the base64 encoded user-data type VirtualMachineUserData struct { - UserData string `json:"userdata,omitempty" doc:"Base 64 encoded VM user data"` - VirtualMachineID string `json:"virtualmachineid,omitempty" doc:"the ID of the virtual machine"` + UserData string `json:"userdata" doc:"Base 64 encoded VM user data"` + VirtualMachineID *UUID `json:"virtualmachineid" doc:"the ID of the virtual machine"` } // Decode decodes as a readable string the content of the user-data (base64 · gzip) @@ -232,41 +262,33 @@ func (userdata VirtualMachineUserData) Decode() (string, error) { // // Regarding the UserData field, the client is responsible to base64 (and probably gzip) it. Doing it within this library would make the integration with other tools, e.g. Terraform harder. type DeployVirtualMachine struct { - Account string `json:"account,omitempty" doc:"an optional account for the virtual machine. Must be used with domainId."` - AffinityGroupIDs []string `json:"affinitygroupids,omitempty" doc:"comma separated list of affinity groups id that are going to be applied to the virtual machine. Mutually exclusive with affinitygroupnames parameter"` + AffinityGroupIDs []UUID `json:"affinitygroupids,omitempty" doc:"comma separated list of affinity groups id that are going to be applied to the virtual machine. Mutually exclusive with affinitygroupnames parameter"` AffinityGroupNames []string `json:"affinitygroupnames,omitempty" doc:"comma separated list of affinity groups names that are going to be applied to the virtual machine.Mutually exclusive with affinitygroupids parameter"` - CustomID string `json:"customid,omitempty" doc:"an optional field, in case you want to set a custom id to the resource. Allowed to Root Admins only"` - DeploymentPlanner string `json:"deploymentplanner,omitempty" doc:"Deployment planner to use for vm allocation. Available to ROOT admin only"` Details map[string]string `json:"details,omitempty" doc:"used to specify the custom parameters."` - DiskOfferingID string `json:"diskofferingid,omitempty" doc:"the ID of the disk offering for the virtual machine. If the template is of ISO format, the diskOfferingId is for the root disk volume. Otherwise this parameter is used to indicate the offering for the data disk volume. If the templateId parameter passed is from a Template object, the diskOfferingId refers to a DATA Disk Volume created. If the templateId parameter passed is from an ISO object, the diskOfferingId refers to a ROOT Disk Volume created."` + DiskOfferingID *UUID `json:"diskofferingid,omitempty" doc:"the ID of the disk offering for the virtual machine. If the template is of ISO format, the diskofferingid is for the root disk volume. Otherwise this parameter is used to indicate the offering for the data disk volume. If the templateid parameter passed is from a Template object, the diskofferingid refers to a DATA Disk Volume created. If the templateid parameter passed is from an ISO object, the diskofferingid refers to a ROOT Disk Volume created."` DisplayName string `json:"displayname,omitempty" doc:"an optional user generated name for the virtual machine"` - DisplayVM *bool `json:"displayvm,omitempty" doc:"an optional field, whether to the display the vm to the end user or not."` - DomainID string `json:"domainid,omitempty" doc:"an optional domainId for the virtual machine. If the account parameter is used, domainId must also be used."` Group string `json:"group,omitempty" doc:"an optional group for the virtual machine"` - HostID string `json:"hostid,omitempty" doc:"destination Host ID to deploy the VM to - parameter available for root admin only"` - Hypervisor string `json:"hypervisor,omitempty" doc:"the hypervisor on which to deploy the virtual machine"` IP4 *bool `json:"ip4,omitempty" doc:"True to set an IPv4 to the default interface"` IP6 *bool `json:"ip6,omitempty" doc:"True to set an IPv6 to the default interface"` IP6Address net.IP `json:"ip6address,omitempty" doc:"the ipv6 address for default vm's network"` IPAddress net.IP `json:"ipaddress,omitempty" doc:"the ip address for default vm's network"` - IPToNetworkList []IPToNetwork `json:"iptonetworklist,omitempty" doc:"ip to network mapping. Can't be specified with networkIds parameter. Example: iptonetworklist[0].ip=10.10.10.11&iptonetworklist[0].ipv6=fc00:1234:5678::abcd&iptonetworklist[0].networkid=uuid - requests to use ip 10.10.10.11 in network id=uuid"` Keyboard string `json:"keyboard,omitempty" doc:"an optional keyboard device type for the virtual machine. valid value can be one of de,de-ch,es,fi,fr,fr-be,fr-ch,is,it,jp,nl-be,no,pt,uk,us"` KeyPair string `json:"keypair,omitempty" doc:"name of the ssh key pair used to login to the virtual machine"` Name string `json:"name,omitempty" doc:"host name for the virtual machine"` - NetworkIDs []string `json:"networkids,omitempty" doc:"list of network ids used by virtual machine. Can't be specified with ipToNetworkList parameter"` + NetworkIDs []UUID `json:"networkids,omitempty" doc:"list of network ids used by virtual machine. Can't be specified with ipToNetworkList parameter"` RootDiskSize int64 `json:"rootdisksize,omitempty" doc:"Optional field to resize root disk on deploy. Value is in GB. Only applies to template-based deployments. Analogous to details[0].rootdisksize, which takes precedence over this parameter if both are provided"` - SecurityGroupIDs []string `json:"securitygroupids,omitempty" doc:"comma separated list of security groups id that going to be applied to the virtual machine. Should be passed only when vm is created from a zone with Basic Network support. Mutually exclusive with securitygroupnames parameter"` + SecurityGroupIDs []UUID `json:"securitygroupids,omitempty" doc:"comma separated list of security groups id that going to be applied to the virtual machine. Should be passed only when vm is created from a zone with Basic Network support. Mutually exclusive with securitygroupnames parameter"` SecurityGroupNames []string `json:"securitygroupnames,omitempty" doc:"comma separated list of security groups names that going to be applied to the virtual machine. Should be passed only when vm is created from a zone with Basic Network support. Mutually exclusive with securitygroupids parameter"` - ServiceOfferingID string `json:"serviceofferingid" doc:"the ID of the service offering for the virtual machine"` - Size int64 `json:"size,omitempty" doc:"the arbitrary size for the DATADISK volume. Mutually exclusive with diskOfferingId"` + ServiceOfferingID *UUID `json:"serviceofferingid" doc:"the ID of the service offering for the virtual machine"` + Size int64 `json:"size,omitempty" doc:"the arbitrary size for the DATADISK volume. Mutually exclusive with diskofferingid"` StartVM *bool `json:"startvm,omitempty" doc:"true if start vm after creating. Default value is true"` - TemplateID string `json:"templateid" doc:"the ID of the template for the virtual machine"` + TemplateID *UUID `json:"templateid" doc:"the ID of the template for the virtual machine"` UserData string `json:"userdata,omitempty" doc:"an optional binary data that can be sent to the virtual machine upon a successful deployment. This binary data must be base64 encoded before adding it to the request. Using HTTP GET (via querystring), you can send up to 2KB of data after base64 encoding. Using HTTP POST(via POST body), you can send up to 32K of data after base64 encoding."` - ZoneID string `json:"zoneid" doc:"availability zone for the virtual machine"` + ZoneID *UUID `json:"zoneid" doc:"availability zone for the virtual machine"` _ bool `name:"deployVirtualMachine" description:"Creates and automatically starts a virtual machine based on a service offering, disk offering, and template."` } -func (req DeployVirtualMachine) onBeforeSend(params url.Values) error { +func (req DeployVirtualMachine) onBeforeSend(_ url.Values) error { // Either AffinityGroupIDs or AffinityGroupNames must be set if len(req.AffinityGroupIDs) > 0 && len(req.AffinityGroupNames) > 0 { return fmt.Errorf("either AffinityGroupIDs or AffinityGroupNames must be set") @@ -280,132 +302,142 @@ func (req DeployVirtualMachine) onBeforeSend(params url.Values) error { return nil } -func (DeployVirtualMachine) response() interface{} { +// Response returns the struct to unmarshal +func (DeployVirtualMachine) Response() interface{} { return new(AsyncJobResult) } -func (DeployVirtualMachine) asyncResponse() interface{} { +// AsyncResponse returns the struct to unmarshal the async job +func (DeployVirtualMachine) AsyncResponse() interface{} { return new(VirtualMachine) } // StartVirtualMachine (Async) represents the creation of the virtual machine type StartVirtualMachine struct { - ID string `json:"id" doc:"The ID of the virtual machine"` - DeploymentPlanner string `json:"deploymentplanner,omitempty" doc:"Deployment planner to use for vm allocation. Available to ROOT admin only"` - HostID string `json:"hostid,omitempty" doc:"destination Host ID to deploy the VM to - parameter available for root admin only"` - _ bool `name:"startVirtualMachine" description:"Starts a virtual machine."` + ID *UUID `json:"id" doc:"The ID of the virtual machine"` + RescueProfile string `json:"rescueprofile,omitempty" doc:"An optional rescue profile to use when booting"` + _ bool `name:"startVirtualMachine" description:"Starts a virtual machine."` } -func (StartVirtualMachine) response() interface{} { +// Response returns the struct to unmarshal +func (StartVirtualMachine) Response() interface{} { return new(AsyncJobResult) } -func (StartVirtualMachine) asyncResponse() interface{} { +// AsyncResponse returns the struct to unmarshal the async job +func (StartVirtualMachine) AsyncResponse() interface{} { return new(VirtualMachine) } // StopVirtualMachine (Async) represents the stopping of the virtual machine type StopVirtualMachine struct { - ID string `json:"id" doc:"The ID of the virtual machine"` - Forced *bool `json:"forced,omitempty" doc:"Force stop the VM (vm is marked as Stopped even when command fails to be send to the backend). The caller knows the VM is stopped."` - _ bool `name:"stopVirtualMachine" description:"Stops a virtual machine."` + ID *UUID `json:"id" doc:"The ID of the virtual machine"` + Forced *bool `json:"forced,omitempty" doc:"Force stop the VM (vm is marked as Stopped even when command fails to be send to the backend). The caller knows the VM is stopped."` + _ bool `name:"stopVirtualMachine" description:"Stops a virtual machine."` } -func (StopVirtualMachine) response() interface{} { +// Response returns the struct to unmarshal +func (StopVirtualMachine) Response() interface{} { return new(AsyncJobResult) } -func (StopVirtualMachine) asyncResponse() interface{} { +// AsyncResponse returns the struct to unmarshal the async job +func (StopVirtualMachine) AsyncResponse() interface{} { return new(VirtualMachine) } // RebootVirtualMachine (Async) represents the rebooting of the virtual machine type RebootVirtualMachine struct { - ID string `json:"id" doc:"The ID of the virtual machine"` - _ bool `name:"rebootVirtualMachine" description:"Reboots a virtual machine."` + ID *UUID `json:"id" doc:"The ID of the virtual machine"` + _ bool `name:"rebootVirtualMachine" description:"Reboots a virtual machine."` } -func (RebootVirtualMachine) response() interface{} { +// Response returns the struct to unmarshal +func (RebootVirtualMachine) Response() interface{} { return new(AsyncJobResult) } -func (RebootVirtualMachine) asyncResponse() interface{} { +// AsyncResponse returns the struct to unmarshal the async job +func (RebootVirtualMachine) AsyncResponse() interface{} { return new(VirtualMachine) } // RestoreVirtualMachine (Async) represents the restoration of the virtual machine type RestoreVirtualMachine struct { - VirtualMachineID string `json:"virtualmachineid" doc:"Virtual Machine ID"` - TemplateID string `json:"templateid,omitempty" doc:"an optional template Id to restore vm from the new template. This can be an ISO id in case of restore vm deployed using ISO"` - RootDiskSize int64 `json:"rootdisksize,omitempty" doc:"Optional field to resize root disk on restore. Value is in GB. Only applies to template-based deployments."` - _ bool `name:"restoreVirtualMachine" description:"Restore a VM to original template/ISO or new template/ISO"` + VirtualMachineID *UUID `json:"virtualmachineid" doc:"Virtual Machine ID"` + TemplateID *UUID `json:"templateid,omitempty" doc:"an optional template Id to restore vm from the new template. This can be an ISO id in case of restore vm deployed using ISO"` + RootDiskSize int64 `json:"rootdisksize,omitempty" doc:"Optional field to resize root disk on restore. Value is in GB. Only applies to template-based deployments."` + _ bool `name:"restoreVirtualMachine" description:"Restore a VM to original template/ISO or new template/ISO"` } -func (RestoreVirtualMachine) response() interface{} { +// Response returns the struct to unmarshal +func (RestoreVirtualMachine) Response() interface{} { return new(AsyncJobResult) } -func (RestoreVirtualMachine) asyncResponse() interface{} { +// AsyncResponse returns the struct to unmarshal the async job +func (RestoreVirtualMachine) AsyncResponse() interface{} { return new(VirtualMachine) } // RecoverVirtualMachine represents the restoration of the virtual machine type RecoverVirtualMachine struct { - ID string `json:"id" doc:"The ID of the virtual machine"` - _ bool `name:"recoverVirtualMachine" description:"Recovers a virtual machine."` + ID *UUID `json:"id" doc:"The ID of the virtual machine"` + _ bool `name:"recoverVirtualMachine" description:"Recovers a virtual machine."` } -func (RecoverVirtualMachine) response() interface{} { +// Response returns the struct to unmarshal +func (RecoverVirtualMachine) Response() interface{} { return new(VirtualMachine) } // DestroyVirtualMachine (Async) represents the destruction of the virtual machine type DestroyVirtualMachine struct { - ID string `json:"id" doc:"The ID of the virtual machine"` - Expunge *bool `json:"expunge,omitempty" doc:"If true is passed, the vm is expunged immediately. False by default."` - _ bool `name:"destroyVirtualMachine" description:"Destroys a virtual machine."` + ID *UUID `json:"id" doc:"The ID of the virtual machine"` + _ bool `name:"destroyVirtualMachine" description:"Destroys a virtual machine."` } -func (DestroyVirtualMachine) response() interface{} { +// Response returns the struct to unmarshal +func (DestroyVirtualMachine) Response() interface{} { return new(AsyncJobResult) } -func (DestroyVirtualMachine) asyncResponse() interface{} { +// AsyncResponse returns the struct to unmarshal the async job +func (DestroyVirtualMachine) AsyncResponse() interface{} { return new(VirtualMachine) } // UpdateVirtualMachine represents the update of the virtual machine type UpdateVirtualMachine struct { - ID string `json:"id" doc:"The ID of the virtual machine"` - CustomID string `json:"customid,omitempty" doc:"an optional field, in case you want to set a custom id to the resource. Allowed to Root Admins only"` - Details map[string]string `json:"details,omitempty" doc:"Details in key/value pairs."` - DisplayName string `json:"displayname,omitempty" doc:"user generated name"` - DisplayVM *bool `json:"displayvm,omitempty" doc:"an optional field, whether to the display the vm to the end user or not."` - Group string `json:"group,omitempty" doc:"group of the virtual machine"` - HAEnable *bool `json:"haenable,omitempty" doc:"true if high-availability is enabled for the virtual machine, false otherwise"` - IsDynamicallyScalable *bool `json:"isdynamicallyscalable,omitempty" doc:"true if VM contains XS/VMWare tools inorder to support dynamic scaling of VM cpu/memory"` - Name string `json:"name,omitempty" doc:"new host name of the vm. The VM has to be stopped/started for this update to take affect"` - SecurityGroupIDs []string `json:"securitygroupids,omitempty" doc:"list of security group ids to be applied on the virtual machine."` - UserData string `json:"userdata,omitempty" doc:"an optional binary data that can be sent to the virtual machine upon a successful deployment. This binary data must be base64 encoded before adding it to the request. Using HTTP GET (via querystring), you can send up to 2KB of data after base64 encoding. Using HTTP POST(via POST body), you can send up to 32K of data after base64 encoding."` - _ bool `name:"updateVirtualMachine" description:"Updates properties of a virtual machine. The VM has to be stopped and restarted for the new properties to take effect. UpdateVirtualMachine does not first check whether the VM is stopped. Therefore, stop the VM manually before issuing this call."` + ID *UUID `json:"id" doc:"The ID of the virtual machine"` + Details map[string]string `json:"details,omitempty" doc:"Details in key/value pairs."` + DisplayName string `json:"displayname,omitempty" doc:"user generated name"` + Group string `json:"group,omitempty" doc:"group of the virtual machine"` + Name string `json:"name,omitempty" doc:"new host name of the vm. The VM has to be stopped/started for this update to take affect"` + SecurityGroupIDs []UUID `json:"securitygroupids,omitempty" doc:"list of security group ids to be applied on the virtual machine."` + UserData string `json:"userdata,omitempty" doc:"an optional binary data that can be sent to the virtual machine upon a successful deployment. This binary data must be base64 encoded before adding it to the request. Using HTTP GET (via querystring), you can send up to 2KB of data after base64 encoding. Using HTTP POST(via POST body), you can send up to 32K of data after base64 encoding."` + _ bool `name:"updateVirtualMachine" description:"Updates properties of a virtual machine. The VM has to be stopped and restarted for the new properties to take effect. UpdateVirtualMachine does not first check whether the VM is stopped. Therefore, stop the VM manually before issuing this call."` } -func (UpdateVirtualMachine) response() interface{} { +// Response returns the struct to unmarshal +func (UpdateVirtualMachine) Response() interface{} { return new(VirtualMachine) } // ExpungeVirtualMachine represents the annihilation of a VM type ExpungeVirtualMachine struct { - ID string `json:"id" doc:"The ID of the virtual machine"` - _ bool `name:"expungeVirtualMachine" description:"Expunge a virtual machine. Once expunged, it cannot be recoverd."` + ID *UUID `json:"id" doc:"The ID of the virtual machine"` + _ bool `name:"expungeVirtualMachine" description:"Expunge a virtual machine. Once expunged, it cannot be recoverd."` } -func (ExpungeVirtualMachine) response() interface{} { +// Response returns the struct to unmarshal +func (ExpungeVirtualMachine) Response() interface{} { return new(AsyncJobResult) } -func (ExpungeVirtualMachine) asyncResponse() interface{} { - return new(booleanResponse) +// AsyncResponse returns the struct to unmarshal the async job +func (ExpungeVirtualMachine) AsyncResponse() interface{} { + return new(BooleanResponse) } // ScaleVirtualMachine (Async) scales the virtual machine to a new service offering. @@ -413,82 +445,84 @@ func (ExpungeVirtualMachine) asyncResponse() interface{} { // ChangeServiceForVirtualMachine does the same thing but returns the // new Virtual Machine which is more consistent with the rest of the API. type ScaleVirtualMachine struct { - ID string `json:"id" doc:"The ID of the virtual machine"` - ServiceOfferingID string `json:"serviceofferingid" doc:"the ID of the service offering for the virtual machine"` + ID *UUID `json:"id" doc:"The ID of the virtual machine"` + ServiceOfferingID *UUID `json:"serviceofferingid" doc:"the ID of the service offering for the virtual machine"` Details map[string]string `json:"details,omitempty" doc:"name value pairs of custom parameters for cpu,memory and cpunumber. example details[i].name=value"` _ bool `name:"scaleVirtualMachine" description:"Scales the virtual machine to a new service offering."` } -func (ScaleVirtualMachine) response() interface{} { +// Response returns the struct to unmarshal +func (ScaleVirtualMachine) Response() interface{} { return new(AsyncJobResult) } -func (ScaleVirtualMachine) asyncResponse() interface{} { - return new(booleanResponse) +// AsyncResponse returns the struct to unmarshal the async job +func (ScaleVirtualMachine) AsyncResponse() interface{} { + return new(BooleanResponse) } // ChangeServiceForVirtualMachine changes the service offering for a virtual machine. The virtual machine must be in a "Stopped" state for this command to take effect. type ChangeServiceForVirtualMachine struct { - ID string `json:"id" doc:"The ID of the virtual machine"` - ServiceOfferingID string `json:"serviceofferingid" doc:"the service offering ID to apply to the virtual machine"` + ID *UUID `json:"id" doc:"The ID of the virtual machine"` + ServiceOfferingID *UUID `json:"serviceofferingid" doc:"the service offering ID to apply to the virtual machine"` Details map[string]string `json:"details,omitempty" doc:"name value pairs of custom parameters for cpu, memory and cpunumber. example details[i].name=value"` _ bool `name:"changeServiceForVirtualMachine" description:"Changes the service offering for a virtual machine. The virtual machine must be in a \"Stopped\" state for this command to take effect."` } -func (ChangeServiceForVirtualMachine) response() interface{} { +// Response returns the struct to unmarshal +func (ChangeServiceForVirtualMachine) Response() interface{} { return new(VirtualMachine) } // ResetPasswordForVirtualMachine resets the password for virtual machine. The virtual machine must be in a "Stopped" state... type ResetPasswordForVirtualMachine struct { - ID string `json:"id" doc:"The ID of the virtual machine"` - _ bool `name:"resetPasswordForVirtualMachine" description:"Resets the password for virtual machine. The virtual machine must be in a \"Stopped\" state and the template must already support this feature for this command to take effect."` + ID *UUID `json:"id" doc:"The ID of the virtual machine"` + _ bool `name:"resetPasswordForVirtualMachine" description:"Resets the password for virtual machine. The virtual machine must be in a \"Stopped\" state and the template must already support this feature for this command to take effect."` } -func (ResetPasswordForVirtualMachine) response() interface{} { +// Response returns the struct to unmarshal +func (ResetPasswordForVirtualMachine) Response() interface{} { return new(AsyncJobResult) } -func (ResetPasswordForVirtualMachine) asyncResponse() interface{} { + +// AsyncResponse returns the struct to unmarshal the async job +func (ResetPasswordForVirtualMachine) AsyncResponse() interface{} { return new(VirtualMachine) } // GetVMPassword asks for an encrypted password type GetVMPassword struct { - ID string `json:"id" doc:"The ID of the virtual machine"` - _ bool `name:"getVMPassword" description:"Returns an encrypted password for the VM"` + ID *UUID `json:"id" doc:"The ID of the virtual machine"` + _ bool `name:"getVMPassword" description:"Returns an encrypted password for the VM"` } -func (GetVMPassword) response() interface{} { +// Response returns the struct to unmarshal +func (GetVMPassword) Response() interface{} { return new(Password) } +//go:generate go run generate/main.go -interface=Listable ListVirtualMachines + // ListVirtualMachines represents a search for a VM type ListVirtualMachines struct { - Account string `json:"account,omitempty" doc:"list resources by account. Must be used with the domainId parameter."` - AffinityGroupID string `json:"affinitygroupid,omitempty" doc:"list vms by affinity group"` + AffinityGroupID *UUID `json:"affinitygroupid,omitempty" doc:"list vms by affinity group"` Details []string `json:"details,omitempty" doc:"comma separated list of host details requested, value can be a list of [all, group, nics, stats, secgrp, tmpl, servoff, diskoff, iso, volume, min, affgrp]. If no parameter is passed in, the details will be defaulted to all"` - DisplayVM *bool `json:"displayvm,omitempty" doc:"list resources by display flag; only ROOT admin is eligible to pass this parameter"` - DomainID string `json:"domainid,omitempty" doc:"list only resources belonging to the domain specified"` ForVirtualNetwork *bool `json:"forvirtualnetwork,omitempty" doc:"list by network type; true if need to list vms using Virtual Network, false otherwise"` - GroupID string `json:"groupid,omitempty" doc:"the group ID"` - HostID string `json:"hostid,omitempty" doc:"the host ID"` - Hypervisor string `json:"hypervisor,omitempty" doc:"the target hypervisor for the template"` - ID string `json:"id,omitempty" doc:"the ID of the virtual machine"` - IDs []string `json:"ids,omitempty" doc:"the IDs of the virtual machines, mutually exclusive with id"` + GroupID *UUID `json:"groupid,omitempty" doc:"the group ID"` + ID *UUID `json:"id,omitempty" doc:"the ID of the virtual machine"` + IDs []UUID `json:"ids,omitempty" doc:"the IDs of the virtual machines, mutually exclusive with id"` IPAddress net.IP `json:"ipaddress,omitempty" doc:"an IP address to filter the result"` - IsoID string `json:"isoid,omitempty" doc:"list vms by iso"` - IsRecursive *bool `json:"isrecursive,omitempty" doc:"defaults to false, but if true, lists all resources from the parent specified by the domainId till leaves."` + IsoID *UUID `json:"isoid,omitempty" doc:"list vms by iso"` Keyword string `json:"keyword,omitempty" doc:"List by keyword"` - ListAll *bool `json:"listall,omitempty" doc:"If set to false, list only resources belonging to the command's caller; if set to true - list resources that the caller is authorized to see. Default value is false"` Name string `json:"name,omitempty" doc:"name of the virtual machine"` - NetworkID string `json:"networkid,omitempty" doc:"list by network id"` + NetworkID *UUID `json:"networkid,omitempty" doc:"list by network id"` Page int `json:"page,omitempty"` PageSize int `json:"pagesize,omitempty"` - ServiceOfferindID string `json:"serviceofferingid,omitempty" doc:"list by the service offering"` + ServiceOfferindID *UUID `json:"serviceofferingid,omitempty" doc:"list by the service offering"` State string `json:"state,omitempty" doc:"state of the virtual machine"` Tags []ResourceTag `json:"tags,omitempty" doc:"List resources by tags (key/value pairs)"` - TemplateID string `json:"templateid,omitempty" doc:"list vms by template"` - ZoneID string `json:"zoneid,omitempty" doc:"the availability zone ID"` + TemplateID *UUID `json:"templateid,omitempty" doc:"list vms by template"` + ZoneID *UUID `json:"zoneid,omitempty" doc:"the availability zone ID"` _ bool `name:"listVirtualMachines" description:"List the virtual machines owned by the account."` } @@ -498,103 +532,82 @@ type ListVirtualMachinesResponse struct { VirtualMachine []VirtualMachine `json:"virtualmachine"` } -func (ListVirtualMachines) response() interface{} { - return new(ListVirtualMachinesResponse) -} - -// SetPage sets the current page -func (ls *ListVirtualMachines) SetPage(page int) { - ls.Page = page -} - -// SetPageSize sets the page size -func (ls *ListVirtualMachines) SetPageSize(pageSize int) { - ls.PageSize = pageSize -} - -func (ListVirtualMachines) each(resp interface{}, callback IterateItemFunc) { - vms, ok := resp.(*ListVirtualMachinesResponse) - if !ok { - callback(nil, fmt.Errorf("wrong type. ListVirtualMachinesResponse expected, got %T", resp)) - return - } - - for i := range vms.VirtualMachine { - if !callback(&vms.VirtualMachine[i], nil) { - break - } - } -} - // AddNicToVirtualMachine (Async) adds a NIC to a VM type AddNicToVirtualMachine struct { - NetworkID string `json:"networkid" doc:"Network ID"` - VirtualMachineID string `json:"virtualmachineid" doc:"Virtual Machine ID"` - IPAddress net.IP `json:"ipaddress,omitempty" doc:"IP Address for the new network"` + NetworkID *UUID `json:"networkid" doc:"Network ID"` + VirtualMachineID *UUID `json:"virtualmachineid" doc:"Virtual Machine ID"` + IPAddress net.IP `json:"ipaddress,omitempty" doc:"Static IP address lease for the corresponding NIC and network which should be in the range defined in the network"` _ bool `name:"addNicToVirtualMachine" description:"Adds VM to specified network by creating a NIC"` } -func (AddNicToVirtualMachine) response() interface{} { +// Response returns the struct to unmarshal +func (AddNicToVirtualMachine) Response() interface{} { return new(AsyncJobResult) } -func (AddNicToVirtualMachine) asyncResponse() interface{} { +// AsyncResponse returns the struct to unmarshal the async job +func (AddNicToVirtualMachine) AsyncResponse() interface{} { return new(VirtualMachine) } // RemoveNicFromVirtualMachine (Async) removes a NIC from a VM type RemoveNicFromVirtualMachine struct { - NicID string `json:"nicid" doc:"NIC ID"` - VirtualMachineID string `json:"virtualmachineid" doc:"Virtual Machine ID"` - _ bool `name:"removeNicFromVirtualMachine" description:"Removes VM from specified network by deleting a NIC"` + NicID *UUID `json:"nicid" doc:"NIC ID"` + VirtualMachineID *UUID `json:"virtualmachineid" doc:"Virtual Machine ID"` + _ bool `name:"removeNicFromVirtualMachine" description:"Removes VM from specified network by deleting a NIC"` } -func (RemoveNicFromVirtualMachine) response() interface{} { +// Response returns the struct to unmarshal +func (RemoveNicFromVirtualMachine) Response() interface{} { return new(AsyncJobResult) } -func (RemoveNicFromVirtualMachine) asyncResponse() interface{} { +// AsyncResponse returns the struct to unmarshal the async job +func (RemoveNicFromVirtualMachine) AsyncResponse() interface{} { return new(VirtualMachine) } // UpdateDefaultNicForVirtualMachine (Async) adds a NIC to a VM type UpdateDefaultNicForVirtualMachine struct { - NicID string `json:"nicid" doc:"NIC ID"` - VirtualMachineID string `json:"virtualmachineid" doc:"Virtual Machine ID"` - _ bool `name:"updateDefaultNicForVirtualMachine" description:"Changes the default NIC on a VM"` + NicID *UUID `json:"nicid" doc:"NIC ID"` + VirtualMachineID *UUID `json:"virtualmachineid" doc:"Virtual Machine ID"` + _ bool `name:"updateDefaultNicForVirtualMachine" description:"Changes the default NIC on a VM"` } -func (UpdateDefaultNicForVirtualMachine) response() interface{} { +// Response returns the struct to unmarshal +func (UpdateDefaultNicForVirtualMachine) Response() interface{} { return new(AsyncJobResult) } -func (UpdateDefaultNicForVirtualMachine) asyncResponse() interface{} { + +// AsyncResponse returns the struct to unmarshal the async job +func (UpdateDefaultNicForVirtualMachine) AsyncResponse() interface{} { return new(VirtualMachine) } // GetVirtualMachineUserData returns the user-data of the given VM type GetVirtualMachineUserData struct { - VirtualMachineID string `json:"virtualmachineid" doc:"The ID of the virtual machine"` - _ bool `name:"getVirtualMachineUserData" description:"Returns user data associated with the VM"` + VirtualMachineID *UUID `json:"virtualmachineid" doc:"The ID of the virtual machine"` + _ bool `name:"getVirtualMachineUserData" description:"Returns user data associated with the VM"` } -func (GetVirtualMachineUserData) response() interface{} { +// Response returns the struct to unmarshal +func (GetVirtualMachineUserData) Response() interface{} { return new(VirtualMachineUserData) } -// Decode decodes the base64 / gzipped encoded user data - -// MigrateVirtualMachine (Async) attempts migration of a VM to a different host or Root volume of the vm to a different storage pool -type MigrateVirtualMachine struct { - HostID string `json:"hostid,omitempty" doc:"Destination Host ID to migrate VM to. Required for live migrating a VM from host to host"` - StorageID string `json:"storageid,omitempty" doc:"Destination storage pool ID to migrate VM volumes to. Required for migrating the root disk volume"` - VirtualMachineID string `json:"virtualmachineid" doc:"the ID of the virtual machine"` - _ bool `name:"migrateVirtualMachine" description:"Attempts Migration of a VM to a different host or Root volume of the vm to a different storage pool"` +// UpdateVMNicIP updates the default IP address of a VM Nic +type UpdateVMNicIP struct { + _ bool `name:"updateVmNicIp" description:"Update the default Ip of a VM Nic"` + IPAddress net.IP `json:"ipaddress,omitempty" doc:"Static IP address lease for the corresponding NIC and network which should be in the range defined in the network. If absent, the call removes the lease associated with the nic."` + NicID *UUID `json:"nicid" doc:"the ID of the nic."` } -func (MigrateVirtualMachine) response() interface{} { +// Response returns the struct to unmarshal +func (UpdateVMNicIP) Response() interface{} { return new(AsyncJobResult) } -func (MigrateVirtualMachine) asyncResponse() interface{} { +// AsyncResponse returns the struct to unmarshal the async job +func (UpdateVMNicIP) AsyncResponse() interface{} { return new(VirtualMachine) } diff --git a/vendor/github.com/exoscale/egoscale/virtualmachines_response.go b/vendor/github.com/exoscale/egoscale/virtualmachines_response.go new file mode 100644 index 000000000..9aafb01a3 --- /dev/null +++ b/vendor/github.com/exoscale/egoscale/virtualmachines_response.go @@ -0,0 +1,43 @@ +// code generated; DO NOT EDIT. + +package egoscale + +import "fmt" + +// Response returns the struct to unmarshal +func (ListVirtualMachines) Response() interface{} { + return new(ListVirtualMachinesResponse) +} + +// ListRequest returns itself +func (ls *ListVirtualMachines) ListRequest() (ListCommand, error) { + if ls == nil { + return nil, fmt.Errorf("%T cannot be nil", ls) + } + return ls, nil +} + +// SetPage sets the current apge +func (ls *ListVirtualMachines) SetPage(page int) { + ls.Page = page +} + +// SetPageSize sets the page size +func (ls *ListVirtualMachines) SetPageSize(pageSize int) { + ls.PageSize = pageSize +} + +// Each triggers the callback for each, valid answer or any non 404 issue +func (ListVirtualMachines) Each(resp interface{}, callback IterateItemFunc) { + items, ok := resp.(*ListVirtualMachinesResponse) + if !ok { + callback(nil, fmt.Errorf("wrong type, ListVirtualMachinesResponse was expected, got %T", resp)) + return + } + + for i := range items.VirtualMachine { + if !callback(&items.VirtualMachine[i], nil) { + break + } + } +} diff --git a/vendor/github.com/exoscale/egoscale/vm_groups.go b/vendor/github.com/exoscale/egoscale/vm_groups.go deleted file mode 100644 index fc348723c..000000000 --- a/vendor/github.com/exoscale/egoscale/vm_groups.go +++ /dev/null @@ -1,68 +0,0 @@ -package egoscale - -// InstanceGroup represents a group of VM -type InstanceGroup struct { - Account string `json:"account,omitempty" doc:"the account owning the instance group"` - Created string `json:"created,omitempty" doc:"time and date the instance group was created"` - Domain string `json:"domain,omitempty" doc:"the domain name of the instance group"` - DomainID string `json:"domainid,omitempty" doc:"the domain ID of the instance group"` - ID string `json:"id,omitempty" doc:"the id of the instance group"` - Name string `json:"name,omitempty" doc:"the name of the instance group"` -} - -// CreateInstanceGroup creates a VM group -type CreateInstanceGroup struct { - Name string `json:"name" doc:"the name of the instance group"` - Account string `json:"account,omitempty" doc:"the account of the instance group. The account parameter must be used with the domainId parameter."` - DomainID string `json:"domainid,omitempty" doc:"the domain ID of account owning the instance group"` - _ bool `name:"createInstanceGroup" description:"Creates a vm group"` -} - -func (CreateInstanceGroup) response() interface{} { - return new(InstanceGroup) -} - -// UpdateInstanceGroup updates a VM group -type UpdateInstanceGroup struct { - ID string `json:"id" doc:"Instance group ID"` - Name string `json:"name,omitempty" doc:"new instance group name"` - _ bool `name:"updateInstanceGroup" description:"Updates a vm group"` -} - -func (UpdateInstanceGroup) response() interface{} { - return new(InstanceGroup) -} - -// DeleteInstanceGroup deletes a VM group -type DeleteInstanceGroup struct { - ID string `json:"id" doc:"the ID of the instance group"` - _ bool `name:"deleteInstanceGroup" description:"Deletes a vm group"` -} - -func (DeleteInstanceGroup) response() interface{} { - return new(booleanResponse) -} - -// ListInstanceGroups lists VM groups -type ListInstanceGroups struct { - Account string `json:"account,omitempty" doc:"list resources by account. Must be used with the domainId parameter."` - DomainID string `json:"domainid,omitempty" doc:"list only resources belonging to the domain specified"` - ID string `json:"id,omitempty" doc:"list instance groups by ID"` - IsRecursive *bool `json:"isrecursive,omitempty" doc:"defaults to false, but if true, lists all resources from the parent specified by the domainId till leaves."` - Keyword string `json:"keyword,omitempty" doc:"List by keyword"` - ListAll *bool `json:"listall,omitempty" doc:"If set to false, list only resources belonging to the command's caller; if set to true - list resources that the caller is authorized to see. Default value is false"` - Name string `json:"name,omitempty" doc:"list instance groups by name"` - Page int `json:"page,omitempty"` - PageSize int `json:"pagesize,omitempty"` - _ bool `name:"listInstanceGroups" description:"Lists vm groups"` -} - -// ListInstanceGroupsResponse represents a list of instance groups -type ListInstanceGroupsResponse struct { - Count int `json:"count"` - InstanceGroup []InstanceGroup `json:"instancegroup"` -} - -func (ListInstanceGroups) response() interface{} { - return new(ListInstanceGroupsResponse) -} diff --git a/vendor/github.com/exoscale/egoscale/volumes.go b/vendor/github.com/exoscale/egoscale/volumes.go index f81056112..f942890a4 100644 --- a/vendor/github.com/exoscale/egoscale/volumes.go +++ b/vendor/github.com/exoscale/egoscale/volumes.go @@ -1,15 +1,11 @@ package egoscale -import ( - "fmt" -) - // Volume represents a volume linked to a VM type Volume struct { Account string `json:"account,omitempty" doc:"the account associated with the disk volume"` Attached string `json:"attached,omitempty" doc:"the date the volume was attached to a VM instance"` ChainInfo string `json:"chaininfo,omitempty" doc:"the chain info of the volume"` - ClusterID string `json:"clusterid,omitempty" doc:"ID of the cluster"` + ClusterID *UUID `json:"clusterid,omitempty" doc:"ID of the cluster"` ClusterName string `json:"clustername,omitempty" doc:"name of the cluster"` Created string `json:"created,omitempty" doc:"the date the disk volume was created"` Destroyed bool `json:"destroyed,omitempty" doc:"the boolean state of whether the volume is destroyed or not"` @@ -19,44 +15,42 @@ type Volume struct { DiskIopsReadRate int64 `json:"diskIopsReadRate,omitempty" doc:"io requests read rate of the disk volume"` DiskIopsWriteRate int64 `json:"diskIopsWriteRate,omitempty" doc:"io requests write rate of the disk volume"` DiskOfferingDisplayText string `json:"diskofferingdisplaytext,omitempty" doc:"the display text of the disk offering"` - DiskOfferingID string `json:"diskofferingid,omitempty" doc:"ID of the disk offering"` + DiskOfferingID *UUID `json:"diskofferingid,omitempty" doc:"ID of the disk offering"` DiskOfferingName string `json:"diskofferingname,omitempty" doc:"name of the disk offering"` DisplayVolume bool `json:"displayvolume,omitempty" doc:"an optional field whether to the display the volume to the end user or not."` - Domain string `json:"domain,omitempty" doc:"the domain associated with the disk volume"` - DomainID string `json:"domainid,omitempty" doc:"the ID of the domain associated with the disk volume"` Hypervisor string `json:"hypervisor,omitempty" doc:"Hypervisor the volume belongs to"` - ID string `json:"id,omitempty" doc:"ID of the disk volume"` + ID *UUID `json:"id,omitempty" doc:"ID of the disk volume"` IsExtractable *bool `json:"isextractable,omitempty" doc:"true if the volume is extractable, false otherwise"` IsoDisplayText string `json:"isodisplaytext,omitempty" doc:"an alternate display text of the ISO attached to the virtual machine"` - IsoID string `json:"isoid,omitempty" doc:"the ID of the ISO attached to the virtual machine"` + IsoID *UUID `json:"isoid,omitempty" doc:"the ID of the ISO attached to the virtual machine"` IsoName string `json:"isoname,omitempty" doc:"the name of the ISO attached to the virtual machine"` MaxIops int64 `json:"maxiops,omitempty" doc:"max iops of the disk volume"` MinIops int64 `json:"miniops,omitempty" doc:"min iops of the disk volume"` Name string `json:"name,omitempty" doc:"name of the disk volume"` Path string `json:"path,omitempty" doc:"the path of the volume"` - PodID string `json:"podid,omitempty" doc:"ID of the pod"` + PodID *UUID `json:"podid,omitempty" doc:"ID of the pod"` PodName string `json:"podname,omitempty" doc:"name of the pod"` QuiesceVM bool `json:"quiescevm,omitempty" doc:"need quiesce vm or not when taking snapshot"` ServiceOfferingDisplayText string `json:"serviceofferingdisplaytext,omitempty" doc:"the display text of the service offering for root disk"` - ServiceOfferingID string `json:"serviceofferingid,omitempty" doc:"ID of the service offering for root disk"` + ServiceOfferingID *UUID `json:"serviceofferingid,omitempty" doc:"ID of the service offering for root disk"` ServiceOfferingName string `json:"serviceofferingname,omitempty" doc:"name of the service offering for root disk"` Size uint64 `json:"size,omitempty" doc:"size of the disk volume"` - SnapshotID string `json:"snapshotid,omitempty" doc:"ID of the snapshot from which this volume was created"` + SnapshotID *UUID `json:"snapshotid,omitempty" doc:"ID of the snapshot from which this volume was created"` State string `json:"state,omitempty" doc:"the state of the disk volume"` Status string `json:"status,omitempty" doc:"the status of the volume"` Storage string `json:"storage,omitempty" doc:"name of the primary storage hosting the disk volume"` - StorageID string `json:"storageid,omitempty" doc:"id of the primary storage hosting the disk volume; returned to admin user only"` + StorageID *UUID `json:"storageid,omitempty" doc:"id of the primary storage hosting the disk volume; returned to admin user only"` StorageType string `json:"storagetype,omitempty" doc:"shared or local storage"` Tags []ResourceTag `json:"tags,omitempty" doc:"the list of resource tags associated with volume"` TemplateDisplayText string `json:"templatedisplaytext,omitempty" doc:"an alternate display text of the template for the virtual machine"` - TemplateID string `json:"templateid,omitempty" doc:"the ID of the template for the virtual machine. A -1 is returned if the virtual machine was created from an ISO file."` + TemplateID *UUID `json:"templateid,omitempty" doc:"the ID of the template for the virtual machine. A -1 is returned if the virtual machine was created from an ISO file."` // no *UUID because of the -1 thingy... TemplateName string `json:"templatename,omitempty" doc:"the name of the template for the virtual machine"` Type string `json:"type,omitempty" doc:"type of the disk volume (ROOT or DATADISK)"` - VirtualMachineID string `json:"virtualmachineid,omitempty" doc:"id of the virtual machine"` + VirtualMachineID *UUID `json:"virtualmachineid,omitempty" doc:"id of the virtual machine"` VMDisplayName string `json:"vmdisplayname,omitempty" doc:"display name of the virtual machine"` VMName string `json:"vmname,omitempty" doc:"name of the virtual machine"` VMState string `json:"vmstate,omitempty" doc:"state of the virtual machine"` - ZoneID string `json:"zoneid,omitempty" doc:"ID of the availability zone"` + ZoneID *UUID `json:"zoneid,omitempty" doc:"ID of the availability zone"` ZoneName string `json:"zonename,omitempty" doc:"name of the availability zone"` } @@ -68,8 +62,6 @@ func (Volume) ResourceType() string { // ListRequest builds the ListVolumes request func (vol Volume) ListRequest() (ListCommand, error) { req := &ListVolumes{ - Account: vol.Account, - DomainID: vol.DomainID, Name: vol.Name, Type: vol.Type, VirtualMachineID: vol.VirtualMachineID, @@ -81,41 +73,36 @@ func (vol Volume) ListRequest() (ListCommand, error) { // ResizeVolume (Async) resizes a volume type ResizeVolume struct { - ID string `json:"id" doc:"the ID of the disk volume"` - DiskOfferingID string `json:"diskofferingid,omitempty" doc:"new disk offering id"` - ShrinkOk *bool `json:"shrinkok,omitempty" doc:"Verify OK to Shrink"` - Size int64 `json:"size,omitempty" doc:"New volume size in G"` - _ bool `name:"resizeVolume" description:"Resizes a volume"` + ID *UUID `json:"id" doc:"the ID of the disk volume"` + DiskOfferingID *UUID `json:"diskofferingid,omitempty" doc:"new disk offering id"` + Size int64 `json:"size,omitempty" doc:"New volume size in G (must be larger than current size since shrinking the disk is not supported)"` + _ bool `name:"resizeVolume" description:"Resizes a volume"` } -func (ResizeVolume) response() interface{} { +// Response returns the struct to unmarshal +func (ResizeVolume) Response() interface{} { return new(AsyncJobResult) } -func (ResizeVolume) asyncResponse() interface{} { +// AsyncResponse returns the struct to unmarshal the async job +func (ResizeVolume) AsyncResponse() interface{} { return new(Volume) } +//go:generate go run generate/main.go -interface=Listable ListVolumes + // ListVolumes represents a query listing volumes type ListVolumes struct { - Account string `json:"account,omitempty" doc:"list resources by account. Must be used with the domainId parameter."` - DiskOfferingID string `json:"diskofferingid,omitempty" doc:"list volumes by disk offering"` - DisplayVolume *bool `json:"displayvolume,omitempty" doc:"list resources by display flag; only ROOT admin is eligible to pass this parameter"` - DomainID string `json:"domainid,omitempty" doc:"list only resources belonging to the domain specified"` - HostID string `json:"hostid,omitempty" doc:"list volumes on specified host"` - ID string `json:"id,omitempty" doc:"the ID of the disk volume"` - IsRecursive *bool `json:"isrecursive,omitempty" doc:"defaults to false, but if true, lists all resources from the parent specified by the domainId till leaves."` + DiskOfferingID *UUID `json:"diskofferingid,omitempty" doc:"List volumes by disk offering"` + ID *UUID `json:"id,omitempty" doc:"The ID of the disk volume"` Keyword string `json:"keyword,omitempty" doc:"List by keyword"` - ListAll *bool `json:"listall,omitempty" doc:"If set to false, list only resources belonging to the command's caller; if set to true - list resources that the caller is authorized to see. Default value is false"` - Name string `json:"name,omitempty" doc:"the name of the disk volume"` + Name string `json:"name,omitempty" doc:"The name of the disk volume"` Page int `json:"page,omitempty"` PageSize int `json:"pagesize,omitempty"` - PodID string `json:"podid,omitempty" doc:"the pod id the disk volume belongs to"` - StorageID string `json:"storageid,omitempty" doc:"the ID of the storage pool, available to ROOT admin only"` Tags []ResourceTag `json:"tags,omitempty" doc:"List resources by tags (key/value pairs)"` - Type string `json:"type,omitempty" doc:"the type of disk volume"` - VirtualMachineID string `json:"virtualmachineid,omitempty" doc:"the ID of the virtual machine"` - ZoneID string `json:"zoneid,omitempty" doc:"the ID of the availability zone"` + Type string `json:"type,omitempty" doc:"The type of disk volume"` + VirtualMachineID *UUID `json:"virtualmachineid,omitempty" doc:"The ID of the virtual machine"` + ZoneID *UUID `json:"zoneid,omitempty" doc:"The ID of the availability zone"` _ bool `name:"listVolumes" description:"Lists all volumes."` } @@ -124,31 +111,3 @@ type ListVolumesResponse struct { Count int `json:"count"` Volume []Volume `json:"volume"` } - -func (ListVolumes) response() interface{} { - return new(ListVolumesResponse) -} - -// SetPage sets the current page -func (ls *ListVolumes) SetPage(page int) { - ls.Page = page -} - -// SetPageSize sets the page size -func (ls *ListVolumes) SetPageSize(pageSize int) { - ls.PageSize = pageSize -} - -func (ListVolumes) each(resp interface{}, callback IterateItemFunc) { - volumes, ok := resp.(*ListVolumesResponse) - if !ok { - callback(nil, fmt.Errorf("wrong type. ListVolumesResponse expected, got %T", resp)) - return - } - - for i := range volumes.Volume { - if !callback(&volumes.Volume[i], nil) { - break - } - } -} diff --git a/vendor/github.com/exoscale/egoscale/volumes_response.go b/vendor/github.com/exoscale/egoscale/volumes_response.go new file mode 100644 index 000000000..c7486bc1e --- /dev/null +++ b/vendor/github.com/exoscale/egoscale/volumes_response.go @@ -0,0 +1,43 @@ +// code generated; DO NOT EDIT. + +package egoscale + +import "fmt" + +// Response returns the struct to unmarshal +func (ListVolumes) Response() interface{} { + return new(ListVolumesResponse) +} + +// ListRequest returns itself +func (ls *ListVolumes) ListRequest() (ListCommand, error) { + if ls == nil { + return nil, fmt.Errorf("%T cannot be nil", ls) + } + return ls, nil +} + +// SetPage sets the current apge +func (ls *ListVolumes) SetPage(page int) { + ls.Page = page +} + +// SetPageSize sets the page size +func (ls *ListVolumes) SetPageSize(pageSize int) { + ls.PageSize = pageSize +} + +// Each triggers the callback for each, valid answer or any non 404 issue +func (ListVolumes) Each(resp interface{}, callback IterateItemFunc) { + items, ok := resp.(*ListVolumesResponse) + if !ok { + callback(nil, fmt.Errorf("wrong type, ListVolumesResponse was expected, got %T", resp)) + return + } + + for i := range items.Volume { + if !callback(&items.Volume[i], nil) { + break + } + } +} diff --git a/vendor/github.com/exoscale/egoscale/zones.go b/vendor/github.com/exoscale/egoscale/zones.go index 22e912ec8..763246033 100644 --- a/vendor/github.com/exoscale/egoscale/zones.go +++ b/vendor/github.com/exoscale/egoscale/zones.go @@ -1,7 +1,6 @@ package egoscale import ( - "fmt" "net" ) @@ -15,11 +14,8 @@ type Zone struct { DisplayText string `json:"displaytext,omitempty" doc:"the display text of the zone"` DNS1 net.IP `json:"dns1,omitempty" doc:"the first DNS for the Zone"` DNS2 net.IP `json:"dns2,omitempty" doc:"the second DNS for the Zone"` - Domain string `json:"domain,omitempty" doc:"Network domain name for the networks in the zone"` - DomainID string `json:"domainid,omitempty" doc:"the UUID of the containing domain, null for public zones"` - DomainName string `json:"domainname,omitempty" doc:"the name of the containing domain, null for public zones"` - GuestCidrAddress string `json:"guestcidraddress,omitempty" doc:"the guest CIDR address for the Zone"` - ID string `json:"id,omitempty" doc:"Zone id"` + GuestCIDRAddress *CIDR `json:"guestcidraddress,omitempty" doc:"the guest CIDR address for the Zone"` + ID *UUID `json:"id,omitempty" doc:"Zone id"` InternalDNS1 net.IP `json:"internaldns1,omitempty" doc:"the first internal DNS for the Zone"` InternalDNS2 net.IP `json:"internaldns2,omitempty" doc:"the second internal DNS for the Zone"` IP6DNS1 net.IP `json:"ip6dns1,omitempty" doc:"the first IPv6 DNS for the Zone"` @@ -37,19 +33,19 @@ type Zone struct { // ListRequest builds the ListZones request func (zone Zone) ListRequest() (ListCommand, error) { req := &ListZones{ - DomainID: zone.DomainID, - ID: zone.ID, - Name: zone.Name, + ID: zone.ID, + Name: zone.Name, } return req, nil } +//go:generate go run generate/main.go -interface=Listable ListZones + // ListZones represents a query for zones type ListZones struct { Available *bool `json:"available,omitempty" doc:"true if you want to retrieve all available Zones. False if you only want to return the Zones from which you have at least one VM. Default is false."` - DomainID string `json:"domainid,omitempty" doc:"the ID of the domain associated with the zone"` - ID string `json:"id,omitempty" doc:"the ID of the zone"` + ID *UUID `json:"id,omitempty" doc:"the ID of the zone"` Keyword string `json:"keyword,omitempty" doc:"List by keyword"` Name string `json:"name,omitempty" doc:"the name of the zone"` Page int `json:"page,omitempty"` @@ -64,31 +60,3 @@ type ListZonesResponse struct { Count int `json:"count"` Zone []Zone `json:"zone"` } - -func (ListZones) response() interface{} { - return new(ListZonesResponse) -} - -// SetPage sets the current page -func (ls *ListZones) SetPage(page int) { - ls.Page = page -} - -// SetPageSize sets the page size -func (ls *ListZones) SetPageSize(pageSize int) { - ls.PageSize = pageSize -} - -func (ListZones) each(resp interface{}, callback IterateItemFunc) { - zones, ok := resp.(*ListZonesResponse) - if !ok { - callback(nil, fmt.Errorf("wrong type. ListZonesResponse was expected, got %T", resp)) - return - } - - for i := range zones.Zone { - if !callback(&zones.Zone[i], nil) { - break - } - } -} diff --git a/vendor/github.com/exoscale/egoscale/zones_response.go b/vendor/github.com/exoscale/egoscale/zones_response.go new file mode 100644 index 000000000..0fe7d06d7 --- /dev/null +++ b/vendor/github.com/exoscale/egoscale/zones_response.go @@ -0,0 +1,43 @@ +// code generated; DO NOT EDIT. + +package egoscale + +import "fmt" + +// Response returns the struct to unmarshal +func (ListZones) Response() interface{} { + return new(ListZonesResponse) +} + +// ListRequest returns itself +func (ls *ListZones) ListRequest() (ListCommand, error) { + if ls == nil { + return nil, fmt.Errorf("%T cannot be nil", ls) + } + return ls, nil +} + +// SetPage sets the current apge +func (ls *ListZones) SetPage(page int) { + ls.Page = page +} + +// SetPageSize sets the page size +func (ls *ListZones) SetPageSize(pageSize int) { + ls.PageSize = pageSize +} + +// Each triggers the callback for each, valid answer or any non 404 issue +func (ListZones) Each(resp interface{}, callback IterateItemFunc) { + items, ok := resp.(*ListZonesResponse) + if !ok { + callback(nil, fmt.Errorf("wrong type, ListZonesResponse was expected, got %T", resp)) + return + } + + for i := range items.Zone { + if !callback(&items.Zone[i], nil) { + break + } + } +} diff --git a/vendor/github.com/gofrs/uuid/.gitignore b/vendor/github.com/gofrs/uuid/.gitignore new file mode 100644 index 000000000..666dbbb5b --- /dev/null +++ b/vendor/github.com/gofrs/uuid/.gitignore @@ -0,0 +1,15 @@ +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib + +# Test binary, build with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + +# binary bundle generated by go-fuzz +uuid-fuzz.zip diff --git a/vendor/github.com/gofrs/uuid/.travis.yml b/vendor/github.com/gofrs/uuid/.travis.yml new file mode 100644 index 000000000..ee1e4fa00 --- /dev/null +++ b/vendor/github.com/gofrs/uuid/.travis.yml @@ -0,0 +1,23 @@ +language: go +sudo: false +go: + - 1.7.x + - 1.8.x + - 1.9.x + - 1.10.x + - 1.11.x + - tip +matrix: + allow_failures: + - go: tip + fast_finish: true +env: + - GO111MODULE=on +before_install: + - go get golang.org/x/tools/cmd/cover +script: + - go test ./... -race -coverprofile=coverage.txt -covermode=atomic +after_success: + - bash <(curl -s https://codecov.io/bash) +notifications: + email: false diff --git a/vendor/github.com/gofrs/uuid/LICENSE b/vendor/github.com/gofrs/uuid/LICENSE new file mode 100644 index 000000000..926d54987 --- /dev/null +++ b/vendor/github.com/gofrs/uuid/LICENSE @@ -0,0 +1,20 @@ +Copyright (C) 2013-2018 by Maxim Bublis + +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. diff --git a/vendor/github.com/gofrs/uuid/README.md b/vendor/github.com/gofrs/uuid/README.md new file mode 100644 index 000000000..efc3204fc --- /dev/null +++ b/vendor/github.com/gofrs/uuid/README.md @@ -0,0 +1,109 @@ +# UUID + +[![License](https://img.shields.io/github/license/gofrs/uuid.svg)](https://github.com/gofrs/uuid/blob/master/LICENSE) +[![Build Status](https://travis-ci.org/gofrs/uuid.svg?branch=master)](https://travis-ci.org/gofrs/uuid) +[![GoDoc](http://godoc.org/github.com/gofrs/uuid?status.svg)](http://godoc.org/github.com/gofrs/uuid) +[![Coverage Status](https://codecov.io/gh/gofrs/uuid/branch/master/graphs/badge.svg?branch=master)](https://codecov.io/gh/gofrs/uuid/) +[![Go Report Card](https://goreportcard.com/badge/github.com/gofrs/uuid)](https://goreportcard.com/report/github.com/gofrs/uuid) + +Package uuid provides a pure Go implementation of Universally Unique Identifiers +(UUID) variant as defined in RFC-4122. This package supports both the creation +and parsing of UUIDs in different formats. + +This package supports the following UUID versions: +* Version 1, based on timestamp and MAC address (RFC-4122) +* Version 2, based on timestamp, MAC address and POSIX UID/GID (DCE 1.1) +* Version 3, based on MD5 hashing of a named value (RFC-4122) +* Version 4, based on random numbers (RFC-4122) +* Version 5, based on SHA-1 hashing of a named value (RFC-4122) + +## Project History + +This project was originally forked from the +[github.com/satori/go.uuid](https://github.com/satori/go.uuid) repository after +it appeared to be no longer maintained, while exhibiting [critical +flaws](https://github.com/satori/go.uuid/issues/73). We have decided to take +over this project to ensure it receives regular maintenance for the benefit of +the larger Go community. + +We'd like to thank Maxim Bublis for his hard work on the original iteration of +the package. + +## License + +This source code of this package is released under the MIT License. Please see +the [LICENSE](https://github.com/gofrs/uuid/blob/master/LICENSE) for the full +content of the license. + +## Recommended Package Version + +We recommend using v2.0.0+ of this package, as versions prior to 2.0.0 were +created before our fork of the original package and have some known +deficiencies. + +## Installation + +It is recommended to use a package manager like `dep` that understands tagged +releases of a package, as well as semantic versioning. + +If you are unable to make use of a dependency manager with your project, you can +use the `go get` command to download it directly: + +```Shell +$ go get github.com/gofrs/uuid +``` + +## Requirements + +Due to subtests not being supported in older versions of Go, this package is +only regularly tested against Go 1.7+. This package may work perfectly fine with +Go 1.2+, but support for these older versions is not actively maintained. + +## Go 1.11 Modules + +As of v3.2.0, this repository no longer adopts Go modules, and v3.2.0 no longer has a `go.mod` file. As a result, v3.2.0 also drops support for the `github.com/gofrs/uuid/v3` import path. Only module-based consumers are impacted. With the v3.2.0 release, _all_ gofrs/uuid consumers should use the `github.com/gofrs/uuid` import path. + +An existing module-based consumer will continue to be able to build using the `github.com/gofrs/uuid/v3` import path using any valid consumer `go.mod` that worked prior to the publishing of v3.2.0, but any module-based consumer should start using the `github.com/gofrs/uuid` import path when possible and _must_ use the `github.com/gofrs/uuid` import path prior to upgrading to v3.2.0. + +Please refer to [Issue #61](https://github.com/gofrs/uuid/issues/61) and [Issue #66](https://github.com/gofrs/uuid/issues/66) for more details. + +## Usage + +Here is a quick overview of how to use this package. For more detailed +documentation, please see the [GoDoc Page](http://godoc.org/github.com/gofrs/uuid). + +```go +package main + +import ( + "log" + + "github.com/gofrs/uuid" +) + +// Create a Version 4 UUID, panicking on error. +// Use this form to initialize package-level variables. +var u1 = uuid.Must(uuid.NewV4()) + +func main() { + // Create a Version 4 UUID. + u2, err := uuid.NewV4() + if err != nil { + log.Fatalf("failed to generate UUID: %v", err) + } + log.Printf("generated Version 4 UUID %v", u2) + + // Parse a UUID from a string. + s := "6ba7b810-9dad-11d1-80b4-00c04fd430c8" + u3, err := uuid.FromString(s) + if err != nil { + log.Fatalf("failed to parse UUID %q: %v", s, err) + } + log.Printf("successfully parsed UUID %v", u3) +} +``` + +## References + +* [RFC-4122](https://tools.ietf.org/html/rfc4122) +* [DCE 1.1: Authentication and Security Services](http://pubs.opengroup.org/onlinepubs/9696989899/chap5.htm#tagcjh_08_02_01_01) diff --git a/vendor/github.com/gofrs/uuid/codec.go b/vendor/github.com/gofrs/uuid/codec.go new file mode 100644 index 000000000..e3d8cfb4d --- /dev/null +++ b/vendor/github.com/gofrs/uuid/codec.go @@ -0,0 +1,212 @@ +// Copyright (C) 2013-2018 by Maxim Bublis +// +// 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. + +package uuid + +import ( + "bytes" + "encoding/hex" + "fmt" +) + +// FromBytes returns a UUID generated from the raw byte slice input. +// It will return an error if the slice isn't 16 bytes long. +func FromBytes(input []byte) (UUID, error) { + u := UUID{} + err := u.UnmarshalBinary(input) + return u, err +} + +// FromBytesOrNil returns a UUID generated from the raw byte slice input. +// Same behavior as FromBytes(), but returns uuid.Nil instead of an error. +func FromBytesOrNil(input []byte) UUID { + uuid, err := FromBytes(input) + if err != nil { + return Nil + } + return uuid +} + +// FromString returns a UUID parsed from the input string. +// Input is expected in a form accepted by UnmarshalText. +func FromString(input string) (UUID, error) { + u := UUID{} + err := u.UnmarshalText([]byte(input)) + return u, err +} + +// FromStringOrNil returns a UUID parsed from the input string. +// Same behavior as FromString(), but returns uuid.Nil instead of an error. +func FromStringOrNil(input string) UUID { + uuid, err := FromString(input) + if err != nil { + return Nil + } + return uuid +} + +// MarshalText implements the encoding.TextMarshaler interface. +// The encoding is the same as returned by the String() method. +func (u UUID) MarshalText() ([]byte, error) { + return []byte(u.String()), nil +} + +// UnmarshalText implements the encoding.TextUnmarshaler interface. +// Following formats are supported: +// +// "6ba7b810-9dad-11d1-80b4-00c04fd430c8", +// "{6ba7b810-9dad-11d1-80b4-00c04fd430c8}", +// "urn:uuid:6ba7b810-9dad-11d1-80b4-00c04fd430c8" +// "6ba7b8109dad11d180b400c04fd430c8" +// "{6ba7b8109dad11d180b400c04fd430c8}", +// "urn:uuid:6ba7b8109dad11d180b400c04fd430c8" +// +// ABNF for supported UUID text representation follows: +// +// URN := 'urn' +// UUID-NID := 'uuid' +// +// hexdig := '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' | +// 'a' | 'b' | 'c' | 'd' | 'e' | 'f' | +// 'A' | 'B' | 'C' | 'D' | 'E' | 'F' +// +// hexoct := hexdig hexdig +// 2hexoct := hexoct hexoct +// 4hexoct := 2hexoct 2hexoct +// 6hexoct := 4hexoct 2hexoct +// 12hexoct := 6hexoct 6hexoct +// +// hashlike := 12hexoct +// canonical := 4hexoct '-' 2hexoct '-' 2hexoct '-' 6hexoct +// +// plain := canonical | hashlike +// uuid := canonical | hashlike | braced | urn +// +// braced := '{' plain '}' | '{' hashlike '}' +// urn := URN ':' UUID-NID ':' plain +// +func (u *UUID) UnmarshalText(text []byte) error { + switch len(text) { + case 32: + return u.decodeHashLike(text) + case 34, 38: + return u.decodeBraced(text) + case 36: + return u.decodeCanonical(text) + case 41, 45: + return u.decodeURN(text) + default: + return fmt.Errorf("uuid: incorrect UUID length: %s", text) + } +} + +// decodeCanonical decodes UUID strings that are formatted as defined in RFC-4122 (section 3): +// "6ba7b810-9dad-11d1-80b4-00c04fd430c8". +func (u *UUID) decodeCanonical(t []byte) error { + if t[8] != '-' || t[13] != '-' || t[18] != '-' || t[23] != '-' { + return fmt.Errorf("uuid: incorrect UUID format %s", t) + } + + src := t + dst := u[:] + + for i, byteGroup := range byteGroups { + if i > 0 { + src = src[1:] // skip dash + } + _, err := hex.Decode(dst[:byteGroup/2], src[:byteGroup]) + if err != nil { + return err + } + src = src[byteGroup:] + dst = dst[byteGroup/2:] + } + + return nil +} + +// decodeHashLike decodes UUID strings that are using the following format: +// "6ba7b8109dad11d180b400c04fd430c8". +func (u *UUID) decodeHashLike(t []byte) error { + src := t[:] + dst := u[:] + + _, err := hex.Decode(dst, src) + return err +} + +// decodeBraced decodes UUID strings that are using the following formats: +// "{6ba7b810-9dad-11d1-80b4-00c04fd430c8}" +// "{6ba7b8109dad11d180b400c04fd430c8}". +func (u *UUID) decodeBraced(t []byte) error { + l := len(t) + + if t[0] != '{' || t[l-1] != '}' { + return fmt.Errorf("uuid: incorrect UUID format %s", t) + } + + return u.decodePlain(t[1 : l-1]) +} + +// decodeURN decodes UUID strings that are using the following formats: +// "urn:uuid:6ba7b810-9dad-11d1-80b4-00c04fd430c8" +// "urn:uuid:6ba7b8109dad11d180b400c04fd430c8". +func (u *UUID) decodeURN(t []byte) error { + total := len(t) + + urnUUIDPrefix := t[:9] + + if !bytes.Equal(urnUUIDPrefix, urnPrefix) { + return fmt.Errorf("uuid: incorrect UUID format: %s", t) + } + + return u.decodePlain(t[9:total]) +} + +// decodePlain decodes UUID strings that are using the following formats: +// "6ba7b810-9dad-11d1-80b4-00c04fd430c8" or in hash-like format +// "6ba7b8109dad11d180b400c04fd430c8". +func (u *UUID) decodePlain(t []byte) error { + switch len(t) { + case 32: + return u.decodeHashLike(t) + case 36: + return u.decodeCanonical(t) + default: + return fmt.Errorf("uuid: incorrect UUID length: %s", t) + } +} + +// MarshalBinary implements the encoding.BinaryMarshaler interface. +func (u UUID) MarshalBinary() ([]byte, error) { + return u.Bytes(), nil +} + +// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface. +// It will return an error if the slice isn't 16 bytes long. +func (u *UUID) UnmarshalBinary(data []byte) error { + if len(data) != Size { + return fmt.Errorf("uuid: UUID must be exactly 16 bytes long, got %d bytes", len(data)) + } + copy(u[:], data) + + return nil +} diff --git a/vendor/github.com/gofrs/uuid/fuzz.go b/vendor/github.com/gofrs/uuid/fuzz.go new file mode 100644 index 000000000..afaefbc8e --- /dev/null +++ b/vendor/github.com/gofrs/uuid/fuzz.go @@ -0,0 +1,47 @@ +// Copyright (c) 2018 Andrei Tudor Călin +// +// 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. + +// +build gofuzz + +package uuid + +// Fuzz implements a simple fuzz test for FromString / UnmarshalText. +// +// To run: +// +// $ go get github.com/dvyukov/go-fuzz/... +// $ cd $GOPATH/src/github.com/gofrs/uuid +// $ go-fuzz-build github.com/gofrs/uuid +// $ go-fuzz -bin=uuid-fuzz.zip -workdir=./testdata +// +// If you make significant changes to FromString / UnmarshalText and add +// new cases to fromStringTests (in codec_test.go), please run +// +// $ go test -seed_fuzz_corpus +// +// to seed the corpus with the new interesting inputs, then run the fuzzer. +func Fuzz(data []byte) int { + _, err := FromString(string(data)) + if err != nil { + return 0 + } + return 1 +} diff --git a/vendor/github.com/gofrs/uuid/generator.go b/vendor/github.com/gofrs/uuid/generator.go new file mode 100644 index 000000000..4257761f1 --- /dev/null +++ b/vendor/github.com/gofrs/uuid/generator.go @@ -0,0 +1,299 @@ +// Copyright (C) 2013-2018 by Maxim Bublis +// +// 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. + +package uuid + +import ( + "crypto/md5" + "crypto/rand" + "crypto/sha1" + "encoding/binary" + "fmt" + "hash" + "io" + "net" + "os" + "sync" + "time" +) + +// Difference in 100-nanosecond intervals between +// UUID epoch (October 15, 1582) and Unix epoch (January 1, 1970). +const epochStart = 122192928000000000 + +type epochFunc func() time.Time + +// HWAddrFunc is the function type used to provide hardware (MAC) addresses. +type HWAddrFunc func() (net.HardwareAddr, error) + +// DefaultGenerator is the default UUID Generator used by this package. +var DefaultGenerator Generator = NewGen() + +var ( + posixUID = uint32(os.Getuid()) + posixGID = uint32(os.Getgid()) +) + +// NewV1 returns a UUID based on the current timestamp and MAC address. +func NewV1() (UUID, error) { + return DefaultGenerator.NewV1() +} + +// NewV2 returns a DCE Security UUID based on the POSIX UID/GID. +func NewV2(domain byte) (UUID, error) { + return DefaultGenerator.NewV2(domain) +} + +// NewV3 returns a UUID based on the MD5 hash of the namespace UUID and name. +func NewV3(ns UUID, name string) UUID { + return DefaultGenerator.NewV3(ns, name) +} + +// NewV4 returns a randomly generated UUID. +func NewV4() (UUID, error) { + return DefaultGenerator.NewV4() +} + +// NewV5 returns a UUID based on SHA-1 hash of the namespace UUID and name. +func NewV5(ns UUID, name string) UUID { + return DefaultGenerator.NewV5(ns, name) +} + +// Generator provides an interface for generating UUIDs. +type Generator interface { + NewV1() (UUID, error) + NewV2(domain byte) (UUID, error) + NewV3(ns UUID, name string) UUID + NewV4() (UUID, error) + NewV5(ns UUID, name string) UUID +} + +// Gen is a reference UUID generator based on the specifications laid out in +// RFC-4122 and DCE 1.1: Authentication and Security Services. This type +// satisfies the Generator interface as defined in this package. +// +// For consumers who are generating V1 UUIDs, but don't want to expose the MAC +// address of the node generating the UUIDs, the NewGenWithHWAF() function has been +// provided as a convenience. See the function's documentation for more info. +// +// The authors of this package do not feel that the majority of users will need +// to obfuscate their MAC address, and so we recommend using NewGen() to create +// a new generator. +type Gen struct { + clockSequenceOnce sync.Once + hardwareAddrOnce sync.Once + storageMutex sync.Mutex + + rand io.Reader + + epochFunc epochFunc + hwAddrFunc HWAddrFunc + lastTime uint64 + clockSequence uint16 + hardwareAddr [6]byte +} + +// interface check -- build will fail if *Gen doesn't satisfy Generator +var _ Generator = (*Gen)(nil) + +// NewGen returns a new instance of Gen with some default values set. Most +// people should use this. +func NewGen() *Gen { + return NewGenWithHWAF(defaultHWAddrFunc) +} + +// NewGenWithHWAF builds a new UUID generator with the HWAddrFunc provided. Most +// consumers should use NewGen() instead. +// +// This is used so that consumers can generate their own MAC addresses, for use +// in the generated UUIDs, if there is some concern about exposing the physical +// address of the machine generating the UUID. +// +// The Gen generator will only invoke the HWAddrFunc once, and cache that MAC +// address for all the future UUIDs generated by it. If you'd like to switch the +// MAC address being used, you'll need to create a new generator using this +// function. +func NewGenWithHWAF(hwaf HWAddrFunc) *Gen { + return &Gen{ + epochFunc: time.Now, + hwAddrFunc: hwaf, + rand: rand.Reader, + } +} + +// NewV1 returns a UUID based on the current timestamp and MAC address. +func (g *Gen) NewV1() (UUID, error) { + u := UUID{} + + timeNow, clockSeq, err := g.getClockSequence() + if err != nil { + return Nil, err + } + binary.BigEndian.PutUint32(u[0:], uint32(timeNow)) + binary.BigEndian.PutUint16(u[4:], uint16(timeNow>>32)) + binary.BigEndian.PutUint16(u[6:], uint16(timeNow>>48)) + binary.BigEndian.PutUint16(u[8:], clockSeq) + + hardwareAddr, err := g.getHardwareAddr() + if err != nil { + return Nil, err + } + copy(u[10:], hardwareAddr) + + u.SetVersion(V1) + u.SetVariant(VariantRFC4122) + + return u, nil +} + +// NewV2 returns a DCE Security UUID based on the POSIX UID/GID. +func (g *Gen) NewV2(domain byte) (UUID, error) { + u, err := g.NewV1() + if err != nil { + return Nil, err + } + + switch domain { + case DomainPerson: + binary.BigEndian.PutUint32(u[:], posixUID) + case DomainGroup: + binary.BigEndian.PutUint32(u[:], posixGID) + } + + u[9] = domain + + u.SetVersion(V2) + u.SetVariant(VariantRFC4122) + + return u, nil +} + +// NewV3 returns a UUID based on the MD5 hash of the namespace UUID and name. +func (g *Gen) NewV3(ns UUID, name string) UUID { + u := newFromHash(md5.New(), ns, name) + u.SetVersion(V3) + u.SetVariant(VariantRFC4122) + + return u +} + +// NewV4 returns a randomly generated UUID. +func (g *Gen) NewV4() (UUID, error) { + u := UUID{} + if _, err := io.ReadFull(g.rand, u[:]); err != nil { + return Nil, err + } + u.SetVersion(V4) + u.SetVariant(VariantRFC4122) + + return u, nil +} + +// NewV5 returns a UUID based on SHA-1 hash of the namespace UUID and name. +func (g *Gen) NewV5(ns UUID, name string) UUID { + u := newFromHash(sha1.New(), ns, name) + u.SetVersion(V5) + u.SetVariant(VariantRFC4122) + + return u +} + +// Returns the epoch and clock sequence. +func (g *Gen) getClockSequence() (uint64, uint16, error) { + var err error + g.clockSequenceOnce.Do(func() { + buf := make([]byte, 2) + if _, err = io.ReadFull(g.rand, buf); err != nil { + return + } + g.clockSequence = binary.BigEndian.Uint16(buf) + }) + if err != nil { + return 0, 0, err + } + + g.storageMutex.Lock() + defer g.storageMutex.Unlock() + + timeNow := g.getEpoch() + // Clock didn't change since last UUID generation. + // Should increase clock sequence. + if timeNow <= g.lastTime { + g.clockSequence++ + } + g.lastTime = timeNow + + return timeNow, g.clockSequence, nil +} + +// Returns the hardware address. +func (g *Gen) getHardwareAddr() ([]byte, error) { + var err error + g.hardwareAddrOnce.Do(func() { + var hwAddr net.HardwareAddr + if hwAddr, err = g.hwAddrFunc(); err == nil { + copy(g.hardwareAddr[:], hwAddr) + return + } + + // Initialize hardwareAddr randomly in case + // of real network interfaces absence. + if _, err = io.ReadFull(g.rand, g.hardwareAddr[:]); err != nil { + return + } + // Set multicast bit as recommended by RFC-4122 + g.hardwareAddr[0] |= 0x01 + }) + if err != nil { + return []byte{}, err + } + return g.hardwareAddr[:], nil +} + +// Returns the difference between UUID epoch (October 15, 1582) +// and current time in 100-nanosecond intervals. +func (g *Gen) getEpoch() uint64 { + return epochStart + uint64(g.epochFunc().UnixNano()/100) +} + +// Returns the UUID based on the hashing of the namespace UUID and name. +func newFromHash(h hash.Hash, ns UUID, name string) UUID { + u := UUID{} + h.Write(ns[:]) + h.Write([]byte(name)) + copy(u[:], h.Sum(nil)) + + return u +} + +// Returns the hardware address. +func defaultHWAddrFunc() (net.HardwareAddr, error) { + ifaces, err := net.Interfaces() + if err != nil { + return []byte{}, err + } + for _, iface := range ifaces { + if len(iface.HardwareAddr) >= 6 { + return iface.HardwareAddr, nil + } + } + return []byte{}, fmt.Errorf("uuid: no HW address found") +} diff --git a/vendor/github.com/gofrs/uuid/sql.go b/vendor/github.com/gofrs/uuid/sql.go new file mode 100644 index 000000000..6f254a4fd --- /dev/null +++ b/vendor/github.com/gofrs/uuid/sql.go @@ -0,0 +1,109 @@ +// Copyright (C) 2013-2018 by Maxim Bublis +// +// 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. + +package uuid + +import ( + "bytes" + "database/sql/driver" + "encoding/json" + "fmt" +) + +// Value implements the driver.Valuer interface. +func (u UUID) Value() (driver.Value, error) { + return u.String(), nil +} + +// Scan implements the sql.Scanner interface. +// A 16-byte slice will be handled by UnmarshalBinary, while +// a longer byte slice or a string will be handled by UnmarshalText. +func (u *UUID) Scan(src interface{}) error { + switch src := src.(type) { + case UUID: // support gorm convert from UUID to NullUUID + *u = src + return nil + + case []byte: + if len(src) == Size { + return u.UnmarshalBinary(src) + } + return u.UnmarshalText(src) + + case string: + return u.UnmarshalText([]byte(src)) + } + + return fmt.Errorf("uuid: cannot convert %T to UUID", src) +} + +// NullUUID can be used with the standard sql package to represent a +// UUID value that can be NULL in the database. +type NullUUID struct { + UUID UUID + Valid bool +} + +// Value implements the driver.Valuer interface. +func (u NullUUID) Value() (driver.Value, error) { + if !u.Valid { + return nil, nil + } + // Delegate to UUID Value function + return u.UUID.Value() +} + +// Scan implements the sql.Scanner interface. +func (u *NullUUID) Scan(src interface{}) error { + if src == nil { + u.UUID, u.Valid = Nil, false + return nil + } + + // Delegate to UUID Scan function + u.Valid = true + return u.UUID.Scan(src) +} + +// MarshalJSON marshals the NullUUID as null or the nested UUID +func (u NullUUID) MarshalJSON() ([]byte, error) { + if !u.Valid { + return json.Marshal(nil) + } + + return json.Marshal(u.UUID) +} + +// UnmarshalJSON unmarshals a NullUUID +func (u *NullUUID) UnmarshalJSON(b []byte) error { + if bytes.Equal(b, []byte("null")) { + u.UUID, u.Valid = Nil, false + return nil + } + + if err := json.Unmarshal(b, &u.UUID); err != nil { + return err + } + + u.Valid = true + + return nil +} diff --git a/vendor/github.com/gofrs/uuid/uuid.go b/vendor/github.com/gofrs/uuid/uuid.go new file mode 100644 index 000000000..29ef44059 --- /dev/null +++ b/vendor/github.com/gofrs/uuid/uuid.go @@ -0,0 +1,189 @@ +// Copyright (C) 2013-2018 by Maxim Bublis +// +// 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. + +// Package uuid provides implementations of the Universally Unique Identifier (UUID), as specified in RFC-4122 and DCE 1.1. +// +// RFC-4122[1] provides the specification for versions 1, 3, 4, and 5. +// +// DCE 1.1[2] provides the specification for version 2. +// +// [1] https://tools.ietf.org/html/rfc4122 +// [2] http://pubs.opengroup.org/onlinepubs/9696989899/chap5.htm#tagcjh_08_02_01_01 +package uuid + +import ( + "encoding/binary" + "encoding/hex" + "fmt" + "time" +) + +// Size of a UUID in bytes. +const Size = 16 + +// UUID is an array type to represent the value of a UUID, as defined in RFC-4122. +type UUID [Size]byte + +// UUID versions. +const ( + _ byte = iota + V1 // Version 1 (date-time and MAC address) + V2 // Version 2 (date-time and MAC address, DCE security version) + V3 // Version 3 (namespace name-based) + V4 // Version 4 (random) + V5 // Version 5 (namespace name-based) +) + +// UUID layout variants. +const ( + VariantNCS byte = iota + VariantRFC4122 + VariantMicrosoft + VariantFuture +) + +// UUID DCE domains. +const ( + DomainPerson = iota + DomainGroup + DomainOrg +) + +// Timestamp is the count of 100-nanosecond intervals since 00:00:00.00, +// 15 October 1582 within a V1 UUID. This type has no meaning for V2-V5 +// UUIDs since they don't have an embedded timestamp. +type Timestamp uint64 + +const _100nsPerSecond = 10000000 + +// Time returns the UTC time.Time representation of a Timestamp +func (t Timestamp) Time() (time.Time, error) { + secs := uint64(t) / _100nsPerSecond + nsecs := 100 * (uint64(t) % _100nsPerSecond) + return time.Unix(int64(secs)-(epochStart/_100nsPerSecond), int64(nsecs)), nil +} + +// TimestampFromV1 returns the Timestamp embedded within a V1 UUID. +// Returns an error if the UUID is any version other than 1. +func TimestampFromV1(u UUID) (Timestamp, error) { + if u.Version() != 1 { + err := fmt.Errorf("uuid: %s is version %d, not version 1", u, u.Version()) + return 0, err + } + low := binary.BigEndian.Uint32(u[0:4]) + mid := binary.BigEndian.Uint16(u[4:6]) + hi := binary.BigEndian.Uint16(u[6:8]) & 0xfff + return Timestamp(uint64(low) + (uint64(mid) << 32) + (uint64(hi) << 48)), nil +} + +// String parse helpers. +var ( + urnPrefix = []byte("urn:uuid:") + byteGroups = []int{8, 4, 4, 4, 12} +) + +// Nil is the nil UUID, as specified in RFC-4122, that has all 128 bits set to +// zero. +var Nil = UUID{} + +// Predefined namespace UUIDs. +var ( + NamespaceDNS = Must(FromString("6ba7b810-9dad-11d1-80b4-00c04fd430c8")) + NamespaceURL = Must(FromString("6ba7b811-9dad-11d1-80b4-00c04fd430c8")) + NamespaceOID = Must(FromString("6ba7b812-9dad-11d1-80b4-00c04fd430c8")) + NamespaceX500 = Must(FromString("6ba7b814-9dad-11d1-80b4-00c04fd430c8")) +) + +// Version returns the algorithm version used to generate the UUID. +func (u UUID) Version() byte { + return u[6] >> 4 +} + +// Variant returns the UUID layout variant. +func (u UUID) Variant() byte { + switch { + case (u[8] >> 7) == 0x00: + return VariantNCS + case (u[8] >> 6) == 0x02: + return VariantRFC4122 + case (u[8] >> 5) == 0x06: + return VariantMicrosoft + case (u[8] >> 5) == 0x07: + fallthrough + default: + return VariantFuture + } +} + +// Bytes returns a byte slice representation of the UUID. +func (u UUID) Bytes() []byte { + return u[:] +} + +// String returns a canonical RFC-4122 string representation of the UUID: +// xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx. +func (u UUID) String() string { + buf := make([]byte, 36) + + hex.Encode(buf[0:8], u[0:4]) + buf[8] = '-' + hex.Encode(buf[9:13], u[4:6]) + buf[13] = '-' + hex.Encode(buf[14:18], u[6:8]) + buf[18] = '-' + hex.Encode(buf[19:23], u[8:10]) + buf[23] = '-' + hex.Encode(buf[24:], u[10:]) + + return string(buf) +} + +// SetVersion sets the version bits. +func (u *UUID) SetVersion(v byte) { + u[6] = (u[6] & 0x0f) | (v << 4) +} + +// SetVariant sets the variant bits. +func (u *UUID) SetVariant(v byte) { + switch v { + case VariantNCS: + u[8] = (u[8]&(0xff>>1) | (0x00 << 7)) + case VariantRFC4122: + u[8] = (u[8]&(0xff>>2) | (0x02 << 6)) + case VariantMicrosoft: + u[8] = (u[8]&(0xff>>3) | (0x06 << 5)) + case VariantFuture: + fallthrough + default: + u[8] = (u[8]&(0xff>>3) | (0x07 << 5)) + } +} + +// Must is a helper that wraps a call to a function returning (UUID, error) +// and panics if the error is non-nil. It is intended for use in variable +// initializations such as +// var packageUUID = uuid.Must(uuid.FromString("123e4567-e89b-12d3-a456-426655440000")) +func Must(u UUID, err error) UUID { + if err != nil { + panic(err) + } + return u +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 9a8d00914..fdf63599e 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -79,7 +79,7 @@ github.com/digitalocean/godo github.com/dimchansky/utfbom # github.com/dnsimple/dnsimple-go v0.31.0 github.com/dnsimple/dnsimple-go/dnsimple -# github.com/exoscale/egoscale v0.10.5 +# github.com/exoscale/egoscale v0.23.0 github.com/exoscale/egoscale # github.com/go-acme/lego v2.7.2+incompatible github.com/go-acme/lego/acme @@ -107,6 +107,8 @@ github.com/gobwas/glob/syntax/ast github.com/gobwas/glob/syntax/lexer github.com/gobwas/glob/util/runes github.com/gobwas/glob/util/strings +# github.com/gofrs/uuid v3.2.0+incompatible +github.com/gofrs/uuid # github.com/golang/protobuf v1.3.3 github.com/golang/protobuf/proto github.com/golang/protobuf/ptypes