fixup! Remove "exoscale-import" post-processor

This commit is contained in:
Marc Falzon 2020-08-10 08:41:43 +02:00 committed by Wilken Rivera
parent 125a2f1f76
commit 9a1f2d0c97
83 changed files with 1 additions and 8224 deletions

1
go.mod
View File

@ -25,7 +25,6 @@ require (
github.com/dgrijalva/jwt-go v3.2.0+incompatible github.com/dgrijalva/jwt-go v3.2.0+incompatible
github.com/digitalocean/go-qemu v0.0.0-20201211181942-d361e7b4965f github.com/digitalocean/go-qemu v0.0.0-20201211181942-d361e7b4965f
github.com/digitalocean/godo v1.11.1 github.com/digitalocean/godo v1.11.1
github.com/exoscale/egoscale v0.18.1
github.com/fatih/camelcase v1.0.0 github.com/fatih/camelcase v1.0.0
github.com/fatih/structtag v1.0.0 github.com/fatih/structtag v1.0.0
github.com/go-ini/ini v1.25.4 github.com/go-ini/ini v1.25.4

2
go.sum
View File

@ -176,7 +176,6 @@ github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymF
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/exoscale/egoscale v0.18.1 h1:1FNZVk8jHUx0AvWhOZxLEDNlacTU0chMXUUNkm9EZaI=
github.com/exoscale/egoscale v0.18.1/go.mod h1:Z7OOdzzTOz1Q1PjQXumlz9Wn/CddH0zSYdCF3rnBKXE= github.com/exoscale/egoscale v0.18.1/go.mod h1:Z7OOdzzTOz1Q1PjQXumlz9Wn/CddH0zSYdCF3rnBKXE=
github.com/fatih/camelcase v1.0.0 h1:hxNvNX/xYBp0ovncs8WyWZrOrpBNub/JfaMvbURyft8= github.com/fatih/camelcase v1.0.0 h1:hxNvNX/xYBp0ovncs8WyWZrOrpBNub/JfaMvbURyft8=
github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc= github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc=
@ -381,7 +380,6 @@ github.com/hashicorp/packer v1.6.7-0.20210217093213-201869d627bf/go.mod h1:+EWPP
github.com/hashicorp/packer-plugin-docker v0.0.2 h1:j/hQTogaN2pZfZohlZTRu5YvNZg2/qtYYHkxPBxv2Oo= github.com/hashicorp/packer-plugin-docker v0.0.2 h1:j/hQTogaN2pZfZohlZTRu5YvNZg2/qtYYHkxPBxv2Oo=
github.com/hashicorp/packer-plugin-docker v0.0.2/go.mod h1:A2p9qztS4n88KsNF+qBM7BWw2HndW636GpFIjNSvbKM= github.com/hashicorp/packer-plugin-docker v0.0.2/go.mod h1:A2p9qztS4n88KsNF+qBM7BWw2HndW636GpFIjNSvbKM=
github.com/hashicorp/packer-plugin-sdk v0.0.6/go.mod h1:Nvh28f+Jmpp2rcaN79bULTouNkGNDRfHckhHKTAXtyU= github.com/hashicorp/packer-plugin-sdk v0.0.6/go.mod h1:Nvh28f+Jmpp2rcaN79bULTouNkGNDRfHckhHKTAXtyU=
github.com/hashicorp/packer-plugin-sdk v0.0.6/go.mod h1:Nvh28f+Jmpp2rcaN79bULTouNkGNDRfHckhHKTAXtyU=
github.com/hashicorp/packer-plugin-sdk v0.0.7-0.20210111224258-fd30ebb797f0/go.mod h1:YdWTt5w6cYfaQG7IOi5iorL+3SXnz8hI0gJCi8Db/LI= github.com/hashicorp/packer-plugin-sdk v0.0.7-0.20210111224258-fd30ebb797f0/go.mod h1:YdWTt5w6cYfaQG7IOi5iorL+3SXnz8hI0gJCi8Db/LI=
github.com/hashicorp/packer-plugin-sdk v0.0.7-0.20210120105339-f6fd68d2570a/go.mod h1:exN0C+Pe+3zu18l4nxueNjX5cfmslxUX/m/xk4IVmZQ= github.com/hashicorp/packer-plugin-sdk v0.0.7-0.20210120105339-f6fd68d2570a/go.mod h1:exN0C+Pe+3zu18l4nxueNjX5cfmslxUX/m/xk4IVmZQ=
github.com/hashicorp/packer-plugin-sdk v0.0.7-0.20210122130548-45a6ca0a9365/go.mod h1:K7VsU0lfJBDyiUrSNnS/j+zMxSRwwH9WC9QvHv32KsU= github.com/hashicorp/packer-plugin-sdk v0.0.7-0.20210122130548-45a6ca0a9365/go.mod h1:K7VsU0lfJBDyiUrSNnS/j+zMxSRwwH9WC9QvHv32KsU=

View File

@ -1,31 +0,0 @@
version: "2"
checks:
argument-count:
enabled: false
complex-logic:
enabled: false
file-lines:
enabled: false
method-complexity:
enabled: false
method-count:
enabled: false
method-lines:
enabled: false
nested-control-flow:
enabled: false
return-statements:
enabled: false
similar-code:
enabled: false
identical-code:
enabled: false
plugins:
gofmt:
enabled: true
golint:
enabled: true
govet:
enabled: true

View File

@ -1,5 +0,0 @@
.token
dist
ops.asc
vendor
listApis.json

View File

@ -1,27 +0,0 @@
linters-settings:
golint:
min-confidence: 0.3
gocyclo:
min-complexity: 28
goimports:
local-prefixes: github.com
linters:
enable:
- deadcode
- dupl
- errcheck
- gocyclo
- goimports
- golint
- gosimple
- govet
- ineffassign
- megacheck
- nakedret
- scopelint
- staticcheck
- structcheck
- unused
- varcheck
disable-all: true

View File

@ -1,25 +0,0 @@
{
"Test": false,
"Enable": [
"deadcode",
"errcheck",
"golint",
"gosimple",
"gotype",
"ineffassign",
"interfacer",
"misspell",
"structcheck",
"unconvert",
"varcheck",
"vet",
"vetshadow"
],
"Disable": [
"goconst",
"gocyclo",
"gosec",
"maligned"
],
"Skip": ["vendor"]
}

View File

@ -1,49 +0,0 @@
language: go
dist: xenial
sudo: required
go:
- "1.7.x"
- "1.8.x"
- "1.9.x"
- "1.10.x"
- "1.11.x"
- "1.12.x"
- tip
env:
- GOLANGCI_LINT_VERSION=1.15.0 GO111MODULES=on
cache: apt
addons:
apt:
update: true
packages:
- rpm
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" | perl -pe "s/\\.[x\\d]+$//")" = "1.11" ] && go mod vendor || go get -u github.com/gofrs/uuid'
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: golangci-lint
go: 1.10.x
if: type = pull_request
script:
- go get -u github.com/gofrs/uuid
- golangci-lint run .

View File

@ -1,9 +0,0 @@
Pierre-Yves Ritschard
Vincent Bernat
Chris Baumbauer
Marc-Aurèle Brothier
Sebastien Goasguen
Yoan Blanc
Stefano Marengo
Pierre-Emmanuel Jacquier
Fabrizio Steiner

View File

@ -1,457 +0,0 @@
Changelog
=========
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`
- feat: `Client.TraceOn`/`ClientTraceOff` to toggle the HTTP tracing
0.10.4
------
- feat: `CIDR` to replace string string
- fix: prevent panic on nil
0.10.3
------
- feat: `Account` is Listable
- feat: `MACAddress` to replace string type
- fix: Go 1.7 support
0.10.2
------
- fix: ActivateIP6 response
0.10.1
------
- feat: expose `SyncRequest` and `SyncRequestWithContext`
- feat: addition of reverse DNS calls
- feat: addition of `SecurityGroup.UserSecurityGroup`
0.10.0
------
- global: cloudstack documentation links are moved into cs
- global: removal of all the `...Response` types
- feat: `Network` is `Listable`
- feat: addition of `deleteUser`
- feat: addition of `listHosts`
- feat: addition of `updateHost`
- feat: exo cmd (kudos to @pierre-emmanuelJ)
- change: refactor `Gettable` to use `ListRequest`
0.9.31
------
- fix: `IPAddress`.`ListRequest` with boolean fields
- fix: `Network`.`ListRequest` with boolean fields
- fix: `ServiceOffering`.`ListRequest` with boolean fields
0.9.30
------
- fix: `VirtualMachine` `PCIDevice` representation was incomplete
0.9.29
------
- change: `DNSErrorResponse` is a proper `error`
0.9.28
------
- feat: addition of `GetDomains`
- fix: `UpdateDomain` may contain more empty fields than `CreateDomain`
0.9.27
------
- fix: expects body to be `application/json`
0.9.26
------
- change: async timeout strategy wait two seconds and not fib(n) seconds
0.9.25
------
- fix: `GetVirtualUserData` response with `Decode` method handling base64 and gzip
0.9.24
------
- feat: `Template` is `Gettable`
- feat: `ServiceOffering` is `Gettable`
- feat: addition of `GetAPILimit`
- feat: addition of `CreateTemplate`, `PrepareTemplate`, `CopyTemplate`, `UpdateTemplate`, `RegisterTemplate`
- feat: addition of `MigrateVirtualMachine`
- feat: cmd cli
- change: remove useless fields related to Project and VPC
0.9.23
------
- feat: `booleanResponse` supports true booleans: https://github.com/apache/cloudstack/pull/2428
0.9.22
------
- feat: `ListUsers`, `CreateUser`, `UpdateUser`
- feat: `ListResourceDetails`
- feat: `SecurityGroup` helper `RuleByID`
- feat: `Sign` signs the payload
- feat: `UpdateNetworkOffering`
- feat: `GetVirtualMachineUserData`
- feat: `EnableAccount` and `DisableAccount` (admin stuff)
- feat: `AsyncRequest` and `AsyncRequestWithContext` to examine the polling
- fix: `AuthorizeSecurityGroupIngress` support for ICMPv6
- change: move `APIName()` into the `Client`, nice godoc
- change: `Payload` doesn't sign the request anymore
- change: `Client` exposes more of its underlying data
- change: requests are sent as GET unless it body size is too big
0.9.21
------
- feat: `Network` is `Listable`
- feat: `Zone` is `Gettable`
- feat: `Client.Payload` to help preview the HTTP parameters
- feat: generate command utility
- fix: `CreateSnapshot` was missing the `Name` attribute
- fix: `ListSnapshots` was missing the `IDs` attribute
- fix: `ListZones` was missing the `NetworkType` attribute
- fix: `ListAsyncJobs` was missing the `ListAll` attribute
- change: ICMP Type/Code are uint8 and TCP/UDP port are uint16
0.9.20
------
- feat: `Template` is `Listable`
- feat: `IPAddress` is `Listable`
- change: `List` and `Paginate` return pointers
- fix: `Template` was missing `tags`
0.9.19
------
- feat: `SSHKeyPair` is `Listable`
0.9.18
------
- feat: `VirtualMachine` is `Listable`
- feat: new `Client.Paginate` and `Client.PaginateWithContext`
- change: the inner logic of `Listable`
- remove: not working `Client.AsyncList`
0.9.17
------
- fix: `AuthorizeSecurityGroup(In|E)gress` startport may be zero
0.9.16
------
- feat: new `Listable` interface
- feat: `Nic` is `Listable`
- feat: `Volume` is `Listable`
- feat: `Zone` is `Listable`
- feat: `AffinityGroup` is `Listable`
- remove: deprecated methods `ListNics`, `AddIPToNic`, and `RemoveIPFromNic`
- remove: deprecated method `GetRootVolumeForVirtualMachine`
0.9.15
------
- feat: `IPAddress` is `Gettable` and `Deletable`
- fix: serialization of *bool
0.9.14
------
- fix: `GetVMPassword` response
- remove: deprecated `GetTopology`, `GetImages`, and al
0.9.13
------
- feat: IP4 and IP6 flags to DeployVirtualMachine
- feat: add ActivateIP6
- fix: error message was gobbled on 40x
0.9.12
------
- feat: add `BooleanRequestWithContext`
- feat: add `client.Get`, `client.GetWithContext` to fetch a resource
- feat: add `cleint.Delete`, `client.DeleteWithContext` to delete a resource
- feat: `SSHKeyPair` is `Gettable` and `Deletable`
- feat: `VirtualMachine` is `Gettable` and `Deletable`
- feat: `AffinityGroup` is `Gettable` and `Deletable`
- feat: `SecurityGroup` is `Gettable` and `Deletable`
- remove: deprecated methods `CreateAffinityGroup`, `DeleteAffinityGroup`
- remove: deprecated methods `CreateKeypair`, `DeleteKeypair`, `RegisterKeypair`
- remove: deprecated method `GetSecurityGroupID`
0.9.11
------
- feat: CloudStack API name is now public `APIName()`
- feat: enforce the mutual exclusivity of some fields
- feat: add `context.Context` to `RequestWithContext`
- change: `AsyncRequest` and `BooleanAsyncRequest` are gone, use `Request` and `BooleanRequest` instead.
- change: `AsyncInfo` is no more
0.9.10
------
- fix: typo made ListAll required in ListPublicIPAddresses
- fix: all bool are now *bool, respecting CS default value
- feat: (*VM).DefaultNic() to obtain the main Nic
0.9.9
-----
- fix: affinity groups virtualmachineIds attribute
- fix: uuidList is not a list of strings
0.9.8
-----
- feat: add RootDiskSize to RestoreVirtualMachine
- fix: monotonic polling using Context
0.9.7
-----
- feat: add Taggable interface to expose ResourceType
- feat: add (Create|Update|Delete|List)InstanceGroup(s)
- feat: add RegisterUserKeys
- feat: add ListResourceLimits
- feat: add ListAccounts
0.9.6
-----
- fix: update UpdateVirtualMachine userdata
- fix: Network's name/displaytext might be empty
0.9.5
-----
- fix: serialization of slice
0.9.4
-----
- fix: constants
0.9.3
-----
- change: userdata expects a string
- change: no pointer in sub-struct's
0.9.2
-----
- bug: createNetwork is a sync call
- bug: typo in listVirtualMachines' domainid
- bug: serialization of map[string], e.g. UpdateVirtualMachine
- change: IPAddress's use net.IP type
- feat: helpers VM.NicsByType, VM.NicByNetworkID, VM.NicByID
- feat: addition of CloudStack ApiErrorCode constants
0.9.1
-----
- bug: sync calls returns succes as a string rather than a bool
- change: unexport BooleanResponse types
- feat: original CloudStack error response can be obtained
0.9.0
-----
Big refactoring, addition of the documentation, compliance to golint.
0.1.0
-----
Initial library

View File

@ -1,201 +0,0 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2014 exoscale(tm)
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@ -1,27 +0,0 @@
---
title: Egoscale
description: the Go library for Exoscale
---
<a href="https://gopherize.me/gopher/9c1bc7cfe1d84cf43e477dbfc4aa86332065f1fd"><img src="gopher.png" align="right" alt=""></a>
[![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)
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
may not use this file except in compliance with the License. You may
obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0

View File

@ -1,80 +0,0 @@
package egoscale
// Account provides the detailed account information
type Account struct {
AccountDetails map[string]string `json:"accountdetails,omitempty" doc:"details for the account"`
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 *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 *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"`
IsCleanupRequired bool `json:"iscleanuprequired,omitempty" doc:"true if the account requires cleanup"`
IsDefault bool `json:"isdefault,omitempty" doc:"true if account is default, false otherwise"`
MemoryAvailable string `json:"memoryavailable,omitempty" doc:"the total memory (in MB) available to be created for this account"`
MemoryLimit string `json:"memorylimit,omitempty" doc:"the total memory (in MB) the account can own"`
MemoryTotal int64 `json:"memorytotal,omitempty" doc:"the total memory (in MB) owned by account"`
Name string `json:"name,omitempty" doc:"the name of the account"`
NetworkAvailable string `json:"networkavailable,omitempty" doc:"the total number of networks available to be created for this account"`
NetworkDomain string `json:"networkdomain,omitempty" doc:"the network domain"`
NetworkLimit string `json:"networklimit,omitempty" doc:"the total number of networks the account can own"`
NetworkTotal int64 `json:"networktotal,omitempty" doc:"the total number of networks owned by account"`
PrimaryStorageAvailable string `json:"primarystorageavailable,omitempty" doc:"the total primary storage space (in GiB) available to be used for this account"`
PrimaryStorageLimit string `json:"primarystoragelimit,omitempty" doc:"the total primary storage space (in GiB) the account can own"`
PrimaryStorageTotal int64 `json:"primarystoragetotal,omitempty" doc:"the total primary storage space (in GiB) owned by account"`
ProjectAvailable string `json:"projectavailable,omitempty" doc:"the total number of projects available for administration by this account"`
ProjectLimit string `json:"projectlimit,omitempty" doc:"the total number of projects the account can own"`
ProjectTotal int64 `json:"projecttotal,omitempty" doc:"the total number of projects being administrated by this account"`
SecondaryStorageAvailable string `json:"secondarystorageavailable,omitempty" doc:"the total secondary storage space (in GiB) available to be used for this account"`
SecondaryStorageLimit string `json:"secondarystoragelimit,omitempty" doc:"the total secondary storage space (in GiB) the account can own"`
SecondaryStorageTotal int64 `json:"secondarystoragetotal,omitempty" doc:"the total secondary storage space (in GiB) owned by account"`
SMTP bool `json:"smtp,omitempty" doc:"if SMTP outbound is allowed"`
SnapshotAvailable string `json:"snapshotavailable,omitempty" doc:"the total number of snapshots available for this account"`
SnapshotLimit string `json:"snapshotlimit,omitempty" doc:"the total number of snapshots which can be stored by this account"`
SnapshotTotal int64 `json:"snapshottotal,omitempty" doc:"the total number of snapshots stored by this account"`
State string `json:"state,omitempty" doc:"the state of the account"`
TemplateAvailable string `json:"templateavailable,omitempty" doc:"the total number of templates available to be created by this account"`
TemplateLimit string `json:"templatelimit,omitempty" doc:"the total number of templates which can be created by this account"`
TemplateTotal int64 `json:"templatetotal,omitempty" doc:"the total number of templates which have been created by this account"`
User []User `json:"user,omitempty" doc:"the list of users associated with account"`
VMAvailable string `json:"vmavailable,omitempty" doc:"the total number of virtual machines available for this account to acquire"`
VMLimit string `json:"vmlimit,omitempty" doc:"the total number of virtual machines that can be deployed by this account"`
VMRunning int `json:"vmrunning,omitempty" doc:"the total number of virtual machines running for this account"`
VMStopped int `json:"vmstopped,omitempty" doc:"the total number of virtual machines stopped for this account"`
VMTotal int64 `json:"vmtotal,omitempty" doc:"the total number of virtual machines deployed by this account"`
VolumeAvailable string `json:"volumeavailable,omitempty" doc:"the total volume available for this account"`
VolumeLimit string `json:"volumelimit,omitempty" doc:"the total volume which can be used by this account"`
VolumeTotal int64 `json:"volumetotal,omitempty" doc:"the total volume being used by this account"`
}
// ListRequest builds the ListAccountsGroups request
func (a Account) ListRequest() (ListCommand, error) {
return &ListAccounts{
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 {
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
type ListAccountsResponse struct {
Count int `json:"count"`
Account []Account `json:"account"`
}

View File

@ -1,43 +0,0 @@
// 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
}
}
}

View File

@ -1,179 +0,0 @@
package egoscale
import (
"context"
"fmt"
"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 {
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 *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"`
ForVirtualNetwork bool `json:"forvirtualnetwork,omitempty" doc:"the virtual network for the IP address"`
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 *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 *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 *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:"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"`
}
// ResourceType returns the type of the resource
func (IPAddress) ResourceType() string {
return "PublicIpAddress"
}
// ListRequest builds the ListAdresses request
func (ipaddress IPAddress) ListRequest() (ListCommand, error) {
req := &ListPublicIPAddresses{
AssociatedNetworkID: ipaddress.AssociatedNetworkID,
ID: ipaddress.ID,
IPAddress: ipaddress.IPAddress,
PhysicalNetworkID: ipaddress.PhysicalNetworkID,
VlanID: ipaddress.VlanID,
ZoneID: ipaddress.ZoneID,
}
if ipaddress.IsElastic {
req.IsElastic = &ipaddress.IsElastic
}
if ipaddress.IsSourceNat {
req.IsSourceNat = &ipaddress.IsSourceNat
}
if ipaddress.ForVirtualNetwork {
req.ForVirtualNetwork = &ipaddress.ForVirtualNetwork
}
return req, nil
}
// Delete removes the resource
func (ipaddress IPAddress) Delete(ctx context.Context, client *Client) error {
if ipaddress.ID == nil {
return fmt.Errorf("an IPAddress may only be deleted using ID")
}
return client.BooleanRequestWithContext(ctx, &DisassociateIPAddress{
ID: ipaddress.ID,
})
}
// AssociateIPAddress (Async) represents the IP creation
type AssociateIPAddress struct {
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."`
}
// Response returns the struct to unmarshal
func (AssociateIPAddress) Response() interface{} {
return new(AsyncJobResult)
}
// 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 *UUID `json:"id" doc:"the id of the public ip address to disassociate"`
_ bool `name:"disassociateIpAddress" description:"Disassociates an ip address from the account."`
}
// Response returns the struct to unmarshal
func (DisassociateIPAddress) Response() interface{} {
return new(AsyncJobResult)
}
// 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 {
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"`
}
// Response returns the struct to unmarshal
func (UpdateIPAddress) Response() interface{} {
return new(AsyncJobResult)
}
// 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 {
AllocatedOnly *bool `json:"allocatedonly,omitempty" doc:"limits search results to allocated public IP addresses"`
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 *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"`
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"`
Page int `json:"page,omitempty"`
PageSize int `json:"pagesize,omitempty"`
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 *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"`
}
// ListPublicIPAddressesResponse represents a list of public IP addresses
type ListPublicIPAddressesResponse struct {
Count int `json:"count"`
PublicIPAddress []IPAddress `json:"publicipaddress"`
}

View File

@ -1,158 +0,0 @@
package egoscale
import (
"context"
"fmt"
"net/url"
)
// AffinityGroup represents an (anti-)affinity group
//
// 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"`
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
func (ag AffinityGroup) ListRequest() (ListCommand, error) {
return &ListAffinityGroups{
ID: ag.ID,
Name: ag.Name,
}, nil
}
// Delete removes the given Affinity Group
func (ag AffinityGroup) Delete(ctx context.Context, client *Client) error {
if ag.ID == nil && ag.Name == "" {
return fmt.Errorf("an 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)
}
// AffinityGroupType represent an affinity group type
type AffinityGroupType struct {
Type string `json:"type,omitempty" doc:"the type of the affinity group"`
}
// CreateAffinityGroup (Async) represents a new (anti-)affinity group
type CreateAffinityGroup struct {
Description string `json:"description,omitempty" doc:"Optional description of the affinity group"`
Name string `json:"name,omitempty" 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"`
}
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)
}
// 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
type UpdateVMAffinityGroup struct {
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/anti-affinity 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
if len(req.AffinityGroupIDs) == 0 && len(req.AffinityGroupNames) == 0 {
params.Set("affinitygroupids", "")
}
return nil
}
// Response returns the struct to unmarshal
func (UpdateVMAffinityGroup) Response() interface{} {
return new(AsyncJobResult)
}
// 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
type DeleteAffinityGroup struct {
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"`
}
// Response returns the struct to unmarshal
func (DeleteAffinityGroup) Response() interface{} {
return new(AsyncJobResult)
}
// AsyncResponse returns the struct to unmarshal the async job
func (DeleteAffinityGroup) AsyncResponse() interface{} {
return new(BooleanResponse)
}
//go:generate go run generate/main.go -interface=Listable ListAffinityGroups
// ListAffinityGroups represents an (anti-)affinity groups search
type ListAffinityGroups struct {
ID *UUID `json:"id,omitempty" doc:"List the affinity group by the ID provided"`
Keyword string `json:"keyword,omitempty" doc:"List by keyword"`
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 *UUID `json:"virtualmachineid,omitempty" doc:"Lists affinity groups by virtual machine ID"`
_ bool `name:"listAffinityGroups" description:"Lists affinity groups"`
}
// ListAffinityGroupsResponse represents a list of (anti-)affinity groups
type ListAffinityGroupsResponse struct {
Count int `json:"count"`
AffinityGroup []AffinityGroup `json:"affinitygroup"`
}
// ListAffinityGroupTypes represents an (anti-)affinity groups 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"`
}
// Response returns the struct to unmarshal
func (ListAffinityGroupTypes) Response() interface{} {
return new(ListAffinityGroupTypesResponse)
}
// ListAffinityGroupTypesResponse represents a list of (anti-)affinity group types
type ListAffinityGroupTypesResponse struct {
Count int `json:"count"`
AffinityGroupType []AffinityGroupType `json:"affinitygrouptype"`
}

View File

@ -1,43 +0,0 @@
// 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 apge
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
}
}
}

View File

@ -1,48 +0,0 @@
package egoscale
// API represents an API service
type API struct {
Description string `json:"description,omitempty" doc:"description of the api"`
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 []APIField `json:"response,omitempty" doc:"api response fields"`
}
// APIParam represents an API parameter field
type APIParam struct {
Description string `json:"description"`
Length int64 `json:"length"`
Name string `json:"name"`
Required bool `json:"required"`
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"`
}
// ListAPIsResponse represents a list of API
type ListAPIsResponse struct {
Count int `json:"count"`
API []API `json:"api"`
}
// Response returns the struct to unmarshal
func (*ListAPIs) Response() interface{} {
return new(ListAPIsResponse)
}

View File

@ -1,138 +0,0 @@
package egoscale
import (
"encoding/json"
"errors"
)
// AsyncJobResult represents an asynchronous job result
type AsyncJobResult struct {
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 {
return e
}
return r
}
// QueryAsyncJobResult represents a query to fetch the status of async job
type QueryAsyncJobResult struct {
JobID *UUID `json:"jobid" doc:"the ID of the asynchronous job"`
_ bool `name:"queryAsyncJobResult" description:"Retrieves the current status of asynchronous job."`
}
// 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 {
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"`
AsyncJob []AsyncJobResult `json:"asyncjobs"`
}
// Result unmarshals the result of an AsyncJobResult into the given interface
func (a AsyncJobResult) Result(i interface{}) error {
if a.JobStatus == Failure {
return a.Error()
}
if a.JobStatus == Success {
m := map[string]json.RawMessage{}
err := json.Unmarshal(*(a.JobResult), &m)
if err == nil {
if len(m) >= 1 {
if _, ok := m["success"]; ok {
return json.Unmarshal(*(a.JobResult), i)
}
// otherwise, pick the first key
for k := range m {
return json.Unmarshal(m[k], i)
}
}
return errors.New("empty response")
}
}
return nil
}

View File

@ -1,43 +0,0 @@
// 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
}
}
}

View File

@ -1,62 +0,0 @@
package egoscale
import (
"bytes"
"encoding/json"
"fmt"
"net"
)
// CIDR represents a nicely JSON serializable net.IPNet
type CIDR struct {
net.IPNet
}
// UnmarshalJSON unmarshals the raw JSON into the MAC address
func (cidr *CIDR) UnmarshalJSON(b []byte) error {
var s string
if err := json.Unmarshal(b, &s); err != nil {
return err
}
c, err := ParseCIDR(s)
if err != nil {
return err
}
*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)), 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
func ParseCIDR(s string) (*CIDR, error) {
_, net, err := net.ParseCIDR(s)
if err != nil {
return nil, err
}
return &CIDR{*net}, nil
}
// MustParseCIDR forces parseCIDR or panics
func MustParseCIDR(s string) *CIDR {
cidr, err := ParseCIDR(s)
if err != nil {
panic(err)
}
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))
}

View File

@ -1,418 +0,0 @@
package egoscale
import (
"context"
"fmt"
"io/ioutil"
"log"
"net/http"
"net/http/httputil"
"os"
"reflect"
"runtime"
"strings"
"time"
)
// 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 {
// ResourceType is the name of the Taggable type
ResourceType() string
}
// Deletable represents an Interface that can be "Delete" by the client
type Deletable interface {
// Delete removes the given resource(s) or throws
Delete(context context.Context, client *Client) error
}
// Listable represents an Interface that can be "List" by the client
type Listable interface {
// ListRequest builds the list command
ListRequest() (ListCommand, error)
}
// Client represents the API client
type Client struct {
// HTTPClient holds the HTTP client
HTTPClient *http.Client
// Endpoint is the HTTP URL
Endpoint string
// APIKey is the API identifier
APIKey string
// apisecret is the API secret, hence non exposed
apiSecret string
// PageSize represents the default size for a paginated result
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 the API
type RetryStrategyFunc func(int64) time.Duration
// IterateItemFunc represents the callback to iterate a list of results, if false stops
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 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,
}
client := &Client{
HTTPClient: httpClient,
Endpoint: endpoint,
APIKey: apiKey,
apiSecret: apiSecret,
PageSize: 50,
Timeout: timeout,
Expiration: expiration,
RetryStrategy: MonotonicRetryStrategyFunc(2),
Logger: log.New(ioutil.Discard, "", 0),
}
if prefix, ok := os.LookupEnv("EXOSCALE_TRACE"); ok {
client.Logger = log.New(os.Stderr, prefix, log.LstdFlags)
client.TraceOn()
}
return client
}
// Get populates the given resource or fails
func (client *Client) Get(ls Listable) (interface{}, error) {
ctx, cancel := context.WithTimeout(context.Background(), client.Timeout)
defer cancel()
return client.GetWithContext(ctx, ls)
}
// GetWithContext populates the given resource or fails
func (client *Client) GetWithContext(ctx context.Context, ls Listable) (interface{}, error) {
gs, err := client.ListWithContext(ctx, ls)
if err != nil {
return nil, err
}
count := len(gs)
if count != 1 {
req, err := ls.ListRequest()
if err != nil {
return nil, err
}
params, err := client.Payload(req)
if err != nil {
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 nil, &ErrorResponse{
CSErrorCode: ServerAPIException,
ErrorCode: ParamError,
ErrorText: fmt.Sprintf("not found, query: %s", payload),
}
}
return nil, fmt.Errorf("more than one element found: %s", payload)
}
return gs[0], nil
}
// Delete removes the given resource of fails
func (client *Client) Delete(g Deletable) error {
ctx, cancel := context.WithTimeout(context.Background(), client.Timeout)
defer cancel()
return client.DeleteWithContext(ctx, g)
}
// DeleteWithContext removes the given resource of fails
func (client *Client) DeleteWithContext(ctx context.Context, g Deletable) error {
return g.Delete(ctx, client)
}
// List lists the given resource (and paginate till the end)
func (client *Client) List(g Listable) ([]interface{}, error) {
ctx, cancel := context.WithTimeout(context.Background(), client.Timeout)
defer cancel()
return client.ListWithContext(ctx, g)
}
// ListWithContext lists the given resources (and paginate till the end)
func (client *Client) ListWithContext(ctx context.Context, g Listable) (s []interface{}, err error) {
s = make([]interface{}, 0)
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
}
client.PaginateWithContext(ctx, req, func(item interface{}, e error) bool {
if item != nil {
s = append(s, item)
return true
}
err = e
return false
})
return
}
// AsyncListWithContext lists the given resources (and paginate till the end)
//
//
// // NB: goroutine may leak if not read until the end. Create a proper context!
// ctx, cancel := context.WithCancel(context.Background())
// defer cancel()
//
// outChan, errChan := client.AsyncListWithContext(ctx, new(egoscale.VirtualMachine))
//
// for {
// select {
// case i, ok := <- outChan:
// if ok {
// vm := i.(egoscale.VirtualMachine)
// // ...
// } else {
// outChan = nil
// }
// case err, ok := <- errChan:
// if ok {
// // do something
// }
// // Once an error has been received, you can expect the channels to be closed.
// errChan = nil
// }
// if errChan == nil && outChan == nil {
// break
// }
// }
//
func (client *Client) AsyncListWithContext(ctx context.Context, g Listable) (<-chan interface{}, <-chan error) {
outChan := make(chan interface{}, client.PageSize)
errChan := make(chan error)
go func() {
defer close(outChan)
defer close(errChan)
req, err := g.ListRequest()
if err != nil {
errChan <- err
return
}
client.PaginateWithContext(ctx, req, func(item interface{}, e error) bool {
if item != nil {
outChan <- item
return true
}
errChan <- e
return false
})
}()
return outChan, errChan
}
// Paginate runs the ListCommand and paginates
func (client *Client) Paginate(g Listable, callback IterateItemFunc) {
ctx, cancel := context.WithTimeout(context.Background(), client.Timeout)
defer cancel()
client.PaginateWithContext(ctx, g, callback)
}
// PaginateWithContext runs the ListCommand as long as the ctx is valid
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
for {
req.SetPage(page)
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 {
// If the context was cancelled, kill it in flight
if e := ctx.Err(); e != nil {
element = nil
err = e
}
if callback(element, err) {
size++
return true
}
didErr = true
return false
})
if size < pageSize || didErr {
break
}
page++
}
}
// 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
_, ok := command.(*AuthorizeSecurityGroupEgress)
_, okPtr := command.(AuthorizeSecurityGroupEgress)
if ok || okPtr {
return "authorizeSecurityGroupEgress"
}
info, err := info(command)
if err != nil {
panic(err)
}
return info.Name
}
// APIDescription returns the description of the given command
func (client *Client) APIDescription(command Command) string {
info, err := info(command)
if err != nil {
return "*missing description*"
}
return info.Description
}
// Response returns the response structure of the given command
func (client *Client) Response(command Command) interface{} {
switch c := command.(type) {
case AsyncCommand:
return c.AsyncResponse()
default:
return command.Response()
}
}
// TraceOn activates the HTTP tracer
func (client *Client) TraceOn() {
if _, ok := client.HTTPClient.Transport.(*traceTransport); !ok {
client.HTTPClient.Transport = &traceTransport{
transport: client.HTTPClient.Transport,
logger: client.Logger,
}
}
}
// TraceOff deactivates the HTTP tracer
func (client *Client) TraceOff() {
if rt, ok := client.HTTPClient.Transport.(*traceTransport); ok {
client.HTTPClient.Transport = rt.transport
}
}
// traceTransport contains the original HTTP transport to enable it to be reverted
type traceTransport struct {
transport http.RoundTripper
logger *log.Logger
}
// RoundTrip executes a single HTTP transaction
func (t *traceTransport) RoundTrip(req *http.Request) (*http.Response, error) {
if dump, err := httputil.DumpRequest(req, true); err == nil {
t.logger.Printf("%s", dump)
}
resp, err := t.transport.RoundTrip(req)
if err != nil {
return nil, err
}
if dump, err := httputil.DumpResponse(resp, true); err == nil {
t.logger.Printf("%s", dump)
}
return resp, nil
}
// MonotonicRetryStrategyFunc returns a function that waits for n seconds for each iteration
func MonotonicRetryStrategyFunc(seconds int) RetryStrategyFunc {
return func(iteration int64) time.Duration {
return time.Duration(seconds) * time.Second
}
}
// FibonacciRetryStrategy waits for an increasing amount of time following the Fibonacci sequence
func FibonacciRetryStrategy(iteration int64) time.Duration {
var a, b, i, tmp int64
a = 0
b = 1
for i = 0; i < iteration; i++ {
tmp = a + b
a = b
b = tmp
}
return time.Duration(a) * time.Second
}

View File

@ -1,47 +0,0 @@
// Code generated by "stringer -type CSErrorCode"; DO NOT EDIT.
package egoscale
import "strconv"
const _CSErrorCode_name = "CloudRuntimeExceptionExecutionExceptionHypervisorVersionChangedExceptionCloudExceptionAccountLimitExceptionAgentUnavailableExceptionCloudAuthenticationExceptionConcurrentOperationExceptionConflictingNetworkSettingsExceptionDiscoveredWithErrorExceptionHAStateExceptionInsufficientAddressCapacityExceptionInsufficientCapacityExceptionInsufficientNetworkCapacityExceptionInsufficientServerCapacityExceptionInsufficientStorageCapacityExceptionInternalErrorExceptionInvalidParameterValueExceptionManagementServerExceptionNetworkRuleConflictExceptionPermissionDeniedExceptionResourceAllocationExceptionResourceInUseExceptionResourceUnavailableExceptionStorageUnavailableExceptionUnsupportedServiceExceptionVirtualMachineMigrationExceptionAsyncCommandQueuedRequestLimitExceptionServerAPIException"
var _CSErrorCode_map = map[CSErrorCode]string{
4250: _CSErrorCode_name[0:21],
4260: _CSErrorCode_name[21:39],
4265: _CSErrorCode_name[39:72],
4275: _CSErrorCode_name[72:86],
4280: _CSErrorCode_name[86:107],
4285: _CSErrorCode_name[107:132],
4290: _CSErrorCode_name[132:160],
4300: _CSErrorCode_name[160:188],
4305: _CSErrorCode_name[188:223],
4310: _CSErrorCode_name[223:251],
4315: _CSErrorCode_name[251:267],
4320: _CSErrorCode_name[267:303],
4325: _CSErrorCode_name[303:332],
4330: _CSErrorCode_name[332:368],
4335: _CSErrorCode_name[368:403],
4340: _CSErrorCode_name[403:439],
4345: _CSErrorCode_name[439:461],
4350: _CSErrorCode_name[461:491],
4355: _CSErrorCode_name[491:516],
4360: _CSErrorCode_name[516:544],
4365: _CSErrorCode_name[544:569],
4370: _CSErrorCode_name[569:596],
4375: _CSErrorCode_name[596:618],
4380: _CSErrorCode_name[618:646],
4385: _CSErrorCode_name[646:673],
4390: _CSErrorCode_name[673:700],
4395: _CSErrorCode_name[700:732],
4540: _CSErrorCode_name[732:750],
4545: _CSErrorCode_name[750:771],
9999: _CSErrorCode_name[771:789],
}
func (i CSErrorCode) String() string {
if str, ok := _CSErrorCode_map[i]; ok {
return str
}
return "CSErrorCode(" + strconv.FormatInt(int64(i), 10) + ")"
}

View File

@ -1,364 +0,0 @@
package egoscale
import (
"context"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"net/url"
"strconv"
"strings"
)
// DNSDomain represents a domain
type DNSDomain struct {
ID int64 `json:"id"`
Name string `json:"name"`
UnicodeName string `json:"unicode_name"`
Token string `json:"token"`
State string `json:"state"`
Language string `json:"language,omitempty"`
Lockable bool `json:"lockable"`
AutoRenew bool `json:"auto_renew"`
WhoisProtected bool `json:"whois_protected"`
RecordCount int64 `json:"record_count"`
ServiceCount int64 `json:"service_count"`
ExpiresOn string `json:"expires_on,omitempty"`
CreatedAt string `json:"created_at"`
UpdatedAt string `json:"updated_at"`
}
// DNSDomainResponse represents a domain creation response
type DNSDomainResponse struct {
Domain *DNSDomain `json:"domain"`
}
// DNSRecord represents a DNS record
type DNSRecord struct {
ID int64 `json:"id,omitempty"`
DomainID int64 `json:"domain_id,omitempty"`
Name string `json:"name"`
TTL int `json:"ttl,omitempty"`
CreatedAt string `json:"created_at,omitempty"`
UpdatedAt string `json:"updated_at,omitempty"`
Content string `json:"content"`
RecordType string `json:"record_type"`
Prio int `json:"prio,omitempty"`
}
// DNSRecordResponse represents the creation of a DNS record
type DNSRecordResponse struct {
Record DNSRecord `json:"record"`
}
// UpdateDNSRecord represents a DNS record
type UpdateDNSRecord struct {
ID int64 `json:"id,omitempty"`
DomainID int64 `json:"domain_id,omitempty"`
Name string `json:"name,omitempty"`
TTL int `json:"ttl,omitempty"`
CreatedAt string `json:"created_at,omitempty"`
UpdatedAt string `json:"updated_at,omitempty"`
Content string `json:"content,omitempty"`
RecordType string `json:"record_type,omitempty"`
Prio int `json:"prio,omitempty"`
}
// UpdateDNSRecordResponse represents the creation of a DNS record
type UpdateDNSRecordResponse struct {
Record UpdateDNSRecord `json:"record"`
}
// DNSErrorResponse represents an error in the API
type DNSErrorResponse struct {
Message string `json:"message,omitempty"`
Errors map[string][]string `json:"errors"`
}
// Record represent record type
type Record int
//go:generate stringer -type=Record
const (
// A record type
A Record = iota
// AAAA record type
AAAA
// ALIAS record type
ALIAS
// CNAME record type
CNAME
// HINFO record type
HINFO
// MX record type
MX
// NAPTR record type
NAPTR
// NS record type
NS
// POOL record type
POOL
// SPF record type
SPF
// SRV record type
SRV
// SSHFP record type
SSHFP
// TXT record type
TXT
// URL record type
URL
)
// Error formats the DNSerror into a string
func (req *DNSErrorResponse) Error() string {
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(ctx context.Context, name string) (*DNSDomain, error) {
m, err := json.Marshal(DNSDomainResponse{
Domain: &DNSDomain{
Name: name,
},
})
if err != nil {
return nil, err
}
resp, err := client.dnsRequest(ctx, "/v1/domains", nil, string(m), "POST")
if err != nil {
return nil, err
}
var d *DNSDomainResponse
if err := json.Unmarshal(resp, &d); err != nil {
return nil, err
}
return d.Domain, nil
}
// GetDomain gets a DNS domain
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
}
var d *DNSDomainResponse
if err := json.Unmarshal(resp, &d); err != nil {
return nil, err
}
return d.Domain, nil
}
// GetDomains gets DNS domains
func (client *Client) GetDomains(ctx context.Context) ([]DNSDomain, error) {
resp, err := client.dnsRequest(ctx, "/v1/domains", nil, "", "GET")
if err != nil {
return nil, err
}
var d []DNSDomainResponse
if err := json.Unmarshal(resp, &d); err != nil {
return nil, err
}
domains := make([]DNSDomain, len(d))
for i := range d {
domains[i] = *d[i].Domain
}
return domains, nil
}
// DeleteDomain delets a DNS domain
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(ctx context.Context, domain string, recordID int64) (*DNSRecord, error) {
id := strconv.FormatInt(recordID, 10)
resp, err := client.dnsRequest(ctx, "/v1/domains/"+domain+"/records/"+id, nil, "", "GET")
if err != nil {
return nil, err
}
var r DNSRecordResponse
if err = json.Unmarshal(resp, &r); err != nil {
return nil, err
}
return &(r.Record), nil
}
// GetRecords returns the DNS records
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
}
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
}
// CreateRecord creates a DNS record
func (client *Client) CreateRecord(ctx context.Context, name string, rec DNSRecord) (*DNSRecord, error) {
body, err := json.Marshal(DNSRecordResponse{
Record: rec,
})
if err != nil {
return nil, err
}
resp, err := client.dnsRequest(ctx, "/v1/domains/"+name+"/records", nil, string(body), "POST")
if err != nil {
return nil, err
}
var r DNSRecordResponse
if err = json.Unmarshal(resp, &r); err != nil {
return nil, err
}
return &(r.Record), nil
}
// UpdateRecord updates a DNS record
func (client *Client) UpdateRecord(ctx context.Context, name string, rec UpdateDNSRecord) (*DNSRecord, error) {
body, err := json.Marshal(UpdateDNSRecordResponse{
Record: rec,
})
if err != nil {
return nil, err
}
id := strconv.FormatInt(rec.ID, 10)
resp, err := client.dnsRequest(ctx, "/v1/domains/"+name+"/records/"+id, nil, string(body), "PUT")
if err != nil {
return nil, err
}
var r DNSRecordResponse
if err = json.Unmarshal(resp, &r); err != nil {
return nil, err
}
return &(r.Record), nil
}
// DeleteRecord deletes a record
func (client *Client) DeleteRecord(ctx context.Context, name string, recordID int64) error {
id := strconv.FormatInt(recordID, 10)
_, err := client.dnsRequest(ctx, "/v1/domains/"+name+"/records/"+id, nil, "", "DELETE")
return err
}
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", UserAgent)
hdr.Add("Accept", "application/json")
if params != "" {
hdr.Add("Content-Type", "application/json")
}
req.Header = hdr
resp, err := client.HTTPClient.Do(req.WithContext(ctx))
if err != nil {
return nil, err
}
defer resp.Body.Close() // nolint: errcheck
contentType := resp.Header.Get("content-type")
if !strings.Contains(contentType, "application/json") {
return nil, fmt.Errorf(`response content-type expected to be "application/json", got %q`, contentType)
}
b, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}
if resp.StatusCode >= 400 {
e := new(DNSErrorResponse)
if err := json.Unmarshal(b, e); err != nil {
return nil, err
}
return nil, e
}
return b, nil
}

View File

@ -1,180 +0,0 @@
/*
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. If anything feels odd or unclear, please let us know: https://github.com/exoscale/egoscale/issues
req := &egoscale.DeployVirtualMachine{
Size: 10,
ServiceOfferingID: egoscale.MustParseUUID("..."),
TemplateID: egoscale.MustParseUUID("..."),
ZoneID: egoscale.MastParseUUID("..."),
}
fmt.Println("Deployment started")
resp, err := cs.Request(req)
if err != nil {
panic(err)
}
vm := resp.(*egoscale.VirtualMachine)
fmt.Printf("Virtual Machine ID: %s\n", vm.ID)
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: egoscale.MustParseUUID("..."),
TemplateID: egoscale.MustParseUUID("..."),
ZoneID: egoscale.MustParseUUID("..."),
}
vm := &egoscale.VirtualMachine{}
fmt.Println("Deployment started")
cs.AsyncRequest(req, func(jobResult *egoscale.AsyncJobResult, err error) bool {
if err != nil {
// any kind of error
panic(err)
}
// Keep waiting
if jobResult.JobStatus == egoscale.Pending {
fmt.Println("wait...")
return true
}
// Unmarshal the response into the response struct
if err := jobResult.Response(vm); err != nil {
// JSON unmarshaling error
panic(err)
}
// Stop waiting
return false
})
fmt.Printf("Virtual Machine ID: %s\n", vm.ID)
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.com/compute", "EXO...", "...")
// sets a logger on stderr
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, 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.
cs := egoscale.NewClient("https://api.exoscale.com/compute", "EXO...", "...")
resp, err := cs.Request(&egoscale.ListAPIs{})
if err != nil {
panic(err)
}
for _, api := range resp.(*egoscale.ListAPIsResponse).API {
fmt.Printf("%s %s\n", api.Name, api.Description)
}
// Output:
// listNetworks Lists all available networks
// ...
Security Groups
Security Groups provide a way to isolate traffic to VMs. Rules are added via the two Authorization commands.
resp, err := cs.Request(&egoscale.CreateSecurityGroup{
Name: "Load balancer",
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: []CIDR{
*egoscale.MustParseCIDR("0.0.0.0/0"),
*egoscale.MustParseCIDR("::/0"),
},
Protocol: "tcp",
StartPort: 22,
EndPort: 22,
})
// The modified SecurityGroup is returned
securityGroup := resp.(*egoscale.SecurityGroup)
// ...
err = client.BooleanRequest(&egoscale.DeleteSecurityGroup{
ID: securityGroup.ID,
})
// ...
Security Group also implement the generic List, Get and Delete interfaces (Listable and Deletable).
// List all Security Groups
sgs, _ := cs.List(&egoscale.SecurityGroup{})
for _, s := range sgs {
sg := s.(egoscale.SecurityGroup)
// ...
}
// Get a Security Group
sgQuery := &egoscale.SecurityGroup{Name: "Load balancer"}
resp, err := cs.Get(sgQuery); err != nil {
...
}
sg := resp.(*egoscale.SecurityGroup)
if err := cs.Delete(sg); err != nil {
...
}
// The SecurityGroup has been deleted
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 request while the second one hide them and you only manipulate the structs of your interest.
// Using ListZones request
req := &egoscale.ListZones{}
resp, err := client.Request(req)
if err != nil {
panic(err)
}
for _, zone := range resp.(*egoscale.ListZonesResponse) {
...
}
// Using client.List
zone := &egoscale.Zone{}
zones, err := client.List(zone)
if err != nil {
panic(err)
}
for _, z := range zones {
zone := z.(egoscale.Zone)
...
}
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: https://community.exoscale.com/documentation/compute/eip/
*/
package egoscale

View File

@ -1,37 +0,0 @@
// Code generated by "stringer -type ErrorCode"; DO NOT EDIT.
package egoscale
import "strconv"
const (
_ErrorCode_name_0 = "Unauthorized"
_ErrorCode_name_1 = "MethodNotAllowed"
_ErrorCode_name_2 = "UnsupportedActionError"
_ErrorCode_name_3 = "APILimitExceededMalformedParameterErrorParamError"
_ErrorCode_name_4 = "InternalErrorAccountErrorAccountResourceLimitErrorInsufficientCapacityErrorResourceUnavailableErrorResourceAllocationErrorResourceInUseErrorNetworkRuleConflictError"
)
var (
_ErrorCode_index_3 = [...]uint8{0, 16, 39, 49}
_ErrorCode_index_4 = [...]uint8{0, 13, 25, 50, 75, 99, 122, 140, 164}
)
func (i ErrorCode) String() string {
switch {
case i == 401:
return _ErrorCode_name_0
case i == 405:
return _ErrorCode_name_1
case i == 422:
return _ErrorCode_name_2
case 429 <= i && i <= 431:
i -= 429
return _ErrorCode_name_3[_ErrorCode_index_3[i]:_ErrorCode_index_3[i+1]]
case 530 <= i && i <= 537:
i -= 530
return _ErrorCode_name_4[_ErrorCode_index_4[i]:_ErrorCode_index_4[i+1]]
default:
return "ErrorCode(" + strconv.FormatInt(int64(i), 10) + ")"
}
}

View File

@ -1,76 +0,0 @@
package egoscale
// Event represents an event in the system
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"`
ID *UUID `json:"id" doc:"the ID of the event"`
Level string `json:"level,omitempty" doc:"the event level (INFO, WARN, ERROR)"`
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 {
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
type ListEventsResponse struct {
Count int `json:"count"`
Event []Event `json:"event"`
}
//go:generate go run generate/main.go -interface=Listable ListEventTypes
// ListEventTypes list the event types
type ListEventTypes struct {
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
type ListEventTypesResponse struct {
Count int `json:"count"`
EventType []EventType `json:"eventtype"`
_ bool `name:"listEventTypes" description:"List Event Types"`
}

View File

@ -1,43 +0,0 @@
// 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
}
}
}

View File

@ -1,43 +0,0 @@
// 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
}
}
}

View File

@ -1,3 +0,0 @@
module github.com/exoscale/egoscale
require github.com/gofrs/uuid v3.2.0+incompatible

View File

@ -1,2 +0,0 @@
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=

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

View File

@ -1,71 +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"`
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"`
}

View File

@ -1,43 +0,0 @@
// 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
}
}
}

View File

@ -1,94 +0,0 @@
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)
}

View File

@ -1,43 +0,0 @@
// 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
}
}
}

View File

@ -1,16 +0,0 @@
// Code generated by "stringer -type JobStatusType"; DO NOT EDIT.
package egoscale
import "strconv"
const _JobStatusType_name = "PendingSuccessFailure"
var _JobStatusType_index = [...]uint8{0, 7, 14, 21}
func (i JobStatusType) String() string {
if i < 0 || i >= JobStatusType(len(_JobStatusType_index)-1) {
return "JobStatusType(" + strconv.FormatInt(int64(i), 10) + ")"
}
return _JobStatusType_name[_JobStatusType_index[i]:_JobStatusType_index[i+1]]
}

View File

@ -1,63 +0,0 @@
package egoscale
import (
"encoding/json"
"fmt"
"net"
)
// MACAddress is a nicely JSON serializable net.HardwareAddr
type MACAddress net.HardwareAddr
// String returns the MAC address in standard format
func (mac MACAddress) String() string {
return (net.HardwareAddr)(mac).String()
}
// MAC48 builds a MAC-48 MACAddress
func MAC48(a, b, c, d, e, f byte) MACAddress {
m := make(MACAddress, 6)
m[0] = a
m[1] = b
m[2] = c
m[3] = d
m[4] = e
m[5] = f
return m
}
// UnmarshalJSON unmarshals the raw JSON into the MAC address
func (mac *MACAddress) UnmarshalJSON(b []byte) error {
var addr string
if err := json.Unmarshal(b, &addr); err != nil {
return err
}
hw, err := ParseMAC(addr)
if err != nil {
return err
}
*mac = make(MACAddress, 6)
copy(*mac, hw)
return nil
}
// MarshalJSON converts the MAC Address to a string representation
func (mac MACAddress) MarshalJSON() ([]byte, error) {
return []byte(fmt.Sprintf("%q", mac.String())), nil
}
// ParseMAC converts a string into a MACAddress
func ParseMAC(s string) (MACAddress, error) {
hw, err := net.ParseMAC(s)
return (MACAddress)(hw), err
}
// 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)
}
return mac
}

View File

@ -1,91 +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 *UUID `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 *UUID `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."`
}
// ListRequest builds the ListNetworkOfferings request
//
// This doesn't take into account the IsDefault flag as the default value is true.
func (no NetworkOffering) ListRequest() (ListCommand, error) {
req := &ListNetworkOfferings{
Availability: no.Availability,
ID: no.ID,
Name: no.Name,
State: no.State,
TrafficType: no.TrafficType,
}
return req, nil
}
//go:generate go run generate/main.go -interface=Listable ListNetworkOfferings
// 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 *UUID `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 *UUID `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 *UUID `json:"zoneid,omitempty" doc:"list network 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"`
}
// 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 *UUID `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."`
}
// Response returns the struct to unmarshal
func (UpdateNetworkOffering) Response() interface{} {
return new(NetworkOffering)
}

View File

@ -1,43 +0,0 @@
// code generated; DO NOT EDIT.
package egoscale
import "fmt"
// Response returns the struct to unmarshal
func (ListNetworkOfferings) Response() interface{} {
return new(ListNetworkOfferingsResponse)
}
// ListRequest returns itself
func (ls *ListNetworkOfferings) 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 *ListNetworkOfferings) SetPage(page int) {
ls.Page = page
}
// SetPageSize sets the page size
func (ls *ListNetworkOfferings) SetPageSize(pageSize int) {
ls.PageSize = pageSize
}
// Each triggers the callback for each, valid answer or any non 404 issue
func (ListNetworkOfferings) Each(resp interface{}, callback IterateItemFunc) {
items, ok := resp.(*ListNetworkOfferingsResponse)
if !ok {
callback(nil, fmt.Errorf("wrong type, ListNetworkOfferingsResponse was expected, got %T", resp))
return
}
for i := range items.NetworkOffering {
if !callback(&items.NetworkOffering[i], nil) {
break
}
}
}

View File

@ -1,229 +0,0 @@
package egoscale
import (
"net"
"net/url"
)
// Network represents a network
//
// 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 *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"`
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 *UUID `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 *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{
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,
ZoneID: network.ZoneID,
}
if network.CanUseForDeploy {
req.CanUseForDeploy = &network.CanUseForDeploy
}
if network.RestartRequired {
req.RestartRequired = &network.RestartRequired
}
return req, nil
}
// ResourceType returns the type of the resource
func (Network) ResourceType() string {
return "Network"
}
// Service is a feature of a network
type Service struct {
Capability []ServiceCapability `json:"capability,omitempty"`
Name string `json:"name"`
Provider []ServiceProvider `json:"provider,omitempty"`
}
// ServiceCapability represents optional capability of a service
type ServiceCapability struct {
CanChooseServiceCapability bool `json:"canchooseservicecapability"`
Name string `json:"name"`
Value string `json:"value"`
}
// ServiceProvider represents the provider of the service
type ServiceProvider struct {
CanEnableIndividualService bool `json:"canenableindividualservice"`
DestinationPhysicalNetworkID *UUID `json:"destinationphysicalnetworkid"`
ID *UUID `json:"id"`
Name string `json:"name"`
PhysicalNetworkID *UUID `json:"physicalnetworkid"`
ServiceList []string `json:"servicelist,omitempty"`
}
// CreateNetwork creates a network
type CreateNetwork struct {
DisplayText string `json:"displaytext,omitempty" doc:"the display text of the network"` // This field is required but might be empty
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 managed networks."`
NetworkDomain string `json:"networkdomain,omitempty" doc:"network domain"`
NetworkOfferingID *UUID `json:"networkofferingid" doc:"the network offering id"`
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"`
Vlan string `json:"vlan,omitempty" doc:"the ID or VID of the network"`
ZoneID *UUID `json:"zoneid" doc:"the Zone ID for the network"`
_ bool `name:"createNetwork" description:"Creates a network"`
}
// Response returns the struct to unmarshal
func (CreateNetwork) Response() interface{} {
return new(Network)
}
func (req CreateNetwork) onBeforeSend(params url.Values) error {
// Those fields are required but might be empty
if req.Name == "" {
params.Set("name", "")
}
if req.DisplayText == "" {
params.Set("displaytext", "")
}
return nil
}
// UpdateNetwork (Async) updates a network
type UpdateNetwork struct {
_ 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"`
NetworkOfferingID *UUID `json:"networkofferingid,omitempty" doc:"network offering ID"`
StartIP net.IP `json:"startip,omitempty" doc:"the beginning IP address in the network IP range. Required for managed networks."`
}
// Response returns the struct to unmarshal
func (UpdateNetwork) Response() interface{} {
return new(AsyncJobResult)
}
// 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 *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"`
}
// Response returns the struct to unmarshal
func (RestartNetwork) Response() interface{} {
return new(AsyncJobResult)
}
// AsyncResponse returns the struct to unmarshal the async job
func (RestartNetwork) AsyncResponse() interface{} {
return new(Network)
}
// DeleteNetwork deletes a network
type DeleteNetwork struct {
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"`
}
// Response returns the struct to unmarshal
func (DeleteNetwork) Response() interface{} {
return new(AsyncJobResult)
}
// 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 {
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"`
Page int `json:"page,omitempty"`
PageSize int `json:"pagesize,omitempty"`
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 *UUID `json:"zoneid,omitempty" doc:"The Zone ID of the network"`
_ bool `name:"listNetworks" description:"Lists all available networks."`
}
// ListNetworksResponse represents the list of networks
type ListNetworksResponse struct {
Count int `json:"count"`
Network []Network `json:"network"`
}

View File

@ -1,43 +0,0 @@
// 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
}
}
}

View File

@ -1,120 +0,0 @@
package egoscale
import (
"net"
)
// Nic represents a Network Interface Controller (NIC)
//
// 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 *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 *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"`
IPAddress net.IP `json:"ipaddress,omitempty" doc:"the ip address of the nic"`
IsDefault bool `json:"isdefault,omitempty" doc:"true if nic is default, false otherwise"`
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 *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 *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) {
req := &ListNics{
VirtualMachineID: nic.VirtualMachineID,
NicID: nic.ID,
NetworkID: nic.NetworkID,
}
return req, nil
}
// NicSecondaryIP represents a link between NicID and IPAddress
type NicSecondaryIP struct {
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 *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 {
Keyword string `json:"keyword,omitempty" doc:"List by keyword"`
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 *UUID `json:"virtualmachineid,omitempty" doc:"the ID of the vm"`
_ bool `name:"listNics" description:"list the vm nics IP to NIC"`
}
// ListNicsResponse represents a list of templates
type ListNicsResponse struct {
Count int `json:"count"`
Nic []Nic `json:"nic"`
}
// AddIPToNic (Async) represents the assignation of a secondary IP
type AddIPToNic struct {
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"`
}
// Response returns the struct to unmarshal
func (AddIPToNic) Response() interface{} {
return new(AsyncJobResult)
}
// 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 *UUID `json:"id" doc:"the ID of the secondary ip address to nic"`
_ bool `name:"removeIpFromNic" description:"Removes secondary IP from the NIC."`
}
// Response returns the struct to unmarshal
func (RemoveIPFromNic) Response() interface{} {
return new(AsyncJobResult)
}
// 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
type ActivateIP6 struct {
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"`
}
// Response returns the struct to unmarshal
func (ActivateIP6) Response() interface{} {
return new(AsyncJobResult)
}
// AsyncResponse returns the struct to unmarshal the async job
func (ActivateIP6) AsyncResponse() interface{} {
return new(Nic)
}

View File

@ -1,43 +0,0 @@
// 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
}
}
}

View File

@ -1,43 +0,0 @@
// 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
}
}
}

View File

@ -1,43 +0,0 @@
// 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
}
}
}

View File

@ -1,16 +0,0 @@
// Code generated by "stringer -type=Record"; DO NOT EDIT.
package egoscale
import "strconv"
const _Record_name = "AAAAAALIASCNAMEHINFOMXNAPTRNSPOOLSPFSRVSSHFPTXTURL"
var _Record_index = [...]uint8{0, 1, 5, 10, 15, 20, 22, 27, 29, 33, 36, 39, 44, 47, 50}
func (i Record) String() string {
if i < 0 || i >= Record(len(_Record_index)-1) {
return "Record(" + strconv.FormatInt(int64(i), 10) + ")"
}
return _Record_name[_Record_index[i]:_Record_index[i+1]]
}

View File

@ -1,405 +0,0 @@
package egoscale
import (
"bytes"
"context"
"crypto/hmac"
"crypto/sha1"
"encoding/base64"
"encoding/json"
"fmt"
"io"
"io/ioutil"
"net/http"
"net/url"
"sort"
"strconv"
"strings"
"time"
)
// Error formats a CloudStack error into a standard error
func (e ErrorResponse) Error() string {
return fmt.Sprintf("API error %s %d (%s %d): %s", e.ErrorCode, e.ErrorCode, e.CSErrorCode, e.CSErrorCode, e.ErrorText)
}
// Error formats a CloudStack job response into a standard error
func (e BooleanResponse) Error() error {
if !e.Success {
return fmt.Errorf("API error: %s", e.DisplayText)
}
return nil
}
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
}
m := map[string]json.RawMessage{}
if err := json.Unmarshal(b, &m); err != nil {
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 {
// 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)
}
}
}
if resp.StatusCode >= 400 {
errorResponse := new(ErrorResponse)
if e := json.Unmarshal(response, errorResponse); e != nil && errorResponse.ErrorCode <= 0 {
return nil, fmt.Errorf("%d %s", resp.StatusCode, b)
}
return nil, errorResponse
}
n := map[string]json.RawMessage{}
if err := json.Unmarshal(response, &n); err != nil {
return nil, err
}
// list response may contain only one key
if len(n) > 1 || strings.HasPrefix(key, "list") {
return response, nil
}
if len(n) == 1 {
for k := range n {
// boolean response and asyncjob result may also contain
// only one key
if k == "success" || k == "jobid" {
return response, nil
}
return n[k], nil
}
}
return response, nil
}
// asyncRequest perform an asynchronous job with a context
func (client *Client) asyncRequest(ctx context.Context, asyncCommand AsyncCommand) (interface{}, error) {
var err error
resp := asyncCommand.AsyncResponse()
client.AsyncRequestWithContext(
ctx,
asyncCommand,
func(j *AsyncJobResult, e error) bool {
if e != nil {
err = e
return false
}
if j.JobStatus != Pending {
if r := j.Result(resp); r != nil {
err = r
}
return false
}
return true
},
)
return resp, err
}
// SyncRequestWithContext performs a sync request with a context
func (client *Client) SyncRequestWithContext(ctx context.Context, command Command) (interface{}, error) {
body, err := client.request(ctx, command)
if err != nil {
return nil, err
}
response := command.Response()
b, ok := response.(*BooleanResponse)
if ok {
m := make(map[string]interface{})
if errUnmarshal := json.Unmarshal(body, &m); errUnmarshal != nil {
return nil, errUnmarshal
}
b.DisplayText, _ = m["displaytext"].(string)
if success, okSuccess := m["success"].(string); okSuccess {
b.Success = success == "true"
}
if success, okSuccess := m["success"].(bool); okSuccess {
b.Success = success
}
return b, nil
}
if err := json.Unmarshal(body, response); err != nil {
errResponse := new(ErrorResponse)
if e := json.Unmarshal(body, errResponse); e == nil && errResponse.ErrorCode > 0 {
return errResponse, nil
}
return nil, err
}
return response, nil
}
// BooleanRequest performs the given boolean command
func (client *Client) BooleanRequest(command Command) error {
resp, err := client.Request(command)
if err != nil {
return err
}
if b, ok := resp.(*BooleanResponse); ok {
return b.Error()
}
panic(fmt.Errorf("command %q is not a proper boolean response. %#v", client.APIName(command), resp))
}
// BooleanRequestWithContext performs the given boolean command
func (client *Client) BooleanRequestWithContext(ctx context.Context, command Command) error {
resp, err := client.RequestWithContext(ctx, command)
if err != nil {
return err
}
if b, ok := resp.(*BooleanResponse); ok {
return b.Error()
}
panic(fmt.Errorf("command %q is not a proper boolean response. %#v", client.APIName(command), resp))
}
// Request performs the given command
func (client *Client) Request(command Command) (interface{}, error) {
ctx, cancel := context.WithTimeout(context.Background(), client.Timeout)
defer cancel()
return client.RequestWithContext(ctx, command)
}
// RequestWithContext preforms a command with a context
func (client *Client) RequestWithContext(ctx context.Context, command Command) (interface{}, error) {
switch c := command.(type) {
case AsyncCommand:
return client.asyncRequest(ctx, c)
default:
return client.SyncRequestWithContext(ctx, command)
}
}
// SyncRequest performs the command as is
func (client *Client) SyncRequest(command Command) (interface{}, error) {
ctx, cancel := context.WithTimeout(context.Background(), client.Timeout)
defer cancel()
return client.SyncRequestWithContext(ctx, command)
}
// AsyncRequest performs the given command
func (client *Client) AsyncRequest(asyncCommand AsyncCommand, callback WaitAsyncJobResultFunc) {
ctx, cancel := context.WithTimeout(context.Background(), client.Timeout)
defer cancel()
client.AsyncRequestWithContext(ctx, asyncCommand, callback)
}
// AsyncRequestWithContext preforms a request with a context
func (client *Client) AsyncRequestWithContext(ctx context.Context, asyncCommand AsyncCommand, callback WaitAsyncJobResultFunc) {
result, err := client.SyncRequestWithContext(ctx, asyncCommand)
if err != nil {
if !callback(nil, err) {
return
}
}
jobResult, ok := result.(*AsyncJobResult)
if !ok {
callback(nil, fmt.Errorf("wrong type, AsyncJobResult was expected instead of %T", result))
}
// Successful response
if jobResult.JobID == nil || jobResult.JobStatus != Pending {
callback(jobResult, nil)
// without a JobID, the next requests will only fail
return
}
for iteration := 0; ; iteration++ {
time.Sleep(client.RetryStrategy(int64(iteration)))
req := &QueryAsyncJobResult{JobID: jobResult.JobID}
resp, err := client.SyncRequestWithContext(ctx, req)
if err != nil && !callback(nil, err) {
return
}
result, ok := resp.(*AsyncJobResult)
if !ok {
if !callback(nil, fmt.Errorf("wrong type. AsyncJobResult expected, got %T", resp)) {
return
}
}
if !callback(result, nil) {
return
}
}
}
// 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 nil, err
}
if hookReq, ok := command.(onBeforeHook); ok {
if err := hookReq.onBeforeSend(params); err != nil {
return params, err
}
}
params.Set("apikey", client.APIKey)
params.Set("command", client.APIName(command))
params.Set("response", "json")
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"))
}
return params, nil
}
// 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(query))
if err != nil {
return "", err
}
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) {
params, err := client.Payload(command)
if err != nil {
return nil, err
}
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
// respect Internet Explorer limit of 2048
if len(url) > 2048 {
url = client.Endpoint
method = "POST"
body = strings.NewReader(query)
}
request, err := http.NewRequest(method, url, body)
if err != nil {
return nil, err
}
request = request.WithContext(ctx)
request.Header.Add("User-Agent", UserAgent)
if method == "POST" {
request.Header.Add("Content-Type", "application/x-www-form-urlencoded")
request.Header.Add("Content-Length", strconv.Itoa(len(query)))
}
resp, err := client.HTTPClient.Do(request)
if err != nil {
return nil, err
}
defer resp.Body.Close() // nolint: errcheck
contentType := resp.Header.Get("content-type")
if !strings.Contains(contentType, "application/json") {
return nil, fmt.Errorf(`body content-type response expected "application/json", got %q`, contentType)
}
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()
}

View File

@ -1,184 +0,0 @@
package egoscale
import (
"net/url"
)
// Command represents a generic request
type Command interface {
Response() interface{}
}
// AsyncCommand represents a async request
type AsyncCommand interface {
Command
AsyncResponse() interface{}
}
// 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)
}
// onBeforeHook represents an action to be done on the params before sending them
//
// This little took helps with issue of relying on JSON serialization logic only.
// `omitempty` may make sense in some cases but not all the time.
type onBeforeHook interface {
onBeforeSend(params url.Values) error
}
// CommandInfo represents the meta data related to a Command
type CommandInfo struct {
Name string
Description string
RootOnly bool
}
// JobStatusType represents the status of a Job
type JobStatusType int
//go:generate stringer -type JobStatusType
const (
// Pending represents a job in progress
Pending JobStatusType = iota
// Success represents a successfully completed job
Success
// Failure represents a job that has failed to complete
Failure
)
// ErrorCode represents the CloudStack ApiErrorCode enum
//
// 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
// MethodNotAllowed represents ... (TODO)
MethodNotAllowed ErrorCode = 405
// UnsupportedActionError represents ... (TODO)
UnsupportedActionError ErrorCode = 422
// APILimitExceeded represents ... (TODO)
APILimitExceeded ErrorCode = 429
// MalformedParameterError represents ... (TODO)
MalformedParameterError ErrorCode = 430
// ParamError represents ... (TODO)
ParamError ErrorCode = 431
// InternalError represents a server error
InternalError ErrorCode = 530
// AccountError represents ... (TODO)
AccountError ErrorCode = 531
// AccountResourceLimitError represents ... (TODO)
AccountResourceLimitError ErrorCode = 532
// InsufficientCapacityError represents ... (TODO)
InsufficientCapacityError ErrorCode = 533
// ResourceUnavailableError represents ... (TODO)
ResourceUnavailableError ErrorCode = 534
// ResourceAllocationError represents ... (TODO)
ResourceAllocationError ErrorCode = 535
// ResourceInUseError represents ... (TODO)
ResourceInUseError ErrorCode = 536
// NetworkRuleConflictError represents ... (TODO)
NetworkRuleConflictError ErrorCode = 537
)
// CSErrorCode represents the CloudStack CSExceptionErrorCode enum
//
// See: https://github.com/apache/cloudstack/blob/master/utils/src/main/java/com/cloud/utils/exception/CSExceptionErrorCode.java
type CSErrorCode int
//go:generate stringer -type CSErrorCode
const (
// CloudRuntimeException ... (TODO)
CloudRuntimeException CSErrorCode = 4250
// ExecutionException ... (TODO)
ExecutionException CSErrorCode = 4260
// HypervisorVersionChangedException ... (TODO)
HypervisorVersionChangedException CSErrorCode = 4265
// CloudException ... (TODO)
CloudException CSErrorCode = 4275
// AccountLimitException ... (TODO)
AccountLimitException CSErrorCode = 4280
// AgentUnavailableException ... (TODO)
AgentUnavailableException CSErrorCode = 4285
// CloudAuthenticationException ... (TODO)
CloudAuthenticationException CSErrorCode = 4290
// ConcurrentOperationException ... (TODO)
ConcurrentOperationException CSErrorCode = 4300
// ConflictingNetworksException ... (TODO)
ConflictingNetworkSettingsException CSErrorCode = 4305
// DiscoveredWithErrorException ... (TODO)
DiscoveredWithErrorException CSErrorCode = 4310
// HAStateException ... (TODO)
HAStateException CSErrorCode = 4315
// InsufficientAddressCapacityException ... (TODO)
InsufficientAddressCapacityException CSErrorCode = 4320
// InsufficientCapacityException ... (TODO)
InsufficientCapacityException CSErrorCode = 4325
// InsufficientNetworkCapacityException ... (TODO)
InsufficientNetworkCapacityException CSErrorCode = 4330
// InsufficientServerCapaticyException ... (TODO)
InsufficientServerCapacityException CSErrorCode = 4335
// InsufficientStorageCapacityException ... (TODO)
InsufficientStorageCapacityException CSErrorCode = 4340
// InternalErrorException ... (TODO)
InternalErrorException CSErrorCode = 4345
// InvalidParameterValueException ... (TODO)
InvalidParameterValueException CSErrorCode = 4350
// ManagementServerException ... (TODO)
ManagementServerException CSErrorCode = 4355
// NetworkRuleConflictException ... (TODO)
NetworkRuleConflictException CSErrorCode = 4360
// PermissionDeniedException ... (TODO)
PermissionDeniedException CSErrorCode = 4365
// ResourceAllocationException ... (TODO)
ResourceAllocationException CSErrorCode = 4370
// ResourceInUseException ... (TODO)
ResourceInUseException CSErrorCode = 4375
// ResourceUnavailableException ... (TODO)
ResourceUnavailableException CSErrorCode = 4380
// StorageUnavailableException ... (TODO)
StorageUnavailableException CSErrorCode = 4385
// UnsupportedServiceException ... (TODO)
UnsupportedServiceException CSErrorCode = 4390
// VirtualMachineMigrationException ... (TODO)
VirtualMachineMigrationException CSErrorCode = 4395
// AsyncCommandQueued ... (TODO)
AsyncCommandQueued CSErrorCode = 4540
// RequestLimitException ... (TODO)
RequestLimitException CSErrorCode = 4545
// ServerAPIException ... (TODO)
ServerAPIException CSErrorCode = 9999
)
// ErrorResponse represents the standard error response
type ErrorResponse struct {
CSErrorCode CSErrorCode `json:"cserrorcode"`
ErrorCode ErrorCode `json:"errorcode"`
ErrorText string `json:"errortext"`
UUIDList []UUIDItem `json:"uuidList,omitempty"` // uuid*L*ist is not a typo
}
// UUIDItem represents an item of the UUIDList part of an ErrorResponse
type UUIDItem struct {
Description string `json:"description,omitempty"`
SerialVersionUID int64 `json:"serialVersionUID,omitempty"`
UUID string `json:"uuid"`
}
// BooleanResponse represents a boolean response (usually after a deletion)
type BooleanResponse struct {
DisplayText string `json:"displaytext,omitempty"`
Success bool `json:"success"`
}

View File

@ -1,100 +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 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"`
}

View File

@ -1,41 +0,0 @@
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"`
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"`
Page int `json:"page,omitempty"`
PageSize int `json:"pagesize,omitempty"`
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"`
_ bool `name:"listResourceDetails" description:"List resource detail(s)"`
}
// ListResourceDetailsResponse represents a list of resource details
type ListResourceDetailsResponse struct {
Count int `json:"count"`
ResourceDetail []ResourceTag `json:"resourcedetail"`
}

View File

@ -1,43 +0,0 @@
// 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
}
}
}

View File

@ -1,43 +0,0 @@
// 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
}
}
}

View File

@ -1,83 +0,0 @@
package egoscale
import (
"net"
)
// ReverseDNS represents the PTR record linked with an IPAddress or IP6Address belonging to a Virtual Machine or a Public IP Address (Elastic IP) instance
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 *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 *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"`
}
// 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 *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"`
}
// 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 *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"`
}
// 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 *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"`
}
// 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 *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"`
}
// 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 *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"`
}
// Response returns the struct to unmarshal
func (*UpdateReverseDNSForVirtualMachine) Response() interface{} {
return new(VirtualMachine)
}

View File

@ -1,131 +0,0 @@
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
}

View File

@ -1,37 +0,0 @@
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
}

View File

@ -1,175 +0,0 @@
package egoscale
import (
"context"
"encoding/json"
"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, fmt.Errorf("%#v not found", incident)
}
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
}

View File

@ -1,208 +0,0 @@
package egoscale
import (
"context"
"encoding/json"
"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, fmt.Errorf("%#v not found", maintenance)
}
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
}

View File

@ -1,168 +0,0 @@
package egoscale
import (
"context"
"encoding/json"
"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, fmt.Errorf("%#v not found", page)
}
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
}
}

View File

@ -1,201 +0,0 @@
package egoscale
import (
"context"
"encoding/json"
"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, fmt.Errorf("%#v not found", service)
}
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
}
}

View File

@ -1,226 +0,0 @@
package egoscale
import (
"context"
"fmt"
"net/url"
"strconv"
"strings"
)
// SecurityGroup represent a firewalling set of rules
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"`
EgressRule []EgressRule `json:"egressrule,omitempty" doc:"the list of egress rules associated with 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"`
}
// UserSecurityGroup converts a SecurityGroup to a UserSecurityGroup
func (sg SecurityGroup) UserSecurityGroup() UserSecurityGroup {
return UserSecurityGroup{
Group: sg.Name,
}
}
// ListRequest builds the ListSecurityGroups request
func (sg SecurityGroup) ListRequest() (ListCommand, error) {
req := &ListSecurityGroups{
ID: sg.ID,
SecurityGroupName: sg.Name,
}
return req, nil
}
// Delete deletes the given Security Group
func (sg SecurityGroup) Delete(ctx context.Context, client *Client) error {
if sg.ID == nil && sg.Name == "" {
return fmt.Errorf("a SecurityGroup may only be deleted using ID or Name")
}
req := &DeleteSecurityGroup{}
if sg.ID != nil {
req.ID = sg.ID
} else {
req.Name = sg.Name
}
return client.BooleanRequestWithContext(ctx, req)
}
// RuleByID returns IngressRule or EgressRule by a rule ID
func (sg SecurityGroup) RuleByID(ruleID UUID) (*IngressRule, *EgressRule) {
for i, in := range sg.IngressRule {
if in.RuleID.Equal(ruleID) {
return &sg.IngressRule[i], nil
}
}
for i, out := range sg.EgressRule {
if out.RuleID.Equal(ruleID) {
return nil, &sg.EgressRule[i]
}
}
return nil, nil
}
// IngressRule represents the ingress rule
type IngressRule struct {
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
type EgressRule IngressRule
// UserSecurityGroup represents the traffic of another security group
type UserSecurityGroup struct {
Group string `json:"group,omitempty"`
}
// String gives the UserSecurityGroup name
func (usg UserSecurityGroup) String() string {
return usg.Group
}
// CreateSecurityGroup represents a security group creation
type CreateSecurityGroup struct {
Name string `json:"name" doc:"name of the security group"`
Description string `json:"description,omitempty" doc:"the description of the security group"`
_ bool `name:"createSecurityGroup" description:"Creates a security group"`
}
// Response returns the struct to unmarshal
func (CreateSecurityGroup) Response() interface{} {
return new(SecurityGroup)
}
// DeleteSecurityGroup represents a security group deletion
type DeleteSecurityGroup struct {
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"`
}
// Response returns the struct to unmarshal
func (DeleteSecurityGroup) Response() interface{} {
return new(BooleanResponse)
}
// AuthorizeSecurityGroupIngress (Async) represents the ingress rule creation
type AuthorizeSecurityGroupIngress struct {
CIDRList []CIDR `json:"cidrlist,omitempty" doc:"the cidr list associated"`
Description string `json:"description,omitempty" doc:"the description of the ingress/egress 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, 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/egress rule"`
UserSecurityGroupList []UserSecurityGroup `json:"usersecuritygrouplist,omitempty" doc:"user to security group mapping"`
_ bool `name:"authorizeSecurityGroupIngress" description:"Authorize a particular ingress/egress rule for this security group"`
}
// Response returns the struct to unmarshal
func (AuthorizeSecurityGroupIngress) Response() interface{} {
return new(AsyncJobResult)
}
// AsyncResponse returns the struct to unmarshal the async job
func (AuthorizeSecurityGroupIngress) AsyncResponse() interface{} {
return new(SecurityGroup)
}
func (req AuthorizeSecurityGroupIngress) onBeforeSend(params url.Values) error {
// ICMP code and type may be zero but can also be omitted...
if strings.HasPrefix(strings.ToLower(req.Protocol), "icmp") {
params.Set("icmpcode", strconv.FormatInt(int64(req.IcmpCode), 10))
params.Set("icmptype", strconv.FormatInt(int64(req.IcmpType), 10))
}
// StartPort may be zero but can also be omitted...
if req.EndPort != 0 && req.StartPort == 0 {
params.Set("startport", "0")
}
return nil
}
// AuthorizeSecurityGroupEgress (Async) represents the egress rule creation
type AuthorizeSecurityGroupEgress AuthorizeSecurityGroupIngress
// Response returns the struct to unmarshal
func (AuthorizeSecurityGroupEgress) Response() interface{} {
return new(AsyncJobResult)
}
// AsyncResponse returns the struct to unmarshal the async job
func (AuthorizeSecurityGroupEgress) AsyncResponse() interface{} {
return new(SecurityGroup)
}
func (req AuthorizeSecurityGroupEgress) onBeforeSend(params url.Values) error {
return (AuthorizeSecurityGroupIngress)(req).onBeforeSend(params)
}
// RevokeSecurityGroupIngress (Async) represents the ingress/egress rule deletion
type RevokeSecurityGroupIngress struct {
ID *UUID `json:"id" doc:"The ID of the ingress rule"`
_ bool `name:"revokeSecurityGroupIngress" description:"Deletes a particular ingress rule from this security group"`
}
// Response returns the struct to unmarshal
func (RevokeSecurityGroupIngress) Response() interface{} {
return new(AsyncJobResult)
}
// 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 *UUID `json:"id" doc:"The ID of the egress rule"`
_ bool `name:"revokeSecurityGroupEgress" description:"Deletes a particular egress rule from this security group"`
}
// Response returns the struct to unmarshal
func (RevokeSecurityGroupEgress) Response() interface{} {
return new(AsyncJobResult)
}
// 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 {
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
type ListSecurityGroupsResponse struct {
Count int `json:"count"`
SecurityGroup []SecurityGroup `json:"securitygroup"`
}

View File

@ -1,43 +0,0 @@
// 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
}
}
}

View File

@ -1,402 +0,0 @@
package egoscale
import (
"encoding/base64"
"fmt"
"log"
"net"
"net/url"
"reflect"
"strconv"
"strings"
)
func csQuotePlus(s string) string {
s = strings.Replace(s, "+", "%20", -1)
return s
}
func csEncode(s string) string {
return csQuotePlus(url.QueryEscape(s))
}
// info returns the meta info of a command
//
// command is not a Command so it's easier to Test
func info(command interface{}) (*CommandInfo, error) {
typeof := reflect.TypeOf(command)
// Going up the pointer chain to find the underlying struct
for typeof.Kind() == reflect.Ptr {
typeof = typeof.Elem()
}
field, ok := typeof.FieldByName("_")
if !ok {
return nil, fmt.Errorf(`missing meta ("_") field in %#v`, command)
}
name, nameOk := field.Tag.Lookup("name")
description, _ := field.Tag.Lookup("description")
if !nameOk {
return nil, fmt.Errorf(`missing "name" key in the tag string of %#v`, command)
}
info := &CommandInfo{
Name: name,
Description: description,
}
return info, nil
}
// prepareValues uses a command to build a POST request
//
// command is not a Command so it's easier to Test
func prepareValues(prefix string, command interface{}) (url.Values, error) {
params := url.Values{}
value := reflect.ValueOf(command)
typeof := reflect.TypeOf(command)
// Going up the pointer chain to find the underlying struct
for typeof.Kind() == reflect.Ptr {
typeof = typeof.Elem()
value = value.Elem()
}
// Checking for nil commands
if !value.IsValid() {
return nil, fmt.Errorf("cannot serialize the invalid value %#v", command)
}
for i := 0; i < typeof.NumField(); i++ {
field := typeof.Field(i)
if field.Name == "_" {
continue
}
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
switch val.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
value, err = prepareInt(val.Int(), required)
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
value, err = prepareUint(val.Uint(), required)
case reflect.Float32, reflect.Float64:
value, err = prepareFloat(val.Float(), required)
case reflect.String:
value, err = prepareString(val.String(), required)
case reflect.Bool:
value, err = prepareBool(val.Bool(), required)
case reflect.Map:
if val.Len() == 0 {
if required {
err = fmt.Errorf("field is required, got empty map")
}
} else {
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:
value, err = prepareStruct(val.Interface(), required)
default:
if required {
err = fmt.Errorf("unsupported type")
}
}
} else {
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 params, nil
}
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++ {
ps, err := prepareValues(fmt.Sprintf("%s[%d].", prefix, i), value.Index(i).Interface())
if err != nil {
return nil, err
}
for k, xs := range ps {
for _, x := range xs {
params.Add(k, x)
}
}
}
return params, nil
}
func prepareMap(prefix string, m interface{}) (url.Values, error) {
value := url.Values{}
v := reflect.ValueOf(m)
for i, key := range v.MapKeys() {
var keyName string
var keyValue string
switch key.Kind() {
case reflect.String:
keyName = key.String()
default:
return value, fmt.Errorf("only map[string]string are supported (XXX)")
}
val := v.MapIndex(key)
switch val.Kind() {
case reflect.String:
keyValue = val.String()
default:
return value, fmt.Errorf("only map[string]string are supported (XXX)")
}
value.Set(fmt.Sprintf("%s[%d].%s", prefix, i, keyName), keyValue)
}
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)
func ExtractJSONTag(defaultName, jsonTag string) (string, bool) {
tags := strings.Split(jsonTag, ",")
name := tags[0]
required := true
for _, tag := range tags {
if tag == "omitempty" {
required = false
}
}
if name == "" || name == "omitempty" {
name = defaultName
}
return name, required
}

View File

@ -1,77 +0,0 @@
package egoscale
// ServiceOffering corresponds to the Compute Offerings
//
// A service offering correspond to some hardware features (CPU, RAM).
//
// See: http://docs.cloudstack.apache.org/projects/cloudstack-administration/en/latest/service_offerings.html
type ServiceOffering struct {
Authorized bool `json:"authorized,omitempty" doc:"is the account/domain authorized to use this service offering"`
CPUNumber int `json:"cpunumber,omitempty" doc:"the number of CPU"`
CPUSpeed int `json:"cpuspeed,omitempty" doc:"the clock rate CPU speed in Mhz"`
Created string `json:"created,omitempty" doc:"the date this service offering was created"`
DefaultUse bool `json:"defaultuse,omitempty" doc:"is this a default system vm offering"`
DeploymentPlanner string `json:"deploymentplanner,omitempty" doc:"deployment strategy used to deploy VM."`
DiskBytesReadRate int64 `json:"diskBytesReadRate,omitempty" doc:"bytes read rate of the service offering"`
DiskBytesWriteRate int64 `json:"diskBytesWriteRate,omitempty" doc:"bytes write rate of the service offering"`
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."`
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 *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"`
IsVolatile bool `json:"isvolatile,omitempty" doc:"true if the vm needs to be volatile, i.e., on every reboot of vm from API root disk is discarded and creates a new root disk"`
LimitCPUUse bool `json:"limitcpuuse,omitempty" doc:"restrict the CPU usage to committed service offering"`
MaxIops int64 `json:"maxiops,omitempty" doc:"the max iops of the disk offering"`
Memory int `json:"memory,omitempty" doc:"the memory in MB"`
MinIops int64 `json:"miniops,omitempty" doc:"the min iops of the disk offering"`
Name string `json:"name,omitempty" doc:"the name of the service offering"`
NetworkRate int `json:"networkrate,omitempty" doc:"data transfer rate in megabits per second allowed."`
OfferHA bool `json:"offerha,omitempty" doc:"the ha support in the service offering"`
Restricted bool `json:"restricted,omitempty" doc:"is this offering restricted"`
ServiceOfferingDetails map[string]string `json:"serviceofferingdetails,omitempty" doc:"additional key/value details tied with this service offering"`
StorageType string `json:"storagetype,omitempty" doc:"the storage type for this service offering"`
SystemVMType string `json:"systemvmtype,omitempty" doc:"is this a the systemvm type for system vm offering"`
Tags string `json:"tags,omitempty" doc:"the tags for the service offering"`
}
// ListRequest builds the ListSecurityGroups request
func (so ServiceOffering) ListRequest() (ListCommand, error) {
// Restricted cannot be applied here because it really has three states
req := &ListServiceOfferings{
ID: so.ID,
Name: so.Name,
SystemVMType: so.SystemVMType,
}
if so.IsSystem {
req.IsSystem = &so.IsSystem
}
return req, nil
}
//go:generate go run generate/main.go -interface=Listable ListServiceOfferings
// ListServiceOfferings represents a query for service offerings
type ListServiceOfferings struct {
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"`
Page int `json:"page,omitempty"`
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 *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."`
}
// ListServiceOfferingsResponse represents a list of service offerings
type ListServiceOfferingsResponse struct {
Count int `json:"count"`
ServiceOffering []ServiceOffering `json:"serviceoffering"`
}

View File

@ -1,43 +0,0 @@
// 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
}
}
}

View File

@ -1,139 +0,0 @@
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 string
const (
// Allocated ... (TODO)
Allocated SnapshotState = "Allocated"
// Creating ... (TODO)
Creating SnapshotState = "Creating"
// CreatedOnPrimary ... (TODO)
CreatedOnPrimary SnapshotState = "CreatedOnPrimary"
// BackingUp ... (TODO)
BackingUp SnapshotState = "BackingUp"
// BackedUp ... (TODO)
BackedUp SnapshotState = "BackedUp"
// Copying ... (TODO)
Copying SnapshotState = "Copying"
// Destroying ... (TODO)
Destroying SnapshotState = "Destroying"
// Destroyed ... (TODO)
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 *UUID `json:"accountid,omitempty" doc:"the account ID associated with the snapshot"`
Created string `json:"created,omitempty" doc:"the date the snapshot was created"`
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 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 *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 *UUID `json:"zoneid,omitempty" doc:"id of the availability zone"`
}
// ResourceType returns the type of the resource
func (Snapshot) ResourceType() string {
return "Snapshot"
}
// CreateSnapshot (Async) creates an instant snapshot of a volume
type CreateSnapshot struct {
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."`
}
// Response returns the struct to unmarshal
func (CreateSnapshot) Response() interface{} {
return new(AsyncJobResult)
}
// 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 {
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."`
Keyword string `json:"keyword,omitempty" doc:"List by keyword"`
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 *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."`
}
// ListSnapshotsResponse represents a list of volume snapshots
type ListSnapshotsResponse struct {
Count int `json:"count"`
Snapshot []Snapshot `json:"snapshot"`
}
// DeleteSnapshot (Async) deletes a snapshot of a disk volume
type DeleteSnapshot struct {
ID *UUID `json:"id" doc:"The ID of the snapshot"`
_ bool `name:"deleteSnapshot" description:"Deletes a snapshot of a disk volume."`
}
// Response returns the struct to unmarshal
func (DeleteSnapshot) Response() interface{} {
return new(AsyncJobResult)
}
// 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 *UUID `json:"id" doc:"The ID of the snapshot"`
_ bool `name:"revertSnapshot" description:"revert a volume snapshot."`
}
// Response returns the struct to unmarshal
func (RevertSnapshot) Response() interface{} {
return new(AsyncJobResult)
}
// AsyncResponse returns the struct to unmarshal the async job
func (RevertSnapshot) AsyncResponse() interface{} {
return new(BooleanResponse)
}

View File

@ -1,43 +0,0 @@
// 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
}
}
}

View File

@ -1,105 +0,0 @@
package egoscale
import (
"context"
"fmt"
)
// SSHKeyPair represents an SSH key pair
//
// See: http://docs.cloudstack.apache.org/projects/cloudstack-administration/en/stable/virtual_machines.html#creating-the-ssh-keypair
type SSHKeyPair struct {
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
func (ssh SSHKeyPair) Delete(ctx context.Context, client *Client) error {
if ssh.Name == "" {
return fmt.Errorf("an SSH Key Pair may only be deleted using Name")
}
return client.BooleanRequestWithContext(ctx, &DeleteSSHKeyPair{
Name: ssh.Name,
})
}
// ListRequest builds the ListSSHKeyPairs request
func (ssh SSHKeyPair) ListRequest() (ListCommand, error) {
req := &ListSSHKeyPairs{
Fingerprint: ssh.Fingerprint,
Name: ssh.Name,
}
return req, nil
}
// CreateSSHKeyPair represents a new keypair to be created
type CreateSSHKeyPair struct {
Name string `json:"name" doc:"Name of the keypair"`
_ bool `name:"createSSHKeyPair" description:"Create a new keypair and returns the private key"`
}
// 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"`
_ bool `name:"deleteSSHKeyPair" description:"Deletes a keypair by name"`
}
// 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"`
_ bool `name:"registerSSHKeyPair" description:"Register a public key in a keypair under a certain name"`
}
// 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 {
Fingerprint string `json:"fingerprint,omitempty" doc:"A public key fingerprint to look for"`
Keyword string `json:"keyword,omitempty" doc:"List by keyword"`
Name string `json:"name,omitempty" doc:"A key pair name to look for"`
Page int `json:"page,omitempty"`
PageSize int `json:"pagesize,omitempty"`
_ bool `name:"listSSHKeyPairs" description:"List registered keypairs"`
}
// ListSSHKeyPairsResponse represents a list of SSH key pairs
type ListSSHKeyPairsResponse struct {
Count int `json:"count"`
SSHKeyPair []SSHKeyPair `json:"sshkeypair"`
}
// ResetSSHKeyForVirtualMachine (Async) represents a change for the key pairs
type ResetSSHKeyForVirtualMachine struct {
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."`
}
// Response returns the struct to unmarshal
func (ResetSSHKeyForVirtualMachine) Response() interface{} {
return new(AsyncJobResult)
}
// AsyncResponse returns the struct to unmarshal the async job
func (ResetSSHKeyForVirtualMachine) AsyncResponse() interface{} {
return new(VirtualMachine)
}

View File

@ -1,43 +0,0 @@
// 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
}
}
}

View File

@ -1,84 +0,0 @@
package egoscale
// ResourceTag is a tag associated with a resource
//
// 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"`
Key string `json:"key,omitempty" doc:"tag key name"`
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 []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)"`
}
// Response returns the struct to unmarshal
func (CreateTags) Response() interface{} {
return new(AsyncJobResult)
}
// 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 []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)"`
}
// Response returns the struct to unmarshal
func (DeleteTags) Response() interface{} {
return new(AsyncJobResult)
}
// 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 {
Customer string `json:"customer,omitempty" doc:"list by customer name"`
Key string `json:"key,omitempty" doc:"list by key"`
Keyword string `json:"keyword,omitempty" doc:"List by keyword"`
Page int `json:"page,omitempty"`
PageSize int `json:"pagesize,omitempty"`
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)"`
}
// ListTagsResponse represents a list of resource tags
type ListTagsResponse struct {
Count int `json:"count"`
Tag []ResourceTag `json:"tag"`
}

View File

@ -1,43 +0,0 @@
// 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
}
}
}

View File

@ -1,163 +0,0 @@
package egoscale
// 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 *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"`
Format string `json:"format,omitempty" doc:"the format of 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 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"`
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 *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"`
TemplateDirectory string `json:"templatedirectory,omitempty" doc:"Template directory"`
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 *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"`
}
// ResourceType returns the type of the resource
func (Template) ResourceType() string {
return "Template"
}
// ListRequest builds the ListTemplates request
func (template Template) ListRequest() (ListCommand, error) {
req := &ListTemplates{
ID: template.ID,
Name: template.Name,
ZoneID: template.ZoneID,
}
if template.IsFeatured {
req.TemplateFilter = "featured"
}
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."`
ID *UUID `json:"id,omitempty" doc:"the template ID"`
Keyword string `json:"keyword,omitempty" doc:"List by keyword"`
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"`
Tags []ResourceTag `json:"tags,omitempty" doc:"List resources by tags (key/value pairs)"`
ZoneID *UUID `json:"zoneid,omitempty" doc:"list templates by zoneid"`
_ bool `name:"listTemplates" description:"List all public, private, and privileged templates."`
}
// ListTemplatesResponse represents a list of templates
type ListTemplatesResponse struct {
Count int `json:"count"`
Template []Template `json:"template"`
}
// 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"`
}
// ListRequest builds the ListOSCategories request
func (osCat OSCategory) ListRequest() (ListCommand, error) {
req := &ListOSCategories{
Name: osCat.Name,
ID: osCat.ID,
}
return req, nil
}
//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."`
}
// ListOSCategoriesResponse represents a list of OS categories
type ListOSCategoriesResponse struct {
Count int `json:"count"`
OSCategory []OSCategory `json:"oscategory"`
}
// DeleteTemplate deletes a template by ID
type DeleteTemplate struct {
_ bool `name:"deleteTemplate" description:"Deletes a template"`
ID *UUID `json:"id" doc:"the ID of the template"`
}
// Response returns the struct to unmarshal
func (DeleteTemplate) Response() interface{} {
return new(AsyncJobResult)
}
// AsyncResponse returns the struct to unmarshal the async job
func (DeleteTemplate) AsyncResponse() interface{} {
return new(BooleanResponse)
}
// 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"`
}
// Response returns the struct to unmarshal
func (RegisterCustomTemplate) Response() interface{} {
return new(AsyncJobResult)
}
// AsyncResponse returns the struct to unmarshal the async job
func (RegisterCustomTemplate) AsyncResponse() interface{} {
return new([]Template)
}

View File

@ -1,43 +0,0 @@
// 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
}
}
}

View File

@ -1,63 +0,0 @@
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 *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 *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"`
}
// Response returns the struct to unmarshal
func (RegisterUserKeys) Response() interface{} {
return new(User)
}
//go:generate go run generate/main.go -interface=Listable ListUsers
// ListUsers represents the search for Users
type ListUsers struct {
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
type ListUsersResponse struct {
Count int `json:"count"`
User []User `json:"user"`
}

View File

@ -1,43 +0,0 @@
// 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
}
}
}

View File

@ -1,79 +0,0 @@
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
}

View File

@ -1,4 +0,0 @@
package egoscale
// Version of the library
const Version = "0.18.1"

View File

@ -1,613 +0,0 @@
package egoscale
import (
"bytes"
"compress/gzip"
"context"
"encoding/base64"
"fmt"
"io/ioutil"
"net"
"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 *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
func (VirtualMachine) ResourceType() string {
return "UserVM"
}
// Delete destroys the VM
func (vm VirtualMachine) Delete(ctx context.Context, client *Client) error {
_, err := client.RequestWithContext(ctx, &DestroyVirtualMachine{
ID: vm.ID,
})
return err
}
// ListRequest builds the ListVirtualMachines request
func (vm VirtualMachine) ListRequest() (ListCommand, error) {
// XXX: AffinityGroupID, SecurityGroupID
req := &ListVirtualMachines{
GroupID: vm.GroupID,
ID: vm.ID,
Name: vm.Name,
State: vm.State,
TemplateID: vm.TemplateID,
ZoneID: vm.ZoneID,
}
nic := vm.DefaultNic()
if nic != nil {
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 i, nic := range vm.Nic {
if nic.IsDefault {
return &vm.Nic[i]
}
}
return nil
}
// IP returns the default nic IP address
func (vm VirtualMachine) IP() *net.IP {
nic := vm.DefaultNic()
if nic != nil {
ip := nic.IPAddress
return &ip
}
return nil
}
// NicsByType returns the corresponding interfaces base on the given type
func (vm VirtualMachine) NicsByType(nicType string) []Nic {
nics := make([]Nic, 0)
for _, nic := range vm.Nic {
if nic.Type == nicType {
// XXX The API forgets to specify it
n := nic
n.VirtualMachineID = vm.ID
nics = append(nics, n)
}
}
return nics
}
// 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 UUID) *Nic {
for _, nic := range vm.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 UUID) *Nic {
for _, nic := range vm.Nic {
if nic.ID.Equal(nicID) {
n := nic
n.VirtualMachineID = vm.ID
return &n
}
}
return nil
}
// IPToNetwork represents a mapping between ip and networks
type IPToNetwork struct {
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
type PCIDevice struct {
PCIVendorName string `json:"pcivendorname,omitempty" doc:"Device vendor name of pci card"`
DeviceID string `json:"deviceid,omitempty" doc:"Device model ID of pci card"`
RemainingCapacity int `json:"remainingcapacity,omitempty" doc:"Remaining capacity in terms of no. of more VMs that can be deployped with this vGPU type"`
MaxCapacity int `json:"maxcapacity,omitempty" doc:"Maximum vgpu can be created with this vgpu type on the given pci group"`
PCIVendorID string `json:"pcivendorid,omitempty" doc:"Device vendor ID of pci card"`
PCIDeviceName string `json:"pcidevicename,omitempty" doc:"Device model name of pci card"`
}
// Password represents an encrypted password
//
// TODO: method to decrypt it, https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=34014652
type Password struct {
EncryptedPassword string `json:"encryptedpassword"`
}
// VirtualMachineUserData represents the base64 encoded user-data
type VirtualMachineUserData struct {
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)
func (userdata VirtualMachineUserData) Decode() (string, error) {
data, err := base64.StdEncoding.DecodeString(userdata.UserData)
if err != nil {
return "", err
}
// 0x1f8b is the magic number for gzip
if len(data) < 2 || data[0] != 0x1f || data[1] != 0x8b {
return string(data), nil
}
gr, err := gzip.NewReader(bytes.NewBuffer(data))
if err != nil {
return "", err
}
defer gr.Close() // nolint: errcheck
str, err := ioutil.ReadAll(gr)
if err != nil {
return "", err
}
return string(str), nil
}
// DeployVirtualMachine (Async) represents the machine creation
//
// 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 {
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"`
Details map[string]string `json:"details,omitempty" doc:"used to specify the custom parameters."`
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"`
Group string `json:"group,omitempty" doc:"an optional group for 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"`
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 []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 []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 *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 *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 *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(_ 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")
}
// Either SecurityGroupIDs or SecurityGroupNames must be set
if len(req.SecurityGroupIDs) > 0 && len(req.SecurityGroupNames) > 0 {
return fmt.Errorf("either SecurityGroupIDs or SecurityGroupNames must be set")
}
return nil
}
// Response returns the struct to unmarshal
func (DeployVirtualMachine) Response() interface{} {
return new(AsyncJobResult)
}
// 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 *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."`
}
// Response returns the struct to unmarshal
func (StartVirtualMachine) Response() interface{} {
return new(AsyncJobResult)
}
// 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 *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."`
}
// Response returns the struct to unmarshal
func (StopVirtualMachine) Response() interface{} {
return new(AsyncJobResult)
}
// 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 *UUID `json:"id" doc:"The ID of the virtual machine"`
_ bool `name:"rebootVirtualMachine" description:"Reboots a virtual machine."`
}
// Response returns the struct to unmarshal
func (RebootVirtualMachine) Response() interface{} {
return new(AsyncJobResult)
}
// 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 *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"`
}
// Response returns the struct to unmarshal
func (RestoreVirtualMachine) Response() interface{} {
return new(AsyncJobResult)
}
// 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 *UUID `json:"id" doc:"The ID of the virtual machine"`
_ bool `name:"recoverVirtualMachine" description:"Recovers a virtual machine."`
}
// 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 *UUID `json:"id" doc:"The ID of the virtual machine"`
_ bool `name:"destroyVirtualMachine" description:"Destroys a virtual machine."`
}
// Response returns the struct to unmarshal
func (DestroyVirtualMachine) Response() interface{} {
return new(AsyncJobResult)
}
// 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 *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."`
}
// Response returns the struct to unmarshal
func (UpdateVirtualMachine) Response() interface{} {
return new(VirtualMachine)
}
// ExpungeVirtualMachine represents the annihilation of a VM
type ExpungeVirtualMachine struct {
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."`
}
// Response returns the struct to unmarshal
func (ExpungeVirtualMachine) Response() interface{} {
return new(AsyncJobResult)
}
// 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.
//
// 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 *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."`
}
// Response returns the struct to unmarshal
func (ScaleVirtualMachine) Response() interface{} {
return new(AsyncJobResult)
}
// 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 *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."`
}
// 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 *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."`
}
// Response returns the struct to unmarshal
func (ResetPasswordForVirtualMachine) Response() interface{} {
return new(AsyncJobResult)
}
// 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 *UUID `json:"id" doc:"The ID of the virtual machine"`
_ bool `name:"getVMPassword" description:"Returns an encrypted password for the VM"`
}
// 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 {
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"`
ForVirtualNetwork *bool `json:"forvirtualnetwork,omitempty" doc:"list by network type; true if need to list vms using Virtual Network, false otherwise"`
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 *UUID `json:"isoid,omitempty" doc:"list vms by iso"`
Keyword string `json:"keyword,omitempty" doc:"List by keyword"`
Name string `json:"name,omitempty" doc:"name of the virtual machine"`
NetworkID *UUID `json:"networkid,omitempty" doc:"list by network id"`
Page int `json:"page,omitempty"`
PageSize int `json:"pagesize,omitempty"`
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 *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."`
}
// ListVirtualMachinesResponse represents a list of virtual machines
type ListVirtualMachinesResponse struct {
Count int `json:"count"`
VirtualMachine []VirtualMachine `json:"virtualmachine"`
}
// AddNicToVirtualMachine (Async) adds a NIC to a VM
type AddNicToVirtualMachine struct {
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"`
}
// Response returns the struct to unmarshal
func (AddNicToVirtualMachine) Response() interface{} {
return new(AsyncJobResult)
}
// 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 *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"`
}
// Response returns the struct to unmarshal
func (RemoveNicFromVirtualMachine) Response() interface{} {
return new(AsyncJobResult)
}
// 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 *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"`
}
// Response returns the struct to unmarshal
func (UpdateDefaultNicForVirtualMachine) Response() interface{} {
return new(AsyncJobResult)
}
// 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 *UUID `json:"virtualmachineid" doc:"The ID of the virtual machine"`
_ bool `name:"getVirtualMachineUserData" description:"Returns user data associated with the VM"`
}
// Response returns the struct to unmarshal
func (GetVirtualMachineUserData) Response() interface{} {
return new(VirtualMachineUserData)
}
// 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."`
}
// Response returns the struct to unmarshal
func (UpdateVMNicIP) Response() interface{} {
return new(AsyncJobResult)
}
// AsyncResponse returns the struct to unmarshal the async job
func (UpdateVMNicIP) AsyncResponse() interface{} {
return new(VirtualMachine)
}

View File

@ -1,43 +0,0 @@
// 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
}
}
}

View File

@ -1,113 +0,0 @@
package egoscale
// 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 *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"`
DeviceID int64 `json:"deviceid,omitempty" doc:"the ID of the device on user vm the volume is attahed to. This tag is not returned when the volume is detached."`
DiskBytesReadRate int64 `json:"diskBytesReadRate,omitempty" doc:"bytes read rate of the disk volume"`
DiskBytesWriteRate int64 `json:"diskBytesWriteRate,omitempty" doc:"bytes write rate of the disk volume"`
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 *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."`
Hypervisor string `json:"hypervisor,omitempty" doc:"Hypervisor the volume belongs to"`
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 *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 *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 *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 *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 *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 *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 *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 *UUID `json:"zoneid,omitempty" doc:"ID of the availability zone"`
ZoneName string `json:"zonename,omitempty" doc:"name of the availability zone"`
}
// ResourceType returns the type of the resource
func (Volume) ResourceType() string {
return "Volume"
}
// ListRequest builds the ListVolumes request
func (vol Volume) ListRequest() (ListCommand, error) {
req := &ListVolumes{
Name: vol.Name,
Type: vol.Type,
VirtualMachineID: vol.VirtualMachineID,
ZoneID: vol.ZoneID,
}
return req, nil
}
// ResizeVolume (Async) resizes a volume
type ResizeVolume struct {
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"`
}
// Response returns the struct to unmarshal
func (ResizeVolume) Response() interface{} {
return new(AsyncJobResult)
}
// 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 {
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"`
Name string `json:"name,omitempty" doc:"The name of the disk volume"`
Page int `json:"page,omitempty"`
PageSize int `json:"pagesize,omitempty"`
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 *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."`
}
// ListVolumesResponse represents a list of volumes
type ListVolumesResponse struct {
Count int `json:"count"`
Volume []Volume `json:"volume"`
}

View File

@ -1,43 +0,0 @@
// 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
}
}
}

View File

@ -1,62 +0,0 @@
package egoscale
import (
"net"
)
// Zone represents a data center
//
// TODO: represent correctly the capacity field.
type Zone struct {
AllocationState string `json:"allocationstate,omitempty" doc:"the allocation state of the cluster"`
Description string `json:"description,omitempty" doc:"Zone description"`
DhcpProvider string `json:"dhcpprovider,omitempty" doc:"the dhcp Provider for the Zone"`
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"`
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"`
IP6DNS2 net.IP `json:"ip6dns2,omitempty" doc:"the second IPv6 DNS for the Zone"`
LocalStorageEnabled *bool `json:"localstorageenabled,omitempty" doc:"true if local storage offering enabled, false otherwise"`
Name string `json:"name,omitempty" doc:"Zone name"`
NetworkType string `json:"networktype,omitempty" doc:"the network type of the zone; can be Basic or Advanced"`
ResourceDetails map[string]string `json:"resourcedetails,omitempty" doc:"Meta data associated with the zone (key/value pairs)"`
SecurityGroupsEnabled *bool `json:"securitygroupsenabled,omitempty" doc:"true if security groups support is enabled, false otherwise"`
Tags []ResourceTag `json:"tags,omitempty" doc:"the list of resource tags associated with zone."`
Vlan string `json:"vlan,omitempty" doc:"the vlan range of the zone"`
ZoneToken string `json:"zonetoken,omitempty" doc:"Zone Token"`
}
// ListRequest builds the ListZones request
func (zone Zone) ListRequest() (ListCommand, error) {
req := &ListZones{
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."`
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"`
PageSize int `json:"pagesize,omitempty"`
ShowCapacities *bool `json:"showcapacities,omitempty" doc:"flag to display the capacity of the zones"`
Tags []ResourceTag `json:"tags,omitempty" doc:"List zones by resource tags (key/value pairs)"`
_ bool `name:"listZones" description:"Lists zones"`
}
// ListZonesResponse represents a list of zones
type ListZonesResponse struct {
Count int `json:"count"`
Zone []Zone `json:"zone"`
}

View File

@ -1,43 +0,0 @@
// 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
}
}
}

4
vendor/modules.txt vendored
View File

@ -216,10 +216,8 @@ github.com/digitalocean/godo
github.com/dimchansky/utfbom github.com/dimchansky/utfbom
# github.com/dylanmei/iso8601 v0.1.0 # github.com/dylanmei/iso8601 v0.1.0
github.com/dylanmei/iso8601 github.com/dylanmei/iso8601
# github.com/exoscale/egoscale v0.18.1
## explicit ## explicit
github.com/exoscale/egoscale github.com/fatih/camelcase v1.0.0
# github.com/fatih/camelcase v1.0.0
## explicit ## explicit
github.com/fatih/camelcase github.com/fatih/camelcase
# github.com/fatih/color v1.9.0 # github.com/fatih/color v1.9.0