Merge pull request #6362 from rickard-von-essen/os-token
openstack: Add support for token authorization and cloud.yaml
This commit is contained in:
commit
5d35c71358
@ -2,14 +2,14 @@ package openstack
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"crypto/x509"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
||||
"github.com/gophercloud/gophercloud"
|
||||
"github.com/gophercloud/gophercloud/openstack"
|
||||
"github.com/gophercloud/utils/openstack/clientconfig"
|
||||
"github.com/hashicorp/go-cleanhttp"
|
||||
"github.com/hashicorp/packer/template/interpolate"
|
||||
)
|
||||
@ -30,6 +30,8 @@ type AccessConfig struct {
|
||||
CACertFile string `mapstructure:"cacert"`
|
||||
ClientCertFile string `mapstructure:"cert"`
|
||||
ClientKeyFile string `mapstructure:"key"`
|
||||
Token string `mapstructure:"token"`
|
||||
Cloud string `mapstructure:"cloud"`
|
||||
|
||||
osClient *gophercloud.ProviderClient
|
||||
}
|
||||
@ -42,10 +44,6 @@ func (c *AccessConfig) Prepare(ctx *interpolate.Context) []error {
|
||||
return []error{fmt.Errorf("Invalid endpoint type provided")}
|
||||
}
|
||||
|
||||
if c.Region == "" {
|
||||
c.Region = os.Getenv("OS_REGION_NAME")
|
||||
}
|
||||
|
||||
// Legacy RackSpace stuff. We're keeping this around to keep things BC.
|
||||
if c.Password == "" {
|
||||
c.Password = os.Getenv("SDK_PASSWORD")
|
||||
@ -59,6 +57,15 @@ func (c *AccessConfig) Prepare(ctx *interpolate.Context) []error {
|
||||
if c.Username == "" {
|
||||
c.Username = os.Getenv("SDK_USERNAME")
|
||||
}
|
||||
// End RackSpace
|
||||
|
||||
if c.Cloud == "" {
|
||||
c.Cloud = os.Getenv("OS_CLOUD")
|
||||
}
|
||||
if c.Region == "" {
|
||||
c.Region = os.Getenv("OS_REGION_NAME")
|
||||
}
|
||||
|
||||
if c.CACertFile == "" {
|
||||
c.CACertFile = os.Getenv("OS_CACERT")
|
||||
}
|
||||
@ -69,8 +76,39 @@ func (c *AccessConfig) Prepare(ctx *interpolate.Context) []error {
|
||||
c.ClientKeyFile = os.Getenv("OS_KEY")
|
||||
}
|
||||
|
||||
// Get as much as possible from the end
|
||||
ao, _ := openstack.AuthOptionsFromEnv()
|
||||
clientOpts := new(clientconfig.ClientOpts)
|
||||
|
||||
// If a cloud entry was given, base AuthOptions on a clouds.yaml file.
|
||||
if c.Cloud != "" {
|
||||
clientOpts.Cloud = c.Cloud
|
||||
|
||||
cloud, err := clientconfig.GetCloudFromYAML(clientOpts)
|
||||
if err != nil {
|
||||
return []error{err}
|
||||
}
|
||||
|
||||
if c.Region == "" && cloud.RegionName != "" {
|
||||
c.Region = cloud.RegionName
|
||||
}
|
||||
} else {
|
||||
authInfo := &clientconfig.AuthInfo{
|
||||
AuthURL: c.IdentityEndpoint,
|
||||
DomainID: c.DomainID,
|
||||
DomainName: c.DomainName,
|
||||
Password: c.Password,
|
||||
ProjectID: c.TenantID,
|
||||
ProjectName: c.TenantName,
|
||||
Token: c.Token,
|
||||
Username: c.Username,
|
||||
UserID: c.UserID,
|
||||
}
|
||||
clientOpts.AuthInfo = authInfo
|
||||
}
|
||||
|
||||
ao, err := clientconfig.AuthOptions(clientOpts)
|
||||
if err != nil {
|
||||
return []error{err}
|
||||
}
|
||||
|
||||
// Make sure we reauth as needed
|
||||
ao.AllowReauth = true
|
||||
@ -87,6 +125,7 @@ func (c *AccessConfig) Prepare(ctx *interpolate.Context) []error {
|
||||
{&c.TenantName, &ao.TenantName},
|
||||
{&c.DomainID, &ao.DomainID},
|
||||
{&c.DomainName, &ao.DomainName},
|
||||
{&c.Token, &ao.TokenID},
|
||||
}
|
||||
for _, s := range overrides {
|
||||
if *s.From != "" {
|
||||
@ -132,7 +171,7 @@ func (c *AccessConfig) Prepare(ctx *interpolate.Context) []error {
|
||||
client.HTTPClient.Transport = transport
|
||||
|
||||
// Auth
|
||||
err = openstack.Authenticate(client, ao)
|
||||
err = openstack.Authenticate(client, *ao)
|
||||
if err != nil {
|
||||
return []error{err}
|
||||
}
|
||||
|
148
vendor/github.com/gophercloud/gophercloud/FAQ.md
generated
vendored
148
vendor/github.com/gophercloud/gophercloud/FAQ.md
generated
vendored
@ -1,148 +0,0 @@
|
||||
# Tips
|
||||
|
||||
## Implementing default logging and re-authentication attempts
|
||||
|
||||
You can implement custom logging and/or limit re-auth attempts by creating a custom HTTP client
|
||||
like the following and setting it as the provider client's HTTP Client (via the
|
||||
`gophercloud.ProviderClient.HTTPClient` field):
|
||||
|
||||
```go
|
||||
//...
|
||||
|
||||
// LogRoundTripper satisfies the http.RoundTripper interface and is used to
|
||||
// customize the default Gophercloud RoundTripper to allow for logging.
|
||||
type LogRoundTripper struct {
|
||||
rt http.RoundTripper
|
||||
numReauthAttempts int
|
||||
}
|
||||
|
||||
// newHTTPClient return a custom HTTP client that allows for logging relevant
|
||||
// information before and after the HTTP request.
|
||||
func newHTTPClient() http.Client {
|
||||
return http.Client{
|
||||
Transport: &LogRoundTripper{
|
||||
rt: http.DefaultTransport,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// RoundTrip performs a round-trip HTTP request and logs relevant information about it.
|
||||
func (lrt *LogRoundTripper) RoundTrip(request *http.Request) (*http.Response, error) {
|
||||
glog.Infof("Request URL: %s\n", request.URL)
|
||||
|
||||
response, err := lrt.rt.RoundTrip(request)
|
||||
if response == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if response.StatusCode == http.StatusUnauthorized {
|
||||
if lrt.numReauthAttempts == 3 {
|
||||
return response, fmt.Errorf("Tried to re-authenticate 3 times with no success.")
|
||||
}
|
||||
lrt.numReauthAttempts++
|
||||
}
|
||||
|
||||
glog.Debugf("Response Status: %s\n", response.Status)
|
||||
|
||||
return response, nil
|
||||
}
|
||||
|
||||
endpoint := "https://127.0.0.1/auth"
|
||||
pc := openstack.NewClient(endpoint)
|
||||
pc.HTTPClient = newHTTPClient()
|
||||
|
||||
//...
|
||||
```
|
||||
|
||||
|
||||
## Implementing custom objects
|
||||
|
||||
OpenStack request/response objects may differ among variable names or types.
|
||||
|
||||
### Custom request objects
|
||||
|
||||
To pass custom options to a request, implement the desired `<ACTION>OptsBuilder` interface. For
|
||||
example, to pass in
|
||||
|
||||
```go
|
||||
type MyCreateServerOpts struct {
|
||||
Name string
|
||||
Size int
|
||||
}
|
||||
```
|
||||
|
||||
to `servers.Create`, simply implement the `servers.CreateOptsBuilder` interface:
|
||||
|
||||
```go
|
||||
func (o MyCreateServeropts) ToServerCreateMap() (map[string]interface{}, error) {
|
||||
return map[string]interface{}{
|
||||
"name": o.Name,
|
||||
"size": o.Size,
|
||||
}, nil
|
||||
}
|
||||
```
|
||||
|
||||
create an instance of your custom options object, and pass it to `servers.Create`:
|
||||
|
||||
```go
|
||||
// ...
|
||||
myOpts := MyCreateServerOpts{
|
||||
Name: "s1",
|
||||
Size: "100",
|
||||
}
|
||||
server, err := servers.Create(computeClient, myOpts).Extract()
|
||||
// ...
|
||||
```
|
||||
|
||||
### Custom response objects
|
||||
|
||||
Some OpenStack services have extensions. Extensions that are supported in Gophercloud can be
|
||||
combined to create a custom object:
|
||||
|
||||
```go
|
||||
// ...
|
||||
type MyVolume struct {
|
||||
volumes.Volume
|
||||
tenantattr.VolumeExt
|
||||
}
|
||||
|
||||
var v struct {
|
||||
MyVolume `json:"volume"`
|
||||
}
|
||||
|
||||
err := volumes.Get(client, volID).ExtractInto(&v)
|
||||
// ...
|
||||
```
|
||||
|
||||
## Overriding default `UnmarshalJSON` method
|
||||
|
||||
For some response objects, a field may be a custom type or may be allowed to take on
|
||||
different types. In these cases, overriding the default `UnmarshalJSON` method may be
|
||||
necessary. To do this, declare the JSON `struct` field tag as "-" and create an `UnmarshalJSON`
|
||||
method on the type:
|
||||
|
||||
```go
|
||||
// ...
|
||||
type MyVolume struct {
|
||||
ID string `json: "id"`
|
||||
TimeCreated time.Time `json: "-"`
|
||||
}
|
||||
|
||||
func (r *MyVolume) UnmarshalJSON(b []byte) error {
|
||||
type tmp MyVolume
|
||||
var s struct {
|
||||
tmp
|
||||
TimeCreated gophercloud.JSONRFC3339MilliNoZ `json:"created_at"`
|
||||
}
|
||||
err := json.Unmarshal(b, &s)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*r = Volume(s.tmp)
|
||||
|
||||
r.TimeCreated = time.Time(s.CreatedAt)
|
||||
|
||||
return err
|
||||
}
|
||||
// ...
|
||||
```
|
32
vendor/github.com/gophercloud/gophercloud/MIGRATING.md
generated
vendored
32
vendor/github.com/gophercloud/gophercloud/MIGRATING.md
generated
vendored
@ -1,32 +0,0 @@
|
||||
# Compute
|
||||
|
||||
## Floating IPs
|
||||
|
||||
* `github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/floatingip` is now `github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/floatingips`
|
||||
* `floatingips.Associate` and `floatingips.Disassociate` have been removed.
|
||||
* `floatingips.DisassociateOpts` is now required to disassociate a Floating IP.
|
||||
|
||||
## Security Groups
|
||||
|
||||
* `secgroups.AddServerToGroup` is now `secgroups.AddServer`.
|
||||
* `secgroups.RemoveServerFromGroup` is now `secgroups.RemoveServer`.
|
||||
|
||||
## Servers
|
||||
|
||||
* `servers.Reboot` now requires a `servers.RebootOpts` struct:
|
||||
|
||||
```golang
|
||||
rebootOpts := &servers.RebootOpts{
|
||||
Type: servers.SoftReboot,
|
||||
}
|
||||
res := servers.Reboot(client, server.ID, rebootOpts)
|
||||
```
|
||||
|
||||
# Identity
|
||||
|
||||
## V3
|
||||
|
||||
### Tokens
|
||||
|
||||
* `Token.ExpiresAt` is now of type `gophercloud.JSONRFC3339Milli` instead of
|
||||
`time.Time`
|
18
vendor/github.com/gophercloud/gophercloud/README.md
generated
vendored
18
vendor/github.com/gophercloud/gophercloud/README.md
generated
vendored
@ -127,7 +127,7 @@ new resource in the `server` variable (a
|
||||
|
||||
## Advanced Usage
|
||||
|
||||
Have a look at the [FAQ](./FAQ.md) for some tips on customizing the way Gophercloud works.
|
||||
Have a look at the [FAQ](./docs/FAQ.md) for some tips on customizing the way Gophercloud works.
|
||||
|
||||
## Backwards-Compatibility Guarantees
|
||||
|
||||
@ -141,3 +141,19 @@ See the [contributing guide](./.github/CONTRIBUTING.md).
|
||||
|
||||
If you're struggling with something or have spotted a potential bug, feel free
|
||||
to submit an issue to our [bug tracker](/issues).
|
||||
|
||||
## Thank You
|
||||
|
||||
We'd like to extend special thanks and appreciation to the following:
|
||||
|
||||
### OpenLab
|
||||
|
||||
<a href="http://openlabtesting.org/"><img src="./docs/assets/openlab.png" width="600px"></a>
|
||||
|
||||
OpenLab is providing a full CI environment to test each PR and merge for a variety of OpenStack releases.
|
||||
|
||||
### VEXXHOST
|
||||
|
||||
<a href="https://vexxhost.com/"><img src="./docs/assets/vexxhost.png" width="600px"></a>
|
||||
|
||||
VEXXHOST is providing their services to assist with the development and testing of Gophercloud.
|
||||
|
74
vendor/github.com/gophercloud/gophercloud/STYLEGUIDE.md
generated
vendored
74
vendor/github.com/gophercloud/gophercloud/STYLEGUIDE.md
generated
vendored
@ -1,74 +0,0 @@
|
||||
|
||||
## On Pull Requests
|
||||
|
||||
- Before you start a PR there needs to be a Github issue and a discussion about it
|
||||
on that issue with a core contributor, even if it's just a 'SGTM'.
|
||||
|
||||
- A PR's description must reference the issue it closes with a `For <ISSUE NUMBER>` (e.g. For #293).
|
||||
|
||||
- A PR's description must contain link(s) to the line(s) in the OpenStack
|
||||
source code (on Github) that prove(s) the PR code to be valid. Links to documentation
|
||||
are not good enough. The link(s) should be to a non-`master` branch. For example,
|
||||
a pull request implementing the creation of a Neutron v2 subnet might put the
|
||||
following link in the description:
|
||||
|
||||
https://github.com/openstack/neutron/blob/stable/mitaka/neutron/api/v2/attributes.py#L749
|
||||
|
||||
From that link, a reviewer (or user) can verify the fields in the request/response
|
||||
objects in the PR.
|
||||
|
||||
- A PR that is in-progress should have `[wip]` in front of the PR's title. When
|
||||
ready for review, remove the `[wip]` and ping a core contributor with an `@`.
|
||||
|
||||
- Forcing PRs to be small can have the effect of users submitting PRs in a hierarchical chain, with
|
||||
one depending on the next. If a PR depends on another one, it should have a [Pending #PRNUM]
|
||||
prefix in the PR title. In addition, it will be the PR submitter's responsibility to remove the
|
||||
[Pending #PRNUM] tag once the PR has been updated with the merged, dependent PR. That will
|
||||
let reviewers know it is ready to review.
|
||||
|
||||
- A PR should be small. Even if you intend on implementing an entire
|
||||
service, a PR should only be one route of that service
|
||||
(e.g. create server or get server, but not both).
|
||||
|
||||
- Unless explicitly asked, do not squash commits in the middle of a review; only
|
||||
append. It makes it difficult for the reviewer to see what's changed from one
|
||||
review to the next.
|
||||
|
||||
## On Code
|
||||
|
||||
- In re design: follow as closely as is reasonable the code already in the library.
|
||||
Most operations (e.g. create, delete) admit the same design.
|
||||
|
||||
- Unit tests and acceptance (integration) tests must be written to cover each PR.
|
||||
Tests for operations with several options (e.g. list, create) should include all
|
||||
the options in the tests. This will allow users to verify an operation on their
|
||||
own infrastructure and see an example of usage.
|
||||
|
||||
- If in doubt, ask in-line on the PR.
|
||||
|
||||
### File Structure
|
||||
|
||||
- The following should be used in most cases:
|
||||
|
||||
- `requests.go`: contains all the functions that make HTTP requests and the
|
||||
types associated with the HTTP request (parameters for URL, body, etc)
|
||||
- `results.go`: contains all the response objects and their methods
|
||||
- `urls.go`: contains the endpoints to which the requests are made
|
||||
|
||||
### Naming
|
||||
|
||||
- For methods on a type in `results.go`, the receiver should be named `r` and the
|
||||
variable into which it will be unmarshalled `s`.
|
||||
|
||||
- Functions in `requests.go`, with the exception of functions that return a
|
||||
`pagination.Pager`, should be named returns of the name `r`.
|
||||
|
||||
- Functions in `requests.go` that accept request bodies should accept as their
|
||||
last parameter an `interface` named `<Action>OptsBuilder` (eg `CreateOptsBuilder`).
|
||||
This `interface` should have at the least a method named `To<Resource><Action>Map`
|
||||
(eg `ToPortCreateMap`).
|
||||
|
||||
- Functions in `requests.go` that accept query strings should accept as their
|
||||
last parameter an `interface` named `<Action>OptsBuilder` (eg `ListOptsBuilder`).
|
||||
This `interface` should have at the least a method named `To<Resource><Action>Query`
|
||||
(eg `ToServerListQuery`).
|
112
vendor/github.com/gophercloud/gophercloud/auth_options.go
generated
vendored
112
vendor/github.com/gophercloud/gophercloud/auth_options.go
generated
vendored
@ -9,12 +9,32 @@ ProviderClient representing an active session on that provider.
|
||||
|
||||
Its fields are the union of those recognized by each identity implementation and
|
||||
provider.
|
||||
|
||||
An example of manually providing authentication information:
|
||||
|
||||
opts := gophercloud.AuthOptions{
|
||||
IdentityEndpoint: "https://openstack.example.com:5000/v2.0",
|
||||
Username: "{username}",
|
||||
Password: "{password}",
|
||||
TenantID: "{tenant_id}",
|
||||
}
|
||||
|
||||
provider, err := openstack.AuthenticatedClient(opts)
|
||||
|
||||
An example of using AuthOptionsFromEnv(), where the environment variables can
|
||||
be read from a file, such as a standard openrc file:
|
||||
|
||||
opts, err := openstack.AuthOptionsFromEnv()
|
||||
provider, err := openstack.AuthenticatedClient(opts)
|
||||
*/
|
||||
type AuthOptions struct {
|
||||
// IdentityEndpoint specifies the HTTP endpoint that is required to work with
|
||||
// the Identity API of the appropriate version. While it's ultimately needed by
|
||||
// all of the identity services, it will often be populated by a provider-level
|
||||
// function.
|
||||
//
|
||||
// The IdentityEndpoint is typically referred to as the "auth_url" or
|
||||
// "OS_AUTH_URL" in the information provided by the cloud operator.
|
||||
IdentityEndpoint string `json:"-"`
|
||||
|
||||
// Username is required if using Identity V2 API. Consult with your provider's
|
||||
@ -39,7 +59,7 @@ type AuthOptions struct {
|
||||
// If DomainID or DomainName are provided, they will also apply to TenantName.
|
||||
// It is not currently possible to authenticate with Username and a Domain
|
||||
// and scope to a Project in a different Domain by using TenantName. To
|
||||
// accomplish that, the ProjectID will need to be provided to the TenantID
|
||||
// accomplish that, the ProjectID will need to be provided as the TenantID
|
||||
// option.
|
||||
TenantID string `json:"tenantId,omitempty"`
|
||||
TenantName string `json:"tenantName,omitempty"`
|
||||
@ -50,15 +70,28 @@ type AuthOptions struct {
|
||||
// false, it will not cache these settings, but re-authentication will not be
|
||||
// possible. This setting defaults to false.
|
||||
//
|
||||
// NOTE: The reauth function will try to re-authenticate endlessly if left unchecked.
|
||||
// The way to limit the number of attempts is to provide a custom HTTP client to the provider client
|
||||
// and provide a transport that implements the RoundTripper interface and stores the number of failed retries.
|
||||
// For an example of this, see here: https://github.com/rackspace/rack/blob/1.0.0/auth/clients.go#L311
|
||||
// NOTE: The reauth function will try to re-authenticate endlessly if left
|
||||
// unchecked. The way to limit the number of attempts is to provide a custom
|
||||
// HTTP client to the provider client and provide a transport that implements
|
||||
// the RoundTripper interface and stores the number of failed retries. For an
|
||||
// example of this, see here:
|
||||
// https://github.com/rackspace/rack/blob/1.0.0/auth/clients.go#L311
|
||||
AllowReauth bool `json:"-"`
|
||||
|
||||
// TokenID allows users to authenticate (possibly as another user) with an
|
||||
// authentication token ID.
|
||||
TokenID string `json:"-"`
|
||||
|
||||
// Scope determines the scoping of the authentication request.
|
||||
Scope *AuthScope `json:"-"`
|
||||
}
|
||||
|
||||
// AuthScope allows a created token to be limited to a specific domain or project.
|
||||
type AuthScope struct {
|
||||
ProjectID string
|
||||
ProjectName string
|
||||
DomainID string
|
||||
DomainName string
|
||||
}
|
||||
|
||||
// ToTokenV2CreateMap allows AuthOptions to satisfy the AuthOptionsBuilder
|
||||
@ -241,82 +274,85 @@ func (opts *AuthOptions) ToTokenV3CreateMap(scope map[string]interface{}) (map[s
|
||||
}
|
||||
|
||||
func (opts *AuthOptions) ToTokenV3ScopeMap() (map[string]interface{}, error) {
|
||||
|
||||
var scope struct {
|
||||
ProjectID string
|
||||
ProjectName string
|
||||
DomainID string
|
||||
DomainName string
|
||||
}
|
||||
|
||||
if opts.TenantID != "" {
|
||||
scope.ProjectID = opts.TenantID
|
||||
} else {
|
||||
if opts.TenantName != "" {
|
||||
scope.ProjectName = opts.TenantName
|
||||
scope.DomainID = opts.DomainID
|
||||
scope.DomainName = opts.DomainName
|
||||
// For backwards compatibility.
|
||||
// If AuthOptions.Scope was not set, try to determine it.
|
||||
// This works well for common scenarios.
|
||||
if opts.Scope == nil {
|
||||
opts.Scope = new(AuthScope)
|
||||
if opts.TenantID != "" {
|
||||
opts.Scope.ProjectID = opts.TenantID
|
||||
} else {
|
||||
if opts.TenantName != "" {
|
||||
opts.Scope.ProjectName = opts.TenantName
|
||||
opts.Scope.DomainID = opts.DomainID
|
||||
opts.Scope.DomainName = opts.DomainName
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if scope.ProjectName != "" {
|
||||
if opts.Scope.ProjectName != "" {
|
||||
// ProjectName provided: either DomainID or DomainName must also be supplied.
|
||||
// ProjectID may not be supplied.
|
||||
if scope.DomainID == "" && scope.DomainName == "" {
|
||||
if opts.Scope.DomainID == "" && opts.Scope.DomainName == "" {
|
||||
return nil, ErrScopeDomainIDOrDomainName{}
|
||||
}
|
||||
if scope.ProjectID != "" {
|
||||
if opts.Scope.ProjectID != "" {
|
||||
return nil, ErrScopeProjectIDOrProjectName{}
|
||||
}
|
||||
|
||||
if scope.DomainID != "" {
|
||||
if opts.Scope.DomainID != "" {
|
||||
// ProjectName + DomainID
|
||||
return map[string]interface{}{
|
||||
"project": map[string]interface{}{
|
||||
"name": &scope.ProjectName,
|
||||
"domain": map[string]interface{}{"id": &scope.DomainID},
|
||||
"name": &opts.Scope.ProjectName,
|
||||
"domain": map[string]interface{}{"id": &opts.Scope.DomainID},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
if scope.DomainName != "" {
|
||||
if opts.Scope.DomainName != "" {
|
||||
// ProjectName + DomainName
|
||||
return map[string]interface{}{
|
||||
"project": map[string]interface{}{
|
||||
"name": &scope.ProjectName,
|
||||
"domain": map[string]interface{}{"name": &scope.DomainName},
|
||||
"name": &opts.Scope.ProjectName,
|
||||
"domain": map[string]interface{}{"name": &opts.Scope.DomainName},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
} else if scope.ProjectID != "" {
|
||||
} else if opts.Scope.ProjectID != "" {
|
||||
// ProjectID provided. ProjectName, DomainID, and DomainName may not be provided.
|
||||
if scope.DomainID != "" {
|
||||
if opts.Scope.DomainID != "" {
|
||||
return nil, ErrScopeProjectIDAlone{}
|
||||
}
|
||||
if scope.DomainName != "" {
|
||||
if opts.Scope.DomainName != "" {
|
||||
return nil, ErrScopeProjectIDAlone{}
|
||||
}
|
||||
|
||||
// ProjectID
|
||||
return map[string]interface{}{
|
||||
"project": map[string]interface{}{
|
||||
"id": &scope.ProjectID,
|
||||
"id": &opts.Scope.ProjectID,
|
||||
},
|
||||
}, nil
|
||||
} else if scope.DomainID != "" {
|
||||
} else if opts.Scope.DomainID != "" {
|
||||
// DomainID provided. ProjectID, ProjectName, and DomainName may not be provided.
|
||||
if scope.DomainName != "" {
|
||||
if opts.Scope.DomainName != "" {
|
||||
return nil, ErrScopeDomainIDOrDomainName{}
|
||||
}
|
||||
|
||||
// DomainID
|
||||
return map[string]interface{}{
|
||||
"domain": map[string]interface{}{
|
||||
"id": &scope.DomainID,
|
||||
"id": &opts.Scope.DomainID,
|
||||
},
|
||||
}, nil
|
||||
} else if opts.Scope.DomainName != "" {
|
||||
// DomainName
|
||||
return map[string]interface{}{
|
||||
"domain": map[string]interface{}{
|
||||
"name": &opts.Scope.DomainName,
|
||||
},
|
||||
}, nil
|
||||
} else if scope.DomainName != "" {
|
||||
return nil, ErrScopeDomainName{}
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
|
34
vendor/github.com/gophercloud/gophercloud/doc.go
generated
vendored
34
vendor/github.com/gophercloud/gophercloud/doc.go
generated
vendored
@ -3,11 +3,17 @@ Package gophercloud provides a multi-vendor interface to OpenStack-compatible
|
||||
clouds. The library has a three-level hierarchy: providers, services, and
|
||||
resources.
|
||||
|
||||
Provider structs represent the service providers that offer and manage a
|
||||
collection of services. The IdentityEndpoint is typically refered to as
|
||||
"auth_url" in information provided by the cloud operator. Additionally,
|
||||
the cloud may refer to TenantID or TenantName as project_id and project_name.
|
||||
These are defined like so:
|
||||
Authenticating with Providers
|
||||
|
||||
Provider structs represent the cloud providers that offer and manage a
|
||||
collection of services. You will generally want to create one Provider
|
||||
client per OpenStack cloud.
|
||||
|
||||
Use your OpenStack credentials to create a Provider client. The
|
||||
IdentityEndpoint is typically refered to as "auth_url" or "OS_AUTH_URL" in
|
||||
information provided by the cloud operator. Additionally, the cloud may refer to
|
||||
TenantID or TenantName as project_id and project_name. Credentials are
|
||||
specified like so:
|
||||
|
||||
opts := gophercloud.AuthOptions{
|
||||
IdentityEndpoint: "https://openstack.example.com:5000/v2.0",
|
||||
@ -18,6 +24,16 @@ These are defined like so:
|
||||
|
||||
provider, err := openstack.AuthenticatedClient(opts)
|
||||
|
||||
You may also use the openstack.AuthOptionsFromEnv() helper function. This
|
||||
function reads in standard environment variables frequently found in an
|
||||
OpenStack `openrc` file. Again note that Gophercloud currently uses "tenant"
|
||||
instead of "project".
|
||||
|
||||
opts, err := openstack.AuthOptionsFromEnv()
|
||||
provider, err := openstack.AuthenticatedClient(opts)
|
||||
|
||||
Service Clients
|
||||
|
||||
Service structs are specific to a provider and handle all of the logic and
|
||||
operations for a particular OpenStack service. Examples of services include:
|
||||
Compute, Object Storage, Block Storage. In order to define one, you need to
|
||||
@ -27,6 +43,8 @@ pass in the parent provider, like so:
|
||||
|
||||
client := openstack.NewComputeV2(provider, opts)
|
||||
|
||||
Resources
|
||||
|
||||
Resource structs are the domain models that services make use of in order
|
||||
to work with and represent the state of API resources:
|
||||
|
||||
@ -62,6 +80,12 @@ of results:
|
||||
return true, nil
|
||||
})
|
||||
|
||||
If you want to obtain the entire collection of pages without doing any
|
||||
intermediary processing on each page, you can use the AllPages method:
|
||||
|
||||
allPages, err := servers.List(client, nil).AllPages()
|
||||
allServers, err := servers.ExtractServers(allPages)
|
||||
|
||||
This top-level package contains utility functions and data types that are used
|
||||
throughout the provider and service packages. Of particular note for end users
|
||||
are the AuthOptions and EndpointOpts structs.
|
||||
|
2
vendor/github.com/gophercloud/gophercloud/endpoint_search.go
generated
vendored
2
vendor/github.com/gophercloud/gophercloud/endpoint_search.go
generated
vendored
@ -27,7 +27,7 @@ const (
|
||||
// unambiguously identify one, and only one, endpoint within the catalog.
|
||||
//
|
||||
// Usually, these are passed to service client factory functions in a provider
|
||||
// package, like "rackspace.NewComputeV2()".
|
||||
// package, like "openstack.NewComputeV2()".
|
||||
type EndpointOpts struct {
|
||||
// Type [required] is the service type for the client (e.g., "compute",
|
||||
// "object-store"). Generally, this will be supplied by the service client
|
||||
|
63
vendor/github.com/gophercloud/gophercloud/errors.go
generated
vendored
63
vendor/github.com/gophercloud/gophercloud/errors.go
generated
vendored
@ -1,6 +1,9 @@
|
||||
package gophercloud
|
||||
|
||||
import "fmt"
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// BaseError is an error type that all other error types embed.
|
||||
type BaseError struct {
|
||||
@ -43,6 +46,33 @@ func (e ErrInvalidInput) Error() string {
|
||||
return e.choseErrString()
|
||||
}
|
||||
|
||||
// ErrMissingEnvironmentVariable is the error when environment variable is required
|
||||
// in a particular situation but not provided by the user
|
||||
type ErrMissingEnvironmentVariable struct {
|
||||
BaseError
|
||||
EnvironmentVariable string
|
||||
}
|
||||
|
||||
func (e ErrMissingEnvironmentVariable) Error() string {
|
||||
e.DefaultErrString = fmt.Sprintf("Missing environment variable [%s]", e.EnvironmentVariable)
|
||||
return e.choseErrString()
|
||||
}
|
||||
|
||||
// ErrMissingAnyoneOfEnvironmentVariables is the error when anyone of the environment variables
|
||||
// is required in a particular situation but not provided by the user
|
||||
type ErrMissingAnyoneOfEnvironmentVariables struct {
|
||||
BaseError
|
||||
EnvironmentVariables []string
|
||||
}
|
||||
|
||||
func (e ErrMissingAnyoneOfEnvironmentVariables) Error() string {
|
||||
e.DefaultErrString = fmt.Sprintf(
|
||||
"Missing one of the following environment variables [%s]",
|
||||
strings.Join(e.EnvironmentVariables, ", "),
|
||||
)
|
||||
return e.choseErrString()
|
||||
}
|
||||
|
||||
// ErrUnexpectedResponseCode is returned by the Request method when a response code other than
|
||||
// those listed in OkCodes is encountered.
|
||||
type ErrUnexpectedResponseCode struct {
|
||||
@ -72,6 +102,11 @@ type ErrDefault401 struct {
|
||||
ErrUnexpectedResponseCode
|
||||
}
|
||||
|
||||
// ErrDefault403 is the default error type returned on a 403 HTTP response code.
|
||||
type ErrDefault403 struct {
|
||||
ErrUnexpectedResponseCode
|
||||
}
|
||||
|
||||
// ErrDefault404 is the default error type returned on a 404 HTTP response code.
|
||||
type ErrDefault404 struct {
|
||||
ErrUnexpectedResponseCode
|
||||
@ -103,11 +138,22 @@ type ErrDefault503 struct {
|
||||
}
|
||||
|
||||
func (e ErrDefault400) Error() string {
|
||||
return "Invalid request due to incorrect syntax or missing required parameters."
|
||||
e.DefaultErrString = fmt.Sprintf(
|
||||
"Bad request with: [%s %s], error message: %s",
|
||||
e.Method, e.URL, e.Body,
|
||||
)
|
||||
return e.choseErrString()
|
||||
}
|
||||
func (e ErrDefault401) Error() string {
|
||||
return "Authentication failed"
|
||||
}
|
||||
func (e ErrDefault403) Error() string {
|
||||
e.DefaultErrString = fmt.Sprintf(
|
||||
"Request forbidden: [%s %s], error message: %s",
|
||||
e.Method, e.URL, e.Body,
|
||||
)
|
||||
return e.choseErrString()
|
||||
}
|
||||
func (e ErrDefault404) Error() string {
|
||||
return "Resource not found"
|
||||
}
|
||||
@ -141,6 +187,12 @@ type Err401er interface {
|
||||
Error401(ErrUnexpectedResponseCode) error
|
||||
}
|
||||
|
||||
// Err403er is the interface resource error types implement to override the error message
|
||||
// from a 403 error.
|
||||
type Err403er interface {
|
||||
Error403(ErrUnexpectedResponseCode) error
|
||||
}
|
||||
|
||||
// Err404er is the interface resource error types implement to override the error message
|
||||
// from a 404 error.
|
||||
type Err404er interface {
|
||||
@ -393,13 +445,6 @@ func (e ErrScopeProjectIDAlone) Error() string {
|
||||
return "ProjectID must be supplied alone in a Scope"
|
||||
}
|
||||
|
||||
// ErrScopeDomainName indicates that a DomainName was provided alone in a Scope.
|
||||
type ErrScopeDomainName struct{ BaseError }
|
||||
|
||||
func (e ErrScopeDomainName) Error() string {
|
||||
return "DomainName must be supplied with a ProjectName or ProjectID in a Scope"
|
||||
}
|
||||
|
||||
// ErrScopeEmpty indicates that no credentials were provided in a Scope.
|
||||
type ErrScopeEmpty struct{ BaseError }
|
||||
|
||||
|
47
vendor/github.com/gophercloud/gophercloud/openstack/auth_env.go
generated
vendored
47
vendor/github.com/gophercloud/gophercloud/openstack/auth_env.go
generated
vendored
@ -8,10 +8,27 @@ import (
|
||||
|
||||
var nilOptions = gophercloud.AuthOptions{}
|
||||
|
||||
// AuthOptionsFromEnv fills out an identity.AuthOptions structure with the settings found on the various OpenStack
|
||||
// OS_* environment variables. The following variables provide sources of truth: OS_AUTH_URL, OS_USERNAME,
|
||||
// OS_PASSWORD, OS_TENANT_ID, and OS_TENANT_NAME. Of these, OS_USERNAME, OS_PASSWORD, and OS_AUTH_URL must
|
||||
// have settings, or an error will result. OS_TENANT_ID and OS_TENANT_NAME are optional.
|
||||
/*
|
||||
AuthOptionsFromEnv fills out an identity.AuthOptions structure with the
|
||||
settings found on the various OpenStack OS_* environment variables.
|
||||
|
||||
The following variables provide sources of truth: OS_AUTH_URL, OS_USERNAME,
|
||||
OS_PASSWORD, OS_TENANT_ID, and OS_TENANT_NAME.
|
||||
|
||||
Of these, OS_USERNAME, OS_PASSWORD, and OS_AUTH_URL must have settings,
|
||||
or an error will result. OS_TENANT_ID, OS_TENANT_NAME, OS_PROJECT_ID, and
|
||||
OS_PROJECT_NAME are optional.
|
||||
|
||||
OS_TENANT_ID and OS_TENANT_NAME are mutually exclusive to OS_PROJECT_ID and
|
||||
OS_PROJECT_NAME. If OS_PROJECT_ID and OS_PROJECT_NAME are set, they will
|
||||
still be referred as "tenant" in Gophercloud.
|
||||
|
||||
To use this function, first set the OS_* environment variables (for example,
|
||||
by sourcing an `openrc` file), then:
|
||||
|
||||
opts, err := openstack.AuthOptionsFromEnv()
|
||||
provider, err := openstack.AuthenticatedClient(opts)
|
||||
*/
|
||||
func AuthOptionsFromEnv() (gophercloud.AuthOptions, error) {
|
||||
authURL := os.Getenv("OS_AUTH_URL")
|
||||
username := os.Getenv("OS_USERNAME")
|
||||
@ -22,18 +39,34 @@ func AuthOptionsFromEnv() (gophercloud.AuthOptions, error) {
|
||||
domainID := os.Getenv("OS_DOMAIN_ID")
|
||||
domainName := os.Getenv("OS_DOMAIN_NAME")
|
||||
|
||||
// If OS_PROJECT_ID is set, overwrite tenantID with the value.
|
||||
if v := os.Getenv("OS_PROJECT_ID"); v != "" {
|
||||
tenantID = v
|
||||
}
|
||||
|
||||
// If OS_PROJECT_NAME is set, overwrite tenantName with the value.
|
||||
if v := os.Getenv("OS_PROJECT_NAME"); v != "" {
|
||||
tenantName = v
|
||||
}
|
||||
|
||||
if authURL == "" {
|
||||
err := gophercloud.ErrMissingInput{Argument: "authURL"}
|
||||
err := gophercloud.ErrMissingEnvironmentVariable{
|
||||
EnvironmentVariable: "OS_AUTH_URL",
|
||||
}
|
||||
return nilOptions, err
|
||||
}
|
||||
|
||||
if username == "" && userID == "" {
|
||||
err := gophercloud.ErrMissingInput{Argument: "username"}
|
||||
err := gophercloud.ErrMissingAnyoneOfEnvironmentVariables{
|
||||
EnvironmentVariables: []string{"OS_USERNAME", "OS_USERID"},
|
||||
}
|
||||
return nilOptions, err
|
||||
}
|
||||
|
||||
if password == "" {
|
||||
err := gophercloud.ErrMissingInput{Argument: "password"}
|
||||
err := gophercloud.ErrMissingEnvironmentVariable{
|
||||
EnvironmentVariable: "OS_PASSWORD",
|
||||
}
|
||||
return nilOptions, err
|
||||
}
|
||||
|
||||
|
201
vendor/github.com/gophercloud/gophercloud/openstack/client.go
generated
vendored
201
vendor/github.com/gophercloud/gophercloud/openstack/client.go
generated
vendored
@ -2,7 +2,6 @@ package openstack
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
"reflect"
|
||||
|
||||
"github.com/gophercloud/gophercloud"
|
||||
@ -12,43 +11,66 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
v20 = "v2.0"
|
||||
v30 = "v3.0"
|
||||
// v2 represents Keystone v2.
|
||||
// It should never increase beyond 2.0.
|
||||
v2 = "v2.0"
|
||||
|
||||
// v3 represents Keystone v3.
|
||||
// The version can be anything from v3 to v3.x.
|
||||
v3 = "v3"
|
||||
)
|
||||
|
||||
// NewClient prepares an unauthenticated ProviderClient instance.
|
||||
// Most users will probably prefer using the AuthenticatedClient function instead.
|
||||
// This is useful if you wish to explicitly control the version of the identity service that's used for authentication explicitly,
|
||||
// for example.
|
||||
/*
|
||||
NewClient prepares an unauthenticated ProviderClient instance.
|
||||
Most users will probably prefer using the AuthenticatedClient function
|
||||
instead.
|
||||
|
||||
This is useful if you wish to explicitly control the version of the identity
|
||||
service that's used for authentication explicitly, for example.
|
||||
|
||||
A basic example of using this would be:
|
||||
|
||||
ao, err := openstack.AuthOptionsFromEnv()
|
||||
provider, err := openstack.NewClient(ao.IdentityEndpoint)
|
||||
client, err := openstack.NewIdentityV3(provider, gophercloud.EndpointOpts{})
|
||||
*/
|
||||
func NewClient(endpoint string) (*gophercloud.ProviderClient, error) {
|
||||
u, err := url.Parse(endpoint)
|
||||
base, err := utils.BaseEndpoint(endpoint)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
hadPath := u.Path != ""
|
||||
u.Path, u.RawQuery, u.Fragment = "", "", ""
|
||||
base := u.String()
|
||||
|
||||
endpoint = gophercloud.NormalizeURL(endpoint)
|
||||
base = gophercloud.NormalizeURL(base)
|
||||
|
||||
if hadPath {
|
||||
return &gophercloud.ProviderClient{
|
||||
IdentityBase: base,
|
||||
IdentityEndpoint: endpoint,
|
||||
}, nil
|
||||
}
|
||||
p := new(gophercloud.ProviderClient)
|
||||
p.IdentityBase = base
|
||||
p.IdentityEndpoint = endpoint
|
||||
p.UseTokenLock()
|
||||
|
||||
return &gophercloud.ProviderClient{
|
||||
IdentityBase: base,
|
||||
IdentityEndpoint: "",
|
||||
}, nil
|
||||
return p, nil
|
||||
}
|
||||
|
||||
// AuthenticatedClient logs in to an OpenStack cloud found at the identity endpoint specified by options, acquires a token, and
|
||||
// returns a Client instance that's ready to operate.
|
||||
// It first queries the root identity endpoint to determine which versions of the identity service are supported, then chooses
|
||||
// the most recent identity service available to proceed.
|
||||
/*
|
||||
AuthenticatedClient logs in to an OpenStack cloud found at the identity endpoint
|
||||
specified by the options, acquires a token, and returns a Provider Client
|
||||
instance that's ready to operate.
|
||||
|
||||
If the full path to a versioned identity endpoint was specified (example:
|
||||
http://example.com:5000/v3), that path will be used as the endpoint to query.
|
||||
|
||||
If a versionless endpoint was specified (example: http://example.com:5000/),
|
||||
the endpoint will be queried to determine which versions of the identity service
|
||||
are available, then chooses the most recent or most supported version.
|
||||
|
||||
Example:
|
||||
|
||||
ao, err := openstack.AuthOptionsFromEnv()
|
||||
provider, err := openstack.AuthenticatedClient(ao)
|
||||
client, err := openstack.NewNetworkV2(client, gophercloud.EndpointOpts{
|
||||
Region: os.Getenv("OS_REGION_NAME"),
|
||||
})
|
||||
*/
|
||||
func AuthenticatedClient(options gophercloud.AuthOptions) (*gophercloud.ProviderClient, error) {
|
||||
client, err := NewClient(options.IdentityEndpoint)
|
||||
if err != nil {
|
||||
@ -62,11 +84,12 @@ func AuthenticatedClient(options gophercloud.AuthOptions) (*gophercloud.Provider
|
||||
return client, nil
|
||||
}
|
||||
|
||||
// Authenticate or re-authenticate against the most recent identity service supported at the provided endpoint.
|
||||
// Authenticate or re-authenticate against the most recent identity service
|
||||
// supported at the provided endpoint.
|
||||
func Authenticate(client *gophercloud.ProviderClient, options gophercloud.AuthOptions) error {
|
||||
versions := []*utils.Version{
|
||||
{ID: v20, Priority: 20, Suffix: "/v2.0/"},
|
||||
{ID: v30, Priority: 30, Suffix: "/v3/"},
|
||||
{ID: v2, Priority: 20, Suffix: "/v2.0/"},
|
||||
{ID: v3, Priority: 30, Suffix: "/v3/"},
|
||||
}
|
||||
|
||||
chosen, endpoint, err := utils.ChooseVersion(client, versions)
|
||||
@ -75,9 +98,9 @@ func Authenticate(client *gophercloud.ProviderClient, options gophercloud.AuthOp
|
||||
}
|
||||
|
||||
switch chosen.ID {
|
||||
case v20:
|
||||
case v2:
|
||||
return v2auth(client, endpoint, options, gophercloud.EndpointOpts{})
|
||||
case v30:
|
||||
case v3:
|
||||
return v3auth(client, endpoint, &options, gophercloud.EndpointOpts{})
|
||||
default:
|
||||
// The switch statement must be out of date from the versions list.
|
||||
@ -123,9 +146,21 @@ func v2auth(client *gophercloud.ProviderClient, endpoint string, options gopherc
|
||||
}
|
||||
|
||||
if options.AllowReauth {
|
||||
// here we're creating a throw-away client (tac). it's a copy of the user's provider client, but
|
||||
// with the token and reauth func zeroed out. combined with setting `AllowReauth` to `false`,
|
||||
// this should retry authentication only once
|
||||
tac := *client
|
||||
tac.ReauthFunc = nil
|
||||
tac.TokenID = ""
|
||||
tao := options
|
||||
tao.AllowReauth = false
|
||||
client.ReauthFunc = func() error {
|
||||
client.TokenID = ""
|
||||
return v2auth(client, endpoint, options, eo)
|
||||
err := v2auth(&tac, endpoint, tao, eo)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
client.TokenID = tac.TokenID
|
||||
return nil
|
||||
}
|
||||
}
|
||||
client.TokenID = token.ID
|
||||
@ -167,9 +202,32 @@ func v3auth(client *gophercloud.ProviderClient, endpoint string, opts tokens3.Au
|
||||
client.TokenID = token.ID
|
||||
|
||||
if opts.CanReauth() {
|
||||
// here we're creating a throw-away client (tac). it's a copy of the user's provider client, but
|
||||
// with the token and reauth func zeroed out. combined with setting `AllowReauth` to `false`,
|
||||
// this should retry authentication only once
|
||||
tac := *client
|
||||
tac.ReauthFunc = nil
|
||||
tac.TokenID = ""
|
||||
var tao tokens3.AuthOptionsBuilder
|
||||
switch ot := opts.(type) {
|
||||
case *gophercloud.AuthOptions:
|
||||
o := *ot
|
||||
o.AllowReauth = false
|
||||
tao = &o
|
||||
case *tokens3.AuthOptions:
|
||||
o := *ot
|
||||
o.AllowReauth = false
|
||||
tao = &o
|
||||
default:
|
||||
tao = opts
|
||||
}
|
||||
client.ReauthFunc = func() error {
|
||||
client.TokenID = ""
|
||||
return v3auth(client, endpoint, opts, eo)
|
||||
err := v3auth(&tac, endpoint, tao, eo)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
client.TokenID = tac.TokenID
|
||||
return nil
|
||||
}
|
||||
}
|
||||
client.EndpointLocator = func(opts gophercloud.EndpointOpts) (string, error) {
|
||||
@ -179,7 +237,8 @@ func v3auth(client *gophercloud.ProviderClient, endpoint string, opts tokens3.Au
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewIdentityV2 creates a ServiceClient that may be used to interact with the v2 identity service.
|
||||
// NewIdentityV2 creates a ServiceClient that may be used to interact with the
|
||||
// v2 identity service.
|
||||
func NewIdentityV2(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
|
||||
endpoint := client.IdentityBase + "v2.0/"
|
||||
clientType := "identity"
|
||||
@ -199,7 +258,8 @@ func NewIdentityV2(client *gophercloud.ProviderClient, eo gophercloud.EndpointOp
|
||||
}, nil
|
||||
}
|
||||
|
||||
// NewIdentityV3 creates a ServiceClient that may be used to access the v3 identity service.
|
||||
// NewIdentityV3 creates a ServiceClient that may be used to access the v3
|
||||
// identity service.
|
||||
func NewIdentityV3(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
|
||||
endpoint := client.IdentityBase + "v3/"
|
||||
clientType := "identity"
|
||||
@ -212,6 +272,19 @@ func NewIdentityV3(client *gophercloud.ProviderClient, eo gophercloud.EndpointOp
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure endpoint still has a suffix of v3.
|
||||
// This is because EndpointLocator might have found a versionless
|
||||
// endpoint or the published endpoint is still /v2.0. In both
|
||||
// cases, we need to fix the endpoint to point to /v3.
|
||||
base, err := utils.BaseEndpoint(endpoint)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
base = gophercloud.NormalizeURL(base)
|
||||
|
||||
endpoint = base + "v3/"
|
||||
|
||||
return &gophercloud.ServiceClient{
|
||||
ProviderClient: client,
|
||||
Endpoint: endpoint,
|
||||
@ -232,33 +305,43 @@ func initClientOpts(client *gophercloud.ProviderClient, eo gophercloud.EndpointO
|
||||
return sc, nil
|
||||
}
|
||||
|
||||
// NewObjectStorageV1 creates a ServiceClient that may be used with the v1 object storage package.
|
||||
// NewObjectStorageV1 creates a ServiceClient that may be used with the v1
|
||||
// object storage package.
|
||||
func NewObjectStorageV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
|
||||
return initClientOpts(client, eo, "object-store")
|
||||
}
|
||||
|
||||
// NewComputeV2 creates a ServiceClient that may be used with the v2 compute package.
|
||||
// NewComputeV2 creates a ServiceClient that may be used with the v2 compute
|
||||
// package.
|
||||
func NewComputeV2(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
|
||||
return initClientOpts(client, eo, "compute")
|
||||
}
|
||||
|
||||
// NewNetworkV2 creates a ServiceClient that may be used with the v2 network package.
|
||||
// NewNetworkV2 creates a ServiceClient that may be used with the v2 network
|
||||
// package.
|
||||
func NewNetworkV2(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
|
||||
sc, err := initClientOpts(client, eo, "network")
|
||||
sc.ResourceBase = sc.Endpoint + "v2.0/"
|
||||
return sc, err
|
||||
}
|
||||
|
||||
// NewBlockStorageV1 creates a ServiceClient that may be used to access the v1 block storage service.
|
||||
// NewBlockStorageV1 creates a ServiceClient that may be used to access the v1
|
||||
// block storage service.
|
||||
func NewBlockStorageV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
|
||||
return initClientOpts(client, eo, "volume")
|
||||
}
|
||||
|
||||
// NewBlockStorageV2 creates a ServiceClient that may be used to access the v2 block storage service.
|
||||
// NewBlockStorageV2 creates a ServiceClient that may be used to access the v2
|
||||
// block storage service.
|
||||
func NewBlockStorageV2(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
|
||||
return initClientOpts(client, eo, "volumev2")
|
||||
}
|
||||
|
||||
// NewBlockStorageV3 creates a ServiceClient that may be used to access the v3 block storage service.
|
||||
func NewBlockStorageV3(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
|
||||
return initClientOpts(client, eo, "volumev3")
|
||||
}
|
||||
|
||||
// NewSharedFileSystemV2 creates a ServiceClient that may be used to access the v2 shared file system service.
|
||||
func NewSharedFileSystemV2(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
|
||||
return initClientOpts(client, eo, "sharev2")
|
||||
@ -270,7 +353,8 @@ func NewCDNV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (
|
||||
return initClientOpts(client, eo, "cdn")
|
||||
}
|
||||
|
||||
// NewOrchestrationV1 creates a ServiceClient that may be used to access the v1 orchestration service.
|
||||
// NewOrchestrationV1 creates a ServiceClient that may be used to access the v1
|
||||
// orchestration service.
|
||||
func NewOrchestrationV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
|
||||
return initClientOpts(client, eo, "orchestration")
|
||||
}
|
||||
@ -280,16 +364,45 @@ func NewDBV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*
|
||||
return initClientOpts(client, eo, "database")
|
||||
}
|
||||
|
||||
// NewDNSV2 creates a ServiceClient that may be used to access the v2 DNS service.
|
||||
// NewDNSV2 creates a ServiceClient that may be used to access the v2 DNS
|
||||
// service.
|
||||
func NewDNSV2(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
|
||||
sc, err := initClientOpts(client, eo, "dns")
|
||||
sc.ResourceBase = sc.Endpoint + "v2/"
|
||||
return sc, err
|
||||
}
|
||||
|
||||
// NewImageServiceV2 creates a ServiceClient that may be used to access the v2 image service.
|
||||
// NewImageServiceV2 creates a ServiceClient that may be used to access the v2
|
||||
// image service.
|
||||
func NewImageServiceV2(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
|
||||
sc, err := initClientOpts(client, eo, "image")
|
||||
sc.ResourceBase = sc.Endpoint + "v2/"
|
||||
return sc, err
|
||||
}
|
||||
|
||||
// NewLoadBalancerV2 creates a ServiceClient that may be used to access the v2
|
||||
// load balancer service.
|
||||
func NewLoadBalancerV2(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
|
||||
sc, err := initClientOpts(client, eo, "load-balancer")
|
||||
sc.ResourceBase = sc.Endpoint + "v2.0/"
|
||||
return sc, err
|
||||
}
|
||||
|
||||
// NewClusteringV1 creates a ServiceClient that may be used with the v1 clustering
|
||||
// package.
|
||||
func NewClusteringV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
|
||||
return initClientOpts(client, eo, "clustering")
|
||||
}
|
||||
|
||||
// NewMessagingV2 creates a ServiceClient that may be used with the v2 messaging
|
||||
// service.
|
||||
func NewMessagingV2(client *gophercloud.ProviderClient, clientID string, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
|
||||
sc, err := initClientOpts(client, eo, "messaging")
|
||||
sc.MoreHeaders = map[string]string{"Client-ID": clientID}
|
||||
return sc, err
|
||||
}
|
||||
|
||||
// NewContainerV1 creates a ServiceClient that may be used with v1 container package
|
||||
func NewContainerV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
|
||||
return initClientOpts(client, eo, "container")
|
||||
}
|
||||
|
15
vendor/github.com/gophercloud/gophercloud/openstack/common/extensions/doc.go
generated
vendored
15
vendor/github.com/gophercloud/gophercloud/openstack/common/extensions/doc.go
generated
vendored
@ -1,15 +0,0 @@
|
||||
// Package extensions provides information and interaction with the different extensions available
|
||||
// for an OpenStack service.
|
||||
//
|
||||
// The purpose of OpenStack API extensions is to:
|
||||
//
|
||||
// - Introduce new features in the API without requiring a version change.
|
||||
// - Introduce vendor-specific niche functionality.
|
||||
// - Act as a proving ground for experimental functionalities that might be included in a future
|
||||
// version of the API.
|
||||
//
|
||||
// Extensions usually have tags that prevent conflicts with other extensions that define attributes
|
||||
// or resources with the same names, and with core resources and attributes.
|
||||
// Because an extension might not be supported by all plug-ins, its availability varies with deployments
|
||||
// and the specific plug-in.
|
||||
package extensions
|
1
vendor/github.com/gophercloud/gophercloud/openstack/common/extensions/errors.go
generated
vendored
1
vendor/github.com/gophercloud/gophercloud/openstack/common/extensions/errors.go
generated
vendored
@ -1 +0,0 @@
|
||||
package extensions
|
20
vendor/github.com/gophercloud/gophercloud/openstack/common/extensions/requests.go
generated
vendored
20
vendor/github.com/gophercloud/gophercloud/openstack/common/extensions/requests.go
generated
vendored
@ -1,20 +0,0 @@
|
||||
package extensions
|
||||
|
||||
import (
|
||||
"github.com/gophercloud/gophercloud"
|
||||
"github.com/gophercloud/gophercloud/pagination"
|
||||
)
|
||||
|
||||
// Get retrieves information for a specific extension using its alias.
|
||||
func Get(c *gophercloud.ServiceClient, alias string) (r GetResult) {
|
||||
_, r.Err = c.Get(ExtensionURL(c, alias), &r.Body, nil)
|
||||
return
|
||||
}
|
||||
|
||||
// List returns a Pager which allows you to iterate over the full collection of extensions.
|
||||
// It does not accept query parameters.
|
||||
func List(c *gophercloud.ServiceClient) pagination.Pager {
|
||||
return pagination.NewPager(c, ListExtensionURL(c), func(r pagination.PageResult) pagination.Page {
|
||||
return ExtensionPage{pagination.SinglePageBase(r)}
|
||||
})
|
||||
}
|
53
vendor/github.com/gophercloud/gophercloud/openstack/common/extensions/results.go
generated
vendored
53
vendor/github.com/gophercloud/gophercloud/openstack/common/extensions/results.go
generated
vendored
@ -1,53 +0,0 @@
|
||||
package extensions
|
||||
|
||||
import (
|
||||
"github.com/gophercloud/gophercloud"
|
||||
"github.com/gophercloud/gophercloud/pagination"
|
||||
)
|
||||
|
||||
// GetResult temporarily stores the result of a Get call.
|
||||
// Use its Extract() method to interpret it as an Extension.
|
||||
type GetResult struct {
|
||||
gophercloud.Result
|
||||
}
|
||||
|
||||
// Extract interprets a GetResult as an Extension.
|
||||
func (r GetResult) Extract() (*Extension, error) {
|
||||
var s struct {
|
||||
Extension *Extension `json:"extension"`
|
||||
}
|
||||
err := r.ExtractInto(&s)
|
||||
return s.Extension, err
|
||||
}
|
||||
|
||||
// Extension is a struct that represents an OpenStack extension.
|
||||
type Extension struct {
|
||||
Updated string `json:"updated"`
|
||||
Name string `json:"name"`
|
||||
Links []interface{} `json:"links"`
|
||||
Namespace string `json:"namespace"`
|
||||
Alias string `json:"alias"`
|
||||
Description string `json:"description"`
|
||||
}
|
||||
|
||||
// ExtensionPage is the page returned by a pager when traversing over a collection of extensions.
|
||||
type ExtensionPage struct {
|
||||
pagination.SinglePageBase
|
||||
}
|
||||
|
||||
// IsEmpty checks whether an ExtensionPage struct is empty.
|
||||
func (r ExtensionPage) IsEmpty() (bool, error) {
|
||||
is, err := ExtractExtensions(r)
|
||||
return len(is) == 0, err
|
||||
}
|
||||
|
||||
// ExtractExtensions accepts a Page struct, specifically an ExtensionPage struct, and extracts the
|
||||
// elements into a slice of Extension structs.
|
||||
// In other words, a generic collection is mapped into a relevant slice.
|
||||
func ExtractExtensions(r pagination.Page) ([]Extension, error) {
|
||||
var s struct {
|
||||
Extensions []Extension `json:"extensions"`
|
||||
}
|
||||
err := (r.(ExtensionPage)).ExtractInto(&s)
|
||||
return s.Extensions, err
|
||||
}
|
13
vendor/github.com/gophercloud/gophercloud/openstack/common/extensions/urls.go
generated
vendored
13
vendor/github.com/gophercloud/gophercloud/openstack/common/extensions/urls.go
generated
vendored
@ -1,13 +0,0 @@
|
||||
package extensions
|
||||
|
||||
import "github.com/gophercloud/gophercloud"
|
||||
|
||||
// ExtensionURL generates the URL for an extension resource by name.
|
||||
func ExtensionURL(c *gophercloud.ServiceClient, name string) string {
|
||||
return c.ServiceURL("extensions", name)
|
||||
}
|
||||
|
||||
// ListExtensionURL generates the URL for the extensions resource collection.
|
||||
func ListExtensionURL(c *gophercloud.ServiceClient) string {
|
||||
return c.ServiceURL("extensions")
|
||||
}
|
23
vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/delegate.go
generated
vendored
23
vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/delegate.go
generated
vendored
@ -1,23 +0,0 @@
|
||||
package extensions
|
||||
|
||||
import (
|
||||
"github.com/gophercloud/gophercloud"
|
||||
common "github.com/gophercloud/gophercloud/openstack/common/extensions"
|
||||
"github.com/gophercloud/gophercloud/pagination"
|
||||
)
|
||||
|
||||
// ExtractExtensions interprets a Page as a slice of Extensions.
|
||||
func ExtractExtensions(page pagination.Page) ([]common.Extension, error) {
|
||||
return common.ExtractExtensions(page)
|
||||
}
|
||||
|
||||
// Get retrieves information for a specific extension using its alias.
|
||||
func Get(c *gophercloud.ServiceClient, alias string) common.GetResult {
|
||||
return common.Get(c, alias)
|
||||
}
|
||||
|
||||
// List returns a Pager which allows you to iterate over the full collection of extensions.
|
||||
// It does not accept query parameters.
|
||||
func List(c *gophercloud.ServiceClient) pagination.Pager {
|
||||
return common.List(c)
|
||||
}
|
3
vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/doc.go
generated
vendored
3
vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/doc.go
generated
vendored
@ -1,3 +0,0 @@
|
||||
// Package extensions provides information and interaction with the
|
||||
// different extensions available for the OpenStack Compute service.
|
||||
package extensions
|
@ -1,3 +1,68 @@
|
||||
// Package floatingips provides the ability to manage floating ips through
|
||||
// nova-network
|
||||
/*
|
||||
Package floatingips provides the ability to manage floating ips through the
|
||||
Nova API.
|
||||
|
||||
This API has been deprecated and will be removed from a future release of the
|
||||
Nova API service.
|
||||
|
||||
For environements that support this extension, this package can be used
|
||||
regardless of if either Neutron or nova-network is used as the cloud's network
|
||||
service.
|
||||
|
||||
Example to List Floating IPs
|
||||
|
||||
allPages, err := floatingips.List(computeClient).AllPages()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
allFloatingIPs, err := floatingips.ExtractFloatingIPs(allPages)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
for _, fip := range allFloatingIPs {
|
||||
fmt.Printf("%+v\n", fip)
|
||||
}
|
||||
|
||||
Example to Create a Floating IP
|
||||
|
||||
createOpts := floatingips.CreateOpts{
|
||||
Pool: "nova",
|
||||
}
|
||||
|
||||
fip, err := floatingips.Create(computeClient, createOpts).Extract()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
Example to Delete a Floating IP
|
||||
|
||||
err := floatingips.Delete(computeClient, "floatingip-id").ExtractErr()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
Example to Associate a Floating IP With a Server
|
||||
|
||||
associateOpts := floatingips.AssociateOpts{
|
||||
FloatingIP: "10.10.10.2",
|
||||
}
|
||||
|
||||
err := floatingips.AssociateInstance(computeClient, "server-id", associateOpts).ExtractErr()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
Example to Disassociate a Floating IP From a Server
|
||||
|
||||
disassociateOpts := floatingips.DisassociateOpts{
|
||||
FloatingIP: "10.10.10.2",
|
||||
}
|
||||
|
||||
err := floatingips.DisassociateInstance(computeClient, "server-id", disassociateOpts).ExtractErr()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
*/
|
||||
package floatingips
|
||||
|
@ -12,15 +12,15 @@ func List(client *gophercloud.ServiceClient) pagination.Pager {
|
||||
})
|
||||
}
|
||||
|
||||
// CreateOptsBuilder describes struct types that can be accepted by the Create call. Notable, the
|
||||
// CreateOpts struct in this package does.
|
||||
// CreateOptsBuilder allows extensions to add additional parameters to the
|
||||
// Create request.
|
||||
type CreateOptsBuilder interface {
|
||||
ToFloatingIPCreateMap() (map[string]interface{}, error)
|
||||
}
|
||||
|
||||
// CreateOpts specifies a Floating IP allocation request
|
||||
// CreateOpts specifies a Floating IP allocation request.
|
||||
type CreateOpts struct {
|
||||
// Pool is the pool of floating IPs to allocate one from
|
||||
// Pool is the pool of Floating IPs to allocate one from.
|
||||
Pool string `json:"pool" required:"true"`
|
||||
}
|
||||
|
||||
@ -29,7 +29,7 @@ func (opts CreateOpts) ToFloatingIPCreateMap() (map[string]interface{}, error) {
|
||||
return gophercloud.BuildRequestBody(opts, "")
|
||||
}
|
||||
|
||||
// Create requests the creation of a new floating IP
|
||||
// Create requests the creation of a new Floating IP.
|
||||
func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) (r CreateResult) {
|
||||
b, err := opts.ToFloatingIPCreateMap()
|
||||
if err != nil {
|
||||
@ -42,29 +42,30 @@ func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) (r Create
|
||||
return
|
||||
}
|
||||
|
||||
// Get returns data about a previously created FloatingIP.
|
||||
// Get returns data about a previously created Floating IP.
|
||||
func Get(client *gophercloud.ServiceClient, id string) (r GetResult) {
|
||||
_, r.Err = client.Get(getURL(client, id), &r.Body, nil)
|
||||
return
|
||||
}
|
||||
|
||||
// Delete requests the deletion of a previous allocated FloatingIP.
|
||||
// Delete requests the deletion of a previous allocated Floating IP.
|
||||
func Delete(client *gophercloud.ServiceClient, id string) (r DeleteResult) {
|
||||
_, r.Err = client.Delete(deleteURL(client, id), nil)
|
||||
return
|
||||
}
|
||||
|
||||
// AssociateOptsBuilder is the interface types must satfisfy to be used as
|
||||
// Associate options
|
||||
// AssociateOptsBuilder allows extensions to add additional parameters to the
|
||||
// Associate request.
|
||||
type AssociateOptsBuilder interface {
|
||||
ToFloatingIPAssociateMap() (map[string]interface{}, error)
|
||||
}
|
||||
|
||||
// AssociateOpts specifies the required information to associate a floating IP with an instance
|
||||
// AssociateOpts specifies the required information to associate a Floating IP with an instance
|
||||
type AssociateOpts struct {
|
||||
// FloatingIP is the floating IP to associate with an instance
|
||||
// FloatingIP is the Floating IP to associate with an instance.
|
||||
FloatingIP string `json:"address" required:"true"`
|
||||
// FixedIP is an optional fixed IP address of the server
|
||||
|
||||
// FixedIP is an optional fixed IP address of the server.
|
||||
FixedIP string `json:"fixed_address,omitempty"`
|
||||
}
|
||||
|
||||
@ -73,7 +74,7 @@ func (opts AssociateOpts) ToFloatingIPAssociateMap() (map[string]interface{}, er
|
||||
return gophercloud.BuildRequestBody(opts, "addFloatingIp")
|
||||
}
|
||||
|
||||
// AssociateInstance pairs an allocated floating IP with an instance.
|
||||
// AssociateInstance pairs an allocated Floating IP with a server.
|
||||
func AssociateInstance(client *gophercloud.ServiceClient, serverID string, opts AssociateOptsBuilder) (r AssociateResult) {
|
||||
b, err := opts.ToFloatingIPAssociateMap()
|
||||
if err != nil {
|
||||
@ -84,23 +85,24 @@ func AssociateInstance(client *gophercloud.ServiceClient, serverID string, opts
|
||||
return
|
||||
}
|
||||
|
||||
// DisassociateOptsBuilder is the interface types must satfisfy to be used as
|
||||
// Disassociate options
|
||||
// DisassociateOptsBuilder allows extensions to add additional parameters to
|
||||
// the Disassociate request.
|
||||
type DisassociateOptsBuilder interface {
|
||||
ToFloatingIPDisassociateMap() (map[string]interface{}, error)
|
||||
}
|
||||
|
||||
// DisassociateOpts specifies the required information to disassociate a floating IP with an instance
|
||||
// DisassociateOpts specifies the required information to disassociate a
|
||||
// Floating IP with a server.
|
||||
type DisassociateOpts struct {
|
||||
FloatingIP string `json:"address" required:"true"`
|
||||
}
|
||||
|
||||
// ToFloatingIPDisassociateMap constructs a request body from AssociateOpts.
|
||||
// ToFloatingIPDisassociateMap constructs a request body from DisassociateOpts.
|
||||
func (opts DisassociateOpts) ToFloatingIPDisassociateMap() (map[string]interface{}, error) {
|
||||
return gophercloud.BuildRequestBody(opts, "removeFloatingIp")
|
||||
}
|
||||
|
||||
// DisassociateInstance decouples an allocated floating IP from an instance
|
||||
// DisassociateInstance decouples an allocated Floating IP from an instance
|
||||
func DisassociateInstance(client *gophercloud.ServiceClient, serverID string, opts DisassociateOptsBuilder) (r DisassociateResult) {
|
||||
b, err := opts.ToFloatingIPDisassociateMap()
|
||||
if err != nil {
|
||||
|
@ -8,21 +8,21 @@ import (
|
||||
"github.com/gophercloud/gophercloud/pagination"
|
||||
)
|
||||
|
||||
// A FloatingIP is an IP that can be associated with an instance
|
||||
// A FloatingIP is an IP that can be associated with a server.
|
||||
type FloatingIP struct {
|
||||
// ID is a unique ID of the Floating IP
|
||||
ID string `json:"-"`
|
||||
|
||||
// FixedIP is the IP of the instance related to the Floating IP
|
||||
// FixedIP is a specific IP on the server to pair the Floating IP with.
|
||||
FixedIP string `json:"fixed_ip,omitempty"`
|
||||
|
||||
// InstanceID is the ID of the instance that is using the Floating IP
|
||||
// InstanceID is the ID of the server that is using the Floating IP.
|
||||
InstanceID string `json:"instance_id"`
|
||||
|
||||
// IP is the actual Floating IP
|
||||
// IP is the actual Floating IP.
|
||||
IP string `json:"ip"`
|
||||
|
||||
// Pool is the pool of floating IPs that this floating IP belongs to
|
||||
// Pool is the pool of Floating IPs that this Floating IP belongs to.
|
||||
Pool string `json:"pool"`
|
||||
}
|
||||
|
||||
@ -49,8 +49,7 @@ func (r *FloatingIP) UnmarshalJSON(b []byte) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// FloatingIPPage stores a single, only page of FloatingIPs
|
||||
// results from a List call.
|
||||
// FloatingIPPage stores a single page of FloatingIPs from a List call.
|
||||
type FloatingIPPage struct {
|
||||
pagination.SinglePageBase
|
||||
}
|
||||
@ -61,8 +60,7 @@ func (page FloatingIPPage) IsEmpty() (bool, error) {
|
||||
return len(va) == 0, err
|
||||
}
|
||||
|
||||
// ExtractFloatingIPs interprets a page of results as a slice of
|
||||
// FloatingIPs.
|
||||
// ExtractFloatingIPs interprets a page of results as a slice of FloatingIPs.
|
||||
func ExtractFloatingIPs(r pagination.Page) ([]FloatingIP, error) {
|
||||
var s struct {
|
||||
FloatingIPs []FloatingIP `json:"floating_ips"`
|
||||
@ -86,32 +84,32 @@ func (r FloatingIPResult) Extract() (*FloatingIP, error) {
|
||||
return s.FloatingIP, err
|
||||
}
|
||||
|
||||
// CreateResult is the response from a Create operation. Call its Extract method to interpret it
|
||||
// as a FloatingIP.
|
||||
// CreateResult is the response from a Create operation. Call its Extract method
|
||||
// to interpret it as a FloatingIP.
|
||||
type CreateResult struct {
|
||||
FloatingIPResult
|
||||
}
|
||||
|
||||
// GetResult is the response from a Get operation. Call its Extract method to interpret it
|
||||
// as a FloatingIP.
|
||||
// GetResult is the response from a Get operation. Call its Extract method to
|
||||
// interpret it as a FloatingIP.
|
||||
type GetResult struct {
|
||||
FloatingIPResult
|
||||
}
|
||||
|
||||
// DeleteResult is the response from a Delete operation. Call its Extract method to determine if
|
||||
// the call succeeded or failed.
|
||||
// DeleteResult is the response from a Delete operation. Call its ExtractErr
|
||||
// method to determine if the call succeeded or failed.
|
||||
type DeleteResult struct {
|
||||
gophercloud.ErrResult
|
||||
}
|
||||
|
||||
// AssociateResult is the response from a Delete operation. Call its Extract method to determine if
|
||||
// the call succeeded or failed.
|
||||
// AssociateResult is the response from a Delete operation. Call its ExtractErr
|
||||
// method to determine if the call succeeded or failed.
|
||||
type AssociateResult struct {
|
||||
gophercloud.ErrResult
|
||||
}
|
||||
|
||||
// DisassociateResult is the response from a Delete operation. Call its Extract method to determine if
|
||||
// the call succeeded or failed.
|
||||
// DisassociateResult is the response from a Delete operation. Call its
|
||||
// ExtractErr method to determine if the call succeeded or failed.
|
||||
type DisassociateResult struct {
|
||||
gophercloud.ErrResult
|
||||
}
|
||||
|
@ -1,3 +1,71 @@
|
||||
// Package keypairs provides information and interaction with the Keypairs
|
||||
// extension for the OpenStack Compute service.
|
||||
/*
|
||||
Package keypairs provides the ability to manage key pairs as well as create
|
||||
servers with a specified key pair.
|
||||
|
||||
Example to List Key Pairs
|
||||
|
||||
allPages, err := keypairs.List(computeClient).AllPages()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
allKeyPairs, err := keypairs.ExtractKeyPairs(allPages)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
for _, kp := range allKeyPairs {
|
||||
fmt.Printf("%+v\n", kp)
|
||||
}
|
||||
|
||||
Example to Create a Key Pair
|
||||
|
||||
createOpts := keypairs.CreateOpts{
|
||||
Name: "keypair-name",
|
||||
}
|
||||
|
||||
keypair, err := keypairs.Create(computeClient, createOpts).Extract()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
fmt.Printf("%+v", keypair)
|
||||
|
||||
Example to Import a Key Pair
|
||||
|
||||
createOpts := keypairs.CreateOpts{
|
||||
Name: "keypair-name",
|
||||
PublicKey: "public-key",
|
||||
}
|
||||
|
||||
keypair, err := keypairs.Create(computeClient, createOpts).Extract()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
Example to Delete a Key Pair
|
||||
|
||||
err := keypairs.Delete(computeClient, "keypair-name").ExtractErr()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
Example to Create a Server With a Key Pair
|
||||
|
||||
serverCreateOpts := servers.CreateOpts{
|
||||
Name: "server_name",
|
||||
ImageRef: "image-uuid",
|
||||
FlavorRef: "flavor-uuid",
|
||||
}
|
||||
|
||||
createOpts := keypairs.CreateOptsExt{
|
||||
CreateOptsBuilder: serverCreateOpts,
|
||||
KeyName: "keypair-name",
|
||||
}
|
||||
|
||||
server, err := servers.Create(computeClient, createOpts).Extract()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
*/
|
||||
package keypairs
|
||||
|
@ -9,11 +9,12 @@ import (
|
||||
// CreateOptsExt adds a KeyPair option to the base CreateOpts.
|
||||
type CreateOptsExt struct {
|
||||
servers.CreateOptsBuilder
|
||||
|
||||
// KeyName is the name of the key pair.
|
||||
KeyName string `json:"key_name,omitempty"`
|
||||
}
|
||||
|
||||
// ToServerCreateMap adds the key_name and, optionally, key_data options to
|
||||
// the base server creation options.
|
||||
// ToServerCreateMap adds the key_name to the base server creation options.
|
||||
func (opts CreateOptsExt) ToServerCreateMap() (map[string]interface{}, error) {
|
||||
base, err := opts.CreateOptsBuilder.ToServerCreateMap()
|
||||
if err != nil {
|
||||
@ -37,18 +38,19 @@ func List(client *gophercloud.ServiceClient) pagination.Pager {
|
||||
})
|
||||
}
|
||||
|
||||
// CreateOptsBuilder describes struct types that can be accepted by the Create call. Notable, the
|
||||
// CreateOpts struct in this package does.
|
||||
// CreateOptsBuilder allows extensions to add additional parameters to the
|
||||
// Create request.
|
||||
type CreateOptsBuilder interface {
|
||||
ToKeyPairCreateMap() (map[string]interface{}, error)
|
||||
}
|
||||
|
||||
// CreateOpts specifies keypair creation or import parameters.
|
||||
// CreateOpts specifies KeyPair creation or import parameters.
|
||||
type CreateOpts struct {
|
||||
// Name is a friendly name to refer to this KeyPair in other services.
|
||||
Name string `json:"name" required:"true"`
|
||||
// PublicKey [optional] is a pregenerated OpenSSH-formatted public key. If provided, this key
|
||||
// will be imported and no new key will be created.
|
||||
|
||||
// PublicKey [optional] is a pregenerated OpenSSH-formatted public key.
|
||||
// If provided, this key will be imported and no new key will be created.
|
||||
PublicKey string `json:"public_key,omitempty"`
|
||||
}
|
||||
|
||||
@ -57,8 +59,8 @@ func (opts CreateOpts) ToKeyPairCreateMap() (map[string]interface{}, error) {
|
||||
return gophercloud.BuildRequestBody(opts, "keypair")
|
||||
}
|
||||
|
||||
// Create requests the creation of a new keypair on the server, or to import a pre-existing
|
||||
// keypair.
|
||||
// Create requests the creation of a new KeyPair on the server, or to import a
|
||||
// pre-existing keypair.
|
||||
func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) (r CreateResult) {
|
||||
b, err := opts.ToKeyPairCreateMap()
|
||||
if err != nil {
|
||||
|
@ -5,29 +5,33 @@ import (
|
||||
"github.com/gophercloud/gophercloud/pagination"
|
||||
)
|
||||
|
||||
// KeyPair is an SSH key known to the OpenStack Cloud that is available to be injected into
|
||||
// servers.
|
||||
// KeyPair is an SSH key known to the OpenStack Cloud that is available to be
|
||||
// injected into servers.
|
||||
type KeyPair struct {
|
||||
// Name is used to refer to this keypair from other services within this region.
|
||||
// Name is used to refer to this keypair from other services within this
|
||||
// region.
|
||||
Name string `json:"name"`
|
||||
|
||||
// Fingerprint is a short sequence of bytes that can be used to authenticate or validate a longer
|
||||
// public key.
|
||||
// Fingerprint is a short sequence of bytes that can be used to authenticate
|
||||
// or validate a longer public key.
|
||||
Fingerprint string `json:"fingerprint"`
|
||||
|
||||
// PublicKey is the public key from this pair, in OpenSSH format. "ssh-rsa AAAAB3Nz..."
|
||||
// PublicKey is the public key from this pair, in OpenSSH format.
|
||||
// "ssh-rsa AAAAB3Nz..."
|
||||
PublicKey string `json:"public_key"`
|
||||
|
||||
// PrivateKey is the private key from this pair, in PEM format.
|
||||
// "-----BEGIN RSA PRIVATE KEY-----\nMIICXA..." It is only present if this keypair was just
|
||||
// returned from a Create call
|
||||
// "-----BEGIN RSA PRIVATE KEY-----\nMIICXA..."
|
||||
// It is only present if this KeyPair was just returned from a Create call.
|
||||
PrivateKey string `json:"private_key"`
|
||||
|
||||
// UserID is the user who owns this keypair.
|
||||
// UserID is the user who owns this KeyPair.
|
||||
UserID string `json:"user_id"`
|
||||
}
|
||||
|
||||
// KeyPairPage stores a single, only page of KeyPair results from a List call.
|
||||
// KeyPairPage stores a single page of all KeyPair results from a List call.
|
||||
// Use the ExtractKeyPairs function to convert the results to a slice of
|
||||
// KeyPairs.
|
||||
type KeyPairPage struct {
|
||||
pagination.SinglePageBase
|
||||
}
|
||||
@ -58,7 +62,8 @@ type keyPairResult struct {
|
||||
gophercloud.Result
|
||||
}
|
||||
|
||||
// Extract is a method that attempts to interpret any KeyPair resource response as a KeyPair struct.
|
||||
// Extract is a method that attempts to interpret any KeyPair resource response
|
||||
// as a KeyPair struct.
|
||||
func (r keyPairResult) Extract() (*KeyPair, error) {
|
||||
var s struct {
|
||||
KeyPair *KeyPair `json:"keypair"`
|
||||
@ -67,20 +72,20 @@ func (r keyPairResult) Extract() (*KeyPair, error) {
|
||||
return s.KeyPair, err
|
||||
}
|
||||
|
||||
// CreateResult is the response from a Create operation. Call its Extract method to interpret it
|
||||
// as a KeyPair.
|
||||
// CreateResult is the response from a Create operation. Call its Extract method
|
||||
// to interpret it as a KeyPair.
|
||||
type CreateResult struct {
|
||||
keyPairResult
|
||||
}
|
||||
|
||||
// GetResult is the response from a Get operation. Call its Extract method to interpret it
|
||||
// as a KeyPair.
|
||||
// GetResult is the response from a Get operation. Call its Extract method to
|
||||
// interpret it as a KeyPair.
|
||||
type GetResult struct {
|
||||
keyPairResult
|
||||
}
|
||||
|
||||
// DeleteResult is the response from a Delete operation. Call its Extract method to determine if
|
||||
// the call succeeded or failed.
|
||||
// DeleteResult is the response from a Delete operation. Call its ExtractErr
|
||||
// method to determine if the call succeeded or failed.
|
||||
type DeleteResult struct {
|
||||
gophercloud.ErrResult
|
||||
}
|
||||
|
@ -1,5 +1,19 @@
|
||||
/*
|
||||
Package startstop provides functionality to start and stop servers that have
|
||||
been provisioned by the OpenStack Compute service.
|
||||
|
||||
Example to Stop and Start a Server
|
||||
|
||||
serverID := "47b6b7b7-568d-40e4-868c-d5c41735532e"
|
||||
|
||||
err := startstop.Stop(computeClient, serverID).ExtractErr()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err := startstop.Start(computeClient, serverID).ExtractErr()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
*/
|
||||
package startstop
|
||||
|
@ -7,13 +7,13 @@ func actionURL(client *gophercloud.ServiceClient, id string) string {
|
||||
}
|
||||
|
||||
// Start is the operation responsible for starting a Compute server.
|
||||
func Start(client *gophercloud.ServiceClient, id string) (r gophercloud.ErrResult) {
|
||||
func Start(client *gophercloud.ServiceClient, id string) (r StartResult) {
|
||||
_, r.Err = client.Post(actionURL(client, id), map[string]interface{}{"os-start": nil}, nil, nil)
|
||||
return
|
||||
}
|
||||
|
||||
// Stop is the operation responsible for stopping a Compute server.
|
||||
func Stop(client *gophercloud.ServiceClient, id string) (r gophercloud.ErrResult) {
|
||||
func Stop(client *gophercloud.ServiceClient, id string) (r StopResult) {
|
||||
_, r.Err = client.Post(actionURL(client, id), map[string]interface{}{"os-stop": nil}, nil, nil)
|
||||
return
|
||||
}
|
||||
|
15
vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/startstop/results.go
generated
vendored
Normal file
15
vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/startstop/results.go
generated
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
package startstop
|
||||
|
||||
import "github.com/gophercloud/gophercloud"
|
||||
|
||||
// StartResult is the response from a Start operation. Call its ExtractErr
|
||||
// method to determine if the request succeeded or failed.
|
||||
type StartResult struct {
|
||||
gophercloud.ErrResult
|
||||
}
|
||||
|
||||
// StopResult is the response from Stop operation. Call its ExtractErr
|
||||
// method to determine if the request succeeded or failed.
|
||||
type StopResult struct {
|
||||
gophercloud.ErrResult
|
||||
}
|
142
vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/flavors/doc.go
generated
vendored
142
vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/flavors/doc.go
generated
vendored
@ -1,7 +1,137 @@
|
||||
// Package flavors provides information and interaction with the flavor API
|
||||
// resource in the OpenStack Compute service.
|
||||
//
|
||||
// A flavor is an available hardware configuration for a server. Each flavor
|
||||
// has a unique combination of disk space, memory capacity and priority for CPU
|
||||
// time.
|
||||
/*
|
||||
Package flavors provides information and interaction with the flavor API
|
||||
in the OpenStack Compute service.
|
||||
|
||||
A flavor is an available hardware configuration for a server. Each flavor
|
||||
has a unique combination of disk space, memory capacity and priority for CPU
|
||||
time.
|
||||
|
||||
Example to List Flavors
|
||||
|
||||
listOpts := flavors.ListOpts{
|
||||
AccessType: flavors.PublicAccess,
|
||||
}
|
||||
|
||||
allPages, err := flavors.ListDetail(computeClient, listOpts).AllPages()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
allFlavors, err := flavors.ExtractFlavors(allPages)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
for _, flavor := range allFlavors {
|
||||
fmt.Printf("%+v\n", flavor)
|
||||
}
|
||||
|
||||
Example to Create a Flavor
|
||||
|
||||
createOpts := flavors.CreateOpts{
|
||||
ID: "1",
|
||||
Name: "m1.tiny",
|
||||
Disk: gophercloud.IntToPointer(1),
|
||||
RAM: 512,
|
||||
VCPUs: 1,
|
||||
RxTxFactor: 1.0,
|
||||
}
|
||||
|
||||
flavor, err := flavors.Create(computeClient, createOpts).Extract()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
Example to List Flavor Access
|
||||
|
||||
flavorID := "e91758d6-a54a-4778-ad72-0c73a1cb695b"
|
||||
|
||||
allPages, err := flavors.ListAccesses(computeClient, flavorID).AllPages()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
allAccesses, err := flavors.ExtractAccesses(allPages)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
for _, access := range allAccesses {
|
||||
fmt.Printf("%+v", access)
|
||||
}
|
||||
|
||||
Example to Grant Access to a Flavor
|
||||
|
||||
flavorID := "e91758d6-a54a-4778-ad72-0c73a1cb695b"
|
||||
|
||||
accessOpts := flavors.AddAccessOpts{
|
||||
Tenant: "15153a0979884b59b0592248ef947921",
|
||||
}
|
||||
|
||||
accessList, err := flavors.AddAccess(computeClient, flavor.ID, accessOpts).Extract()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
Example to Remove/Revoke Access to a Flavor
|
||||
|
||||
flavorID := "e91758d6-a54a-4778-ad72-0c73a1cb695b"
|
||||
|
||||
accessOpts := flavors.RemoveAccessOpts{
|
||||
Tenant: "15153a0979884b59b0592248ef947921",
|
||||
}
|
||||
|
||||
accessList, err := flavors.RemoveAccess(computeClient, flavor.ID, accessOpts).Extract()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
Example to Create Extra Specs for a Flavor
|
||||
|
||||
flavorID := "e91758d6-a54a-4778-ad72-0c73a1cb695b"
|
||||
|
||||
createOpts := flavors.ExtraSpecsOpts{
|
||||
"hw:cpu_policy": "CPU-POLICY",
|
||||
"hw:cpu_thread_policy": "CPU-THREAD-POLICY",
|
||||
}
|
||||
createdExtraSpecs, err := flavors.CreateExtraSpecs(computeClient, flavorID, createOpts).Extract()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
fmt.Printf("%+v", createdExtraSpecs)
|
||||
|
||||
Example to Get Extra Specs for a Flavor
|
||||
|
||||
flavorID := "e91758d6-a54a-4778-ad72-0c73a1cb695b"
|
||||
|
||||
extraSpecs, err := flavors.ListExtraSpecs(computeClient, flavorID).Extract()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
fmt.Printf("%+v", extraSpecs)
|
||||
|
||||
Example to Update Extra Specs for a Flavor
|
||||
|
||||
flavorID := "e91758d6-a54a-4778-ad72-0c73a1cb695b"
|
||||
|
||||
updateOpts := flavors.ExtraSpecsOpts{
|
||||
"hw:cpu_thread_policy": "CPU-THREAD-POLICY-UPDATED",
|
||||
}
|
||||
updatedExtraSpec, err := flavors.UpdateExtraSpec(computeClient, flavorID, updateOpts).Extract()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
fmt.Printf("%+v", updatedExtraSpec)
|
||||
|
||||
Example to Delete an Extra Spec for a Flavor
|
||||
|
||||
flavorID := "e91758d6-a54a-4778-ad72-0c73a1cb695b"
|
||||
err := flavors.DeleteExtraSpec(computeClient, flavorID, "hw:cpu_thread_policy").ExtractErr()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
*/
|
||||
package flavors
|
||||
|
268
vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/flavors/requests.go
generated
vendored
268
vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/flavors/requests.go
generated
vendored
@ -11,33 +11,44 @@ type ListOptsBuilder interface {
|
||||
ToFlavorListQuery() (string, error)
|
||||
}
|
||||
|
||||
// AccessType maps to OpenStack's Flavor.is_public field. Although the is_public field is boolean, the
|
||||
// request options are ternary, which is why AccessType is a string. The following values are
|
||||
// allowed:
|
||||
//
|
||||
// PublicAccess (the default): Returns public flavors and private flavors associated with that project.
|
||||
// PrivateAccess (admin only): Returns private flavors, across all projects.
|
||||
// AllAccess (admin only): Returns public and private flavors across all projects.
|
||||
//
|
||||
// The AccessType arguement is optional, and if it is not supplied, OpenStack returns the PublicAccess
|
||||
// flavors.
|
||||
/*
|
||||
AccessType maps to OpenStack's Flavor.is_public field. Although the is_public
|
||||
field is boolean, the request options are ternary, which is why AccessType is
|
||||
a string. The following values are allowed:
|
||||
|
||||
The AccessType arguement is optional, and if it is not supplied, OpenStack
|
||||
returns the PublicAccess flavors.
|
||||
*/
|
||||
type AccessType string
|
||||
|
||||
const (
|
||||
PublicAccess AccessType = "true"
|
||||
// PublicAccess returns public flavors and private flavors associated with
|
||||
// that project.
|
||||
PublicAccess AccessType = "true"
|
||||
|
||||
// PrivateAccess (admin only) returns private flavors, across all projects.
|
||||
PrivateAccess AccessType = "false"
|
||||
AllAccess AccessType = "None"
|
||||
|
||||
// AllAccess (admin only) returns public and private flavors across all
|
||||
// projects.
|
||||
AllAccess AccessType = "None"
|
||||
)
|
||||
|
||||
// ListOpts helps control the results returned by the List() function.
|
||||
// For example, a flavor with a minDisk field of 10 will not be returned if you specify MinDisk set to 20.
|
||||
// Typically, software will use the last ID of the previous call to List to set the Marker for the current call.
|
||||
type ListOpts struct {
|
||||
/*
|
||||
ListOpts filters the results returned by the List() function.
|
||||
For example, a flavor with a minDisk field of 10 will not be returned if you
|
||||
specify MinDisk set to 20.
|
||||
|
||||
// ChangesSince, if provided, instructs List to return only those things which have changed since the timestamp provided.
|
||||
Typically, software will use the last ID of the previous call to List to set
|
||||
the Marker for the current call.
|
||||
*/
|
||||
type ListOpts struct {
|
||||
// ChangesSince, if provided, instructs List to return only those things which
|
||||
// have changed since the timestamp provided.
|
||||
ChangesSince string `q:"changes-since"`
|
||||
|
||||
// MinDisk and MinRAM, if provided, elides flavors which do not meet your criteria.
|
||||
// MinDisk and MinRAM, if provided, elides flavors which do not meet your
|
||||
// criteria.
|
||||
MinDisk int `q:"minDisk"`
|
||||
MinRAM int `q:"minRam"`
|
||||
|
||||
@ -45,11 +56,12 @@ type ListOpts struct {
|
||||
// Marker instructs List where to start listing from.
|
||||
Marker string `q:"marker"`
|
||||
|
||||
// Limit instructs List to refrain from sending excessively large lists of flavors.
|
||||
// Limit instructs List to refrain from sending excessively large lists of
|
||||
// flavors.
|
||||
Limit int `q:"limit"`
|
||||
|
||||
// AccessType, if provided, instructs List which set of flavors to return. If IsPublic not provided,
|
||||
// flavors for the current project are returned.
|
||||
// AccessType, if provided, instructs List which set of flavors to return.
|
||||
// If IsPublic not provided, flavors for the current project are returned.
|
||||
AccessType AccessType `q:"is_public"`
|
||||
}
|
||||
|
||||
@ -60,8 +72,8 @@ func (opts ListOpts) ToFlavorListQuery() (string, error) {
|
||||
}
|
||||
|
||||
// ListDetail instructs OpenStack to provide a list of flavors.
|
||||
// You may provide criteria by which List curtails its results for easier processing.
|
||||
// See ListOpts for more details.
|
||||
// You may provide criteria by which List curtails its results for easier
|
||||
// processing.
|
||||
func ListDetail(client *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager {
|
||||
url := listURL(client)
|
||||
if opts != nil {
|
||||
@ -80,31 +92,42 @@ type CreateOptsBuilder interface {
|
||||
ToFlavorCreateMap() (map[string]interface{}, error)
|
||||
}
|
||||
|
||||
// CreateOpts is passed to Create to create a flavor
|
||||
// Source:
|
||||
// https://github.com/openstack/nova/blob/stable/newton/nova/api/openstack/compute/schemas/flavor_manage.py#L20
|
||||
// CreateOpts specifies parameters used for creating a flavor.
|
||||
type CreateOpts struct {
|
||||
// Name is the name of the flavor.
|
||||
Name string `json:"name" required:"true"`
|
||||
// memory size, in MBs
|
||||
RAM int `json:"ram" required:"true"`
|
||||
|
||||
// RAM is the memory of the flavor, measured in MB.
|
||||
RAM int `json:"ram" required:"true"`
|
||||
|
||||
// VCPUs is the number of vcpus for the flavor.
|
||||
VCPUs int `json:"vcpus" required:"true"`
|
||||
// disk size, in GBs
|
||||
Disk *int `json:"disk" required:"true"`
|
||||
ID string `json:"id,omitempty"`
|
||||
// non-zero, positive
|
||||
Swap *int `json:"swap,omitempty"`
|
||||
|
||||
// Disk the amount of root disk space, measured in GB.
|
||||
Disk *int `json:"disk" required:"true"`
|
||||
|
||||
// ID is a unique ID for the flavor.
|
||||
ID string `json:"id,omitempty"`
|
||||
|
||||
// Swap is the amount of swap space for the flavor, measured in MB.
|
||||
Swap *int `json:"swap,omitempty"`
|
||||
|
||||
// RxTxFactor alters the network bandwidth of a flavor.
|
||||
RxTxFactor float64 `json:"rxtx_factor,omitempty"`
|
||||
IsPublic *bool `json:"os-flavor-access:is_public,omitempty"`
|
||||
// ephemeral disk size, in GBs, non-zero, positive
|
||||
|
||||
// IsPublic flags a flavor as being available to all projects or not.
|
||||
IsPublic *bool `json:"os-flavor-access:is_public,omitempty"`
|
||||
|
||||
// Ephemeral is the amount of ephemeral disk space, measured in GB.
|
||||
Ephemeral *int `json:"OS-FLV-EXT-DATA:ephemeral,omitempty"`
|
||||
}
|
||||
|
||||
// ToFlavorCreateMap satisfies the CreateOptsBuilder interface
|
||||
func (opts *CreateOpts) ToFlavorCreateMap() (map[string]interface{}, error) {
|
||||
// ToFlavorCreateMap constructs a request body from CreateOpts.
|
||||
func (opts CreateOpts) ToFlavorCreateMap() (map[string]interface{}, error) {
|
||||
return gophercloud.BuildRequestBody(opts, "flavor")
|
||||
}
|
||||
|
||||
// Create a flavor
|
||||
// Create requests the creation of a new flavor.
|
||||
func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) (r CreateResult) {
|
||||
b, err := opts.ToFlavorCreateMap()
|
||||
if err != nil {
|
||||
@ -117,14 +140,177 @@ func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) (r Create
|
||||
return
|
||||
}
|
||||
|
||||
// Get instructs OpenStack to provide details on a single flavor, identified by its ID.
|
||||
// Use ExtractFlavor to convert its result into a Flavor.
|
||||
// Get retrieves details of a single flavor. Use ExtractFlavor to convert its
|
||||
// result into a Flavor.
|
||||
func Get(client *gophercloud.ServiceClient, id string) (r GetResult) {
|
||||
_, r.Err = client.Get(getURL(client, id), &r.Body, nil)
|
||||
return
|
||||
}
|
||||
|
||||
// IDFromName is a convienience function that returns a flavor's ID given its name.
|
||||
// Delete deletes the specified flavor ID.
|
||||
func Delete(client *gophercloud.ServiceClient, id string) (r DeleteResult) {
|
||||
_, r.Err = client.Delete(deleteURL(client, id), nil)
|
||||
return
|
||||
}
|
||||
|
||||
// ListAccesses retrieves the tenants which have access to a flavor.
|
||||
func ListAccesses(client *gophercloud.ServiceClient, id string) pagination.Pager {
|
||||
url := accessURL(client, id)
|
||||
|
||||
return pagination.NewPager(client, url, func(r pagination.PageResult) pagination.Page {
|
||||
return AccessPage{pagination.SinglePageBase(r)}
|
||||
})
|
||||
}
|
||||
|
||||
// AddAccessOptsBuilder allows extensions to add additional parameters to the
|
||||
// AddAccess requests.
|
||||
type AddAccessOptsBuilder interface {
|
||||
ToFlavorAddAccessMap() (map[string]interface{}, error)
|
||||
}
|
||||
|
||||
// AddAccessOpts represents options for adding access to a flavor.
|
||||
type AddAccessOpts struct {
|
||||
// Tenant is the project/tenant ID to grant access.
|
||||
Tenant string `json:"tenant"`
|
||||
}
|
||||
|
||||
// ToFlavorAddAccessMap constructs a request body from AddAccessOpts.
|
||||
func (opts AddAccessOpts) ToFlavorAddAccessMap() (map[string]interface{}, error) {
|
||||
return gophercloud.BuildRequestBody(opts, "addTenantAccess")
|
||||
}
|
||||
|
||||
// AddAccess grants a tenant/project access to a flavor.
|
||||
func AddAccess(client *gophercloud.ServiceClient, id string, opts AddAccessOptsBuilder) (r AddAccessResult) {
|
||||
b, err := opts.ToFlavorAddAccessMap()
|
||||
if err != nil {
|
||||
r.Err = err
|
||||
return
|
||||
}
|
||||
_, r.Err = client.Post(accessActionURL(client, id), b, &r.Body, &gophercloud.RequestOpts{
|
||||
OkCodes: []int{200},
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// RemoveAccessOptsBuilder allows extensions to add additional parameters to the
|
||||
// RemoveAccess requests.
|
||||
type RemoveAccessOptsBuilder interface {
|
||||
ToFlavorRemoveAccessMap() (map[string]interface{}, error)
|
||||
}
|
||||
|
||||
// RemoveAccessOpts represents options for removing access to a flavor.
|
||||
type RemoveAccessOpts struct {
|
||||
// Tenant is the project/tenant ID to grant access.
|
||||
Tenant string `json:"tenant"`
|
||||
}
|
||||
|
||||
// ToFlavorRemoveAccessMap constructs a request body from RemoveAccessOpts.
|
||||
func (opts RemoveAccessOpts) ToFlavorRemoveAccessMap() (map[string]interface{}, error) {
|
||||
return gophercloud.BuildRequestBody(opts, "removeTenantAccess")
|
||||
}
|
||||
|
||||
// RemoveAccess removes/revokes a tenant/project access to a flavor.
|
||||
func RemoveAccess(client *gophercloud.ServiceClient, id string, opts RemoveAccessOptsBuilder) (r RemoveAccessResult) {
|
||||
b, err := opts.ToFlavorRemoveAccessMap()
|
||||
if err != nil {
|
||||
r.Err = err
|
||||
return
|
||||
}
|
||||
_, r.Err = client.Post(accessActionURL(client, id), b, &r.Body, &gophercloud.RequestOpts{
|
||||
OkCodes: []int{200},
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// ExtraSpecs requests all the extra-specs for the given flavor ID.
|
||||
func ListExtraSpecs(client *gophercloud.ServiceClient, flavorID string) (r ListExtraSpecsResult) {
|
||||
_, r.Err = client.Get(extraSpecsListURL(client, flavorID), &r.Body, nil)
|
||||
return
|
||||
}
|
||||
|
||||
func GetExtraSpec(client *gophercloud.ServiceClient, flavorID string, key string) (r GetExtraSpecResult) {
|
||||
_, r.Err = client.Get(extraSpecsGetURL(client, flavorID, key), &r.Body, nil)
|
||||
return
|
||||
}
|
||||
|
||||
// CreateExtraSpecsOptsBuilder allows extensions to add additional parameters to the
|
||||
// CreateExtraSpecs requests.
|
||||
type CreateExtraSpecsOptsBuilder interface {
|
||||
ToFlavorExtraSpecsCreateMap() (map[string]interface{}, error)
|
||||
}
|
||||
|
||||
// ExtraSpecsOpts is a map that contains key-value pairs.
|
||||
type ExtraSpecsOpts map[string]string
|
||||
|
||||
// ToFlavorExtraSpecsCreateMap assembles a body for a Create request based on
|
||||
// the contents of ExtraSpecsOpts.
|
||||
func (opts ExtraSpecsOpts) ToFlavorExtraSpecsCreateMap() (map[string]interface{}, error) {
|
||||
return map[string]interface{}{"extra_specs": opts}, nil
|
||||
}
|
||||
|
||||
// CreateExtraSpecs will create or update the extra-specs key-value pairs for
|
||||
// the specified Flavor.
|
||||
func CreateExtraSpecs(client *gophercloud.ServiceClient, flavorID string, opts CreateExtraSpecsOptsBuilder) (r CreateExtraSpecsResult) {
|
||||
b, err := opts.ToFlavorExtraSpecsCreateMap()
|
||||
if err != nil {
|
||||
r.Err = err
|
||||
return
|
||||
}
|
||||
_, r.Err = client.Post(extraSpecsCreateURL(client, flavorID), b, &r.Body, &gophercloud.RequestOpts{
|
||||
OkCodes: []int{200},
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateExtraSpecOptsBuilder allows extensions to add additional parameters to
|
||||
// the Update request.
|
||||
type UpdateExtraSpecOptsBuilder interface {
|
||||
ToFlavorExtraSpecUpdateMap() (map[string]string, string, error)
|
||||
}
|
||||
|
||||
// ToFlavorExtraSpecUpdateMap assembles a body for an Update request based on
|
||||
// the contents of a ExtraSpecOpts.
|
||||
func (opts ExtraSpecsOpts) ToFlavorExtraSpecUpdateMap() (map[string]string, string, error) {
|
||||
if len(opts) != 1 {
|
||||
err := gophercloud.ErrInvalidInput{}
|
||||
err.Argument = "flavors.ExtraSpecOpts"
|
||||
err.Info = "Must have 1 and only one key-value pair"
|
||||
return nil, "", err
|
||||
}
|
||||
|
||||
var key string
|
||||
for k := range opts {
|
||||
key = k
|
||||
}
|
||||
|
||||
return opts, key, nil
|
||||
}
|
||||
|
||||
// UpdateExtraSpec will updates the value of the specified flavor's extra spec
|
||||
// for the key in opts.
|
||||
func UpdateExtraSpec(client *gophercloud.ServiceClient, flavorID string, opts UpdateExtraSpecOptsBuilder) (r UpdateExtraSpecResult) {
|
||||
b, key, err := opts.ToFlavorExtraSpecUpdateMap()
|
||||
if err != nil {
|
||||
r.Err = err
|
||||
return
|
||||
}
|
||||
_, r.Err = client.Put(extraSpecUpdateURL(client, flavorID, key), b, &r.Body, &gophercloud.RequestOpts{
|
||||
OkCodes: []int{200},
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// DeleteExtraSpec will delete the key-value pair with the given key for the given
|
||||
// flavor ID.
|
||||
func DeleteExtraSpec(client *gophercloud.ServiceClient, flavorID, key string) (r DeleteExtraSpecResult) {
|
||||
_, r.Err = client.Delete(extraSpecDeleteURL(client, flavorID, key), &gophercloud.RequestOpts{
|
||||
OkCodes: []int{200},
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// IDFromName is a convienience function that returns a flavor's ID given its
|
||||
// name.
|
||||
func IDFromName(client *gophercloud.ServiceClient, name string) (string, error) {
|
||||
count := 0
|
||||
id := ""
|
||||
|
169
vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/flavors/results.go
generated
vendored
169
vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/flavors/results.go
generated
vendored
@ -12,16 +12,26 @@ type commonResult struct {
|
||||
gophercloud.Result
|
||||
}
|
||||
|
||||
// CreateResult is the response of a Get operations. Call its Extract method to
|
||||
// interpret it as a Flavor.
|
||||
type CreateResult struct {
|
||||
commonResult
|
||||
}
|
||||
|
||||
// GetResult temporarily holds the response from a Get call.
|
||||
// GetResult is the response of a Get operations. Call its Extract method to
|
||||
// interpret it as a Flavor.
|
||||
type GetResult struct {
|
||||
commonResult
|
||||
}
|
||||
|
||||
// Extract provides access to the individual Flavor returned by the Get and Create functions.
|
||||
// DeleteResult is the result from a Delete operation. Call its ExtractErr
|
||||
// method to determine if the call succeeded or failed.
|
||||
type DeleteResult struct {
|
||||
gophercloud.ErrResult
|
||||
}
|
||||
|
||||
// Extract provides access to the individual Flavor returned by the Get and
|
||||
// Create functions.
|
||||
func (r commonResult) Extract() (*Flavor, error) {
|
||||
var s struct {
|
||||
Flavor *Flavor `json:"flavor"`
|
||||
@ -30,24 +40,35 @@ func (r commonResult) Extract() (*Flavor, error) {
|
||||
return s.Flavor, err
|
||||
}
|
||||
|
||||
// Flavor records represent (virtual) hardware configurations for server resources in a region.
|
||||
// Flavor represent (virtual) hardware configurations for server resources
|
||||
// in a region.
|
||||
type Flavor struct {
|
||||
// The Id field contains the flavor's unique identifier.
|
||||
// For example, this identifier will be useful when specifying which hardware configuration to use for a new server instance.
|
||||
// ID is the flavor's unique ID.
|
||||
ID string `json:"id"`
|
||||
// The Disk and RA< fields provide a measure of storage space offered by the flavor, in GB and MB, respectively.
|
||||
|
||||
// Disk is the amount of root disk, measured in GB.
|
||||
Disk int `json:"disk"`
|
||||
RAM int `json:"ram"`
|
||||
// The Name field provides a human-readable moniker for the flavor.
|
||||
Name string `json:"name"`
|
||||
|
||||
// RAM is the amount of memory, measured in MB.
|
||||
RAM int `json:"ram"`
|
||||
|
||||
// Name is the name of the flavor.
|
||||
Name string `json:"name"`
|
||||
|
||||
// RxTxFactor describes bandwidth alterations of the flavor.
|
||||
RxTxFactor float64 `json:"rxtx_factor"`
|
||||
// Swap indicates how much space is reserved for swap.
|
||||
// If not provided, this field will be set to 0.
|
||||
|
||||
// Swap is the amount of swap space, measured in MB.
|
||||
Swap int `json:"swap"`
|
||||
|
||||
// VCPUs indicates how many (virtual) CPUs are available for this flavor.
|
||||
VCPUs int `json:"vcpus"`
|
||||
|
||||
// IsPublic indicates whether the flavor is public.
|
||||
IsPublic bool `json:"is_public"`
|
||||
IsPublic bool `json:"os-flavor-access:is_public"`
|
||||
|
||||
// Ephemeral is the amount of ephemeral disk space, measured in GB.
|
||||
Ephemeral int `json:"OS-FLV-EXT-DATA:ephemeral"`
|
||||
}
|
||||
|
||||
func (r *Flavor) UnmarshalJSON(b []byte) error {
|
||||
@ -82,18 +103,19 @@ func (r *Flavor) UnmarshalJSON(b []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// FlavorPage contains a single page of the response from a List call.
|
||||
// FlavorPage contains a single page of all flavors from a ListDetails call.
|
||||
type FlavorPage struct {
|
||||
pagination.LinkedPageBase
|
||||
}
|
||||
|
||||
// IsEmpty determines if a page contains any results.
|
||||
// IsEmpty determines if a FlavorPage contains any results.
|
||||
func (page FlavorPage) IsEmpty() (bool, error) {
|
||||
flavors, err := ExtractFlavors(page)
|
||||
return len(flavors) == 0, err
|
||||
}
|
||||
|
||||
// NextPageURL uses the response's embedded link reference to navigate to the next page of results.
|
||||
// NextPageURL uses the response's embedded link reference to navigate to the
|
||||
// next page of results.
|
||||
func (page FlavorPage) NextPageURL() (string, error) {
|
||||
var s struct {
|
||||
Links []gophercloud.Link `json:"flavors_links"`
|
||||
@ -105,7 +127,8 @@ func (page FlavorPage) NextPageURL() (string, error) {
|
||||
return gophercloud.ExtractNextURL(s.Links)
|
||||
}
|
||||
|
||||
// ExtractFlavors provides access to the list of flavors in a page acquired from the List operation.
|
||||
// ExtractFlavors provides access to the list of flavors in a page acquired
|
||||
// from the ListDetail operation.
|
||||
func ExtractFlavors(r pagination.Page) ([]Flavor, error) {
|
||||
var s struct {
|
||||
Flavors []Flavor `json:"flavors"`
|
||||
@ -113,3 +136,117 @@ func ExtractFlavors(r pagination.Page) ([]Flavor, error) {
|
||||
err := (r.(FlavorPage)).ExtractInto(&s)
|
||||
return s.Flavors, err
|
||||
}
|
||||
|
||||
// AccessPage contains a single page of all FlavorAccess entries for a flavor.
|
||||
type AccessPage struct {
|
||||
pagination.SinglePageBase
|
||||
}
|
||||
|
||||
// IsEmpty indicates whether an AccessPage is empty.
|
||||
func (page AccessPage) IsEmpty() (bool, error) {
|
||||
v, err := ExtractAccesses(page)
|
||||
return len(v) == 0, err
|
||||
}
|
||||
|
||||
// ExtractAccesses interprets a page of results as a slice of FlavorAccess.
|
||||
func ExtractAccesses(r pagination.Page) ([]FlavorAccess, error) {
|
||||
var s struct {
|
||||
FlavorAccesses []FlavorAccess `json:"flavor_access"`
|
||||
}
|
||||
err := (r.(AccessPage)).ExtractInto(&s)
|
||||
return s.FlavorAccesses, err
|
||||
}
|
||||
|
||||
type accessResult struct {
|
||||
gophercloud.Result
|
||||
}
|
||||
|
||||
// AddAccessResult is the response of an AddAccess operation. Call its
|
||||
// Extract method to interpret it as a slice of FlavorAccess.
|
||||
type AddAccessResult struct {
|
||||
accessResult
|
||||
}
|
||||
|
||||
// RemoveAccessResult is the response of a RemoveAccess operation. Call its
|
||||
// Extract method to interpret it as a slice of FlavorAccess.
|
||||
type RemoveAccessResult struct {
|
||||
accessResult
|
||||
}
|
||||
|
||||
// Extract provides access to the result of an access create or delete.
|
||||
// The result will be all accesses that the flavor has.
|
||||
func (r accessResult) Extract() ([]FlavorAccess, error) {
|
||||
var s struct {
|
||||
FlavorAccesses []FlavorAccess `json:"flavor_access"`
|
||||
}
|
||||
err := r.ExtractInto(&s)
|
||||
return s.FlavorAccesses, err
|
||||
}
|
||||
|
||||
// FlavorAccess represents an ACL of tenant access to a specific Flavor.
|
||||
type FlavorAccess struct {
|
||||
// FlavorID is the unique ID of the flavor.
|
||||
FlavorID string `json:"flavor_id"`
|
||||
|
||||
// TenantID is the unique ID of the tenant.
|
||||
TenantID string `json:"tenant_id"`
|
||||
}
|
||||
|
||||
// Extract interprets any extraSpecsResult as ExtraSpecs, if possible.
|
||||
func (r extraSpecsResult) Extract() (map[string]string, error) {
|
||||
var s struct {
|
||||
ExtraSpecs map[string]string `json:"extra_specs"`
|
||||
}
|
||||
err := r.ExtractInto(&s)
|
||||
return s.ExtraSpecs, err
|
||||
}
|
||||
|
||||
// extraSpecsResult contains the result of a call for (potentially) multiple
|
||||
// key-value pairs. Call its Extract method to interpret it as a
|
||||
// map[string]interface.
|
||||
type extraSpecsResult struct {
|
||||
gophercloud.Result
|
||||
}
|
||||
|
||||
// ListExtraSpecsResult contains the result of a Get operation. Call its Extract
|
||||
// method to interpret it as a map[string]interface.
|
||||
type ListExtraSpecsResult struct {
|
||||
extraSpecsResult
|
||||
}
|
||||
|
||||
// CreateExtraSpecResult contains the result of a Create operation. Call its
|
||||
// Extract method to interpret it as a map[string]interface.
|
||||
type CreateExtraSpecsResult struct {
|
||||
extraSpecsResult
|
||||
}
|
||||
|
||||
// extraSpecResult contains the result of a call for individual a single
|
||||
// key-value pair.
|
||||
type extraSpecResult struct {
|
||||
gophercloud.Result
|
||||
}
|
||||
|
||||
// GetExtraSpecResult contains the result of a Get operation. Call its Extract
|
||||
// method to interpret it as a map[string]interface.
|
||||
type GetExtraSpecResult struct {
|
||||
extraSpecResult
|
||||
}
|
||||
|
||||
// UpdateExtraSpecResult contains the result of an Update operation. Call its
|
||||
// Extract method to interpret it as a map[string]interface.
|
||||
type UpdateExtraSpecResult struct {
|
||||
extraSpecResult
|
||||
}
|
||||
|
||||
// DeleteExtraSpecResult contains the result of a Delete operation. Call its
|
||||
// ExtractErr method to determine if the call succeeded or failed.
|
||||
type DeleteExtraSpecResult struct {
|
||||
gophercloud.ErrResult
|
||||
}
|
||||
|
||||
// Extract interprets any extraSpecResult as an ExtraSpec, if possible.
|
||||
func (r extraSpecResult) Extract() (map[string]string, error) {
|
||||
var s map[string]string
|
||||
err := r.ExtractInto(&s)
|
||||
return s, err
|
||||
}
|
||||
|
32
vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/flavors/urls.go
generated
vendored
32
vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/flavors/urls.go
generated
vendored
@ -15,3 +15,35 @@ func listURL(client *gophercloud.ServiceClient) string {
|
||||
func createURL(client *gophercloud.ServiceClient) string {
|
||||
return client.ServiceURL("flavors")
|
||||
}
|
||||
|
||||
func deleteURL(client *gophercloud.ServiceClient, id string) string {
|
||||
return client.ServiceURL("flavors", id)
|
||||
}
|
||||
|
||||
func accessURL(client *gophercloud.ServiceClient, id string) string {
|
||||
return client.ServiceURL("flavors", id, "os-flavor-access")
|
||||
}
|
||||
|
||||
func accessActionURL(client *gophercloud.ServiceClient, id string) string {
|
||||
return client.ServiceURL("flavors", id, "action")
|
||||
}
|
||||
|
||||
func extraSpecsListURL(client *gophercloud.ServiceClient, id string) string {
|
||||
return client.ServiceURL("flavors", id, "os-extra_specs")
|
||||
}
|
||||
|
||||
func extraSpecsGetURL(client *gophercloud.ServiceClient, id, key string) string {
|
||||
return client.ServiceURL("flavors", id, "os-extra_specs", key)
|
||||
}
|
||||
|
||||
func extraSpecsCreateURL(client *gophercloud.ServiceClient, id string) string {
|
||||
return client.ServiceURL("flavors", id, "os-extra_specs")
|
||||
}
|
||||
|
||||
func extraSpecUpdateURL(client *gophercloud.ServiceClient, id, key string) string {
|
||||
return client.ServiceURL("flavors", id, "os-extra_specs", key)
|
||||
}
|
||||
|
||||
func extraSpecDeleteURL(client *gophercloud.ServiceClient, id, key string) string {
|
||||
return client.ServiceURL("flavors", id, "os-extra_specs", key)
|
||||
}
|
||||
|
37
vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/images/doc.go
generated
vendored
37
vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/images/doc.go
generated
vendored
@ -1,7 +1,32 @@
|
||||
// Package images provides information and interaction with the image API
|
||||
// resource in the OpenStack Compute service.
|
||||
//
|
||||
// An image is a collection of files used to create or rebuild a server.
|
||||
// Operators provide a number of pre-built OS images by default. You may also
|
||||
// create custom images from cloud servers you have launched.
|
||||
/*
|
||||
Package images provides information and interaction with the images through
|
||||
the OpenStack Compute service.
|
||||
|
||||
This API is deprecated and will be removed from a future version of the Nova
|
||||
API service.
|
||||
|
||||
An image is a collection of files used to create or rebuild a server.
|
||||
Operators provide a number of pre-built OS images by default. You may also
|
||||
create custom images from cloud servers you have launched.
|
||||
|
||||
Example to List Images
|
||||
|
||||
listOpts := images.ListOpts{
|
||||
Limit: 2,
|
||||
}
|
||||
|
||||
allPages, err := images.ListDetail(computeClient, listOpts).AllPages()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
allImages, err := images.ExtractImages(allPages)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
for _, image := range allImages {
|
||||
fmt.Printf("%+v\n", image)
|
||||
}
|
||||
*/
|
||||
package images
|
||||
|
31
vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/images/requests.go
generated
vendored
31
vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/images/requests.go
generated
vendored
@ -6,26 +6,33 @@ import (
|
||||
)
|
||||
|
||||
// ListOptsBuilder allows extensions to add additional parameters to the
|
||||
// List request.
|
||||
// ListDetail request.
|
||||
type ListOptsBuilder interface {
|
||||
ToImageListQuery() (string, error)
|
||||
}
|
||||
|
||||
// ListOpts contain options for limiting the number of Images returned from a call to ListDetail.
|
||||
// ListOpts contain options filtering Images returned from a call to ListDetail.
|
||||
type ListOpts struct {
|
||||
// When the image last changed status (in date-time format).
|
||||
// ChangesSince filters Images based on the last changed status (in date-time
|
||||
// format).
|
||||
ChangesSince string `q:"changes-since"`
|
||||
// The number of Images to return.
|
||||
|
||||
// Limit limits the number of Images to return.
|
||||
Limit int `q:"limit"`
|
||||
// UUID of the Image at which to set a marker.
|
||||
|
||||
// Mark is an Image UUID at which to set a marker.
|
||||
Marker string `q:"marker"`
|
||||
// The name of the Image.
|
||||
|
||||
// Name is the name of the Image.
|
||||
Name string `q:"name"`
|
||||
// The name of the Server (in URL format).
|
||||
|
||||
// Server is the name of the Server (in URL format).
|
||||
Server string `q:"server"`
|
||||
// The current status of the Image.
|
||||
|
||||
// Status is the current status of the Image.
|
||||
Status string `q:"status"`
|
||||
// The value of the type of image (e.g. BASE, SERVER, ALL)
|
||||
|
||||
// Type is the type of image (e.g. BASE, SERVER, ALL).
|
||||
Type string `q:"type"`
|
||||
}
|
||||
|
||||
@ -50,8 +57,7 @@ func ListDetail(client *gophercloud.ServiceClient, opts ListOptsBuilder) paginat
|
||||
})
|
||||
}
|
||||
|
||||
// Get acquires additional detail about a specific image by ID.
|
||||
// Use ExtractImage() to interpret the result as an openstack Image.
|
||||
// Get returns data about a specific image by its ID.
|
||||
func Get(client *gophercloud.ServiceClient, id string) (r GetResult) {
|
||||
_, r.Err = client.Get(getURL(client, id), &r.Body, nil)
|
||||
return
|
||||
@ -63,7 +69,8 @@ func Delete(client *gophercloud.ServiceClient, id string) (r DeleteResult) {
|
||||
return
|
||||
}
|
||||
|
||||
// IDFromName is a convienience function that returns an image's ID given its name.
|
||||
// IDFromName is a convienience function that returns an image's ID given its
|
||||
// name.
|
||||
func IDFromName(client *gophercloud.ServiceClient, name string) (string, error) {
|
||||
count := 0
|
||||
id := ""
|
||||
|
40
vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/images/results.go
generated
vendored
40
vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/images/results.go
generated
vendored
@ -5,12 +5,14 @@ import (
|
||||
"github.com/gophercloud/gophercloud/pagination"
|
||||
)
|
||||
|
||||
// GetResult temporarily stores a Get response.
|
||||
// GetResult is the response from a Get operation. Call its Extract method to
|
||||
// interpret it as an Image.
|
||||
type GetResult struct {
|
||||
gophercloud.Result
|
||||
}
|
||||
|
||||
// DeleteResult represents the result of an image.Delete operation.
|
||||
// DeleteResult is the result from a Delete operation. Call its ExtractErr
|
||||
// method to determine if the call succeeded or failed.
|
||||
type DeleteResult struct {
|
||||
gophercloud.ErrResult
|
||||
}
|
||||
@ -24,44 +26,53 @@ func (r GetResult) Extract() (*Image, error) {
|
||||
return s.Image, err
|
||||
}
|
||||
|
||||
// Image is used for JSON (un)marshalling.
|
||||
// It provides a description of an OS image.
|
||||
// Image represents an Image returned by the Compute API.
|
||||
type Image struct {
|
||||
// ID contains the image's unique identifier.
|
||||
// ID is the unique ID of an image.
|
||||
ID string
|
||||
|
||||
// Created is the date when the image was created.
|
||||
Created string
|
||||
|
||||
// MinDisk and MinRAM specify the minimum resources a server must provide to be able to install the image.
|
||||
// MinDisk is the minimum amount of disk a flavor must have to be able
|
||||
// to create a server based on the image, measured in GB.
|
||||
MinDisk int
|
||||
MinRAM int
|
||||
|
||||
// MinRAM is the minimum amount of RAM a flavor must have to be able
|
||||
// to create a server based on the image, measured in MB.
|
||||
MinRAM int
|
||||
|
||||
// Name provides a human-readable moniker for the OS image.
|
||||
Name string
|
||||
|
||||
// The Progress and Status fields indicate image-creation status.
|
||||
// Any usable image will have 100% progress.
|
||||
Progress int
|
||||
Status string
|
||||
|
||||
// Status is the current status of the image.
|
||||
Status string
|
||||
|
||||
// Update is the date when the image was updated.
|
||||
Updated string
|
||||
|
||||
// Metadata provides free-form key/value pairs that further describe the
|
||||
// image.
|
||||
Metadata map[string]interface{}
|
||||
}
|
||||
|
||||
// ImagePage contains a single page of results from a List operation.
|
||||
// Use ExtractImages to convert it into a slice of usable structs.
|
||||
// ImagePage contains a single page of all Images returne from a ListDetail
|
||||
// operation. Use ExtractImages to convert it into a slice of usable structs.
|
||||
type ImagePage struct {
|
||||
pagination.LinkedPageBase
|
||||
}
|
||||
|
||||
// IsEmpty returns true if a page contains no Image results.
|
||||
// IsEmpty returns true if an ImagePage contains no Image results.
|
||||
func (page ImagePage) IsEmpty() (bool, error) {
|
||||
images, err := ExtractImages(page)
|
||||
return len(images) == 0, err
|
||||
}
|
||||
|
||||
// NextPageURL uses the response's embedded link reference to navigate to the next page of results.
|
||||
// NextPageURL uses the response's embedded link reference to navigate to the
|
||||
// next page of results.
|
||||
func (page ImagePage) NextPageURL() (string, error) {
|
||||
var s struct {
|
||||
Links []gophercloud.Link `json:"images_links"`
|
||||
@ -73,7 +84,8 @@ func (page ImagePage) NextPageURL() (string, error) {
|
||||
return gophercloud.ExtractNextURL(s.Links)
|
||||
}
|
||||
|
||||
// ExtractImages converts a page of List results into a slice of usable Image structs.
|
||||
// ExtractImages converts a page of List results into a slice of usable Image
|
||||
// structs.
|
||||
func ExtractImages(r pagination.Page) ([]Image, error) {
|
||||
var s struct {
|
||||
Images []Image `json:"images"`
|
||||
|
119
vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/servers/doc.go
generated
vendored
119
vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/servers/doc.go
generated
vendored
@ -1,6 +1,115 @@
|
||||
// Package servers provides information and interaction with the server API
|
||||
// resource in the OpenStack Compute service.
|
||||
//
|
||||
// A server is a virtual machine instance in the compute system. In order for
|
||||
// one to be provisioned, a valid flavor and image are required.
|
||||
/*
|
||||
Package servers provides information and interaction with the server API
|
||||
resource in the OpenStack Compute service.
|
||||
|
||||
A server is a virtual machine instance in the compute system. In order for
|
||||
one to be provisioned, a valid flavor and image are required.
|
||||
|
||||
Example to List Servers
|
||||
|
||||
listOpts := servers.ListOpts{
|
||||
AllTenants: true,
|
||||
}
|
||||
|
||||
allPages, err := servers.List(computeClient, listOpts).AllPages()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
allServers, err := servers.ExtractServers(allPages)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
for _, server := range allServers {
|
||||
fmt.Printf("%+v\n", server)
|
||||
}
|
||||
|
||||
Example to Create a Server
|
||||
|
||||
createOpts := servers.CreateOpts{
|
||||
Name: "server_name",
|
||||
ImageRef: "image-uuid",
|
||||
FlavorRef: "flavor-uuid",
|
||||
}
|
||||
|
||||
server, err := servers.Create(computeClient, createOpts).Extract()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
Example to Delete a Server
|
||||
|
||||
serverID := "d9072956-1560-487c-97f2-18bdf65ec749"
|
||||
err := servers.Delete(computeClient, serverID).ExtractErr()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
Example to Force Delete a Server
|
||||
|
||||
serverID := "d9072956-1560-487c-97f2-18bdf65ec749"
|
||||
err := servers.ForceDelete(computeClient, serverID).ExtractErr()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
Example to Reboot a Server
|
||||
|
||||
rebootOpts := servers.RebootOpts{
|
||||
Type: servers.SoftReboot,
|
||||
}
|
||||
|
||||
serverID := "d9072956-1560-487c-97f2-18bdf65ec749"
|
||||
|
||||
err := servers.Reboot(computeClient, serverID, rebootOpts).ExtractErr()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
Example to Rebuild a Server
|
||||
|
||||
rebuildOpts := servers.RebuildOpts{
|
||||
Name: "new_name",
|
||||
ImageID: "image-uuid",
|
||||
}
|
||||
|
||||
serverID := "d9072956-1560-487c-97f2-18bdf65ec749"
|
||||
|
||||
server, err := servers.Rebuilt(computeClient, serverID, rebuildOpts).Extract()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
Example to Resize a Server
|
||||
|
||||
resizeOpts := servers.ResizeOpts{
|
||||
FlavorRef: "flavor-uuid",
|
||||
}
|
||||
|
||||
serverID := "d9072956-1560-487c-97f2-18bdf65ec749"
|
||||
|
||||
err := servers.Resize(computeClient, serverID, resizeOpts).ExtractErr()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = servers.ConfirmResize(computeClient, serverID).ExtractErr()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
Example to Snapshot a Server
|
||||
|
||||
snapshotOpts := servers.CreateImageOpts{
|
||||
Name: "snapshot_name",
|
||||
}
|
||||
|
||||
serverID := "d9072956-1560-487c-97f2-18bdf65ec749"
|
||||
|
||||
image, err := servers.CreateImage(computeClient, serverID, snapshotOpts).ExtractImageID()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
*/
|
||||
package servers
|
||||
|
234
vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/servers/requests.go
generated
vendored
234
vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/servers/requests.go
generated
vendored
@ -21,13 +21,13 @@ type ListOptsBuilder interface {
|
||||
// the server attributes you want to see returned. Marker and Limit are used
|
||||
// for pagination.
|
||||
type ListOpts struct {
|
||||
// A time/date stamp for when the server last changed status.
|
||||
// ChangesSince is a time/date stamp for when the server last changed status.
|
||||
ChangesSince string `q:"changes-since"`
|
||||
|
||||
// Name of the image in URL format.
|
||||
// Image is the name of the image in URL format.
|
||||
Image string `q:"image"`
|
||||
|
||||
// Name of the flavor in URL format.
|
||||
// Flavor is the name of the flavor in URL format.
|
||||
Flavor string `q:"flavor"`
|
||||
|
||||
// Name of the server as a string; can be queried with regular expressions.
|
||||
@ -36,20 +36,25 @@ type ListOpts struct {
|
||||
// underlying database server implemented for Compute.
|
||||
Name string `q:"name"`
|
||||
|
||||
// Value of the status of the server so that you can filter on "ACTIVE" for example.
|
||||
// Status is the value of the status of the server so that you can filter on
|
||||
// "ACTIVE" for example.
|
||||
Status string `q:"status"`
|
||||
|
||||
// Name of the host as a string.
|
||||
// Host is the name of the host as a string.
|
||||
Host string `q:"host"`
|
||||
|
||||
// UUID of the server at which you want to set a marker.
|
||||
// Marker is a UUID of the server at which you want to set a marker.
|
||||
Marker string `q:"marker"`
|
||||
|
||||
// Integer value for the limit of values to return.
|
||||
// Limit is an integer value for the limit of values to return.
|
||||
Limit int `q:"limit"`
|
||||
|
||||
// Bool to show all tenants
|
||||
// AllTenants is a bool to show all tenants.
|
||||
AllTenants bool `q:"all_tenants"`
|
||||
|
||||
// TenantID lists servers for a particular tenant.
|
||||
// Setting "AllTenants = true" is required.
|
||||
TenantID string `q:"tenant_id"`
|
||||
}
|
||||
|
||||
// ToServerListQuery formats a ListOpts into a query string.
|
||||
@ -73,15 +78,16 @@ func List(client *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pa
|
||||
})
|
||||
}
|
||||
|
||||
// CreateOptsBuilder describes struct types that can be accepted by the Create call.
|
||||
// The CreateOpts struct in this package does.
|
||||
// CreateOptsBuilder allows extensions to add additional parameters to the
|
||||
// Create request.
|
||||
type CreateOptsBuilder interface {
|
||||
ToServerCreateMap() (map[string]interface{}, error)
|
||||
}
|
||||
|
||||
// Network is used within CreateOpts to control a new server's network attachments.
|
||||
// Network is used within CreateOpts to control a new server's network
|
||||
// attachments.
|
||||
type Network struct {
|
||||
// UUID of a nova-network to attach to the newly provisioned server.
|
||||
// UUID of a network to attach to the newly provisioned server.
|
||||
// Required unless Port is provided.
|
||||
UUID string
|
||||
|
||||
@ -89,19 +95,21 @@ type Network struct {
|
||||
// Required unless UUID is provided.
|
||||
Port string
|
||||
|
||||
// FixedIP [optional] specifies a fixed IPv4 address to be used on this network.
|
||||
// FixedIP specifies a fixed IPv4 address to be used on this network.
|
||||
FixedIP string
|
||||
}
|
||||
|
||||
// Personality is an array of files that are injected into the server at launch.
|
||||
type Personality []*File
|
||||
|
||||
// File is used within CreateOpts and RebuildOpts to inject a file into the server at launch.
|
||||
// File implements the json.Marshaler interface, so when a Create or Rebuild operation is requested,
|
||||
// json.Marshal will call File's MarshalJSON method.
|
||||
// File is used within CreateOpts and RebuildOpts to inject a file into the
|
||||
// server at launch.
|
||||
// File implements the json.Marshaler interface, so when a Create or Rebuild
|
||||
// operation is requested, json.Marshal will call File's MarshalJSON method.
|
||||
type File struct {
|
||||
// Path of the file
|
||||
// Path of the file.
|
||||
Path string
|
||||
|
||||
// Contents of the file. Maximum content size is 255 bytes.
|
||||
Contents []byte
|
||||
}
|
||||
@ -123,13 +131,13 @@ type CreateOpts struct {
|
||||
// Name is the name to assign to the newly launched server.
|
||||
Name string `json:"name" required:"true"`
|
||||
|
||||
// ImageRef [optional; required if ImageName is not provided] is the ID or full
|
||||
// URL to the image that contains the server's OS and initial state.
|
||||
// ImageRef [optional; required if ImageName is not provided] is the ID or
|
||||
// full URL to the image that contains the server's OS and initial state.
|
||||
// Also optional if using the boot-from-volume extension.
|
||||
ImageRef string `json:"imageRef"`
|
||||
|
||||
// ImageName [optional; required if ImageRef is not provided] is the name of the
|
||||
// image that contains the server's OS and initial state.
|
||||
// ImageName [optional; required if ImageRef is not provided] is the name of
|
||||
// the image that contains the server's OS and initial state.
|
||||
// Also optional if using the boot-from-volume extension.
|
||||
ImageName string `json:"-"`
|
||||
|
||||
@ -141,7 +149,8 @@ type CreateOpts struct {
|
||||
// the flavor that describes the server's specs.
|
||||
FlavorName string `json:"-"`
|
||||
|
||||
// SecurityGroups lists the names of the security groups to which this server should belong.
|
||||
// SecurityGroups lists the names of the security groups to which this server
|
||||
// should belong.
|
||||
SecurityGroups []string `json:"-"`
|
||||
|
||||
// UserData contains configuration information or scripts to use upon launch.
|
||||
@ -152,10 +161,12 @@ type CreateOpts struct {
|
||||
AvailabilityZone string `json:"availability_zone,omitempty"`
|
||||
|
||||
// Networks dictates how this server will be attached to available networks.
|
||||
// By default, the server will be attached to all isolated networks for the tenant.
|
||||
// By default, the server will be attached to all isolated networks for the
|
||||
// tenant.
|
||||
Networks []Network `json:"-"`
|
||||
|
||||
// Metadata contains key-value pairs (up to 255 bytes each) to attach to the server.
|
||||
// Metadata contains key-value pairs (up to 255 bytes each) to attach to the
|
||||
// server.
|
||||
Metadata map[string]string `json:"metadata,omitempty"`
|
||||
|
||||
// Personality includes files to inject into the server at launch.
|
||||
@ -166,7 +177,7 @@ type CreateOpts struct {
|
||||
ConfigDrive *bool `json:"config_drive,omitempty"`
|
||||
|
||||
// AdminPass sets the root user password. If not set, a randomly-generated
|
||||
// password will be created and returned in the rponse.
|
||||
// password will be created and returned in the response.
|
||||
AdminPass string `json:"adminPass,omitempty"`
|
||||
|
||||
// AccessIPv4 specifies an IPv4 address for the instance.
|
||||
@ -180,7 +191,8 @@ type CreateOpts struct {
|
||||
ServiceClient *gophercloud.ServiceClient `json:"-"`
|
||||
}
|
||||
|
||||
// ToServerCreateMap assembles a request body based on the contents of a CreateOpts.
|
||||
// ToServerCreateMap assembles a request body based on the contents of a
|
||||
// CreateOpts.
|
||||
func (opts CreateOpts) ToServerCreateMap() (map[string]interface{}, error) {
|
||||
sc := opts.ServiceClient
|
||||
opts.ServiceClient = nil
|
||||
@ -274,13 +286,14 @@ func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) (r Create
|
||||
return
|
||||
}
|
||||
|
||||
// Delete requests that a server previously provisioned be removed from your account.
|
||||
// Delete requests that a server previously provisioned be removed from your
|
||||
// account.
|
||||
func Delete(client *gophercloud.ServiceClient, id string) (r DeleteResult) {
|
||||
_, r.Err = client.Delete(deleteURL(client, id), nil)
|
||||
return
|
||||
}
|
||||
|
||||
// ForceDelete forces the deletion of a server
|
||||
// ForceDelete forces the deletion of a server.
|
||||
func ForceDelete(client *gophercloud.ServiceClient, id string) (r ActionResult) {
|
||||
_, r.Err = client.Post(actionURL(client, id), map[string]interface{}{"forceDelete": ""}, nil, nil)
|
||||
return
|
||||
@ -294,12 +307,14 @@ func Get(client *gophercloud.ServiceClient, id string) (r GetResult) {
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateOptsBuilder allows extensions to add additional attributes to the Update request.
|
||||
// UpdateOptsBuilder allows extensions to add additional attributes to the
|
||||
// Update request.
|
||||
type UpdateOptsBuilder interface {
|
||||
ToServerUpdateMap() (map[string]interface{}, error)
|
||||
}
|
||||
|
||||
// UpdateOpts specifies the base attributes that may be updated on an existing server.
|
||||
// UpdateOpts specifies the base attributes that may be updated on an existing
|
||||
// server.
|
||||
type UpdateOpts struct {
|
||||
// Name changes the displayed name of the server.
|
||||
// The server host name will *not* change.
|
||||
@ -331,7 +346,8 @@ func Update(client *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder
|
||||
return
|
||||
}
|
||||
|
||||
// ChangeAdminPassword alters the administrator or root password for a specified server.
|
||||
// ChangeAdminPassword alters the administrator or root password for a specified
|
||||
// server.
|
||||
func ChangeAdminPassword(client *gophercloud.ServiceClient, id, newPassword string) (r ActionResult) {
|
||||
b := map[string]interface{}{
|
||||
"changePassword": map[string]string{
|
||||
@ -354,33 +370,38 @@ const (
|
||||
PowerCycle = HardReboot
|
||||
)
|
||||
|
||||
// RebootOptsBuilder is an interface that options must satisfy in order to be
|
||||
// used when rebooting a server instance
|
||||
// RebootOptsBuilder allows extensions to add additional parameters to the
|
||||
// reboot request.
|
||||
type RebootOptsBuilder interface {
|
||||
ToServerRebootMap() (map[string]interface{}, error)
|
||||
}
|
||||
|
||||
// RebootOpts satisfies the RebootOptsBuilder interface
|
||||
// RebootOpts provides options to the reboot request.
|
||||
type RebootOpts struct {
|
||||
// Type is the type of reboot to perform on the server.
|
||||
Type RebootMethod `json:"type" required:"true"`
|
||||
}
|
||||
|
||||
// ToServerRebootMap allows RebootOpts to satisfiy the RebootOptsBuilder
|
||||
// interface
|
||||
// ToServerRebootMap builds a body for the reboot request.
|
||||
func (opts *RebootOpts) ToServerRebootMap() (map[string]interface{}, error) {
|
||||
return gophercloud.BuildRequestBody(opts, "reboot")
|
||||
}
|
||||
|
||||
// Reboot requests that a given server reboot.
|
||||
// Two methods exist for rebooting a server:
|
||||
//
|
||||
// HardReboot (aka PowerCycle) starts the server instance by physically cutting power to the machine, or if a VM,
|
||||
// terminating it at the hypervisor level.
|
||||
// It's done. Caput. Full stop.
|
||||
// Then, after a brief while, power is rtored or the VM instance rtarted.
|
||||
//
|
||||
// SoftReboot (aka OSReboot) simply tells the OS to rtart under its own procedur.
|
||||
// E.g., in Linux, asking it to enter runlevel 6, or executing "sudo shutdown -r now", or by asking Windows to rtart the machine.
|
||||
/*
|
||||
Reboot requests that a given server reboot.
|
||||
|
||||
Two methods exist for rebooting a server:
|
||||
|
||||
HardReboot (aka PowerCycle) starts the server instance by physically cutting
|
||||
power to the machine, or if a VM, terminating it at the hypervisor level.
|
||||
It's done. Caput. Full stop.
|
||||
Then, after a brief while, power is rtored or the VM instance restarted.
|
||||
|
||||
SoftReboot (aka OSReboot) simply tells the OS to restart under its own
|
||||
procedure.
|
||||
E.g., in Linux, asking it to enter runlevel 6, or executing
|
||||
"sudo shutdown -r now", or by asking Windows to rtart the machine.
|
||||
*/
|
||||
func Reboot(client *gophercloud.ServiceClient, id string, opts RebootOptsBuilder) (r ActionResult) {
|
||||
b, err := opts.ToServerRebootMap()
|
||||
if err != nil {
|
||||
@ -391,31 +412,43 @@ func Reboot(client *gophercloud.ServiceClient, id string, opts RebootOptsBuilder
|
||||
return
|
||||
}
|
||||
|
||||
// RebuildOptsBuilder is an interface that allows extensions to override the
|
||||
// default behaviour of rebuild options
|
||||
// RebuildOptsBuilder allows extensions to provide additional parameters to the
|
||||
// rebuild request.
|
||||
type RebuildOptsBuilder interface {
|
||||
ToServerRebuildMap() (map[string]interface{}, error)
|
||||
}
|
||||
|
||||
// RebuildOpts represents the configuration options used in a server rebuild
|
||||
// operation
|
||||
// operation.
|
||||
type RebuildOpts struct {
|
||||
// The server's admin password
|
||||
// AdminPass is the server's admin password
|
||||
AdminPass string `json:"adminPass,omitempty"`
|
||||
// The ID of the image you want your server to be provisioned on
|
||||
ImageID string `json:"imageRef"`
|
||||
|
||||
// ImageID is the ID of the image you want your server to be provisioned on.
|
||||
ImageID string `json:"imageRef"`
|
||||
|
||||
// ImageName is readable name of an image.
|
||||
ImageName string `json:"-"`
|
||||
|
||||
// Name to set the server to
|
||||
Name string `json:"name,omitempty"`
|
||||
|
||||
// AccessIPv4 [optional] provides a new IPv4 address for the instance.
|
||||
AccessIPv4 string `json:"accessIPv4,omitempty"`
|
||||
|
||||
// AccessIPv6 [optional] provides a new IPv6 address for the instance.
|
||||
AccessIPv6 string `json:"accessIPv6,omitempty"`
|
||||
// Metadata [optional] contains key-value pairs (up to 255 bytes each) to attach to the server.
|
||||
|
||||
// Metadata [optional] contains key-value pairs (up to 255 bytes each)
|
||||
// to attach to the server.
|
||||
Metadata map[string]string `json:"metadata,omitempty"`
|
||||
|
||||
// Personality [optional] includes files to inject into the server at launch.
|
||||
// Rebuild will base64-encode file contents for you.
|
||||
Personality Personality `json:"personality,omitempty"`
|
||||
Personality Personality `json:"personality,omitempty"`
|
||||
|
||||
// ServiceClient will allow calls to be made to retrieve an image or
|
||||
// flavor ID by name.
|
||||
ServiceClient *gophercloud.ServiceClient `json:"-"`
|
||||
}
|
||||
|
||||
@ -458,31 +491,34 @@ func Rebuild(client *gophercloud.ServiceClient, id string, opts RebuildOptsBuild
|
||||
return
|
||||
}
|
||||
|
||||
// ResizeOptsBuilder is an interface that allows extensions to override the default structure of
|
||||
// a Resize request.
|
||||
// ResizeOptsBuilder allows extensions to add additional parameters to the
|
||||
// resize request.
|
||||
type ResizeOptsBuilder interface {
|
||||
ToServerResizeMap() (map[string]interface{}, error)
|
||||
}
|
||||
|
||||
// ResizeOpts represents the configuration options used to control a Resize operation.
|
||||
// ResizeOpts represents the configuration options used to control a Resize
|
||||
// operation.
|
||||
type ResizeOpts struct {
|
||||
// FlavorRef is the ID of the flavor you wish your server to become.
|
||||
FlavorRef string `json:"flavorRef" required:"true"`
|
||||
}
|
||||
|
||||
// ToServerResizeMap formats a ResizeOpts as a map that can be used as a JSON request body for the
|
||||
// Resize request.
|
||||
// ToServerResizeMap formats a ResizeOpts as a map that can be used as a JSON
|
||||
// request body for the Resize request.
|
||||
func (opts ResizeOpts) ToServerResizeMap() (map[string]interface{}, error) {
|
||||
return gophercloud.BuildRequestBody(opts, "resize")
|
||||
}
|
||||
|
||||
// Resize instructs the provider to change the flavor of the server.
|
||||
//
|
||||
// Note that this implies rebuilding it.
|
||||
//
|
||||
// Unfortunately, one cannot pass rebuild parameters to the resize function.
|
||||
// When the resize completes, the server will be in RESIZE_VERIFY state.
|
||||
// While in this state, you can explore the use of the new server's configuration.
|
||||
// If you like it, call ConfirmResize() to commit the resize permanently.
|
||||
// Otherwise, call RevertResize() to restore the old configuration.
|
||||
// When the resize completes, the server will be in VERIFY_RESIZE state.
|
||||
// While in this state, you can explore the use of the new server's
|
||||
// configuration. If you like it, call ConfirmResize() to commit the resize
|
||||
// permanently. Otherwise, call RevertResize() to restore the old configuration.
|
||||
func Resize(client *gophercloud.ServiceClient, id string, opts ResizeOptsBuilder) (r ActionResult) {
|
||||
b, err := opts.ToServerResizeMap()
|
||||
if err != nil {
|
||||
@ -542,8 +578,8 @@ func Rescue(client *gophercloud.ServiceClient, id string, opts RescueOptsBuilder
|
||||
return
|
||||
}
|
||||
|
||||
// ResetMetadataOptsBuilder allows extensions to add additional parameters to the
|
||||
// Reset request.
|
||||
// ResetMetadataOptsBuilder allows extensions to add additional parameters to
|
||||
// the Reset request.
|
||||
type ResetMetadataOptsBuilder interface {
|
||||
ToMetadataResetMap() (map[string]interface{}, error)
|
||||
}
|
||||
@ -551,20 +587,23 @@ type ResetMetadataOptsBuilder interface {
|
||||
// MetadataOpts is a map that contains key-value pairs.
|
||||
type MetadataOpts map[string]string
|
||||
|
||||
// ToMetadataResetMap assembles a body for a Reset request based on the contents of a MetadataOpts.
|
||||
// ToMetadataResetMap assembles a body for a Reset request based on the contents
|
||||
// of a MetadataOpts.
|
||||
func (opts MetadataOpts) ToMetadataResetMap() (map[string]interface{}, error) {
|
||||
return map[string]interface{}{"metadata": opts}, nil
|
||||
}
|
||||
|
||||
// ToMetadataUpdateMap assembles a body for an Update request based on the contents of a MetadataOpts.
|
||||
// ToMetadataUpdateMap assembles a body for an Update request based on the
|
||||
// contents of a MetadataOpts.
|
||||
func (opts MetadataOpts) ToMetadataUpdateMap() (map[string]interface{}, error) {
|
||||
return map[string]interface{}{"metadata": opts}, nil
|
||||
}
|
||||
|
||||
// ResetMetadata will create multiple new key-value pairs for the given server ID.
|
||||
// Note: Using this operation will erase any already-existing metadata and create
|
||||
// the new metadata provided. To keep any already-existing metadata, use the
|
||||
// UpdateMetadatas or UpdateMetadata function.
|
||||
// ResetMetadata will create multiple new key-value pairs for the given server
|
||||
// ID.
|
||||
// Note: Using this operation will erase any already-existing metadata and
|
||||
// create the new metadata provided. To keep any already-existing metadata,
|
||||
// use the UpdateMetadatas or UpdateMetadata function.
|
||||
func ResetMetadata(client *gophercloud.ServiceClient, id string, opts ResetMetadataOptsBuilder) (r ResetMetadataResult) {
|
||||
b, err := opts.ToMetadataResetMap()
|
||||
if err != nil {
|
||||
@ -583,15 +622,15 @@ func Metadata(client *gophercloud.ServiceClient, id string) (r GetMetadataResult
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateMetadataOptsBuilder allows extensions to add additional parameters to the
|
||||
// Create request.
|
||||
// UpdateMetadataOptsBuilder allows extensions to add additional parameters to
|
||||
// the Create request.
|
||||
type UpdateMetadataOptsBuilder interface {
|
||||
ToMetadataUpdateMap() (map[string]interface{}, error)
|
||||
}
|
||||
|
||||
// UpdateMetadata updates (or creates) all the metadata specified by opts for the given server ID.
|
||||
// This operation does not affect already-existing metadata that is not specified
|
||||
// by opts.
|
||||
// UpdateMetadata updates (or creates) all the metadata specified by opts for
|
||||
// the given server ID. This operation does not affect already-existing metadata
|
||||
// that is not specified by opts.
|
||||
func UpdateMetadata(client *gophercloud.ServiceClient, id string, opts UpdateMetadataOptsBuilder) (r UpdateMetadataResult) {
|
||||
b, err := opts.ToMetadataUpdateMap()
|
||||
if err != nil {
|
||||
@ -613,7 +652,8 @@ type MetadatumOptsBuilder interface {
|
||||
// MetadatumOpts is a map of length one that contains a key-value pair.
|
||||
type MetadatumOpts map[string]string
|
||||
|
||||
// ToMetadatumCreateMap assembles a body for a Create request based on the contents of a MetadataumOpts.
|
||||
// ToMetadatumCreateMap assembles a body for a Create request based on the
|
||||
// contents of a MetadataumOpts.
|
||||
func (opts MetadatumOpts) ToMetadatumCreateMap() (map[string]interface{}, string, error) {
|
||||
if len(opts) != 1 {
|
||||
err := gophercloud.ErrInvalidInput{}
|
||||
@ -629,7 +669,8 @@ func (opts MetadatumOpts) ToMetadatumCreateMap() (map[string]interface{}, string
|
||||
return metadatum, key, nil
|
||||
}
|
||||
|
||||
// CreateMetadatum will create or update the key-value pair with the given key for the given server ID.
|
||||
// CreateMetadatum will create or update the key-value pair with the given key
|
||||
// for the given server ID.
|
||||
func CreateMetadatum(client *gophercloud.ServiceClient, id string, opts MetadatumOptsBuilder) (r CreateMetadatumResult) {
|
||||
b, key, err := opts.ToMetadatumCreateMap()
|
||||
if err != nil {
|
||||
@ -642,53 +683,60 @@ func CreateMetadatum(client *gophercloud.ServiceClient, id string, opts Metadatu
|
||||
return
|
||||
}
|
||||
|
||||
// Metadatum requests the key-value pair with the given key for the given server ID.
|
||||
// Metadatum requests the key-value pair with the given key for the given
|
||||
// server ID.
|
||||
func Metadatum(client *gophercloud.ServiceClient, id, key string) (r GetMetadatumResult) {
|
||||
_, r.Err = client.Get(metadatumURL(client, id, key), &r.Body, nil)
|
||||
return
|
||||
}
|
||||
|
||||
// DeleteMetadatum will delete the key-value pair with the given key for the given server ID.
|
||||
// DeleteMetadatum will delete the key-value pair with the given key for the
|
||||
// given server ID.
|
||||
func DeleteMetadatum(client *gophercloud.ServiceClient, id, key string) (r DeleteMetadatumResult) {
|
||||
_, r.Err = client.Delete(metadatumURL(client, id, key), nil)
|
||||
return
|
||||
}
|
||||
|
||||
// ListAddresses makes a request against the API to list the servers IP addresses.
|
||||
// ListAddresses makes a request against the API to list the servers IP
|
||||
// addresses.
|
||||
func ListAddresses(client *gophercloud.ServiceClient, id string) pagination.Pager {
|
||||
return pagination.NewPager(client, listAddressesURL(client, id), func(r pagination.PageResult) pagination.Page {
|
||||
return AddressPage{pagination.SinglePageBase(r)}
|
||||
})
|
||||
}
|
||||
|
||||
// ListAddressesByNetwork makes a request against the API to list the servers IP addresses
|
||||
// for the given network.
|
||||
// ListAddressesByNetwork makes a request against the API to list the servers IP
|
||||
// addresses for the given network.
|
||||
func ListAddressesByNetwork(client *gophercloud.ServiceClient, id, network string) pagination.Pager {
|
||||
return pagination.NewPager(client, listAddressesByNetworkURL(client, id, network), func(r pagination.PageResult) pagination.Page {
|
||||
return NetworkAddressPage{pagination.SinglePageBase(r)}
|
||||
})
|
||||
}
|
||||
|
||||
// CreateImageOptsBuilder is the interface types must satisfy in order to be
|
||||
// used as CreateImage options
|
||||
// CreateImageOptsBuilder allows extensions to add additional parameters to the
|
||||
// CreateImage request.
|
||||
type CreateImageOptsBuilder interface {
|
||||
ToServerCreateImageMap() (map[string]interface{}, error)
|
||||
}
|
||||
|
||||
// CreateImageOpts satisfies the CreateImageOptsBuilder
|
||||
// CreateImageOpts provides options to pass to the CreateImage request.
|
||||
type CreateImageOpts struct {
|
||||
// Name of the image/snapshot
|
||||
// Name of the image/snapshot.
|
||||
Name string `json:"name" required:"true"`
|
||||
// Metadata contains key-value pairs (up to 255 bytes each) to attach to the created image.
|
||||
|
||||
// Metadata contains key-value pairs (up to 255 bytes each) to attach to
|
||||
// the created image.
|
||||
Metadata map[string]string `json:"metadata,omitempty"`
|
||||
}
|
||||
|
||||
// ToServerCreateImageMap formats a CreateImageOpts structure into a request body.
|
||||
// ToServerCreateImageMap formats a CreateImageOpts structure into a request
|
||||
// body.
|
||||
func (opts CreateImageOpts) ToServerCreateImageMap() (map[string]interface{}, error) {
|
||||
return gophercloud.BuildRequestBody(opts, "createImage")
|
||||
}
|
||||
|
||||
// CreateImage makes a request against the nova API to schedule an image to be created of the server
|
||||
// CreateImage makes a request against the nova API to schedule an image to be
|
||||
// created of the server
|
||||
func CreateImage(client *gophercloud.ServiceClient, id string, opts CreateImageOptsBuilder) (r CreateImageResult) {
|
||||
b, err := opts.ToServerCreateImageMap()
|
||||
if err != nil {
|
||||
@ -703,7 +751,8 @@ func CreateImage(client *gophercloud.ServiceClient, id string, opts CreateImageO
|
||||
return
|
||||
}
|
||||
|
||||
// IDFromName is a convienience function that returns a server's ID given its name.
|
||||
// IDFromName is a convienience function that returns a server's ID given its
|
||||
// name.
|
||||
func IDFromName(client *gophercloud.ServiceClient, name string) (string, error) {
|
||||
count := 0
|
||||
id := ""
|
||||
@ -734,7 +783,8 @@ func IDFromName(client *gophercloud.ServiceClient, name string) (string, error)
|
||||
}
|
||||
}
|
||||
|
||||
// GetPassword makes a request against the nova API to get the encrypted administrative password.
|
||||
// GetPassword makes a request against the nova API to get the encrypted
|
||||
// administrative password.
|
||||
func GetPassword(client *gophercloud.ServiceClient, serverId string) (r GetPasswordResult) {
|
||||
_, r.Err = client.Get(passwordURL(client, serverId), &r.Body, nil)
|
||||
return
|
||||
|
156
vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/servers/results.go
generated
vendored
156
vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/servers/results.go
generated
vendored
@ -32,54 +32,64 @@ func ExtractServersInto(r pagination.Page, v interface{}) error {
|
||||
return r.(ServerPage).Result.ExtractIntoSlicePtr(v, "servers")
|
||||
}
|
||||
|
||||
// CreateResult temporarily contains the response from a Create call.
|
||||
// CreateResult is the response from a Create operation. Call its Extract
|
||||
// method to interpret it as a Server.
|
||||
type CreateResult struct {
|
||||
serverResult
|
||||
}
|
||||
|
||||
// GetResult temporarily contains the response from a Get call.
|
||||
// GetResult is the response from a Get operation. Call its Extract
|
||||
// method to interpret it as a Server.
|
||||
type GetResult struct {
|
||||
serverResult
|
||||
}
|
||||
|
||||
// UpdateResult temporarily contains the response from an Update call.
|
||||
// UpdateResult is the response from an Update operation. Call its Extract
|
||||
// method to interpret it as a Server.
|
||||
type UpdateResult struct {
|
||||
serverResult
|
||||
}
|
||||
|
||||
// DeleteResult temporarily contains the response from a Delete call.
|
||||
// DeleteResult is the response from a Delete operation. Call its ExtractErr
|
||||
// method to determine if the call succeeded or failed.
|
||||
type DeleteResult struct {
|
||||
gophercloud.ErrResult
|
||||
}
|
||||
|
||||
// RebuildResult temporarily contains the response from a Rebuild call.
|
||||
// RebuildResult is the response from a Rebuild operation. Call its Extract
|
||||
// method to interpret it as a Server.
|
||||
type RebuildResult struct {
|
||||
serverResult
|
||||
}
|
||||
|
||||
// ActionResult represents the result of server action operations, like reboot
|
||||
// ActionResult represents the result of server action operations, like reboot.
|
||||
// Call its ExtractErr method to determine if the action succeeded or failed.
|
||||
type ActionResult struct {
|
||||
gophercloud.ErrResult
|
||||
}
|
||||
|
||||
// RescueResult represents the result of a server rescue operation
|
||||
// RescueResult is the response from a Rescue operation. Call its ExtractErr
|
||||
// method to determine if the call succeeded or failed.
|
||||
type RescueResult struct {
|
||||
ActionResult
|
||||
}
|
||||
|
||||
// CreateImageResult represents the result of an image creation operation
|
||||
// CreateImageResult is the response from a CreateImage operation. Call its
|
||||
// ExtractImageID method to retrieve the ID of the newly created image.
|
||||
type CreateImageResult struct {
|
||||
gophercloud.Result
|
||||
}
|
||||
|
||||
// GetPasswordResult represent the result of a get os-server-password operation.
|
||||
// Call its ExtractPassword method to retrieve the password.
|
||||
type GetPasswordResult struct {
|
||||
gophercloud.Result
|
||||
}
|
||||
|
||||
// ExtractPassword gets the encrypted password.
|
||||
// If privateKey != nil the password is decrypted with the private key.
|
||||
// If privateKey == nil the encrypted password is returned and can be decrypted with:
|
||||
// If privateKey == nil the encrypted password is returned and can be decrypted
|
||||
// with:
|
||||
// echo '<pwd>' | base64 -D | openssl rsautl -decrypt -inkey <private_key>
|
||||
func (r GetPasswordResult) ExtractPassword(privateKey *rsa.PrivateKey) (string, error) {
|
||||
var s struct {
|
||||
@ -107,7 +117,7 @@ func decryptPassword(encryptedPassword string, privateKey *rsa.PrivateKey) (stri
|
||||
return string(password), nil
|
||||
}
|
||||
|
||||
// ExtractImageID gets the ID of the newly created server image from the header
|
||||
// ExtractImageID gets the ID of the newly created server image from the header.
|
||||
func (r CreateImageResult) ExtractImageID() (string, error) {
|
||||
if r.Err != nil {
|
||||
return "", r.Err
|
||||
@ -133,45 +143,84 @@ func (r RescueResult) Extract() (string, error) {
|
||||
return s.AdminPass, err
|
||||
}
|
||||
|
||||
// Server exposes only the standard OpenStack fields corresponding to a given server on the user's account.
|
||||
// Server represents a server/instance in the OpenStack cloud.
|
||||
type Server struct {
|
||||
// ID uniquely identifies this server amongst all other servers, including those not accessible to the current tenant.
|
||||
// ID uniquely identifies this server amongst all other servers,
|
||||
// including those not accessible to the current tenant.
|
||||
ID string `json:"id"`
|
||||
|
||||
// TenantID identifies the tenant owning this server resource.
|
||||
TenantID string `json:"tenant_id"`
|
||||
|
||||
// UserID uniquely identifies the user account owning the tenant.
|
||||
UserID string `json:"user_id"`
|
||||
|
||||
// Name contains the human-readable name for the server.
|
||||
Name string `json:"name"`
|
||||
// Updated and Created contain ISO-8601 timestamps of when the state of the server last changed, and when it was created.
|
||||
|
||||
// Updated and Created contain ISO-8601 timestamps of when the state of the
|
||||
// server last changed, and when it was created.
|
||||
Updated time.Time `json:"updated"`
|
||||
Created time.Time `json:"created"`
|
||||
HostID string `json:"hostid"`
|
||||
// Status contains the current operational status of the server, such as IN_PROGRESS or ACTIVE.
|
||||
|
||||
// HostID is the host where the server is located in the cloud.
|
||||
HostID string `json:"hostid"`
|
||||
|
||||
// Status contains the current operational status of the server,
|
||||
// such as IN_PROGRESS or ACTIVE.
|
||||
Status string `json:"status"`
|
||||
|
||||
// Progress ranges from 0..100.
|
||||
// A request made against the server completes only once Progress reaches 100.
|
||||
Progress int `json:"progress"`
|
||||
// AccessIPv4 and AccessIPv6 contain the IP addresses of the server, suitable for remote access for administration.
|
||||
|
||||
// AccessIPv4 and AccessIPv6 contain the IP addresses of the server,
|
||||
// suitable for remote access for administration.
|
||||
AccessIPv4 string `json:"accessIPv4"`
|
||||
AccessIPv6 string `json:"accessIPv6"`
|
||||
// Image refers to a JSON object, which itself indicates the OS image used to deploy the server.
|
||||
|
||||
// Image refers to a JSON object, which itself indicates the OS image used to
|
||||
// deploy the server.
|
||||
Image map[string]interface{} `json:"-"`
|
||||
// Flavor refers to a JSON object, which itself indicates the hardware configuration of the deployed server.
|
||||
|
||||
// Flavor refers to a JSON object, which itself indicates the hardware
|
||||
// configuration of the deployed server.
|
||||
Flavor map[string]interface{} `json:"flavor"`
|
||||
// Addresses includes a list of all IP addresses assigned to the server, keyed by pool.
|
||||
|
||||
// Addresses includes a list of all IP addresses assigned to the server,
|
||||
// keyed by pool.
|
||||
Addresses map[string]interface{} `json:"addresses"`
|
||||
// Metadata includes a list of all user-specified key-value pairs attached to the server.
|
||||
|
||||
// Metadata includes a list of all user-specified key-value pairs attached
|
||||
// to the server.
|
||||
Metadata map[string]string `json:"metadata"`
|
||||
// Links includes HTTP references to the itself, useful for passing along to other APIs that might want a server reference.
|
||||
|
||||
// Links includes HTTP references to the itself, useful for passing along to
|
||||
// other APIs that might want a server reference.
|
||||
Links []interface{} `json:"links"`
|
||||
|
||||
// KeyName indicates which public key was injected into the server on launch.
|
||||
KeyName string `json:"key_name"`
|
||||
// AdminPass will generally be empty (""). However, it will contain the administrative password chosen when provisioning a new server without a set AdminPass setting in the first place.
|
||||
|
||||
// AdminPass will generally be empty (""). However, it will contain the
|
||||
// administrative password chosen when provisioning a new server without a
|
||||
// set AdminPass setting in the first place.
|
||||
// Note that this is the ONLY time this field will be valid.
|
||||
AdminPass string `json:"adminPass"`
|
||||
// SecurityGroups includes the security groups that this instance has applied to it
|
||||
|
||||
// SecurityGroups includes the security groups that this instance has applied
|
||||
// to it.
|
||||
SecurityGroups []map[string]interface{} `json:"security_groups"`
|
||||
|
||||
// Fault contains failure information about a server.
|
||||
Fault Fault `json:"fault"`
|
||||
}
|
||||
|
||||
type Fault struct {
|
||||
Code int `json:"code"`
|
||||
Created time.Time `json:"created"`
|
||||
Details string `json:"details"`
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
func (r *Server) UnmarshalJSON(b []byte) error {
|
||||
@ -200,9 +249,10 @@ func (r *Server) UnmarshalJSON(b []byte) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// ServerPage abstracts the raw results of making a List() request against the API.
|
||||
// As OpenStack extensions may freely alter the response bodies of structures returned to the client, you may only safely access the
|
||||
// data provided through the ExtractServers call.
|
||||
// ServerPage abstracts the raw results of making a List() request against
|
||||
// the API. As OpenStack extensions may freely alter the response bodies of
|
||||
// structures returned to the client, you may only safely access the data
|
||||
// provided through the ExtractServers call.
|
||||
type ServerPage struct {
|
||||
pagination.LinkedPageBase
|
||||
}
|
||||
@ -213,7 +263,8 @@ func (r ServerPage) IsEmpty() (bool, error) {
|
||||
return len(s) == 0, err
|
||||
}
|
||||
|
||||
// NextPageURL uses the response's embedded link reference to navigate to the next page of results.
|
||||
// NextPageURL uses the response's embedded link reference to navigate to the
|
||||
// next page of results.
|
||||
func (r ServerPage) NextPageURL() (string, error) {
|
||||
var s struct {
|
||||
Links []gophercloud.Link `json:"servers_links"`
|
||||
@ -225,49 +276,59 @@ func (r ServerPage) NextPageURL() (string, error) {
|
||||
return gophercloud.ExtractNextURL(s.Links)
|
||||
}
|
||||
|
||||
// ExtractServers interprets the results of a single page from a List() call, producing a slice of Server entities.
|
||||
// ExtractServers interprets the results of a single page from a List() call,
|
||||
// producing a slice of Server entities.
|
||||
func ExtractServers(r pagination.Page) ([]Server, error) {
|
||||
var s []Server
|
||||
err := ExtractServersInto(r, &s)
|
||||
return s, err
|
||||
}
|
||||
|
||||
// MetadataResult contains the result of a call for (potentially) multiple key-value pairs.
|
||||
// MetadataResult contains the result of a call for (potentially) multiple
|
||||
// key-value pairs. Call its Extract method to interpret it as a
|
||||
// map[string]interface.
|
||||
type MetadataResult struct {
|
||||
gophercloud.Result
|
||||
}
|
||||
|
||||
// GetMetadataResult temporarily contains the response from a metadata Get call.
|
||||
// GetMetadataResult contains the result of a Get operation. Call its Extract
|
||||
// method to interpret it as a map[string]interface.
|
||||
type GetMetadataResult struct {
|
||||
MetadataResult
|
||||
}
|
||||
|
||||
// ResetMetadataResult temporarily contains the response from a metadata Reset call.
|
||||
// ResetMetadataResult contains the result of a Reset operation. Call its
|
||||
// Extract method to interpret it as a map[string]interface.
|
||||
type ResetMetadataResult struct {
|
||||
MetadataResult
|
||||
}
|
||||
|
||||
// UpdateMetadataResult temporarily contains the response from a metadata Update call.
|
||||
// UpdateMetadataResult contains the result of an Update operation. Call its
|
||||
// Extract method to interpret it as a map[string]interface.
|
||||
type UpdateMetadataResult struct {
|
||||
MetadataResult
|
||||
}
|
||||
|
||||
// MetadatumResult contains the result of a call for individual a single key-value pair.
|
||||
// MetadatumResult contains the result of a call for individual a single
|
||||
// key-value pair.
|
||||
type MetadatumResult struct {
|
||||
gophercloud.Result
|
||||
}
|
||||
|
||||
// GetMetadatumResult temporarily contains the response from a metadatum Get call.
|
||||
// GetMetadatumResult contains the result of a Get operation. Call its Extract
|
||||
// method to interpret it as a map[string]interface.
|
||||
type GetMetadatumResult struct {
|
||||
MetadatumResult
|
||||
}
|
||||
|
||||
// CreateMetadatumResult temporarily contains the response from a metadatum Create call.
|
||||
// CreateMetadatumResult contains the result of a Create operation. Call its
|
||||
// Extract method to interpret it as a map[string]interface.
|
||||
type CreateMetadatumResult struct {
|
||||
MetadatumResult
|
||||
}
|
||||
|
||||
// DeleteMetadatumResult temporarily contains the response from a metadatum Delete call.
|
||||
// DeleteMetadatumResult contains the result of a Delete operation. Call its
|
||||
// ExtractErr method to determine if the call succeeded or failed.
|
||||
type DeleteMetadatumResult struct {
|
||||
gophercloud.ErrResult
|
||||
}
|
||||
@ -296,9 +357,10 @@ type Address struct {
|
||||
Address string `json:"addr"`
|
||||
}
|
||||
|
||||
// AddressPage abstracts the raw results of making a ListAddresses() request against the API.
|
||||
// As OpenStack extensions may freely alter the response bodies of structures returned
|
||||
// to the client, you may only safely access the data provided through the ExtractAddresses call.
|
||||
// AddressPage abstracts the raw results of making a ListAddresses() request
|
||||
// against the API. As OpenStack extensions may freely alter the response bodies
|
||||
// of structures returned to the client, you may only safely access the data
|
||||
// provided through the ExtractAddresses call.
|
||||
type AddressPage struct {
|
||||
pagination.SinglePageBase
|
||||
}
|
||||
@ -309,8 +371,8 @@ func (r AddressPage) IsEmpty() (bool, error) {
|
||||
return len(addresses) == 0, err
|
||||
}
|
||||
|
||||
// ExtractAddresses interprets the results of a single page from a ListAddresses() call,
|
||||
// producing a map of addresses.
|
||||
// ExtractAddresses interprets the results of a single page from a
|
||||
// ListAddresses() call, producing a map of addresses.
|
||||
func ExtractAddresses(r pagination.Page) (map[string][]Address, error) {
|
||||
var s struct {
|
||||
Addresses map[string][]Address `json:"addresses"`
|
||||
@ -319,9 +381,11 @@ func ExtractAddresses(r pagination.Page) (map[string][]Address, error) {
|
||||
return s.Addresses, err
|
||||
}
|
||||
|
||||
// NetworkAddressPage abstracts the raw results of making a ListAddressesByNetwork() request against the API.
|
||||
// As OpenStack extensions may freely alter the response bodies of structures returned
|
||||
// to the client, you may only safely access the data provided through the ExtractAddresses call.
|
||||
// NetworkAddressPage abstracts the raw results of making a
|
||||
// ListAddressesByNetwork() request against the API.
|
||||
// As OpenStack extensions may freely alter the response bodies of structures
|
||||
// returned to the client, you may only safely access the data provided through
|
||||
// the ExtractAddresses call.
|
||||
type NetworkAddressPage struct {
|
||||
pagination.SinglePageBase
|
||||
}
|
||||
@ -332,8 +396,8 @@ func (r NetworkAddressPage) IsEmpty() (bool, error) {
|
||||
return len(addresses) == 0, err
|
||||
}
|
||||
|
||||
// ExtractNetworkAddresses interprets the results of a single page from a ListAddressesByNetwork() call,
|
||||
// producing a slice of addresses.
|
||||
// ExtractNetworkAddresses interprets the results of a single page from a
|
||||
// ListAddressesByNetwork() call, producing a slice of addresses.
|
||||
func ExtractNetworkAddresses(r pagination.Page) ([]Address, error) {
|
||||
var s map[string][]Address
|
||||
err := (r.(NetworkAddressPage)).ExtractInto(&s)
|
||||
|
5
vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/servers/util.go
generated
vendored
5
vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/servers/util.go
generated
vendored
@ -2,8 +2,9 @@ package servers
|
||||
|
||||
import "github.com/gophercloud/gophercloud"
|
||||
|
||||
// WaitForStatus will continually poll a server until it successfully transitions to a specified
|
||||
// status. It will do this for at most the number of seconds specified.
|
||||
// WaitForStatus will continually poll a server until it successfully
|
||||
// transitions to a specified status. It will do this for at most the number
|
||||
// of seconds specified.
|
||||
func WaitForStatus(c *gophercloud.ServiceClient, id, status string, secs int) error {
|
||||
return gophercloud.WaitFor(secs, func() (bool, error) {
|
||||
current, err := Get(c, id).Extract()
|
||||
|
14
vendor/github.com/gophercloud/gophercloud/openstack/doc.go
generated
vendored
Normal file
14
vendor/github.com/gophercloud/gophercloud/openstack/doc.go
generated
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
/*
|
||||
Package openstack contains resources for the individual OpenStack projects
|
||||
supported in Gophercloud. It also includes functions to authenticate to an
|
||||
OpenStack cloud and for provisioning various service-level clients.
|
||||
|
||||
Example of Creating a Service Client
|
||||
|
||||
ao, err := openstack.AuthOptionsFromEnv()
|
||||
provider, err := openstack.AuthenticatedClient(ao)
|
||||
client, err := openstack.NewNetworkV2(client, gophercloud.EndpointOpts{
|
||||
Region: os.Getenv("OS_REGION_NAME"),
|
||||
})
|
||||
*/
|
||||
package openstack
|
34
vendor/github.com/gophercloud/gophercloud/openstack/endpoint_location.go
generated
vendored
34
vendor/github.com/gophercloud/gophercloud/openstack/endpoint_location.go
generated
vendored
@ -6,12 +6,16 @@ import (
|
||||
tokens3 "github.com/gophercloud/gophercloud/openstack/identity/v3/tokens"
|
||||
)
|
||||
|
||||
// V2EndpointURL discovers the endpoint URL for a specific service from a ServiceCatalog acquired
|
||||
// during the v2 identity service. The specified EndpointOpts are used to identify a unique,
|
||||
// unambiguous endpoint to return. It's an error both when multiple endpoints match the provided
|
||||
// criteria and when none do. The minimum that can be specified is a Type, but you will also often
|
||||
// need to specify a Name and/or a Region depending on what's available on your OpenStack
|
||||
// deployment.
|
||||
/*
|
||||
V2EndpointURL discovers the endpoint URL for a specific service from a
|
||||
ServiceCatalog acquired during the v2 identity service.
|
||||
|
||||
The specified EndpointOpts are used to identify a unique, unambiguous endpoint
|
||||
to return. It's an error both when multiple endpoints match the provided
|
||||
criteria and when none do. The minimum that can be specified is a Type, but you
|
||||
will also often need to specify a Name and/or a Region depending on what's
|
||||
available on your OpenStack deployment.
|
||||
*/
|
||||
func V2EndpointURL(catalog *tokens2.ServiceCatalog, opts gophercloud.EndpointOpts) (string, error) {
|
||||
// Extract Endpoints from the catalog entries that match the requested Type, Name if provided, and Region if provided.
|
||||
var endpoints = make([]tokens2.Endpoint, 0, 1)
|
||||
@ -54,12 +58,16 @@ func V2EndpointURL(catalog *tokens2.ServiceCatalog, opts gophercloud.EndpointOpt
|
||||
return "", err
|
||||
}
|
||||
|
||||
// V3EndpointURL discovers the endpoint URL for a specific service from a Catalog acquired
|
||||
// during the v3 identity service. The specified EndpointOpts are used to identify a unique,
|
||||
// unambiguous endpoint to return. It's an error both when multiple endpoints match the provided
|
||||
// criteria and when none do. The minimum that can be specified is a Type, but you will also often
|
||||
// need to specify a Name and/or a Region depending on what's available on your OpenStack
|
||||
// deployment.
|
||||
/*
|
||||
V3EndpointURL discovers the endpoint URL for a specific service from a Catalog
|
||||
acquired during the v3 identity service.
|
||||
|
||||
The specified EndpointOpts are used to identify a unique, unambiguous endpoint
|
||||
to return. It's an error both when multiple endpoints match the provided
|
||||
criteria and when none do. The minimum that can be specified is a Type, but you
|
||||
will also often need to specify a Name and/or a Region depending on what's
|
||||
available on your OpenStack deployment.
|
||||
*/
|
||||
func V3EndpointURL(catalog *tokens3.ServiceCatalog, opts gophercloud.EndpointOpts) (string, error) {
|
||||
// Extract Endpoints from the catalog entries that match the requested Type, Interface,
|
||||
// Name if provided, and Region if provided.
|
||||
@ -76,7 +84,7 @@ func V3EndpointURL(catalog *tokens3.ServiceCatalog, opts gophercloud.EndpointOpt
|
||||
return "", err
|
||||
}
|
||||
if (opts.Availability == gophercloud.Availability(endpoint.Interface)) &&
|
||||
(opts.Region == "" || endpoint.Region == opts.Region) {
|
||||
(opts.Region == "" || endpoint.Region == opts.Region || endpoint.RegionID == opts.Region) {
|
||||
endpoints = append(endpoints, endpoint)
|
||||
}
|
||||
}
|
||||
|
70
vendor/github.com/gophercloud/gophercloud/openstack/identity/v2/tenants/doc.go
generated
vendored
70
vendor/github.com/gophercloud/gophercloud/openstack/identity/v2/tenants/doc.go
generated
vendored
@ -1,7 +1,65 @@
|
||||
// Package tenants provides information and interaction with the
|
||||
// tenants API resource for the OpenStack Identity service.
|
||||
//
|
||||
// See http://developer.openstack.org/api-ref-identity-v2.html#identity-auth-v2
|
||||
// and http://developer.openstack.org/api-ref-identity-v2.html#admin-tenants
|
||||
// for more information.
|
||||
/*
|
||||
Package tenants provides information and interaction with the
|
||||
tenants API resource for the OpenStack Identity service.
|
||||
|
||||
See http://developer.openstack.org/api-ref-identity-v2.html#identity-auth-v2
|
||||
and http://developer.openstack.org/api-ref-identity-v2.html#admin-tenants
|
||||
for more information.
|
||||
|
||||
Example to List Tenants
|
||||
|
||||
listOpts := tenants.ListOpts{
|
||||
Limit: 2,
|
||||
}
|
||||
|
||||
allPages, err := tenants.List(identityClient, listOpts).AllPages()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
allTenants, err := tenants.ExtractTenants(allPages)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
for _, tenant := range allTenants {
|
||||
fmt.Printf("%+v\n", tenant)
|
||||
}
|
||||
|
||||
Example to Create a Tenant
|
||||
|
||||
createOpts := tenants.CreateOpts{
|
||||
Name: "tenant_name",
|
||||
Description: "this is a tenant",
|
||||
Enabled: gophercloud.Enabled,
|
||||
}
|
||||
|
||||
tenant, err := tenants.Create(identityClient, createOpts).Extract()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
Example to Update a Tenant
|
||||
|
||||
tenantID := "e6db6ed6277c461a853458589063b295"
|
||||
|
||||
updateOpts := tenants.UpdateOpts{
|
||||
Description: "this is a new description",
|
||||
Enabled: gophercloud.Disabled,
|
||||
}
|
||||
|
||||
tenant, err := tenants.Update(identityClient, tenantID, updateOpts).Extract()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
Example to Delete a Tenant
|
||||
|
||||
tenantID := "e6db6ed6277c461a853458589063b295"
|
||||
|
||||
err := tenants.Delete(identitYClient, tenantID).ExtractErr()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
*/
|
||||
package tenants
|
||||
|
19
vendor/github.com/gophercloud/gophercloud/openstack/identity/v2/tenants/requests.go
generated
vendored
19
vendor/github.com/gophercloud/gophercloud/openstack/identity/v2/tenants/requests.go
generated
vendored
@ -9,6 +9,7 @@ import (
|
||||
type ListOpts struct {
|
||||
// Marker is the ID of the last Tenant on the previous page.
|
||||
Marker string `q:"marker"`
|
||||
|
||||
// Limit specifies the page size.
|
||||
Limit int `q:"limit"`
|
||||
}
|
||||
@ -32,18 +33,22 @@ func List(client *gophercloud.ServiceClient, opts *ListOpts) pagination.Pager {
|
||||
type CreateOpts struct {
|
||||
// Name is the name of the tenant.
|
||||
Name string `json:"name" required:"true"`
|
||||
|
||||
// Description is the description of the tenant.
|
||||
Description string `json:"description,omitempty"`
|
||||
|
||||
// Enabled sets the tenant status to enabled or disabled.
|
||||
Enabled *bool `json:"enabled,omitempty"`
|
||||
}
|
||||
|
||||
// CreateOptsBuilder describes struct types that can be accepted by the Create call.
|
||||
// CreateOptsBuilder enables extensions to add additional parameters to the
|
||||
// Create request.
|
||||
type CreateOptsBuilder interface {
|
||||
ToTenantCreateMap() (map[string]interface{}, error)
|
||||
}
|
||||
|
||||
// ToTenantCreateMap assembles a request body based on the contents of a CreateOpts.
|
||||
// ToTenantCreateMap assembles a request body based on the contents of
|
||||
// a CreateOpts.
|
||||
func (opts CreateOpts) ToTenantCreateMap() (map[string]interface{}, error) {
|
||||
return gophercloud.BuildRequestBody(opts, "tenant")
|
||||
}
|
||||
@ -67,17 +72,21 @@ func Get(client *gophercloud.ServiceClient, id string) (r GetResult) {
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateOptsBuilder allows extensions to add additional attributes to the Update request.
|
||||
// UpdateOptsBuilder allows extensions to add additional parameters to the
|
||||
// Update request.
|
||||
type UpdateOptsBuilder interface {
|
||||
ToTenantUpdateMap() (map[string]interface{}, error)
|
||||
}
|
||||
|
||||
// UpdateOpts specifies the base attributes that may be updated on an existing server.
|
||||
// UpdateOpts specifies the base attributes that may be updated on an existing
|
||||
// tenant.
|
||||
type UpdateOpts struct {
|
||||
// Name is the name of the tenant.
|
||||
Name string `json:"name,omitempty"`
|
||||
|
||||
// Description is the description of the tenant.
|
||||
Description string `json:"description,omitempty"`
|
||||
|
||||
// Enabled sets the tenant status to enabled or disabled.
|
||||
Enabled *bool `json:"enabled,omitempty"`
|
||||
}
|
||||
@ -100,7 +109,7 @@ func Update(client *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder
|
||||
return
|
||||
}
|
||||
|
||||
// Delete is the operation responsible for permanently deleting an API tenant.
|
||||
// Delete is the operation responsible for permanently deleting a tenant.
|
||||
func Delete(client *gophercloud.ServiceClient, id string) (r DeleteResult) {
|
||||
_, r.Err = client.Delete(deleteURL(client, id), nil)
|
||||
return
|
||||
|
17
vendor/github.com/gophercloud/gophercloud/openstack/identity/v2/tenants/results.go
generated
vendored
17
vendor/github.com/gophercloud/gophercloud/openstack/identity/v2/tenants/results.go
generated
vendored
@ -43,7 +43,8 @@ func (r TenantPage) NextPageURL() (string, error) {
|
||||
return gophercloud.ExtractNextURL(s.Links)
|
||||
}
|
||||
|
||||
// ExtractTenants returns a slice of Tenants contained in a single page of results.
|
||||
// ExtractTenants returns a slice of Tenants contained in a single page of
|
||||
// results.
|
||||
func ExtractTenants(r pagination.Page) ([]Tenant, error) {
|
||||
var s struct {
|
||||
Tenants []Tenant `json:"tenants"`
|
||||
@ -56,7 +57,7 @@ type tenantResult struct {
|
||||
gophercloud.Result
|
||||
}
|
||||
|
||||
// Extract interprets any tenantResults as a tenant.
|
||||
// Extract interprets any tenantResults as a Tenant.
|
||||
func (r tenantResult) Extract() (*Tenant, error) {
|
||||
var s struct {
|
||||
Tenant *Tenant `json:"tenant"`
|
||||
@ -65,22 +66,26 @@ func (r tenantResult) Extract() (*Tenant, error) {
|
||||
return s.Tenant, err
|
||||
}
|
||||
|
||||
// GetResult temporarily contains the response from the Get call.
|
||||
// GetResult is the response from a Get request. Call its Extract method to
|
||||
// interpret it as a Tenant.
|
||||
type GetResult struct {
|
||||
tenantResult
|
||||
}
|
||||
|
||||
// CreateResult temporarily contains the reponse from the Create call.
|
||||
// CreateResult is the response from a Create request. Call its Extract method
|
||||
// to interpret it as a Tenant.
|
||||
type CreateResult struct {
|
||||
tenantResult
|
||||
}
|
||||
|
||||
// DeleteResult temporarily contains the response from the Delete call.
|
||||
// DeleteResult is the response from a Get request. Call its ExtractErr method
|
||||
// to determine if the call succeeded or failed.
|
||||
type DeleteResult struct {
|
||||
gophercloud.ErrResult
|
||||
}
|
||||
|
||||
// UpdateResult temporarily contains the response from the Update call.
|
||||
// UpdateResult is the response from a Update request. Call its Extract method
|
||||
// to interpret it as a Tenant.
|
||||
type UpdateResult struct {
|
||||
tenantResult
|
||||
}
|
||||
|
49
vendor/github.com/gophercloud/gophercloud/openstack/identity/v2/tokens/doc.go
generated
vendored
49
vendor/github.com/gophercloud/gophercloud/openstack/identity/v2/tokens/doc.go
generated
vendored
@ -1,5 +1,46 @@
|
||||
// Package tokens provides information and interaction with the token API
|
||||
// resource for the OpenStack Identity service.
|
||||
// For more information, see:
|
||||
// http://developer.openstack.org/api-ref-identity-v2.html#identity-auth-v2
|
||||
/*
|
||||
Package tokens provides information and interaction with the token API
|
||||
resource for the OpenStack Identity service.
|
||||
|
||||
For more information, see:
|
||||
http://developer.openstack.org/api-ref-identity-v2.html#identity-auth-v2
|
||||
|
||||
Example to Create an Unscoped Token from a Password
|
||||
|
||||
authOpts := gophercloud.AuthOptions{
|
||||
Username: "user",
|
||||
Password: "pass"
|
||||
}
|
||||
|
||||
token, err := tokens.Create(identityClient, authOpts).ExtractToken()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
Example to Create a Token from a Tenant ID and Password
|
||||
|
||||
authOpts := gophercloud.AuthOptions{
|
||||
Username: "user",
|
||||
Password: "password",
|
||||
TenantID: "fc394f2ab2df4114bde39905f800dc57"
|
||||
}
|
||||
|
||||
token, err := tokens.Create(identityClient, authOpts).ExtractToken()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
Example to Create a Token from a Tenant Name and Password
|
||||
|
||||
authOpts := gophercloud.AuthOptions{
|
||||
Username: "user",
|
||||
Password: "password",
|
||||
TenantName: "tenantname"
|
||||
}
|
||||
|
||||
token, err := tokens.Create(identityClient, authOpts).ExtractToken()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
*/
|
||||
package tokens
|
||||
|
28
vendor/github.com/gophercloud/gophercloud/openstack/identity/v2/tokens/requests.go
generated
vendored
28
vendor/github.com/gophercloud/gophercloud/openstack/identity/v2/tokens/requests.go
generated
vendored
@ -2,17 +2,21 @@ package tokens
|
||||
|
||||
import "github.com/gophercloud/gophercloud"
|
||||
|
||||
// PasswordCredentialsV2 represents the required options to authenticate
|
||||
// with a username and password.
|
||||
type PasswordCredentialsV2 struct {
|
||||
Username string `json:"username" required:"true"`
|
||||
Password string `json:"password" required:"true"`
|
||||
}
|
||||
|
||||
// TokenCredentialsV2 represents the required options to authenticate
|
||||
// with a token.
|
||||
type TokenCredentialsV2 struct {
|
||||
ID string `json:"id,omitempty" required:"true"`
|
||||
}
|
||||
|
||||
// AuthOptionsV2 wraps a gophercloud AuthOptions in order to adhere to the AuthOptionsBuilder
|
||||
// interface.
|
||||
// AuthOptionsV2 wraps a gophercloud AuthOptions in order to adhere to the
|
||||
// AuthOptionsBuilder interface.
|
||||
type AuthOptionsV2 struct {
|
||||
PasswordCredentials *PasswordCredentialsV2 `json:"passwordCredentials,omitempty" xor:"TokenCredentials"`
|
||||
|
||||
@ -23,15 +27,16 @@ type AuthOptionsV2 struct {
|
||||
TenantID string `json:"tenantId,omitempty"`
|
||||
TenantName string `json:"tenantName,omitempty"`
|
||||
|
||||
// TokenCredentials allows users to authenticate (possibly as another user) with an
|
||||
// authentication token ID.
|
||||
// TokenCredentials allows users to authenticate (possibly as another user)
|
||||
// with an authentication token ID.
|
||||
TokenCredentials *TokenCredentialsV2 `json:"token,omitempty" xor:"PasswordCredentials"`
|
||||
}
|
||||
|
||||
// AuthOptionsBuilder describes any argument that may be passed to the Create call.
|
||||
// AuthOptionsBuilder allows extensions to add additional parameters to the
|
||||
// token create request.
|
||||
type AuthOptionsBuilder interface {
|
||||
// ToTokenCreateMap assembles the Create request body, returning an error if parameters are
|
||||
// missing or inconsistent.
|
||||
// ToTokenCreateMap assembles the Create request body, returning an error
|
||||
// if parameters are missing or inconsistent.
|
||||
ToTokenV2CreateMap() (map[string]interface{}, error)
|
||||
}
|
||||
|
||||
@ -47,8 +52,7 @@ type AuthOptions struct {
|
||||
TokenID string
|
||||
}
|
||||
|
||||
// ToTokenV2CreateMap allows AuthOptions to satisfy the AuthOptionsBuilder
|
||||
// interface in the v2 tokens package
|
||||
// ToTokenV2CreateMap builds a token request body from the given AuthOptions.
|
||||
func (opts AuthOptions) ToTokenV2CreateMap() (map[string]interface{}, error) {
|
||||
v2Opts := AuthOptionsV2{
|
||||
TenantID: opts.TenantID,
|
||||
@ -74,9 +78,9 @@ func (opts AuthOptions) ToTokenV2CreateMap() (map[string]interface{}, error) {
|
||||
}
|
||||
|
||||
// Create authenticates to the identity service and attempts to acquire a Token.
|
||||
// If successful, the CreateResult
|
||||
// Generally, rather than interact with this call directly, end users should call openstack.AuthenticatedClient(),
|
||||
// which abstracts all of the gory details about navigating service catalogs and such.
|
||||
// Generally, rather than interact with this call directly, end users should
|
||||
// call openstack.AuthenticatedClient(), which abstracts all of the gory details
|
||||
// about navigating service catalogs and such.
|
||||
func Create(client *gophercloud.ServiceClient, auth AuthOptionsBuilder) (r CreateResult) {
|
||||
b, err := auth.ToTokenV2CreateMap()
|
||||
if err != nil {
|
||||
|
67
vendor/github.com/gophercloud/gophercloud/openstack/identity/v2/tokens/results.go
generated
vendored
67
vendor/github.com/gophercloud/gophercloud/openstack/identity/v2/tokens/results.go
generated
vendored
@ -7,20 +7,24 @@ import (
|
||||
"github.com/gophercloud/gophercloud/openstack/identity/v2/tenants"
|
||||
)
|
||||
|
||||
// Token provides only the most basic information related to an authentication token.
|
||||
// Token provides only the most basic information related to an authentication
|
||||
// token.
|
||||
type Token struct {
|
||||
// ID provides the primary means of identifying a user to the OpenStack API.
|
||||
// OpenStack defines this field as an opaque value, so do not depend on its content.
|
||||
// It is safe, however, to compare for equality.
|
||||
// OpenStack defines this field as an opaque value, so do not depend on its
|
||||
// content. It is safe, however, to compare for equality.
|
||||
ID string
|
||||
|
||||
// ExpiresAt provides a timestamp in ISO 8601 format, indicating when the authentication token becomes invalid.
|
||||
// After this point in time, future API requests made using this authentication token will respond with errors.
|
||||
// Either the caller will need to reauthenticate manually, or more preferably, the caller should exploit automatic re-authentication.
|
||||
// ExpiresAt provides a timestamp in ISO 8601 format, indicating when the
|
||||
// authentication token becomes invalid. After this point in time, future
|
||||
// API requests made using this authentication token will respond with
|
||||
// errors. Either the caller will need to reauthenticate manually, or more
|
||||
// preferably, the caller should exploit automatic re-authentication.
|
||||
// See the AuthOptions structure for more details.
|
||||
ExpiresAt time.Time
|
||||
|
||||
// Tenant provides information about the tenant to which this token grants access.
|
||||
// Tenant provides information about the tenant to which this token grants
|
||||
// access.
|
||||
Tenant tenants.Tenant
|
||||
}
|
||||
|
||||
@ -38,13 +42,17 @@ type User struct {
|
||||
}
|
||||
|
||||
// Endpoint represents a single API endpoint offered by a service.
|
||||
// It provides the public and internal URLs, if supported, along with a region specifier, again if provided.
|
||||
// It provides the public and internal URLs, if supported, along with a region
|
||||
// specifier, again if provided.
|
||||
//
|
||||
// The significance of the Region field will depend upon your provider.
|
||||
//
|
||||
// In addition, the interface offered by the service will have version information associated with it
|
||||
// through the VersionId, VersionInfo, and VersionList fields, if provided or supported.
|
||||
// In addition, the interface offered by the service will have version
|
||||
// information associated with it through the VersionId, VersionInfo, and
|
||||
// VersionList fields, if provided or supported.
|
||||
//
|
||||
// In all cases, fields which aren't supported by the provider and service combined will assume a zero-value ("").
|
||||
// In all cases, fields which aren't supported by the provider and service
|
||||
// combined will assume a zero-value ("").
|
||||
type Endpoint struct {
|
||||
TenantID string `json:"tenantId"`
|
||||
PublicURL string `json:"publicURL"`
|
||||
@ -56,38 +64,44 @@ type Endpoint struct {
|
||||
VersionList string `json:"versionList"`
|
||||
}
|
||||
|
||||
// CatalogEntry provides a type-safe interface to an Identity API V2 service catalog listing.
|
||||
// Each class of service, such as cloud DNS or block storage services, will have a single
|
||||
// CatalogEntry representing it.
|
||||
// CatalogEntry provides a type-safe interface to an Identity API V2 service
|
||||
// catalog listing.
|
||||
//
|
||||
// Note: when looking for the desired service, try, whenever possible, to key off the type field.
|
||||
// Otherwise, you'll tie the representation of the service to a specific provider.
|
||||
// Each class of service, such as cloud DNS or block storage services, will have
|
||||
// a single CatalogEntry representing it.
|
||||
//
|
||||
// Note: when looking for the desired service, try, whenever possible, to key
|
||||
// off the type field. Otherwise, you'll tie the representation of the service
|
||||
// to a specific provider.
|
||||
type CatalogEntry struct {
|
||||
// Name will contain the provider-specified name for the service.
|
||||
Name string `json:"name"`
|
||||
|
||||
// Type will contain a type string if OpenStack defines a type for the service.
|
||||
// Otherwise, for provider-specific services, the provider may assign their own type strings.
|
||||
// Type will contain a type string if OpenStack defines a type for the
|
||||
// service. Otherwise, for provider-specific services, the provider may assign
|
||||
// their own type strings.
|
||||
Type string `json:"type"`
|
||||
|
||||
// Endpoints will let the caller iterate over all the different endpoints that may exist for
|
||||
// the service.
|
||||
// Endpoints will let the caller iterate over all the different endpoints that
|
||||
// may exist for the service.
|
||||
Endpoints []Endpoint `json:"endpoints"`
|
||||
}
|
||||
|
||||
// ServiceCatalog provides a view into the service catalog from a previous, successful authentication.
|
||||
// ServiceCatalog provides a view into the service catalog from a previous,
|
||||
// successful authentication.
|
||||
type ServiceCatalog struct {
|
||||
Entries []CatalogEntry
|
||||
}
|
||||
|
||||
// CreateResult defers the interpretation of a created token.
|
||||
// Use ExtractToken() to interpret it as a Token, or ExtractServiceCatalog() to interpret it as a service catalog.
|
||||
// CreateResult is the response from a Create request. Use ExtractToken() to
|
||||
// interpret it as a Token, or ExtractServiceCatalog() to interpret it as a
|
||||
// service catalog.
|
||||
type CreateResult struct {
|
||||
gophercloud.Result
|
||||
}
|
||||
|
||||
// GetResult is the deferred response from a Get call, which is the same with a Created token.
|
||||
// Use ExtractUser() to interpret it as a User.
|
||||
// GetResult is the deferred response from a Get call, which is the same with a
|
||||
// Created token. Use ExtractUser() to interpret it as a User.
|
||||
type GetResult struct {
|
||||
CreateResult
|
||||
}
|
||||
@ -121,7 +135,8 @@ func (r CreateResult) ExtractToken() (*Token, error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
// ExtractServiceCatalog returns the ServiceCatalog that was generated along with the user's Token.
|
||||
// ExtractServiceCatalog returns the ServiceCatalog that was generated along
|
||||
// with the user's Token.
|
||||
func (r CreateResult) ExtractServiceCatalog() (*ServiceCatalog, error) {
|
||||
var s struct {
|
||||
Access struct {
|
||||
|
112
vendor/github.com/gophercloud/gophercloud/openstack/identity/v3/tokens/doc.go
generated
vendored
112
vendor/github.com/gophercloud/gophercloud/openstack/identity/v3/tokens/doc.go
generated
vendored
@ -1,6 +1,108 @@
|
||||
// Package tokens provides information and interaction with the token API
|
||||
// resource for the OpenStack Identity service.
|
||||
//
|
||||
// For more information, see:
|
||||
// http://developer.openstack.org/api-ref-identity-v3.html#tokens-v3
|
||||
/*
|
||||
Package tokens provides information and interaction with the token API
|
||||
resource for the OpenStack Identity service.
|
||||
|
||||
For more information, see:
|
||||
http://developer.openstack.org/api-ref-identity-v3.html#tokens-v3
|
||||
|
||||
Example to Create a Token From a Username and Password
|
||||
|
||||
authOptions := tokens.AuthOptions{
|
||||
UserID: "username",
|
||||
Password: "password",
|
||||
}
|
||||
|
||||
token, err := tokens.Create(identityClient, authOptions).ExtractToken()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
Example to Create a Token From a Username, Password, and Domain
|
||||
|
||||
authOptions := tokens.AuthOptions{
|
||||
UserID: "username",
|
||||
Password: "password",
|
||||
DomainID: "default",
|
||||
}
|
||||
|
||||
token, err := tokens.Create(identityClient, authOptions).ExtractToken()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
authOptions = tokens.AuthOptions{
|
||||
UserID: "username",
|
||||
Password: "password",
|
||||
DomainName: "default",
|
||||
}
|
||||
|
||||
token, err = tokens.Create(identityClient, authOptions).ExtractToken()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
Example to Create a Token From a Token
|
||||
|
||||
authOptions := tokens.AuthOptions{
|
||||
TokenID: "token_id",
|
||||
}
|
||||
|
||||
token, err := tokens.Create(identityClient, authOptions).ExtractToken()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
Example to Create a Token from a Username and Password with Project ID Scope
|
||||
|
||||
scope := tokens.Scope{
|
||||
ProjectID: "0fe36e73809d46aeae6705c39077b1b3",
|
||||
}
|
||||
|
||||
authOptions := tokens.AuthOptions{
|
||||
Scope: &scope,
|
||||
UserID: "username",
|
||||
Password: "password",
|
||||
}
|
||||
|
||||
token, err = tokens.Create(identityClient, authOptions).ExtractToken()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
Example to Create a Token from a Username and Password with Domain ID Scope
|
||||
|
||||
scope := tokens.Scope{
|
||||
DomainID: "default",
|
||||
}
|
||||
|
||||
authOptions := tokens.AuthOptions{
|
||||
Scope: &scope,
|
||||
UserID: "username",
|
||||
Password: "password",
|
||||
}
|
||||
|
||||
token, err = tokens.Create(identityClient, authOptions).ExtractToken()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
Example to Create a Token from a Username and Password with Project Name Scope
|
||||
|
||||
scope := tokens.Scope{
|
||||
ProjectName: "project_name",
|
||||
DomainID: "default",
|
||||
}
|
||||
|
||||
authOptions := tokens.AuthOptions{
|
||||
Scope: &scope,
|
||||
UserID: "username",
|
||||
Password: "password",
|
||||
}
|
||||
|
||||
token, err = tokens.Create(identityClient, authOptions).ExtractToken()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
*/
|
||||
package tokens
|
||||
|
95
vendor/github.com/gophercloud/gophercloud/openstack/identity/v3/tokens/requests.go
generated
vendored
95
vendor/github.com/gophercloud/gophercloud/openstack/identity/v3/tokens/requests.go
generated
vendored
@ -10,20 +10,22 @@ type Scope struct {
|
||||
DomainName string
|
||||
}
|
||||
|
||||
// AuthOptionsBuilder describes any argument that may be passed to the Create call.
|
||||
// AuthOptionsBuilder provides the ability for extensions to add additional
|
||||
// parameters to AuthOptions. Extensions must satisfy all required methods.
|
||||
type AuthOptionsBuilder interface {
|
||||
// ToTokenV3CreateMap assembles the Create request body, returning an error if parameters are
|
||||
// missing or inconsistent.
|
||||
// ToTokenV3CreateMap assembles the Create request body, returning an error
|
||||
// if parameters are missing or inconsistent.
|
||||
ToTokenV3CreateMap(map[string]interface{}) (map[string]interface{}, error)
|
||||
ToTokenV3ScopeMap() (map[string]interface{}, error)
|
||||
CanReauth() bool
|
||||
}
|
||||
|
||||
// AuthOptions represents options for authenticating a user.
|
||||
type AuthOptions struct {
|
||||
// IdentityEndpoint specifies the HTTP endpoint that is required to work with
|
||||
// the Identity API of the appropriate version. While it's ultimately needed by
|
||||
// all of the identity services, it will often be populated by a provider-level
|
||||
// function.
|
||||
// the Identity API of the appropriate version. While it's ultimately needed
|
||||
// by all of the identity services, it will often be populated by a
|
||||
// provider-level function.
|
||||
IdentityEndpoint string `json:"-"`
|
||||
|
||||
// Username is required if using Identity V2 API. Consult with your provider's
|
||||
@ -39,11 +41,11 @@ type AuthOptions struct {
|
||||
DomainID string `json:"-"`
|
||||
DomainName string `json:"name,omitempty"`
|
||||
|
||||
// AllowReauth should be set to true if you grant permission for Gophercloud to
|
||||
// cache your credentials in memory, and to allow Gophercloud to attempt to
|
||||
// re-authenticate automatically if/when your token expires. If you set it to
|
||||
// false, it will not cache these settings, but re-authentication will not be
|
||||
// possible. This setting defaults to false.
|
||||
// AllowReauth should be set to true if you grant permission for Gophercloud
|
||||
// to cache your credentials in memory, and to allow Gophercloud to attempt
|
||||
// to re-authenticate automatically if/when your token expires. If you set
|
||||
// it to false, it will not cache these settings, but re-authentication will
|
||||
// not be possible. This setting defaults to false.
|
||||
AllowReauth bool `json:"-"`
|
||||
|
||||
// TokenID allows users to authenticate (possibly as another user) with an
|
||||
@ -53,6 +55,7 @@ type AuthOptions struct {
|
||||
Scope Scope `json:"-"`
|
||||
}
|
||||
|
||||
// ToTokenV3CreateMap builds a request body from AuthOptions.
|
||||
func (opts *AuthOptions) ToTokenV3CreateMap(scope map[string]interface{}) (map[string]interface{}, error) {
|
||||
gophercloudAuthOpts := gophercloud.AuthOptions{
|
||||
Username: opts.Username,
|
||||
@ -67,68 +70,17 @@ func (opts *AuthOptions) ToTokenV3CreateMap(scope map[string]interface{}) (map[s
|
||||
return gophercloudAuthOpts.ToTokenV3CreateMap(scope)
|
||||
}
|
||||
|
||||
// ToTokenV3CreateMap builds a scope request body from AuthOptions.
|
||||
func (opts *AuthOptions) ToTokenV3ScopeMap() (map[string]interface{}, error) {
|
||||
if opts.Scope.ProjectName != "" {
|
||||
// ProjectName provided: either DomainID or DomainName must also be supplied.
|
||||
// ProjectID may not be supplied.
|
||||
if opts.Scope.DomainID == "" && opts.Scope.DomainName == "" {
|
||||
return nil, gophercloud.ErrScopeDomainIDOrDomainName{}
|
||||
}
|
||||
if opts.Scope.ProjectID != "" {
|
||||
return nil, gophercloud.ErrScopeProjectIDOrProjectName{}
|
||||
}
|
||||
scope := gophercloud.AuthScope(opts.Scope)
|
||||
|
||||
if opts.Scope.DomainID != "" {
|
||||
// ProjectName + DomainID
|
||||
return map[string]interface{}{
|
||||
"project": map[string]interface{}{
|
||||
"name": &opts.Scope.ProjectName,
|
||||
"domain": map[string]interface{}{"id": &opts.Scope.DomainID},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
if opts.Scope.DomainName != "" {
|
||||
// ProjectName + DomainName
|
||||
return map[string]interface{}{
|
||||
"project": map[string]interface{}{
|
||||
"name": &opts.Scope.ProjectName,
|
||||
"domain": map[string]interface{}{"name": &opts.Scope.DomainName},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
} else if opts.Scope.ProjectID != "" {
|
||||
// ProjectID provided. ProjectName, DomainID, and DomainName may not be provided.
|
||||
if opts.Scope.DomainID != "" {
|
||||
return nil, gophercloud.ErrScopeProjectIDAlone{}
|
||||
}
|
||||
if opts.Scope.DomainName != "" {
|
||||
return nil, gophercloud.ErrScopeProjectIDAlone{}
|
||||
}
|
||||
|
||||
// ProjectID
|
||||
return map[string]interface{}{
|
||||
"project": map[string]interface{}{
|
||||
"id": &opts.Scope.ProjectID,
|
||||
},
|
||||
}, nil
|
||||
} else if opts.Scope.DomainID != "" {
|
||||
// DomainID provided. ProjectID, ProjectName, and DomainName may not be provided.
|
||||
if opts.Scope.DomainName != "" {
|
||||
return nil, gophercloud.ErrScopeDomainIDOrDomainName{}
|
||||
}
|
||||
|
||||
// DomainID
|
||||
return map[string]interface{}{
|
||||
"domain": map[string]interface{}{
|
||||
"id": &opts.Scope.DomainID,
|
||||
},
|
||||
}, nil
|
||||
} else if opts.Scope.DomainName != "" {
|
||||
return nil, gophercloud.ErrScopeDomainName{}
|
||||
gophercloudAuthOpts := gophercloud.AuthOptions{
|
||||
Scope: &scope,
|
||||
DomainID: opts.DomainID,
|
||||
DomainName: opts.DomainName,
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
return gophercloudAuthOpts.ToTokenV3ScopeMap()
|
||||
}
|
||||
|
||||
func (opts *AuthOptions) CanReauth() bool {
|
||||
@ -141,7 +93,8 @@ func subjectTokenHeaders(c *gophercloud.ServiceClient, subjectToken string) map[
|
||||
}
|
||||
}
|
||||
|
||||
// Create authenticates and either generates a new token, or changes the Scope of an existing token.
|
||||
// Create authenticates and either generates a new token, or changes the Scope
|
||||
// of an existing token.
|
||||
func Create(c *gophercloud.ServiceClient, opts AuthOptionsBuilder) (r CreateResult) {
|
||||
scope, err := opts.ToTokenV3ScopeMap()
|
||||
if err != nil {
|
||||
@ -180,7 +133,7 @@ func Get(c *gophercloud.ServiceClient, token string) (r GetResult) {
|
||||
|
||||
// Validate determines if a specified token is valid or not.
|
||||
func Validate(c *gophercloud.ServiceClient, token string) (bool, error) {
|
||||
resp, err := c.Request("HEAD", tokenURL(c), &gophercloud.RequestOpts{
|
||||
resp, err := c.Head(tokenURL(c), &gophercloud.RequestOpts{
|
||||
MoreHeaders: subjectTokenHeaders(c, token),
|
||||
OkCodes: []int{200, 204, 404},
|
||||
})
|
||||
|
55
vendor/github.com/gophercloud/gophercloud/openstack/identity/v3/tokens/results.go
generated
vendored
55
vendor/github.com/gophercloud/gophercloud/openstack/identity/v3/tokens/results.go
generated
vendored
@ -13,41 +13,50 @@ import (
|
||||
type Endpoint struct {
|
||||
ID string `json:"id"`
|
||||
Region string `json:"region"`
|
||||
RegionID string `json:"region_id"`
|
||||
Interface string `json:"interface"`
|
||||
URL string `json:"url"`
|
||||
}
|
||||
|
||||
// CatalogEntry provides a type-safe interface to an Identity API V3 service catalog listing.
|
||||
// Each class of service, such as cloud DNS or block storage services, could have multiple
|
||||
// CatalogEntry representing it (one by interface type, e.g public, admin or internal).
|
||||
// CatalogEntry provides a type-safe interface to an Identity API V3 service
|
||||
// catalog listing. Each class of service, such as cloud DNS or block storage
|
||||
// services, could have multiple CatalogEntry representing it (one by interface
|
||||
// type, e.g public, admin or internal).
|
||||
//
|
||||
// Note: when looking for the desired service, try, whenever possible, to key off the type field.
|
||||
// Otherwise, you'll tie the representation of the service to a specific provider.
|
||||
// Note: when looking for the desired service, try, whenever possible, to key
|
||||
// off the type field. Otherwise, you'll tie the representation of the service
|
||||
// to a specific provider.
|
||||
type CatalogEntry struct {
|
||||
// Service ID
|
||||
ID string `json:"id"`
|
||||
|
||||
// Name will contain the provider-specified name for the service.
|
||||
Name string `json:"name"`
|
||||
// Type will contain a type string if OpenStack defines a type for the service.
|
||||
// Otherwise, for provider-specific services, the provider may assign their own type strings.
|
||||
|
||||
// Type will contain a type string if OpenStack defines a type for the
|
||||
// service. Otherwise, for provider-specific services, the provider may
|
||||
// assign their own type strings.
|
||||
Type string `json:"type"`
|
||||
// Endpoints will let the caller iterate over all the different endpoints that may exist for
|
||||
// the service.
|
||||
|
||||
// Endpoints will let the caller iterate over all the different endpoints that
|
||||
// may exist for the service.
|
||||
Endpoints []Endpoint `json:"endpoints"`
|
||||
}
|
||||
|
||||
// ServiceCatalog provides a view into the service catalog from a previous, successful authentication.
|
||||
// ServiceCatalog provides a view into the service catalog from a previous,
|
||||
// successful authentication.
|
||||
type ServiceCatalog struct {
|
||||
Entries []CatalogEntry `json:"catalog"`
|
||||
}
|
||||
|
||||
// Domain provides information about the domain to which this token grants access.
|
||||
// Domain provides information about the domain to which this token grants
|
||||
// access.
|
||||
type Domain struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
// User represents a user resource that exists on the API.
|
||||
// User represents a user resource that exists in the Identity Service.
|
||||
type User struct {
|
||||
Domain Domain `json:"domain"`
|
||||
ID string `json:"id"`
|
||||
@ -67,7 +76,8 @@ type Project struct {
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
// commonResult is the deferred result of a Create or a Get call.
|
||||
// commonResult is the response from a request. A commonResult has various
|
||||
// methods which can be used to extract different details about the result.
|
||||
type commonResult struct {
|
||||
gophercloud.Result
|
||||
}
|
||||
@ -92,7 +102,8 @@ func (r commonResult) ExtractToken() (*Token, error) {
|
||||
return &s, err
|
||||
}
|
||||
|
||||
// ExtractServiceCatalog returns the ServiceCatalog that was generated along with the user's Token.
|
||||
// ExtractServiceCatalog returns the ServiceCatalog that was generated along
|
||||
// with the user's Token.
|
||||
func (r commonResult) ExtractServiceCatalog() (*ServiceCatalog, error) {
|
||||
var s ServiceCatalog
|
||||
err := r.ExtractInto(&s)
|
||||
@ -126,27 +137,31 @@ func (r commonResult) ExtractProject() (*Project, error) {
|
||||
return s.Project, err
|
||||
}
|
||||
|
||||
// CreateResult defers the interpretation of a created token.
|
||||
// Use ExtractToken() to interpret it as a Token, or ExtractServiceCatalog() to interpret it as a service catalog.
|
||||
// CreateResult is the response from a Create request. Use ExtractToken()
|
||||
// to interpret it as a Token, or ExtractServiceCatalog() to interpret it
|
||||
// as a service catalog.
|
||||
type CreateResult struct {
|
||||
commonResult
|
||||
}
|
||||
|
||||
// GetResult is the deferred response from a Get call.
|
||||
// GetResult is the response from a Get request. Use ExtractToken()
|
||||
// to interpret it as a Token, or ExtractServiceCatalog() to interpret it
|
||||
// as a service catalog.
|
||||
type GetResult struct {
|
||||
commonResult
|
||||
}
|
||||
|
||||
// RevokeResult is the deferred response from a Revoke call.
|
||||
// RevokeResult is response from a Revoke request.
|
||||
type RevokeResult struct {
|
||||
commonResult
|
||||
}
|
||||
|
||||
// Token is a string that grants a user access to a controlled set of services in an OpenStack provider.
|
||||
// Each Token is valid for a set length of time.
|
||||
// Token is a string that grants a user access to a controlled set of services
|
||||
// in an OpenStack provider. Each Token is valid for a set length of time.
|
||||
type Token struct {
|
||||
// ID is the issued token.
|
||||
ID string `json:"id"`
|
||||
|
||||
// ExpiresAt is the timestamp at which this token will no longer be accepted.
|
||||
ExpiresAt time.Time `json:"expires_at"`
|
||||
}
|
||||
|
60
vendor/github.com/gophercloud/gophercloud/openstack/imageservice/v2/images/doc.go
generated
vendored
Normal file
60
vendor/github.com/gophercloud/gophercloud/openstack/imageservice/v2/images/doc.go
generated
vendored
Normal file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
Package images enables management and retrieval of images from the OpenStack
|
||||
Image Service.
|
||||
|
||||
Example to List Images
|
||||
|
||||
images.ListOpts{
|
||||
Owner: "a7509e1ae65945fda83f3e52c6296017",
|
||||
}
|
||||
|
||||
allPages, err := images.List(imagesClient, listOpts).AllPages()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
allImages, err := images.ExtractImages(allPages)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
for _, image := range allImages {
|
||||
fmt.Printf("%+v\n", image)
|
||||
}
|
||||
|
||||
Example to Create an Image
|
||||
|
||||
createOpts := images.CreateOpts{
|
||||
Name: "image_name",
|
||||
Visibility: images.ImageVisibilityPrivate,
|
||||
}
|
||||
|
||||
image, err := images.Create(imageClient, createOpts)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
Example to Update an Image
|
||||
|
||||
imageID := "1bea47ed-f6a9-463b-b423-14b9cca9ad27"
|
||||
|
||||
updateOpts := images.UpdateOpts{
|
||||
images.ReplaceImageName{
|
||||
NewName: "new_name",
|
||||
},
|
||||
}
|
||||
|
||||
image, err := images.Update(imageClient, imageID, updateOpts).Extract()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
Example to Delete an Image
|
||||
|
||||
imageID := "1bea47ed-f6a9-463b-b423-14b9cca9ad27"
|
||||
err := images.Delete(imageClient, imageID).ExtractErr()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
*/
|
||||
package images
|
141
vendor/github.com/gophercloud/gophercloud/openstack/imageservice/v2/images/requests.go
generated
vendored
141
vendor/github.com/gophercloud/gophercloud/openstack/imageservice/v2/images/requests.go
generated
vendored
@ -1,6 +1,10 @@
|
||||
package images
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
"github.com/gophercloud/gophercloud"
|
||||
"github.com/gophercloud/gophercloud/pagination"
|
||||
)
|
||||
@ -15,33 +19,106 @@ type ListOptsBuilder interface {
|
||||
// the API. Filtering is achieved by passing in struct field values that map to
|
||||
// the server attributes you want to see returned. Marker and Limit are used
|
||||
// for pagination.
|
||||
//http://developer.openstack.org/api-ref-image-v2.html
|
||||
//
|
||||
// http://developer.openstack.org/api-ref-image-v2.html
|
||||
type ListOpts struct {
|
||||
// ID is the ID of the image.
|
||||
// Multiple IDs can be specified by constructing a string
|
||||
// such as "in:uuid1,uuid2,uuid3".
|
||||
ID string `q:"id"`
|
||||
|
||||
// Integer value for the limit of values to return.
|
||||
Limit int `q:"limit"`
|
||||
|
||||
// UUID of the server at which you want to set a marker.
|
||||
Marker string `q:"marker"`
|
||||
|
||||
Name string `q:"name"`
|
||||
Visibility ImageVisibility `q:"visibility"`
|
||||
// Name filters on the name of the image.
|
||||
// Multiple names can be specified by constructing a string
|
||||
// such as "in:name1,name2,name3".
|
||||
Name string `q:"name"`
|
||||
|
||||
// Visibility filters on the visibility of the image.
|
||||
Visibility ImageVisibility `q:"visibility"`
|
||||
|
||||
// MemberStatus filters on the member status of the image.
|
||||
MemberStatus ImageMemberStatus `q:"member_status"`
|
||||
Owner string `q:"owner"`
|
||||
Status ImageStatus `q:"status"`
|
||||
SizeMin int64 `q:"size_min"`
|
||||
SizeMax int64 `q:"size_max"`
|
||||
SortKey string `q:"sort_key"`
|
||||
SortDir string `q:"sort_dir"`
|
||||
Tag string `q:"tag"`
|
||||
|
||||
// Owner filters on the project ID of the image.
|
||||
Owner string `q:"owner"`
|
||||
|
||||
// Status filters on the status of the image.
|
||||
// Multiple statuses can be specified by constructing a string
|
||||
// such as "in:saving,queued".
|
||||
Status ImageStatus `q:"status"`
|
||||
|
||||
// SizeMin filters on the size_min image property.
|
||||
SizeMin int64 `q:"size_min"`
|
||||
|
||||
// SizeMax filters on the size_max image property.
|
||||
SizeMax int64 `q:"size_max"`
|
||||
|
||||
// Sort sorts the results using the new style of sorting. See the OpenStack
|
||||
// Image API reference for the exact syntax.
|
||||
//
|
||||
// Sort cannot be used with the classic sort options (sort_key and sort_dir).
|
||||
Sort string `q:"sort"`
|
||||
|
||||
// SortKey will sort the results based on a specified image property.
|
||||
SortKey string `q:"sort_key"`
|
||||
|
||||
// SortDir will sort the list results either ascending or decending.
|
||||
SortDir string `q:"sort_dir"`
|
||||
|
||||
// Tags filters on specific image tags.
|
||||
Tags []string `q:"tag"`
|
||||
|
||||
// CreatedAtQuery filters images based on their creation date.
|
||||
CreatedAtQuery *ImageDateQuery
|
||||
|
||||
// UpdatedAtQuery filters images based on their updated date.
|
||||
UpdatedAtQuery *ImageDateQuery
|
||||
|
||||
// ContainerFormat filters images based on the container_format.
|
||||
// Multiple container formats can be specified by constructing a
|
||||
// string such as "in:bare,ami".
|
||||
ContainerFormat string `q:"container_format"`
|
||||
|
||||
// DiskFormat filters images based on the disk_format.
|
||||
// Multiple disk formats can be specified by constructing a string
|
||||
// such as "in:qcow2,iso".
|
||||
DiskFormat string `q:"disk_format"`
|
||||
}
|
||||
|
||||
// ToImageListQuery formats a ListOpts into a query string.
|
||||
func (opts ListOpts) ToImageListQuery() (string, error) {
|
||||
q, err := gophercloud.BuildQueryString(opts)
|
||||
params := q.Query()
|
||||
|
||||
if opts.CreatedAtQuery != nil {
|
||||
createdAt := opts.CreatedAtQuery.Date.Format(time.RFC3339)
|
||||
if v := opts.CreatedAtQuery.Filter; v != "" {
|
||||
createdAt = fmt.Sprintf("%s:%s", v, createdAt)
|
||||
}
|
||||
|
||||
params.Add("created_at", createdAt)
|
||||
}
|
||||
|
||||
if opts.UpdatedAtQuery != nil {
|
||||
updatedAt := opts.UpdatedAtQuery.Date.Format(time.RFC3339)
|
||||
if v := opts.UpdatedAtQuery.Filter; v != "" {
|
||||
updatedAt = fmt.Sprintf("%s:%s", v, updatedAt)
|
||||
}
|
||||
|
||||
params.Add("updated_at", updatedAt)
|
||||
}
|
||||
|
||||
q = &url.URL{RawQuery: params.Encode()}
|
||||
|
||||
return q.String(), err
|
||||
}
|
||||
|
||||
// List implements image list request
|
||||
// List implements image list request.
|
||||
func List(c *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager {
|
||||
url := listURL(c)
|
||||
if opts != nil {
|
||||
@ -56,14 +133,13 @@ func List(c *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager {
|
||||
})
|
||||
}
|
||||
|
||||
// CreateOptsBuilder describes struct types that can be accepted by the Create call.
|
||||
// The CreateOpts struct in this package does.
|
||||
// CreateOptsBuilder allows extensions to add parameters to the Create request.
|
||||
type CreateOptsBuilder interface {
|
||||
// Returns value that can be passed to json.Marshal
|
||||
ToImageCreateMap() (map[string]interface{}, error)
|
||||
}
|
||||
|
||||
// CreateOpts implements CreateOptsBuilder
|
||||
// CreateOpts represents options used to create an image.
|
||||
type CreateOpts struct {
|
||||
// Name is the name of the new image.
|
||||
Name string `json:"name" required:"true"`
|
||||
@ -118,7 +194,7 @@ func (opts CreateOpts) ToImageCreateMap() (map[string]interface{}, error) {
|
||||
return b, nil
|
||||
}
|
||||
|
||||
// Create implements create image request
|
||||
// Create implements create image request.
|
||||
func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) (r CreateResult) {
|
||||
b, err := opts.ToImageCreateMap()
|
||||
if err != nil {
|
||||
@ -129,19 +205,19 @@ func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) (r Create
|
||||
return
|
||||
}
|
||||
|
||||
// Delete implements image delete request
|
||||
// Delete implements image delete request.
|
||||
func Delete(client *gophercloud.ServiceClient, id string) (r DeleteResult) {
|
||||
_, r.Err = client.Delete(deleteURL(client, id), nil)
|
||||
return
|
||||
}
|
||||
|
||||
// Get implements image get request
|
||||
// Get implements image get request.
|
||||
func Get(client *gophercloud.ServiceClient, id string) (r GetResult) {
|
||||
_, r.Err = client.Get(getURL(client, id), &r.Body, nil)
|
||||
return
|
||||
}
|
||||
|
||||
// Update implements image updated request
|
||||
// Update implements image updated request.
|
||||
func Update(client *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) (r UpdateResult) {
|
||||
b, err := opts.ToImageUpdateMap()
|
||||
if err != nil {
|
||||
@ -155,9 +231,11 @@ func Update(client *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateOptsBuilder implements UpdateOptsBuilder
|
||||
// UpdateOptsBuilder allows extensions to add additional parameters to the
|
||||
// Update request.
|
||||
type UpdateOptsBuilder interface {
|
||||
// returns value implementing json.Marshaler which when marshaled matches the patch schema:
|
||||
// returns value implementing json.Marshaler which when marshaled matches
|
||||
// the patch schema:
|
||||
// http://specs.openstack.org/openstack/glance-specs/specs/api/v2/http-patch-image-api-v2.html
|
||||
ToImageUpdateMap() ([]interface{}, error)
|
||||
}
|
||||
@ -165,7 +243,8 @@ type UpdateOptsBuilder interface {
|
||||
// UpdateOpts implements UpdateOpts
|
||||
type UpdateOpts []Patch
|
||||
|
||||
// ToImageUpdateMap builder
|
||||
// ToImageUpdateMap assembles a request body based on the contents of
|
||||
// UpdateOpts.
|
||||
func (opts UpdateOpts) ToImageUpdateMap() ([]interface{}, error) {
|
||||
m := make([]interface{}, len(opts))
|
||||
for i, patch := range opts {
|
||||
@ -175,18 +254,18 @@ func (opts UpdateOpts) ToImageUpdateMap() ([]interface{}, error) {
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// Patch represents a single update to an existing image. Multiple updates to an image can be
|
||||
// submitted at the same time.
|
||||
// Patch represents a single update to an existing image. Multiple updates
|
||||
// to an image can be submitted at the same time.
|
||||
type Patch interface {
|
||||
ToImagePatchMap() map[string]interface{}
|
||||
}
|
||||
|
||||
// UpdateVisibility updated visibility
|
||||
// UpdateVisibility represents an updated visibility property request.
|
||||
type UpdateVisibility struct {
|
||||
Visibility ImageVisibility
|
||||
}
|
||||
|
||||
// ToImagePatchMap builder
|
||||
// ToImagePatchMap assembles a request body based on UpdateVisibility.
|
||||
func (u UpdateVisibility) ToImagePatchMap() map[string]interface{} {
|
||||
return map[string]interface{}{
|
||||
"op": "replace",
|
||||
@ -195,12 +274,12 @@ func (u UpdateVisibility) ToImagePatchMap() map[string]interface{} {
|
||||
}
|
||||
}
|
||||
|
||||
// ReplaceImageName implements Patch
|
||||
// ReplaceImageName represents an updated image_name property request.
|
||||
type ReplaceImageName struct {
|
||||
NewName string
|
||||
}
|
||||
|
||||
// ToImagePatchMap builder
|
||||
// ToImagePatchMap assembles a request body based on ReplaceImageName.
|
||||
func (r ReplaceImageName) ToImagePatchMap() map[string]interface{} {
|
||||
return map[string]interface{}{
|
||||
"op": "replace",
|
||||
@ -209,12 +288,12 @@ func (r ReplaceImageName) ToImagePatchMap() map[string]interface{} {
|
||||
}
|
||||
}
|
||||
|
||||
// ReplaceImageChecksum implements Patch
|
||||
// ReplaceImageChecksum represents an updated checksum property request.
|
||||
type ReplaceImageChecksum struct {
|
||||
Checksum string
|
||||
}
|
||||
|
||||
// ReplaceImageChecksum builder
|
||||
// ReplaceImageChecksum assembles a request body based on ReplaceImageChecksum.
|
||||
func (rc ReplaceImageChecksum) ToImagePatchMap() map[string]interface{} {
|
||||
return map[string]interface{}{
|
||||
"op": "replace",
|
||||
@ -223,12 +302,12 @@ func (rc ReplaceImageChecksum) ToImagePatchMap() map[string]interface{} {
|
||||
}
|
||||
}
|
||||
|
||||
// ReplaceImageTags implements Patch
|
||||
// ReplaceImageTags represents an updated tags property request.
|
||||
type ReplaceImageTags struct {
|
||||
NewTags []string
|
||||
}
|
||||
|
||||
// ToImagePatchMap builder
|
||||
// ToImagePatchMap assembles a request body based on ReplaceImageTags.
|
||||
func (r ReplaceImageTags) ToImagePatchMap() map[string]interface{} {
|
||||
return map[string]interface{}{
|
||||
"op": "replace",
|
||||
|
59
vendor/github.com/gophercloud/gophercloud/openstack/imageservice/v2/images/results.go
generated
vendored
59
vendor/github.com/gophercloud/gophercloud/openstack/imageservice/v2/images/results.go
generated
vendored
@ -11,11 +11,9 @@ import (
|
||||
"github.com/gophercloud/gophercloud/pagination"
|
||||
)
|
||||
|
||||
// Image model
|
||||
// Does not include the literal image data; just metadata.
|
||||
// returned by listing images, and by fetching a specific image.
|
||||
// Image represents an image found in the OpenStack Image service.
|
||||
type Image struct {
|
||||
// ID is the image UUID
|
||||
// ID is the image UUID.
|
||||
ID string `json:"id"`
|
||||
|
||||
// Name is the human-readable display name for the image.
|
||||
@ -34,16 +32,19 @@ type Image struct {
|
||||
ContainerFormat string `json:"container_format"`
|
||||
|
||||
// DiskFormat is the format of the disk.
|
||||
// If set, valid values are ami, ari, aki, vhd, vmdk, raw, qcow2, vdi, and iso.
|
||||
// If set, valid values are ami, ari, aki, vhd, vmdk, raw, qcow2, vdi,
|
||||
// and iso.
|
||||
DiskFormat string `json:"disk_format"`
|
||||
|
||||
// MinDiskGigabytes is the amount of disk space in GB that is required to boot the image.
|
||||
// MinDiskGigabytes is the amount of disk space in GB that is required to
|
||||
// boot the image.
|
||||
MinDiskGigabytes int `json:"min_disk"`
|
||||
|
||||
// MinRAMMegabytes [optional] is the amount of RAM in MB that is required to boot the image.
|
||||
// MinRAMMegabytes [optional] is the amount of RAM in MB that is required to
|
||||
// boot the image.
|
||||
MinRAMMegabytes int `json:"min_ram"`
|
||||
|
||||
// Owner is the tenant the image belongs to.
|
||||
// Owner is the tenant ID the image belongs to.
|
||||
Owner string `json:"owner"`
|
||||
|
||||
// Protected is whether the image is deletable or not.
|
||||
@ -52,7 +53,7 @@ type Image struct {
|
||||
// Visibility defines who can see/use the image.
|
||||
Visibility ImageVisibility `json:"visibility"`
|
||||
|
||||
// Checksum is the checksum of the data that's associated with the image
|
||||
// Checksum is the checksum of the data that's associated with the image.
|
||||
Checksum string `json:"checksum"`
|
||||
|
||||
// SizeBytes is the size of the data that's associated with the image.
|
||||
@ -60,23 +61,27 @@ type Image struct {
|
||||
|
||||
// Metadata is a set of metadata associated with the image.
|
||||
// Image metadata allow for meaningfully define the image properties
|
||||
// and tags. See http://docs.openstack.org/developer/glance/metadefs-concepts.html.
|
||||
// and tags.
|
||||
// See http://docs.openstack.org/developer/glance/metadefs-concepts.html.
|
||||
Metadata map[string]string `json:"metadata"`
|
||||
|
||||
// Properties is a set of key-value pairs, if any, that are associated with the image.
|
||||
// Properties is a set of key-value pairs, if any, that are associated with
|
||||
// the image.
|
||||
Properties map[string]interface{} `json:"-"`
|
||||
|
||||
// CreatedAt is the date when the image has been created.
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
|
||||
// UpdatedAt is the date when the last change has been made to the image or it's properties.
|
||||
// UpdatedAt is the date when the last change has been made to the image or
|
||||
// it's properties.
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
|
||||
// File is the trailing path after the glance endpoint that represent the location
|
||||
// of the image or the path to retrieve it.
|
||||
// File is the trailing path after the glance endpoint that represent the
|
||||
// location of the image or the path to retrieve it.
|
||||
File string `json:"file"`
|
||||
|
||||
// Schema is the path to the JSON-schema that represent the image or image entity.
|
||||
// Schema is the path to the JSON-schema that represent the image or image
|
||||
// entity.
|
||||
Schema string `json:"schema"`
|
||||
|
||||
// VirtualSize is the virtual size of the image
|
||||
@ -97,7 +102,7 @@ func (r *Image) UnmarshalJSON(b []byte) error {
|
||||
|
||||
switch t := s.SizeBytes.(type) {
|
||||
case nil:
|
||||
return nil
|
||||
r.SizeBytes = 0
|
||||
case float32:
|
||||
r.SizeBytes = int64(t)
|
||||
case float64:
|
||||
@ -131,38 +136,43 @@ func (r commonResult) Extract() (*Image, error) {
|
||||
return s, err
|
||||
}
|
||||
|
||||
// CreateResult represents the result of a Create operation
|
||||
// CreateResult represents the result of a Create operation. Call its Extract
|
||||
// method to interpret it as an Image.
|
||||
type CreateResult struct {
|
||||
commonResult
|
||||
}
|
||||
|
||||
// UpdateResult represents the result of an Update operation
|
||||
// UpdateResult represents the result of an Update operation. Call its Extract
|
||||
// method to interpret it as an Image.
|
||||
type UpdateResult struct {
|
||||
commonResult
|
||||
}
|
||||
|
||||
// GetResult represents the result of a Get operation
|
||||
// GetResult represents the result of a Get operation. Call its Extract
|
||||
// method to interpret it as an Image.
|
||||
type GetResult struct {
|
||||
commonResult
|
||||
}
|
||||
|
||||
//DeleteResult model
|
||||
// DeleteResult represents the result of a Delete operation. Call its
|
||||
// ExtractErr method to interpret it as an Image.
|
||||
type DeleteResult struct {
|
||||
gophercloud.ErrResult
|
||||
}
|
||||
|
||||
// ImagePage represents page
|
||||
// ImagePage represents the results of a List request.
|
||||
type ImagePage struct {
|
||||
pagination.LinkedPageBase
|
||||
}
|
||||
|
||||
// IsEmpty returns true if a page contains no Images results.
|
||||
// IsEmpty returns true if an ImagePage contains no Images results.
|
||||
func (r ImagePage) IsEmpty() (bool, error) {
|
||||
images, err := ExtractImages(r)
|
||||
return len(images) == 0, err
|
||||
}
|
||||
|
||||
// NextPageURL uses the response's embedded link reference to navigate to the next page of results.
|
||||
// NextPageURL uses the response's embedded link reference to navigate to
|
||||
// the next page of results.
|
||||
func (r ImagePage) NextPageURL() (string, error) {
|
||||
var s struct {
|
||||
Next string `json:"next"`
|
||||
@ -179,7 +189,8 @@ func (r ImagePage) NextPageURL() (string, error) {
|
||||
return nextPageURL(r.URL.String(), s.Next)
|
||||
}
|
||||
|
||||
// ExtractImages interprets the results of a single page from a List() call, producing a slice of Image entities.
|
||||
// ExtractImages interprets the results of a single page from a List() call,
|
||||
// producing a slice of Image entities.
|
||||
func ExtractImages(r pagination.Page) ([]Image, error) {
|
||||
var s struct {
|
||||
Images []Image `json:"images"`
|
||||
|
45
vendor/github.com/gophercloud/gophercloud/openstack/imageservice/v2/images/types.go
generated
vendored
45
vendor/github.com/gophercloud/gophercloud/openstack/imageservice/v2/images/types.go
generated
vendored
@ -1,5 +1,9 @@
|
||||
package images
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// ImageStatus image statuses
|
||||
// http://docs.openstack.org/developer/glance/statuses.html
|
||||
type ImageStatus string
|
||||
@ -9,7 +13,8 @@ const (
|
||||
// been reserved for an image in the image registry.
|
||||
ImageStatusQueued ImageStatus = "queued"
|
||||
|
||||
// ImageStatusSaving denotes that an image’s raw data is currently being uploaded to Glance
|
||||
// ImageStatusSaving denotes that an image’s raw data is currently being
|
||||
// uploaded to Glance
|
||||
ImageStatusSaving ImageStatus = "saving"
|
||||
|
||||
// ImageStatusActive denotes an image that is fully available in Glance.
|
||||
@ -23,16 +28,18 @@ const (
|
||||
// The image information is retained in the image registry.
|
||||
ImageStatusDeleted ImageStatus = "deleted"
|
||||
|
||||
// ImageStatusPendingDelete is similar to Delete, but the image is not yet deleted.
|
||||
// ImageStatusPendingDelete is similar to Delete, but the image is not yet
|
||||
// deleted.
|
||||
ImageStatusPendingDelete ImageStatus = "pending_delete"
|
||||
|
||||
// ImageStatusDeactivated denotes that access to image data is not allowed to any non-admin user.
|
||||
// ImageStatusDeactivated denotes that access to image data is not allowed to
|
||||
// any non-admin user.
|
||||
ImageStatusDeactivated ImageStatus = "deactivated"
|
||||
)
|
||||
|
||||
// ImageVisibility denotes an image that is fully available in Glance.
|
||||
// This occurs when the image data is uploaded, or the image size
|
||||
// is explicitly set to zero on creation.
|
||||
// This occurs when the image data is uploaded, or the image size is explicitly
|
||||
// set to zero on creation.
|
||||
// According to design
|
||||
// https://wiki.openstack.org/wiki/Glance-v2-community-image-visibility-design
|
||||
type ImageVisibility string
|
||||
@ -52,12 +59,13 @@ const (
|
||||
|
||||
// ImageVisibilityCommunity images:
|
||||
// - all users can see and boot it
|
||||
// - users with tenantId in the member-list of the image with member_status == 'accepted'
|
||||
// have this image in their default image-list
|
||||
// - users with tenantId in the member-list of the image with
|
||||
// member_status == 'accepted' have this image in their default image-list.
|
||||
ImageVisibilityCommunity ImageVisibility = "community"
|
||||
)
|
||||
|
||||
// MemberStatus is a status for adding a new member (tenant) to an image member list.
|
||||
// MemberStatus is a status for adding a new member (tenant) to an image
|
||||
// member list.
|
||||
type ImageMemberStatus string
|
||||
|
||||
const (
|
||||
@ -73,3 +81,24 @@ const (
|
||||
// ImageMemberStatusAll
|
||||
ImageMemberStatusAll ImageMemberStatus = "all"
|
||||
)
|
||||
|
||||
// ImageDateFilter represents a valid filter to use for filtering
|
||||
// images by their date during a List.
|
||||
type ImageDateFilter string
|
||||
|
||||
const (
|
||||
FilterGT ImageDateFilter = "gt"
|
||||
FilterGTE ImageDateFilter = "gte"
|
||||
FilterLT ImageDateFilter = "lt"
|
||||
FilterLTE ImageDateFilter = "lte"
|
||||
FilterNEQ ImageDateFilter = "neq"
|
||||
FilterEQ ImageDateFilter = "eq"
|
||||
)
|
||||
|
||||
// ImageDateQuery represents a date field to be used for listing images.
|
||||
// If no filter is specified, the query will act as though FilterEQ was
|
||||
// set.
|
||||
type ImageDateQuery struct {
|
||||
Date time.Time
|
||||
Filter ImageDateFilter
|
||||
}
|
||||
|
58
vendor/github.com/gophercloud/gophercloud/openstack/imageservice/v2/members/doc.go
generated
vendored
Normal file
58
vendor/github.com/gophercloud/gophercloud/openstack/imageservice/v2/members/doc.go
generated
vendored
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
Package members enables management and retrieval of image members.
|
||||
|
||||
Members are projects other than the image owner who have access to the image.
|
||||
|
||||
Example to List Members of an Image
|
||||
|
||||
imageID := "2b6cacd4-cfd6-4b95-8302-4c04ccf0be3f"
|
||||
|
||||
allPages, err := members.List(imageID).AllPages()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
allMembers, err := members.ExtractMembers(allPages)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
for _, member := range allMembers {
|
||||
fmt.Printf("%+v\n", member)
|
||||
}
|
||||
|
||||
Example to Add a Member to an Image
|
||||
|
||||
imageID := "2b6cacd4-cfd6-4b95-8302-4c04ccf0be3f"
|
||||
projectID := "fc404778935a4cebaddcb4788fb3ff2c"
|
||||
|
||||
member, err := members.Create(imageClient, imageID, projectID).Extract()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
Example to Update the Status of a Member
|
||||
|
||||
imageID := "2b6cacd4-cfd6-4b95-8302-4c04ccf0be3f"
|
||||
projectID := "fc404778935a4cebaddcb4788fb3ff2c"
|
||||
|
||||
updateOpts := members.UpdateOpts{
|
||||
Status: "accepted",
|
||||
}
|
||||
|
||||
member, err := members.Update(imageClient, imageID, projectID, updateOpts).Extract()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
Example to Delete a Member from an Image
|
||||
|
||||
imageID := "2b6cacd4-cfd6-4b95-8302-4c04ccf0be3f"
|
||||
projectID := "fc404778935a4cebaddcb4788fb3ff2c"
|
||||
|
||||
err := members.Delete(imageClient, imageID, projectID).ExtractErr()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
*/
|
||||
package members
|
44
vendor/github.com/gophercloud/gophercloud/openstack/imageservice/v2/members/requests.go
generated
vendored
44
vendor/github.com/gophercloud/gophercloud/openstack/imageservice/v2/members/requests.go
generated
vendored
@ -5,16 +5,24 @@ import (
|
||||
"github.com/gophercloud/gophercloud/pagination"
|
||||
)
|
||||
|
||||
// Create member for specific image
|
||||
//
|
||||
// Preconditions
|
||||
// The specified images must exist.
|
||||
// You can only add a new member to an image which 'visibility' attribute is private.
|
||||
// You must be the owner of the specified image.
|
||||
// Synchronous Postconditions
|
||||
// With correct permissions, you can see the member status of the image as pending through API calls.
|
||||
//
|
||||
// More details here: http://developer.openstack.org/api-ref-image-v2.html#createImageMember-v2
|
||||
/*
|
||||
Create member for specific image
|
||||
|
||||
Preconditions
|
||||
|
||||
* The specified images must exist.
|
||||
* You can only add a new member to an image which 'visibility' attribute is
|
||||
private.
|
||||
* You must be the owner of the specified image.
|
||||
|
||||
Synchronous Postconditions
|
||||
|
||||
With correct permissions, you can see the member status of the image as
|
||||
pending through API calls.
|
||||
|
||||
More details here:
|
||||
http://developer.openstack.org/api-ref-image-v2.html#createImageMember-v2
|
||||
*/
|
||||
func Create(client *gophercloud.ServiceClient, id string, member string) (r CreateResult) {
|
||||
b := map[string]interface{}{"member": member}
|
||||
_, r.Err = client.Post(createMemberURL(client, id), b, &r.Body, &gophercloud.RequestOpts{
|
||||
@ -23,8 +31,7 @@ func Create(client *gophercloud.ServiceClient, id string, member string) (r Crea
|
||||
return
|
||||
}
|
||||
|
||||
// List members returns list of members for specifed image id
|
||||
// More details: http://developer.openstack.org/api-ref-image-v2.html#listImageMembers-v2
|
||||
// List members returns list of members for specifed image id.
|
||||
func List(client *gophercloud.ServiceClient, id string) pagination.Pager {
|
||||
return pagination.NewPager(client, listMembersURL(client, id), func(r pagination.PageResult) pagination.Page {
|
||||
return MemberPage{pagination.SinglePageBase(r)}
|
||||
@ -32,26 +39,24 @@ func List(client *gophercloud.ServiceClient, id string) pagination.Pager {
|
||||
}
|
||||
|
||||
// Get image member details.
|
||||
// More details: http://developer.openstack.org/api-ref-image-v2.html#getImageMember-v2
|
||||
func Get(client *gophercloud.ServiceClient, imageID string, memberID string) (r DetailsResult) {
|
||||
_, r.Err = client.Get(getMemberURL(client, imageID, memberID), &r.Body, &gophercloud.RequestOpts{OkCodes: []int{200}})
|
||||
return
|
||||
}
|
||||
|
||||
// Delete membership for given image.
|
||||
// Callee should be image owner
|
||||
// More details: http://developer.openstack.org/api-ref-image-v2.html#deleteImageMember-v2
|
||||
// Delete membership for given image. Callee should be image owner.
|
||||
func Delete(client *gophercloud.ServiceClient, imageID string, memberID string) (r DeleteResult) {
|
||||
_, r.Err = client.Delete(deleteMemberURL(client, imageID, memberID), &gophercloud.RequestOpts{OkCodes: []int{204}})
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateOptsBuilder allows extensions to add additional attributes to the Update request.
|
||||
// UpdateOptsBuilder allows extensions to add additional attributes to the
|
||||
// Update request.
|
||||
type UpdateOptsBuilder interface {
|
||||
ToImageMemberUpdateMap() (map[string]interface{}, error)
|
||||
}
|
||||
|
||||
// UpdateOpts implements UpdateOptsBuilder
|
||||
// UpdateOpts represents options to an Update request.
|
||||
type UpdateOpts struct {
|
||||
Status string
|
||||
}
|
||||
@ -63,8 +68,7 @@ func (opts UpdateOpts) ToImageMemberUpdateMap() (map[string]interface{}, error)
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Update function updates member
|
||||
// More details: http://developer.openstack.org/api-ref-image-v2.html#updateImageMember-v2
|
||||
// Update function updates member.
|
||||
func Update(client *gophercloud.ServiceClient, imageID string, memberID string, opts UpdateOptsBuilder) (r UpdateResult) {
|
||||
b, err := opts.ToImageMemberUpdateMap()
|
||||
if err != nil {
|
||||
|
21
vendor/github.com/gophercloud/gophercloud/openstack/imageservice/v2/members/results.go
generated
vendored
21
vendor/github.com/gophercloud/gophercloud/openstack/imageservice/v2/members/results.go
generated
vendored
@ -7,7 +7,7 @@ import (
|
||||
"github.com/gophercloud/gophercloud/pagination"
|
||||
)
|
||||
|
||||
// Member model
|
||||
// Member represents a member of an Image.
|
||||
type Member struct {
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
ImageID string `json:"image_id"`
|
||||
@ -17,7 +17,7 @@ type Member struct {
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
// Extract Member model from request if possible
|
||||
// Extract Member model from a request.
|
||||
func (r commonResult) Extract() (*Member, error) {
|
||||
var s *Member
|
||||
err := r.ExtractInto(&s)
|
||||
@ -29,7 +29,8 @@ type MemberPage struct {
|
||||
pagination.SinglePageBase
|
||||
}
|
||||
|
||||
// ExtractMembers returns a slice of Members contained in a single page of results.
|
||||
// ExtractMembers returns a slice of Members contained in a single page
|
||||
// of results.
|
||||
func ExtractMembers(r pagination.Page) ([]Member, error) {
|
||||
var s struct {
|
||||
Members []Member `json:"members"`
|
||||
@ -38,7 +39,7 @@ func ExtractMembers(r pagination.Page) ([]Member, error) {
|
||||
return s.Members, err
|
||||
}
|
||||
|
||||
// IsEmpty determines whether or not a page of Members contains any results.
|
||||
// IsEmpty determines whether or not a MemberPage contains any results.
|
||||
func (r MemberPage) IsEmpty() (bool, error) {
|
||||
members, err := ExtractMembers(r)
|
||||
return len(members) == 0, err
|
||||
@ -48,22 +49,26 @@ type commonResult struct {
|
||||
gophercloud.Result
|
||||
}
|
||||
|
||||
// CreateResult result model
|
||||
// CreateResult represents the result of a Create operation. Call its Extract
|
||||
// method to interpret it as a Member.
|
||||
type CreateResult struct {
|
||||
commonResult
|
||||
}
|
||||
|
||||
// DetailsResult model
|
||||
// DetailsResult represents the result of a Get operation. Call its Extract
|
||||
// method to interpret it as a Member.
|
||||
type DetailsResult struct {
|
||||
commonResult
|
||||
}
|
||||
|
||||
// UpdateResult model
|
||||
// UpdateResult represents the result of an Update operation. Call its Extract
|
||||
// method to interpret it as a Member.
|
||||
type UpdateResult struct {
|
||||
commonResult
|
||||
}
|
||||
|
||||
// DeleteResult model
|
||||
// DeleteResult represents the result of a Delete operation. Call its
|
||||
// ExtractErr method to determine if the request succeeded or failed.
|
||||
type DeleteResult struct {
|
||||
gophercloud.ErrResult
|
||||
}
|
||||
|
29
vendor/github.com/gophercloud/gophercloud/openstack/utils/base_endpoint.go
generated
vendored
Normal file
29
vendor/github.com/gophercloud/gophercloud/openstack/utils/base_endpoint.go
generated
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// BaseEndpoint will return a URL without the /vX.Y
|
||||
// portion of the URL.
|
||||
func BaseEndpoint(endpoint string) (string, error) {
|
||||
var base string
|
||||
|
||||
u, err := url.Parse(endpoint)
|
||||
if err != nil {
|
||||
return base, err
|
||||
}
|
||||
|
||||
u.RawQuery, u.Fragment = "", ""
|
||||
|
||||
versionRe := regexp.MustCompile("v[0-9.]+/?")
|
||||
if version := versionRe.FindString(u.Path); version != "" {
|
||||
base = strings.Replace(u.String(), version, "", -1)
|
||||
} else {
|
||||
base = u.String()
|
||||
}
|
||||
|
||||
return base, nil
|
||||
}
|
31
vendor/github.com/gophercloud/gophercloud/openstack/utils/choose_version.go
generated
vendored
31
vendor/github.com/gophercloud/gophercloud/openstack/utils/choose_version.go
generated
vendored
@ -68,11 +68,6 @@ func ChooseVersion(client *gophercloud.ProviderClient, recognized []*Version) (*
|
||||
return nil, "", err
|
||||
}
|
||||
|
||||
byID := make(map[string]*Version)
|
||||
for _, version := range recognized {
|
||||
byID[version.ID] = version
|
||||
}
|
||||
|
||||
var highest *Version
|
||||
var endpoint string
|
||||
|
||||
@ -84,20 +79,22 @@ func ChooseVersion(client *gophercloud.ProviderClient, recognized []*Version) (*
|
||||
}
|
||||
}
|
||||
|
||||
if matching, ok := byID[value.ID]; ok {
|
||||
// Prefer a version that exactly matches the provided endpoint.
|
||||
if href == identityEndpoint {
|
||||
if href == "" {
|
||||
return nil, "", fmt.Errorf("Endpoint missing in version %s response from %s", value.ID, client.IdentityBase)
|
||||
for _, version := range recognized {
|
||||
if strings.Contains(value.ID, version.ID) {
|
||||
// Prefer a version that exactly matches the provided endpoint.
|
||||
if href == identityEndpoint {
|
||||
if href == "" {
|
||||
return nil, "", fmt.Errorf("Endpoint missing in version %s response from %s", value.ID, client.IdentityBase)
|
||||
}
|
||||
return version, href, nil
|
||||
}
|
||||
return matching, href, nil
|
||||
}
|
||||
|
||||
// Otherwise, find the highest-priority version with a whitelisted status.
|
||||
if goodStatus[strings.ToLower(value.Status)] {
|
||||
if highest == nil || matching.Priority > highest.Priority {
|
||||
highest = matching
|
||||
endpoint = href
|
||||
// Otherwise, find the highest-priority version with a whitelisted status.
|
||||
if goodStatus[strings.ToLower(value.Status)] {
|
||||
if highest == nil || version.Priority > highest.Priority {
|
||||
highest = version
|
||||
endpoint = href
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
1
vendor/github.com/gophercloud/gophercloud/pagination/pager.go
generated
vendored
1
vendor/github.com/gophercloud/gophercloud/pagination/pager.go
generated
vendored
@ -22,7 +22,6 @@ var (
|
||||
// Depending on the pagination strategy of a particular resource, there may be an additional subinterface that the result type
|
||||
// will need to implement.
|
||||
type Page interface {
|
||||
|
||||
// NextPageURL generates the URL for the page of data that follows this collection.
|
||||
// Return "" if no such page exists.
|
||||
NextPageURL() (string, error)
|
||||
|
56
vendor/github.com/gophercloud/gophercloud/params.go
generated
vendored
56
vendor/github.com/gophercloud/gophercloud/params.go
generated
vendored
@ -10,10 +10,28 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// BuildRequestBody builds a map[string]interface from the given `struct`. If
|
||||
// parent is not the empty string, the final map[string]interface returned will
|
||||
// encapsulate the built one
|
||||
//
|
||||
/*
|
||||
BuildRequestBody builds a map[string]interface from the given `struct`. If
|
||||
parent is not an empty string, the final map[string]interface returned will
|
||||
encapsulate the built one. For example:
|
||||
|
||||
disk := 1
|
||||
createOpts := flavors.CreateOpts{
|
||||
ID: "1",
|
||||
Name: "m1.tiny",
|
||||
Disk: &disk,
|
||||
RAM: 512,
|
||||
VCPUs: 1,
|
||||
RxTxFactor: 1.0,
|
||||
}
|
||||
|
||||
body, err := gophercloud.BuildRequestBody(createOpts, "flavor")
|
||||
|
||||
The above example can be run as-is, however it is recommended to look at how
|
||||
BuildRequestBody is used within Gophercloud to more fully understand how it
|
||||
fits within the request process as a whole rather than use it directly as shown
|
||||
above.
|
||||
*/
|
||||
func BuildRequestBody(opts interface{}, parent string) (map[string]interface{}, error) {
|
||||
optsValue := reflect.ValueOf(opts)
|
||||
if optsValue.Kind() == reflect.Ptr {
|
||||
@ -97,10 +115,15 @@ func BuildRequestBody(opts interface{}, parent string) (map[string]interface{},
|
||||
}
|
||||
}
|
||||
|
||||
jsonTag := f.Tag.Get("json")
|
||||
if jsonTag == "-" {
|
||||
continue
|
||||
}
|
||||
|
||||
if v.Kind() == reflect.Struct || (v.Kind() == reflect.Ptr && v.Elem().Kind() == reflect.Struct) {
|
||||
if zero {
|
||||
//fmt.Printf("value before change: %+v\n", optsValue.Field(i))
|
||||
if jsonTag := f.Tag.Get("json"); jsonTag != "" {
|
||||
if jsonTag != "" {
|
||||
jsonTagPieces := strings.Split(jsonTag, ",")
|
||||
if len(jsonTagPieces) > 1 && jsonTagPieces[1] == "omitempty" {
|
||||
if v.CanSet() {
|
||||
@ -329,12 +352,20 @@ func BuildQueryString(opts interface{}) (*url.URL, error) {
|
||||
params.Add(tags[0], v.Index(i).String())
|
||||
}
|
||||
}
|
||||
case reflect.Map:
|
||||
if v.Type().Key().Kind() == reflect.String && v.Type().Elem().Kind() == reflect.String {
|
||||
var s []string
|
||||
for _, k := range v.MapKeys() {
|
||||
value := v.MapIndex(k).String()
|
||||
s = append(s, fmt.Sprintf("'%s':'%s'", k.String(), value))
|
||||
}
|
||||
params.Add(tags[0], fmt.Sprintf("{%s}", strings.Join(s, ", ")))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Otherwise, the field is not set.
|
||||
if len(tags) == 2 && tags[1] == "required" {
|
||||
// And the field is required. Return an error.
|
||||
return nil, fmt.Errorf("Required query parameter [%s] not set.", f.Name)
|
||||
// if the field has a 'required' tag, it can't have a zero-value
|
||||
if requiredTag := f.Tag.Get("required"); requiredTag == "true" {
|
||||
return &url.URL{}, fmt.Errorf("Required query parameter [%s] not set.", f.Name)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -407,10 +438,9 @@ func BuildHeaders(opts interface{}) (map[string]string, error) {
|
||||
optsMap[tags[0]] = strconv.FormatBool(v.Bool())
|
||||
}
|
||||
} else {
|
||||
// Otherwise, the field is not set.
|
||||
if len(tags) == 2 && tags[1] == "required" {
|
||||
// And the field is required. Return an error.
|
||||
return optsMap, fmt.Errorf("Required header not set.")
|
||||
// if the field has a 'required' tag, it can't have a zero-value
|
||||
if requiredTag := f.Tag.Get("required"); requiredTag == "true" {
|
||||
return optsMap, fmt.Errorf("Required header [%s] not set.", f.Name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
108
vendor/github.com/gophercloud/gophercloud/provider_client.go
generated
vendored
108
vendor/github.com/gophercloud/gophercloud/provider_client.go
generated
vendored
@ -7,6 +7,7 @@ import (
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// DefaultUserAgent is the default User-Agent string set in the request header.
|
||||
@ -51,6 +52,8 @@ type ProviderClient struct {
|
||||
IdentityEndpoint string
|
||||
|
||||
// TokenID is the ID of the most recently issued valid token.
|
||||
// NOTE: Aside from within a custom ReauthFunc, this field shouldn't be set by an application.
|
||||
// To safely read or write this value, call `Token` or `SetToken`, respectively
|
||||
TokenID string
|
||||
|
||||
// EndpointLocator describes how this provider discovers the endpoints for
|
||||
@ -68,16 +71,89 @@ type ProviderClient struct {
|
||||
// authentication functions for different Identity service versions.
|
||||
ReauthFunc func() error
|
||||
|
||||
Debug bool
|
||||
mut *sync.RWMutex
|
||||
|
||||
reauthmut *reauthlock
|
||||
}
|
||||
|
||||
type reauthlock struct {
|
||||
sync.RWMutex
|
||||
reauthing bool
|
||||
}
|
||||
|
||||
// AuthenticatedHeaders returns a map of HTTP headers that are common for all
|
||||
// authenticated service requests.
|
||||
func (client *ProviderClient) AuthenticatedHeaders() map[string]string {
|
||||
if client.TokenID == "" {
|
||||
return map[string]string{}
|
||||
func (client *ProviderClient) AuthenticatedHeaders() (m map[string]string) {
|
||||
if client.reauthmut != nil {
|
||||
client.reauthmut.RLock()
|
||||
if client.reauthmut.reauthing {
|
||||
client.reauthmut.RUnlock()
|
||||
return
|
||||
}
|
||||
client.reauthmut.RUnlock()
|
||||
}
|
||||
return map[string]string{"X-Auth-Token": client.TokenID}
|
||||
t := client.Token()
|
||||
if t == "" {
|
||||
return
|
||||
}
|
||||
return map[string]string{"X-Auth-Token": t}
|
||||
}
|
||||
|
||||
// UseTokenLock creates a mutex that is used to allow safe concurrent access to the auth token.
|
||||
// If the application's ProviderClient is not used concurrently, this doesn't need to be called.
|
||||
func (client *ProviderClient) UseTokenLock() {
|
||||
client.mut = new(sync.RWMutex)
|
||||
client.reauthmut = new(reauthlock)
|
||||
}
|
||||
|
||||
// Token safely reads the value of the auth token from the ProviderClient. Applications should
|
||||
// call this method to access the token instead of the TokenID field
|
||||
func (client *ProviderClient) Token() string {
|
||||
if client.mut != nil {
|
||||
client.mut.RLock()
|
||||
defer client.mut.RUnlock()
|
||||
}
|
||||
return client.TokenID
|
||||
}
|
||||
|
||||
// SetToken safely sets the value of the auth token in the ProviderClient. Applications may
|
||||
// use this method in a custom ReauthFunc
|
||||
func (client *ProviderClient) SetToken(t string) {
|
||||
if client.mut != nil {
|
||||
client.mut.Lock()
|
||||
defer client.mut.Unlock()
|
||||
}
|
||||
client.TokenID = t
|
||||
}
|
||||
|
||||
//Reauthenticate calls client.ReauthFunc in a thread-safe way. If this is
|
||||
//called because of a 401 response, the caller may pass the previous token. In
|
||||
//this case, the reauthentication can be skipped if another thread has already
|
||||
//reauthenticated in the meantime. If no previous token is known, an empty
|
||||
//string should be passed instead to force unconditional reauthentication.
|
||||
func (client *ProviderClient) Reauthenticate(previousToken string) (err error) {
|
||||
if client.ReauthFunc == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
if client.mut == nil {
|
||||
return client.ReauthFunc()
|
||||
}
|
||||
client.mut.Lock()
|
||||
defer client.mut.Unlock()
|
||||
|
||||
client.reauthmut.Lock()
|
||||
client.reauthmut.reauthing = true
|
||||
client.reauthmut.Unlock()
|
||||
|
||||
if previousToken == "" || client.TokenID == previousToken {
|
||||
err = client.ReauthFunc()
|
||||
}
|
||||
|
||||
client.reauthmut.Lock()
|
||||
client.reauthmut.reauthing = false
|
||||
client.reauthmut.Unlock()
|
||||
return
|
||||
}
|
||||
|
||||
// RequestOpts customizes the behavior of the provider.Request() method.
|
||||
@ -145,10 +221,6 @@ func (client *ProviderClient) Request(method, url string, options *RequestOpts)
|
||||
}
|
||||
req.Header.Set("Accept", applicationJSON)
|
||||
|
||||
for k, v := range client.AuthenticatedHeaders() {
|
||||
req.Header.Add(k, v)
|
||||
}
|
||||
|
||||
// Set the User-Agent header
|
||||
req.Header.Set("User-Agent", client.UserAgent.Join())
|
||||
|
||||
@ -162,9 +234,16 @@ func (client *ProviderClient) Request(method, url string, options *RequestOpts)
|
||||
}
|
||||
}
|
||||
|
||||
// get latest token from client
|
||||
for k, v := range client.AuthenticatedHeaders() {
|
||||
req.Header.Set(k, v)
|
||||
}
|
||||
|
||||
// Set connection parameter to close the connection immediately when we've got the response
|
||||
req.Close = true
|
||||
|
||||
prereqtok := req.Header.Get("X-Auth-Token")
|
||||
|
||||
// Issue the request.
|
||||
resp, err := client.HTTPClient.Do(req)
|
||||
if err != nil {
|
||||
@ -188,9 +267,6 @@ func (client *ProviderClient) Request(method, url string, options *RequestOpts)
|
||||
if !ok {
|
||||
body, _ := ioutil.ReadAll(resp.Body)
|
||||
resp.Body.Close()
|
||||
//pc := make([]uintptr, 1)
|
||||
//runtime.Callers(2, pc)
|
||||
//f := runtime.FuncForPC(pc[0])
|
||||
respErr := ErrUnexpectedResponseCode{
|
||||
URL: url,
|
||||
Method: method,
|
||||
@ -198,7 +274,6 @@ func (client *ProviderClient) Request(method, url string, options *RequestOpts)
|
||||
Actual: resp.StatusCode,
|
||||
Body: body,
|
||||
}
|
||||
//respErr.Function = "gophercloud.ProviderClient.Request"
|
||||
|
||||
errType := options.ErrorContext
|
||||
switch resp.StatusCode {
|
||||
@ -209,7 +284,7 @@ func (client *ProviderClient) Request(method, url string, options *RequestOpts)
|
||||
}
|
||||
case http.StatusUnauthorized:
|
||||
if client.ReauthFunc != nil {
|
||||
err = client.ReauthFunc()
|
||||
err = client.Reauthenticate(prereqtok)
|
||||
if err != nil {
|
||||
e := &ErrUnableToReauthenticate{}
|
||||
e.ErrOriginal = respErr
|
||||
@ -239,6 +314,11 @@ func (client *ProviderClient) Request(method, url string, options *RequestOpts)
|
||||
if error401er, ok := errType.(Err401er); ok {
|
||||
err = error401er.Error401(respErr)
|
||||
}
|
||||
case http.StatusForbidden:
|
||||
err = ErrDefault403{respErr}
|
||||
if error403er, ok := errType.(Err403er); ok {
|
||||
err = error403er.Error403(respErr)
|
||||
}
|
||||
case http.StatusNotFound:
|
||||
err = ErrDefault404{respErr}
|
||||
if error404er, ok := errType.(Err404er); ok {
|
||||
|
73
vendor/github.com/gophercloud/gophercloud/results.go
generated
vendored
73
vendor/github.com/gophercloud/gophercloud/results.go
generated
vendored
@ -78,6 +78,53 @@ func (r Result) extractIntoPtr(to interface{}, label string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
toValue := reflect.ValueOf(to)
|
||||
if toValue.Kind() == reflect.Ptr {
|
||||
toValue = toValue.Elem()
|
||||
}
|
||||
|
||||
switch toValue.Kind() {
|
||||
case reflect.Slice:
|
||||
typeOfV := toValue.Type().Elem()
|
||||
if typeOfV.Kind() == reflect.Struct {
|
||||
if typeOfV.NumField() > 0 && typeOfV.Field(0).Anonymous {
|
||||
newSlice := reflect.MakeSlice(reflect.SliceOf(typeOfV), 0, 0)
|
||||
newType := reflect.New(typeOfV).Elem()
|
||||
|
||||
for _, v := range m[label].([]interface{}) {
|
||||
b, err := json.Marshal(v)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for i := 0; i < newType.NumField(); i++ {
|
||||
s := newType.Field(i).Addr().Interface()
|
||||
err = json.NewDecoder(bytes.NewReader(b)).Decode(s)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
newSlice = reflect.Append(newSlice, newType)
|
||||
}
|
||||
toValue.Set(newSlice)
|
||||
}
|
||||
}
|
||||
case reflect.Struct:
|
||||
typeOfV := toValue.Type()
|
||||
if typeOfV.NumField() > 0 && typeOfV.Field(0).Anonymous {
|
||||
for i := 0; i < toValue.NumField(); i++ {
|
||||
toField := toValue.Field(i)
|
||||
if toField.Kind() == reflect.Struct {
|
||||
s := toField.Addr().Interface()
|
||||
err = json.NewDecoder(bytes.NewReader(b)).Decode(s)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
err = json.Unmarshal(b, &to)
|
||||
return err
|
||||
}
|
||||
@ -177,9 +224,8 @@ type HeaderResult struct {
|
||||
Result
|
||||
}
|
||||
|
||||
// ExtractHeader will return the http.Header and error from the HeaderResult.
|
||||
//
|
||||
// header, err := objects.Create(client, "my_container", objects.CreateOpts{}).ExtractHeader()
|
||||
// ExtractInto allows users to provide an object into which `Extract` will
|
||||
// extract the http.Header headers of the result.
|
||||
func (r HeaderResult) ExtractInto(to interface{}) error {
|
||||
if r.Err != nil {
|
||||
return r.Err
|
||||
@ -299,6 +345,27 @@ func (jt *JSONRFC3339NoZ) UnmarshalJSON(data []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// RFC3339ZNoT is the time format used in Zun (Containers Service).
|
||||
const RFC3339ZNoT = "2006-01-02 15:04:05-07:00"
|
||||
|
||||
type JSONRFC3339ZNoT time.Time
|
||||
|
||||
func (jt *JSONRFC3339ZNoT) UnmarshalJSON(data []byte) error {
|
||||
var s string
|
||||
if err := json.Unmarshal(data, &s); err != nil {
|
||||
return err
|
||||
}
|
||||
if s == "" {
|
||||
return nil
|
||||
}
|
||||
t, err := time.Parse(RFC3339ZNoT, s)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*jt = JSONRFC3339ZNoT(t)
|
||||
return nil
|
||||
}
|
||||
|
||||
/*
|
||||
Link is an internal type to be used in packages of collection resources that are
|
||||
paginated in a certain way.
|
||||
|
28
vendor/github.com/gophercloud/gophercloud/service_client.go
generated
vendored
28
vendor/github.com/gophercloud/gophercloud/service_client.go
generated
vendored
@ -28,6 +28,10 @@ type ServiceClient struct {
|
||||
|
||||
// The microversion of the service to use. Set this to use a particular microversion.
|
||||
Microversion string
|
||||
|
||||
// MoreHeaders allows users (or Gophercloud) to set service-wide headers on requests. Put another way,
|
||||
// values set in this field will be set on all the HTTP requests the service client sends.
|
||||
MoreHeaders map[string]string
|
||||
}
|
||||
|
||||
// ResourceBaseURL returns the base URL of any resources used by this service. It MUST end with a /.
|
||||
@ -108,15 +112,39 @@ func (client *ServiceClient) Delete(url string, opts *RequestOpts) (*http.Respon
|
||||
return client.Request("DELETE", url, opts)
|
||||
}
|
||||
|
||||
// Head calls `Request` with the "HEAD" HTTP verb.
|
||||
func (client *ServiceClient) Head(url string, opts *RequestOpts) (*http.Response, error) {
|
||||
if opts == nil {
|
||||
opts = new(RequestOpts)
|
||||
}
|
||||
client.initReqOpts(url, nil, nil, opts)
|
||||
return client.Request("HEAD", url, opts)
|
||||
}
|
||||
|
||||
func (client *ServiceClient) setMicroversionHeader(opts *RequestOpts) {
|
||||
switch client.Type {
|
||||
case "compute":
|
||||
opts.MoreHeaders["X-OpenStack-Nova-API-Version"] = client.Microversion
|
||||
case "sharev2":
|
||||
opts.MoreHeaders["X-OpenStack-Manila-API-Version"] = client.Microversion
|
||||
case "volume":
|
||||
opts.MoreHeaders["X-OpenStack-Volume-API-Version"] = client.Microversion
|
||||
}
|
||||
|
||||
if client.Type != "" {
|
||||
opts.MoreHeaders["OpenStack-API-Version"] = client.Type + " " + client.Microversion
|
||||
}
|
||||
}
|
||||
|
||||
// Request carries out the HTTP operation for the service client
|
||||
func (client *ServiceClient) Request(method, url string, options *RequestOpts) (*http.Response, error) {
|
||||
if len(client.MoreHeaders) > 0 {
|
||||
if options == nil {
|
||||
options = new(RequestOpts)
|
||||
}
|
||||
for k, v := range client.MoreHeaders {
|
||||
options.MoreHeaders[k] = v
|
||||
}
|
||||
}
|
||||
return client.ProviderClient.Request(method, url, options)
|
||||
}
|
||||
|
201
vendor/github.com/gophercloud/utils/LICENSE
generated
vendored
Normal file
201
vendor/github.com/gophercloud/utils/LICENSE
generated
vendored
Normal file
@ -0,0 +1,201 @@
|
||||
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 {yyyy} {name of copyright owner}
|
||||
|
||||
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.
|
49
vendor/github.com/gophercloud/utils/openstack/clientconfig/doc.go
generated
vendored
Normal file
49
vendor/github.com/gophercloud/utils/openstack/clientconfig/doc.go
generated
vendored
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
Package clientconfig provides convienent functions for creating OpenStack
|
||||
clients. It is based on the Python os-client-config library.
|
||||
|
||||
See https://docs.openstack.org/os-client-config/latest for details.
|
||||
|
||||
Example to Create a Provider Client From clouds.yaml
|
||||
|
||||
opts := &clientconfig.ClientOpts{
|
||||
Name: "hawaii",
|
||||
}
|
||||
|
||||
pClient, err := clientconfig.AuthenticatedClient(opts)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
|
||||
Example to Manually Create a Provider Client
|
||||
|
||||
opts := &clientconfig.ClientOpts{
|
||||
AuthInfo: &clientconfig.AuthInfo{
|
||||
AuthURL: "https://hi.example.com:5000/v3",
|
||||
Username: "jdoe",
|
||||
Password: "password",
|
||||
ProjectName: "Some Project",
|
||||
DomainName: "default",
|
||||
},
|
||||
}
|
||||
|
||||
pClient, err := clientconfig.AuthenticatedClient(opts)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
|
||||
Example to Create a Service Client from clouds.yaml
|
||||
|
||||
opts := &clientconfig.ClientOpts{
|
||||
Name: "hawaii",
|
||||
}
|
||||
|
||||
computeClient, err := clientconfig.NewServiceClient("compute", opts)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
*/
|
||||
package clientconfig
|
596
vendor/github.com/gophercloud/utils/openstack/clientconfig/requests.go
generated
vendored
Normal file
596
vendor/github.com/gophercloud/utils/openstack/clientconfig/requests.go
generated
vendored
Normal file
@ -0,0 +1,596 @@
|
||||
package clientconfig
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/gophercloud/gophercloud"
|
||||
"github.com/gophercloud/gophercloud/openstack"
|
||||
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
// AuthType respresents a valid method of authentication.
|
||||
type AuthType string
|
||||
|
||||
const (
|
||||
AuthPassword AuthType = "password"
|
||||
AuthToken AuthType = "token"
|
||||
|
||||
AuthV2Password AuthType = "v2password"
|
||||
AuthV2Token AuthType = "v2token"
|
||||
|
||||
AuthV3Password AuthType = "v3password"
|
||||
AuthV3Token AuthType = "v3token"
|
||||
)
|
||||
|
||||
// ClientOpts represents options to customize the way a client is
|
||||
// configured.
|
||||
type ClientOpts struct {
|
||||
// Cloud is the cloud entry in clouds.yaml to use.
|
||||
Cloud string
|
||||
|
||||
// EnvPrefix allows a custom environment variable prefix to be used.
|
||||
EnvPrefix string
|
||||
|
||||
// AuthType specifies the type of authentication to use.
|
||||
// By default, this is "password".
|
||||
AuthType AuthType
|
||||
|
||||
// AuthInfo defines the authentication information needed to
|
||||
// authenticate to a cloud when clouds.yaml isn't used.
|
||||
AuthInfo *AuthInfo
|
||||
}
|
||||
|
||||
// LoadYAML will load a clouds.yaml file and return the full config.
|
||||
func LoadYAML() (map[string]Cloud, error) {
|
||||
content, err := findAndReadYAML()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var clouds Clouds
|
||||
err = yaml.Unmarshal(content, &clouds)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal yaml: %v", err)
|
||||
}
|
||||
|
||||
return clouds.Clouds, nil
|
||||
}
|
||||
|
||||
// GetCloudFromYAML will return a cloud entry from a clouds.yaml file.
|
||||
func GetCloudFromYAML(opts *ClientOpts) (*Cloud, error) {
|
||||
clouds, err := LoadYAML()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to load clouds.yaml: %s", err)
|
||||
}
|
||||
|
||||
// Determine which cloud to use.
|
||||
// First see if a cloud name was explicitly set in opts.
|
||||
var cloudName string
|
||||
if opts != nil && opts.Cloud != "" {
|
||||
cloudName = opts.Cloud
|
||||
}
|
||||
|
||||
// Next see if a cloud name was specified as an environment variable.
|
||||
// This is supposed to override an explicit opts setting.
|
||||
envPrefix := "OS_"
|
||||
if opts.EnvPrefix != "" {
|
||||
envPrefix = opts.EnvPrefix
|
||||
}
|
||||
|
||||
if v := os.Getenv(envPrefix + "CLOUD"); v != "" {
|
||||
cloudName = v
|
||||
}
|
||||
|
||||
var cloud *Cloud
|
||||
if cloudName != "" {
|
||||
v, ok := clouds[cloudName]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("cloud %s does not exist in clouds.yaml", cloudName)
|
||||
}
|
||||
cloud = &v
|
||||
}
|
||||
|
||||
// If a cloud was not specified, and clouds only contains
|
||||
// a single entry, use that entry.
|
||||
if cloudName == "" && len(clouds) == 1 {
|
||||
for _, v := range clouds {
|
||||
cloud = &v
|
||||
}
|
||||
}
|
||||
|
||||
if cloud == nil {
|
||||
return nil, fmt.Errorf("Unable to determine a valid entry in clouds.yaml")
|
||||
}
|
||||
|
||||
return cloud, nil
|
||||
}
|
||||
|
||||
// AuthOptions creates a gophercloud.AuthOptions structure with the
|
||||
// settings found in a specific cloud entry of a clouds.yaml file or
|
||||
// based on authentication settings given in ClientOpts.
|
||||
//
|
||||
// This attempts to be a single point of entry for all OpenStack authentication.
|
||||
//
|
||||
// See http://docs.openstack.org/developer/os-client-config and
|
||||
// https://github.com/openstack/os-client-config/blob/master/os_client_config/config.py.
|
||||
func AuthOptions(opts *ClientOpts) (*gophercloud.AuthOptions, error) {
|
||||
cloud := new(Cloud)
|
||||
|
||||
// If no opts were passed in, create an empty ClientOpts.
|
||||
if opts == nil {
|
||||
opts = new(ClientOpts)
|
||||
}
|
||||
|
||||
// Determine if a clouds.yaml entry should be retrieved.
|
||||
// Start by figuring out the cloud name.
|
||||
// First check if one was explicitly specified in opts.
|
||||
var cloudName string
|
||||
if opts.Cloud != "" {
|
||||
cloudName = opts.Cloud
|
||||
}
|
||||
|
||||
// Next see if a cloud name was specified as an environment variable.
|
||||
envPrefix := "OS_"
|
||||
if opts.EnvPrefix != "" {
|
||||
envPrefix = opts.EnvPrefix
|
||||
}
|
||||
|
||||
if v := os.Getenv(envPrefix + "CLOUD"); v != "" {
|
||||
cloudName = v
|
||||
}
|
||||
|
||||
// If a cloud name was determined, try to look it up in clouds.yaml.
|
||||
if cloudName != "" {
|
||||
// Get the requested cloud.
|
||||
var err error
|
||||
cloud, err = GetCloudFromYAML(opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// If cloud.AuthInfo is nil, then no cloud was specified.
|
||||
if cloud.AuthInfo == nil {
|
||||
// If opts.Auth is not nil, then try using the auth settings from it.
|
||||
if opts.AuthInfo != nil {
|
||||
cloud.AuthInfo = opts.AuthInfo
|
||||
}
|
||||
|
||||
// If cloud.AuthInfo is still nil, then set it to an empty Auth struct
|
||||
// and rely on environment variables to do the authentication.
|
||||
if cloud.AuthInfo == nil {
|
||||
cloud.AuthInfo = new(AuthInfo)
|
||||
}
|
||||
}
|
||||
|
||||
identityAPI := determineIdentityAPI(cloud, opts)
|
||||
switch identityAPI {
|
||||
case "2.0", "2":
|
||||
return v2auth(cloud, opts)
|
||||
case "3":
|
||||
return v3auth(cloud, opts)
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("Unable to build AuthOptions")
|
||||
}
|
||||
|
||||
func determineIdentityAPI(cloud *Cloud, opts *ClientOpts) string {
|
||||
var identityAPI string
|
||||
if cloud.IdentityAPIVersion != "" {
|
||||
identityAPI = cloud.IdentityAPIVersion
|
||||
}
|
||||
|
||||
envPrefix := "OS_"
|
||||
if opts != nil && opts.EnvPrefix != "" {
|
||||
envPrefix = opts.EnvPrefix
|
||||
}
|
||||
|
||||
if v := os.Getenv(envPrefix + "IDENTITY_API_VERSION"); v != "" {
|
||||
identityAPI = v
|
||||
}
|
||||
|
||||
if identityAPI == "" {
|
||||
if cloud.AuthInfo != nil {
|
||||
if strings.Contains(cloud.AuthInfo.AuthURL, "v2.0") {
|
||||
identityAPI = "2.0"
|
||||
}
|
||||
|
||||
if strings.Contains(cloud.AuthInfo.AuthURL, "v3") {
|
||||
identityAPI = "3"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if identityAPI == "" {
|
||||
switch cloud.AuthType {
|
||||
case AuthV2Password:
|
||||
identityAPI = "2.0"
|
||||
case AuthV2Token:
|
||||
identityAPI = "2.0"
|
||||
case AuthV3Password:
|
||||
identityAPI = "3"
|
||||
case AuthV3Token:
|
||||
identityAPI = "3"
|
||||
}
|
||||
}
|
||||
|
||||
// If an Identity API version could not be determined,
|
||||
// default to v3.
|
||||
if identityAPI == "" {
|
||||
identityAPI = "3"
|
||||
}
|
||||
|
||||
return identityAPI
|
||||
}
|
||||
|
||||
// v2auth creates a v2-compatible gophercloud.AuthOptions struct.
|
||||
func v2auth(cloud *Cloud, opts *ClientOpts) (*gophercloud.AuthOptions, error) {
|
||||
// Environment variable overrides.
|
||||
envPrefix := "OS_"
|
||||
if opts != nil && opts.EnvPrefix != "" {
|
||||
envPrefix = opts.EnvPrefix
|
||||
}
|
||||
|
||||
if v := os.Getenv(envPrefix + "AUTH_URL"); v != "" {
|
||||
cloud.AuthInfo.AuthURL = v
|
||||
}
|
||||
|
||||
if v := os.Getenv(envPrefix + "TOKEN"); v != "" {
|
||||
cloud.AuthInfo.Token = v
|
||||
}
|
||||
|
||||
if v := os.Getenv(envPrefix + "AUTH_TOKEN"); v != "" {
|
||||
cloud.AuthInfo.Token = v
|
||||
}
|
||||
|
||||
if v := os.Getenv(envPrefix + "USERNAME"); v != "" {
|
||||
cloud.AuthInfo.Username = v
|
||||
}
|
||||
|
||||
if v := os.Getenv(envPrefix + "PASSWORD"); v != "" {
|
||||
cloud.AuthInfo.Password = v
|
||||
}
|
||||
|
||||
if v := os.Getenv(envPrefix + "TENANT_ID"); v != "" {
|
||||
cloud.AuthInfo.ProjectID = v
|
||||
}
|
||||
|
||||
if v := os.Getenv(envPrefix + "PROJECT_ID"); v != "" {
|
||||
cloud.AuthInfo.ProjectID = v
|
||||
}
|
||||
|
||||
if v := os.Getenv(envPrefix + "TENANT_NAME"); v != "" {
|
||||
cloud.AuthInfo.ProjectName = v
|
||||
}
|
||||
|
||||
if v := os.Getenv(envPrefix + "PROJECT_NAME"); v != "" {
|
||||
cloud.AuthInfo.ProjectName = v
|
||||
}
|
||||
|
||||
ao := &gophercloud.AuthOptions{
|
||||
IdentityEndpoint: cloud.AuthInfo.AuthURL,
|
||||
TokenID: cloud.AuthInfo.Token,
|
||||
Username: cloud.AuthInfo.Username,
|
||||
Password: cloud.AuthInfo.Password,
|
||||
TenantID: cloud.AuthInfo.ProjectID,
|
||||
TenantName: cloud.AuthInfo.ProjectName,
|
||||
}
|
||||
|
||||
return ao, nil
|
||||
}
|
||||
|
||||
// v3auth creates a v3-compatible gophercloud.AuthOptions struct.
|
||||
func v3auth(cloud *Cloud, opts *ClientOpts) (*gophercloud.AuthOptions, error) {
|
||||
// Environment variable overrides.
|
||||
envPrefix := "OS_"
|
||||
if opts != nil && opts.EnvPrefix != "" {
|
||||
envPrefix = opts.EnvPrefix
|
||||
}
|
||||
|
||||
if v := os.Getenv(envPrefix + "AUTH_URL"); v != "" {
|
||||
cloud.AuthInfo.AuthURL = v
|
||||
}
|
||||
|
||||
if v := os.Getenv(envPrefix + "TOKEN"); v != "" {
|
||||
cloud.AuthInfo.Token = v
|
||||
}
|
||||
|
||||
if v := os.Getenv(envPrefix + "AUTH_TOKEN"); v != "" {
|
||||
cloud.AuthInfo.Token = v
|
||||
}
|
||||
|
||||
if v := os.Getenv(envPrefix + "USERNAME"); v != "" {
|
||||
cloud.AuthInfo.Username = v
|
||||
}
|
||||
|
||||
if v := os.Getenv(envPrefix + "USER_ID"); v != "" {
|
||||
cloud.AuthInfo.UserID = v
|
||||
}
|
||||
|
||||
if v := os.Getenv(envPrefix + "PASSWORD"); v != "" {
|
||||
cloud.AuthInfo.Password = v
|
||||
}
|
||||
|
||||
if v := os.Getenv(envPrefix + "TENANT_ID"); v != "" {
|
||||
cloud.AuthInfo.ProjectID = v
|
||||
}
|
||||
|
||||
if v := os.Getenv(envPrefix + "PROJECT_ID"); v != "" {
|
||||
cloud.AuthInfo.ProjectID = v
|
||||
}
|
||||
|
||||
if v := os.Getenv(envPrefix + "TENANT_NAME"); v != "" {
|
||||
cloud.AuthInfo.ProjectName = v
|
||||
}
|
||||
|
||||
if v := os.Getenv(envPrefix + "PROJECT_NAME"); v != "" {
|
||||
cloud.AuthInfo.ProjectName = v
|
||||
}
|
||||
|
||||
if v := os.Getenv(envPrefix + "DOMAIN_ID"); v != "" {
|
||||
cloud.AuthInfo.DomainID = v
|
||||
}
|
||||
|
||||
if v := os.Getenv(envPrefix + "DOMAIN_NAME"); v != "" {
|
||||
cloud.AuthInfo.DomainName = v
|
||||
}
|
||||
|
||||
if v := os.Getenv(envPrefix + "DEFAULT_DOMAIN"); v != "" {
|
||||
cloud.AuthInfo.DefaultDomain = v
|
||||
}
|
||||
|
||||
if v := os.Getenv(envPrefix + "PROJECT_DOMAIN_ID"); v != "" {
|
||||
cloud.AuthInfo.ProjectDomainID = v
|
||||
}
|
||||
|
||||
if v := os.Getenv(envPrefix + "PROJECT_DOMAIN_NAME"); v != "" {
|
||||
cloud.AuthInfo.ProjectDomainName = v
|
||||
}
|
||||
|
||||
if v := os.Getenv(envPrefix + "USER_DOMAIN_ID"); v != "" {
|
||||
cloud.AuthInfo.UserDomainID = v
|
||||
}
|
||||
|
||||
if v := os.Getenv(envPrefix + "USER_DOMAIN_NAME"); v != "" {
|
||||
cloud.AuthInfo.UserDomainName = v
|
||||
}
|
||||
|
||||
// Build a scope and try to do it correctly.
|
||||
// https://github.com/openstack/os-client-config/blob/master/os_client_config/config.py#L595
|
||||
scope := new(gophercloud.AuthScope)
|
||||
|
||||
if !isProjectScoped(cloud.AuthInfo) {
|
||||
if cloud.AuthInfo.DomainID != "" {
|
||||
scope.DomainID = cloud.AuthInfo.DomainID
|
||||
} else if cloud.AuthInfo.DomainName != "" {
|
||||
scope.DomainName = cloud.AuthInfo.DomainName
|
||||
}
|
||||
} else {
|
||||
// If Domain* is set, but UserDomain* or ProjectDomain* aren't,
|
||||
// then use Domain* as the default setting.
|
||||
cloud = setDomainIfNeeded(cloud)
|
||||
|
||||
if cloud.AuthInfo.ProjectID != "" {
|
||||
scope.ProjectID = cloud.AuthInfo.ProjectID
|
||||
} else {
|
||||
scope.ProjectName = cloud.AuthInfo.ProjectName
|
||||
scope.DomainID = cloud.AuthInfo.ProjectDomainID
|
||||
scope.DomainName = cloud.AuthInfo.ProjectDomainName
|
||||
}
|
||||
}
|
||||
|
||||
ao := &gophercloud.AuthOptions{
|
||||
Scope: scope,
|
||||
IdentityEndpoint: cloud.AuthInfo.AuthURL,
|
||||
TokenID: cloud.AuthInfo.Token,
|
||||
Username: cloud.AuthInfo.Username,
|
||||
UserID: cloud.AuthInfo.UserID,
|
||||
Password: cloud.AuthInfo.Password,
|
||||
TenantID: cloud.AuthInfo.ProjectID,
|
||||
TenantName: cloud.AuthInfo.ProjectName,
|
||||
DomainID: cloud.AuthInfo.UserDomainID,
|
||||
DomainName: cloud.AuthInfo.UserDomainName,
|
||||
}
|
||||
|
||||
// If an auth_type of "token" was specified, then make sure
|
||||
// Gophercloud properly authenticates with a token. This involves
|
||||
// unsetting a few other auth options. The reason this is done
|
||||
// here is to wait until all auth settings (both in clouds.yaml
|
||||
// and via environment variables) are set and then unset them.
|
||||
if strings.Contains(string(cloud.AuthType), "token") || ao.TokenID != "" {
|
||||
ao.Username = ""
|
||||
ao.Password = ""
|
||||
ao.UserID = ""
|
||||
ao.DomainID = ""
|
||||
ao.DomainName = ""
|
||||
}
|
||||
|
||||
// Check for absolute minimum requirements.
|
||||
if ao.IdentityEndpoint == "" {
|
||||
err := gophercloud.ErrMissingInput{Argument: "auth_url"}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return ao, nil
|
||||
}
|
||||
|
||||
// AuthenticatedClient is a convenience function to get a new provider client
|
||||
// based on a clouds.yaml entry.
|
||||
func AuthenticatedClient(opts *ClientOpts) (*gophercloud.ProviderClient, error) {
|
||||
ao, err := AuthOptions(opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return openstack.AuthenticatedClient(*ao)
|
||||
}
|
||||
|
||||
// NewServiceClient is a convenience function to get a new service client.
|
||||
func NewServiceClient(service string, opts *ClientOpts) (*gophercloud.ServiceClient, error) {
|
||||
cloud := new(Cloud)
|
||||
|
||||
// If no opts were passed in, create an empty ClientOpts.
|
||||
if opts == nil {
|
||||
opts = new(ClientOpts)
|
||||
}
|
||||
|
||||
// Determine if a clouds.yaml entry should be retrieved.
|
||||
// Start by figuring out the cloud name.
|
||||
// First check if one was explicitly specified in opts.
|
||||
var cloudName string
|
||||
if opts.Cloud != "" {
|
||||
cloudName = opts.Cloud
|
||||
}
|
||||
|
||||
// Next see if a cloud name was specified as an environment variable.
|
||||
envPrefix := "OS_"
|
||||
if opts.EnvPrefix != "" {
|
||||
envPrefix = opts.EnvPrefix
|
||||
}
|
||||
|
||||
if v := os.Getenv(envPrefix + "CLOUD"); v != "" {
|
||||
cloudName = v
|
||||
}
|
||||
|
||||
// If a cloud name was determined, try to look it up in clouds.yaml.
|
||||
if cloudName != "" {
|
||||
// Get the requested cloud.
|
||||
var err error
|
||||
cloud, err = GetCloudFromYAML(opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// Get a Provider Client
|
||||
pClient, err := AuthenticatedClient(opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Determine the region to use.
|
||||
var region string
|
||||
if v := cloud.RegionName; v != "" {
|
||||
region = cloud.RegionName
|
||||
}
|
||||
|
||||
if v := os.Getenv(envPrefix + "REGION_NAME"); v != "" {
|
||||
region = v
|
||||
}
|
||||
|
||||
eo := gophercloud.EndpointOpts{
|
||||
Region: region,
|
||||
}
|
||||
|
||||
switch service {
|
||||
case "clustering":
|
||||
return openstack.NewClusteringV1(pClient, eo)
|
||||
case "compute":
|
||||
return openstack.NewComputeV2(pClient, eo)
|
||||
case "container":
|
||||
return openstack.NewContainerV1(pClient, eo)
|
||||
case "database":
|
||||
return openstack.NewDBV1(pClient, eo)
|
||||
case "dns":
|
||||
return openstack.NewDNSV2(pClient, eo)
|
||||
case "identity":
|
||||
identityVersion := "3"
|
||||
if v := cloud.IdentityAPIVersion; v != "" {
|
||||
identityVersion = v
|
||||
}
|
||||
|
||||
switch identityVersion {
|
||||
case "v2", "2", "2.0":
|
||||
return openstack.NewIdentityV2(pClient, eo)
|
||||
case "v3", "3":
|
||||
return openstack.NewIdentityV3(pClient, eo)
|
||||
default:
|
||||
return nil, fmt.Errorf("invalid identity API version")
|
||||
}
|
||||
case "image":
|
||||
return openstack.NewImageServiceV2(pClient, eo)
|
||||
case "load-balancer":
|
||||
return openstack.NewLoadBalancerV2(pClient, eo)
|
||||
case "network":
|
||||
return openstack.NewNetworkV2(pClient, eo)
|
||||
case "object-store":
|
||||
return openstack.NewObjectStorageV1(pClient, eo)
|
||||
case "orchestration":
|
||||
return openstack.NewOrchestrationV1(pClient, eo)
|
||||
case "sharev2":
|
||||
return openstack.NewSharedFileSystemV2(pClient, eo)
|
||||
case "volume":
|
||||
volumeVersion := "2"
|
||||
if v := cloud.VolumeAPIVersion; v != "" {
|
||||
volumeVersion = v
|
||||
}
|
||||
|
||||
switch volumeVersion {
|
||||
case "v1", "1":
|
||||
return openstack.NewBlockStorageV1(pClient, eo)
|
||||
case "v2", "2":
|
||||
return openstack.NewBlockStorageV2(pClient, eo)
|
||||
case "v3", "3":
|
||||
return openstack.NewBlockStorageV3(pClient, eo)
|
||||
default:
|
||||
return nil, fmt.Errorf("invalid volume API version")
|
||||
}
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("unable to create a service client for %s", service)
|
||||
}
|
||||
|
||||
// isProjectScoped determines if an auth struct is project scoped.
|
||||
func isProjectScoped(authInfo *AuthInfo) bool {
|
||||
if authInfo.ProjectID == "" && authInfo.ProjectName == "" {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// setDomainIfNeeded will set a DomainID and DomainName
|
||||
// to ProjectDomain* and UserDomain* if not already set.
|
||||
func setDomainIfNeeded(cloud *Cloud) *Cloud {
|
||||
if cloud.AuthInfo.DomainID != "" {
|
||||
if cloud.AuthInfo.UserDomainID == "" {
|
||||
cloud.AuthInfo.UserDomainID = cloud.AuthInfo.DomainID
|
||||
}
|
||||
|
||||
if cloud.AuthInfo.ProjectDomainID == "" {
|
||||
cloud.AuthInfo.ProjectDomainID = cloud.AuthInfo.DomainID
|
||||
}
|
||||
|
||||
cloud.AuthInfo.DomainID = ""
|
||||
}
|
||||
|
||||
if cloud.AuthInfo.DomainName != "" {
|
||||
if cloud.AuthInfo.UserDomainName == "" {
|
||||
cloud.AuthInfo.UserDomainName = cloud.AuthInfo.DomainName
|
||||
}
|
||||
|
||||
if cloud.AuthInfo.ProjectDomainName == "" {
|
||||
cloud.AuthInfo.ProjectDomainName = cloud.AuthInfo.DomainName
|
||||
}
|
||||
|
||||
cloud.AuthInfo.DomainName = ""
|
||||
}
|
||||
|
||||
// If Domain fields are still not set, and if DefaultDomain has a value,
|
||||
// set UserDomainID and ProjectDomainID to DefaultDomain.
|
||||
// https://github.com/openstack/osc-lib/blob/86129e6f88289ef14bfaa3f7c9cdfbea8d9fc944/osc_lib/cli/client_config.py#L117-L146
|
||||
if cloud.AuthInfo.DefaultDomain != "" {
|
||||
if cloud.AuthInfo.UserDomainName == "" && cloud.AuthInfo.UserDomainID == "" {
|
||||
cloud.AuthInfo.UserDomainID = cloud.AuthInfo.DefaultDomain
|
||||
}
|
||||
|
||||
if cloud.AuthInfo.ProjectDomainName == "" && cloud.AuthInfo.ProjectDomainID == "" {
|
||||
cloud.AuthInfo.ProjectDomainID = cloud.AuthInfo.DefaultDomain
|
||||
}
|
||||
}
|
||||
|
||||
return cloud
|
||||
}
|
88
vendor/github.com/gophercloud/utils/openstack/clientconfig/results.go
generated
vendored
Normal file
88
vendor/github.com/gophercloud/utils/openstack/clientconfig/results.go
generated
vendored
Normal file
@ -0,0 +1,88 @@
|
||||
package clientconfig
|
||||
|
||||
// Clouds represents a collection of Cloud entries in a clouds.yaml file.
|
||||
// The format of clouds.yaml is documented at
|
||||
// https://docs.openstack.org/os-client-config/latest/user/configuration.html.
|
||||
type Clouds struct {
|
||||
Clouds map[string]Cloud `yaml:"clouds"`
|
||||
}
|
||||
|
||||
// Cloud represents an entry in a clouds.yaml file.
|
||||
type Cloud struct {
|
||||
AuthInfo *AuthInfo `yaml:"auth"`
|
||||
AuthType AuthType `yaml:"auth_type"`
|
||||
RegionName string `yaml:"region_name"`
|
||||
Regions []interface{} `yaml:"regions"`
|
||||
|
||||
// API Version overrides.
|
||||
IdentityAPIVersion string `yaml:"identity_api_version"`
|
||||
VolumeAPIVersion string `yaml:"volume_api_version"`
|
||||
}
|
||||
|
||||
// Auth represents the auth section of a cloud entry or
|
||||
// auth options entered explicitly in ClientOpts.
|
||||
type AuthInfo struct {
|
||||
// AuthURL is the keystone/identity endpoint URL.
|
||||
AuthURL string `yaml:"auth_url"`
|
||||
|
||||
// Token is a pre-generated authentication token.
|
||||
Token string `yaml:"token"`
|
||||
|
||||
// Username is the username of the user.
|
||||
Username string `yaml:"username"`
|
||||
|
||||
// UserID is the unique ID of a user.
|
||||
UserID string `yaml:"user_id"`
|
||||
|
||||
// Password is the password of the user.
|
||||
Password string `yaml:"password"`
|
||||
|
||||
// ProjectName is the common/human-readable name of a project.
|
||||
// Users can be scoped to a project.
|
||||
// ProjectName on its own is not enough to ensure a unique scope. It must
|
||||
// also be combined with either a ProjectDomainName or ProjectDomainID.
|
||||
// ProjectName cannot be combined with ProjectID in a scope.
|
||||
ProjectName string `yaml:"project_name"`
|
||||
|
||||
// ProjectID is the unique ID of a project.
|
||||
// It can be used to scope a user to a specific project.
|
||||
ProjectID string `yaml:"project_id"`
|
||||
|
||||
// UserDomainName is the name of the domain where a user resides.
|
||||
// It is used to identify the source domain of a user.
|
||||
UserDomainName string `yaml:"user_domain_name"`
|
||||
|
||||
// UserDomainID is the unique ID of the domain where a user resides.
|
||||
// It is used to identify the source domain of a user.
|
||||
UserDomainID string `yaml:"user_domain_id"`
|
||||
|
||||
// ProjectDomainName is the name of the domain where a project resides.
|
||||
// It is used to identify the source domain of a project.
|
||||
// ProjectDomainName can be used in addition to a ProjectName when scoping
|
||||
// a user to a specific project.
|
||||
ProjectDomainName string `yaml:"project_domain_name"`
|
||||
|
||||
// ProjectDomainID is the name of the domain where a project resides.
|
||||
// It is used to identify the source domain of a project.
|
||||
// ProjectDomainID can be used in addition to a ProjectName when scoping
|
||||
// a user to a specific project.
|
||||
ProjectDomainID string `yaml:"project_domain_id"`
|
||||
|
||||
// DomainName is the name of a domain which can be used to identify the
|
||||
// source domain of either a user or a project.
|
||||
// If UserDomainName and ProjectDomainName are not specified, then DomainName
|
||||
// is used as a default choice.
|
||||
// It can also be used be used to specify a domain-only scope.
|
||||
DomainName string `yaml:"domain_name"`
|
||||
|
||||
// DomainID is the unique ID of a domain which can be used to identify the
|
||||
// source domain of eitehr a user or a project.
|
||||
// If UserDomainID and ProjectDomainID are not specified, then DomainID is
|
||||
// used as a default choice.
|
||||
// It can also be used be used to specify a domain-only scope.
|
||||
DomainID string `yaml:"domain_id"`
|
||||
|
||||
// DefaultDomain is the domain ID to fall back on if no other domain has
|
||||
// been specified and a domain is required for scope.
|
||||
DefaultDomain string `yaml:"default_domain"`
|
||||
}
|
67
vendor/github.com/gophercloud/utils/openstack/clientconfig/utils.go
generated
vendored
Normal file
67
vendor/github.com/gophercloud/utils/openstack/clientconfig/utils.go
generated
vendored
Normal file
@ -0,0 +1,67 @@
|
||||
package clientconfig
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/user"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
// findAndLoadYAML attempts to locate a clouds.yaml file in the following
|
||||
// locations:
|
||||
//
|
||||
// 1. OS_CLIENT_CONFIG_FILE
|
||||
// 2. Current directory.
|
||||
// 3. unix-specific user_config_dir (~/.config/openstack/clouds.yaml)
|
||||
// 4. unix-specific site_config_dir (/etc/openstack/clouds.yaml)
|
||||
//
|
||||
// If found, the contents of the file is returned.
|
||||
func findAndReadYAML() ([]byte, error) {
|
||||
// OS_CLIENT_CONFIG_FILE
|
||||
if v := os.Getenv("OS_CLIENT_CONFIG_FILE"); v != "" {
|
||||
if ok := fileExists(v); ok {
|
||||
return ioutil.ReadFile(v)
|
||||
}
|
||||
}
|
||||
|
||||
// current directory
|
||||
cwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to determine working directory: %s", err)
|
||||
}
|
||||
|
||||
filename := filepath.Join(cwd, "clouds.yaml")
|
||||
if ok := fileExists(filename); ok {
|
||||
return ioutil.ReadFile(filename)
|
||||
}
|
||||
|
||||
// unix user config directory: ~/.config/openstack.
|
||||
currentUser, err := user.Current()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to get current user: %s", err)
|
||||
}
|
||||
|
||||
homeDir := currentUser.HomeDir
|
||||
if homeDir != "" {
|
||||
filename := filepath.Join(homeDir, ".config/openstack/clouds.yaml")
|
||||
if ok := fileExists(filename); ok {
|
||||
return ioutil.ReadFile(filename)
|
||||
}
|
||||
}
|
||||
|
||||
// unix-specific site config directory: /etc/openstack.
|
||||
if ok := fileExists("/etc/openstack/clouds.yaml"); ok {
|
||||
return ioutil.ReadFile("/etc/openstack/clouds.yaml")
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("no clouds.yaml file found")
|
||||
}
|
||||
|
||||
// fileExists checks for the existence of a file at a given location.
|
||||
func fileExists(filename string) bool {
|
||||
if _, err := os.Stat(filename); err == nil {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
201
vendor/gopkg.in/yaml.v2/LICENSE
generated
vendored
Normal file
201
vendor/gopkg.in/yaml.v2/LICENSE
generated
vendored
Normal file
@ -0,0 +1,201 @@
|
||||
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 {yyyy} {name of copyright owner}
|
||||
|
||||
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.
|
31
vendor/gopkg.in/yaml.v2/LICENSE.libyaml
generated
vendored
Normal file
31
vendor/gopkg.in/yaml.v2/LICENSE.libyaml
generated
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
The following files were ported to Go from C files of libyaml, and thus
|
||||
are still covered by their original copyright and license:
|
||||
|
||||
apic.go
|
||||
emitterc.go
|
||||
parserc.go
|
||||
readerc.go
|
||||
scannerc.go
|
||||
writerc.go
|
||||
yamlh.go
|
||||
yamlprivateh.go
|
||||
|
||||
Copyright (c) 2006 Kirill Simonov
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
13
vendor/gopkg.in/yaml.v2/NOTICE
generated
vendored
Normal file
13
vendor/gopkg.in/yaml.v2/NOTICE
generated
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
Copyright 2011-2016 Canonical Ltd.
|
||||
|
||||
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.
|
133
vendor/gopkg.in/yaml.v2/README.md
generated
vendored
Normal file
133
vendor/gopkg.in/yaml.v2/README.md
generated
vendored
Normal file
@ -0,0 +1,133 @@
|
||||
# YAML support for the Go language
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
The yaml package enables Go programs to comfortably encode and decode YAML
|
||||
values. It was developed within [Canonical](https://www.canonical.com) as
|
||||
part of the [juju](https://juju.ubuntu.com) project, and is based on a
|
||||
pure Go port of the well-known [libyaml](http://pyyaml.org/wiki/LibYAML)
|
||||
C library to parse and generate YAML data quickly and reliably.
|
||||
|
||||
Compatibility
|
||||
-------------
|
||||
|
||||
The yaml package supports most of YAML 1.1 and 1.2, including support for
|
||||
anchors, tags, map merging, etc. Multi-document unmarshalling is not yet
|
||||
implemented, and base-60 floats from YAML 1.1 are purposefully not
|
||||
supported since they're a poor design and are gone in YAML 1.2.
|
||||
|
||||
Installation and usage
|
||||
----------------------
|
||||
|
||||
The import path for the package is *gopkg.in/yaml.v2*.
|
||||
|
||||
To install it, run:
|
||||
|
||||
go get gopkg.in/yaml.v2
|
||||
|
||||
API documentation
|
||||
-----------------
|
||||
|
||||
If opened in a browser, the import path itself leads to the API documentation:
|
||||
|
||||
* [https://gopkg.in/yaml.v2](https://gopkg.in/yaml.v2)
|
||||
|
||||
API stability
|
||||
-------------
|
||||
|
||||
The package API for yaml v2 will remain stable as described in [gopkg.in](https://gopkg.in).
|
||||
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
The yaml package is licensed under the Apache License 2.0. Please see the LICENSE file for details.
|
||||
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
```Go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
var data = `
|
||||
a: Easy!
|
||||
b:
|
||||
c: 2
|
||||
d: [3, 4]
|
||||
`
|
||||
|
||||
// Note: struct fields must be public in order for unmarshal to
|
||||
// correctly populate the data.
|
||||
type T struct {
|
||||
A string
|
||||
B struct {
|
||||
RenamedC int `yaml:"c"`
|
||||
D []int `yaml:",flow"`
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
t := T{}
|
||||
|
||||
err := yaml.Unmarshal([]byte(data), &t)
|
||||
if err != nil {
|
||||
log.Fatalf("error: %v", err)
|
||||
}
|
||||
fmt.Printf("--- t:\n%v\n\n", t)
|
||||
|
||||
d, err := yaml.Marshal(&t)
|
||||
if err != nil {
|
||||
log.Fatalf("error: %v", err)
|
||||
}
|
||||
fmt.Printf("--- t dump:\n%s\n\n", string(d))
|
||||
|
||||
m := make(map[interface{}]interface{})
|
||||
|
||||
err = yaml.Unmarshal([]byte(data), &m)
|
||||
if err != nil {
|
||||
log.Fatalf("error: %v", err)
|
||||
}
|
||||
fmt.Printf("--- m:\n%v\n\n", m)
|
||||
|
||||
d, err = yaml.Marshal(&m)
|
||||
if err != nil {
|
||||
log.Fatalf("error: %v", err)
|
||||
}
|
||||
fmt.Printf("--- m dump:\n%s\n\n", string(d))
|
||||
}
|
||||
```
|
||||
|
||||
This example will generate the following output:
|
||||
|
||||
```
|
||||
--- t:
|
||||
{Easy! {2 [3 4]}}
|
||||
|
||||
--- t dump:
|
||||
a: Easy!
|
||||
b:
|
||||
c: 2
|
||||
d: [3, 4]
|
||||
|
||||
|
||||
--- m:
|
||||
map[a:Easy! b:map[c:2 d:[3 4]]]
|
||||
|
||||
--- m dump:
|
||||
a: Easy!
|
||||
b:
|
||||
c: 2
|
||||
d:
|
||||
- 3
|
||||
- 4
|
||||
```
|
||||
|
739
vendor/gopkg.in/yaml.v2/apic.go
generated
vendored
Normal file
739
vendor/gopkg.in/yaml.v2/apic.go
generated
vendored
Normal file
@ -0,0 +1,739 @@
|
||||
package yaml
|
||||
|
||||
import (
|
||||
"io"
|
||||
)
|
||||
|
||||
func yaml_insert_token(parser *yaml_parser_t, pos int, token *yaml_token_t) {
|
||||
//fmt.Println("yaml_insert_token", "pos:", pos, "typ:", token.typ, "head:", parser.tokens_head, "len:", len(parser.tokens))
|
||||
|
||||
// Check if we can move the queue at the beginning of the buffer.
|
||||
if parser.tokens_head > 0 && len(parser.tokens) == cap(parser.tokens) {
|
||||
if parser.tokens_head != len(parser.tokens) {
|
||||
copy(parser.tokens, parser.tokens[parser.tokens_head:])
|
||||
}
|
||||
parser.tokens = parser.tokens[:len(parser.tokens)-parser.tokens_head]
|
||||
parser.tokens_head = 0
|
||||
}
|
||||
parser.tokens = append(parser.tokens, *token)
|
||||
if pos < 0 {
|
||||
return
|
||||
}
|
||||
copy(parser.tokens[parser.tokens_head+pos+1:], parser.tokens[parser.tokens_head+pos:])
|
||||
parser.tokens[parser.tokens_head+pos] = *token
|
||||
}
|
||||
|
||||
// Create a new parser object.
|
||||
func yaml_parser_initialize(parser *yaml_parser_t) bool {
|
||||
*parser = yaml_parser_t{
|
||||
raw_buffer: make([]byte, 0, input_raw_buffer_size),
|
||||
buffer: make([]byte, 0, input_buffer_size),
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Destroy a parser object.
|
||||
func yaml_parser_delete(parser *yaml_parser_t) {
|
||||
*parser = yaml_parser_t{}
|
||||
}
|
||||
|
||||
// String read handler.
|
||||
func yaml_string_read_handler(parser *yaml_parser_t, buffer []byte) (n int, err error) {
|
||||
if parser.input_pos == len(parser.input) {
|
||||
return 0, io.EOF
|
||||
}
|
||||
n = copy(buffer, parser.input[parser.input_pos:])
|
||||
parser.input_pos += n
|
||||
return n, nil
|
||||
}
|
||||
|
||||
// Reader read handler.
|
||||
func yaml_reader_read_handler(parser *yaml_parser_t, buffer []byte) (n int, err error) {
|
||||
return parser.input_reader.Read(buffer)
|
||||
}
|
||||
|
||||
// Set a string input.
|
||||
func yaml_parser_set_input_string(parser *yaml_parser_t, input []byte) {
|
||||
if parser.read_handler != nil {
|
||||
panic("must set the input source only once")
|
||||
}
|
||||
parser.read_handler = yaml_string_read_handler
|
||||
parser.input = input
|
||||
parser.input_pos = 0
|
||||
}
|
||||
|
||||
// Set a file input.
|
||||
func yaml_parser_set_input_reader(parser *yaml_parser_t, r io.Reader) {
|
||||
if parser.read_handler != nil {
|
||||
panic("must set the input source only once")
|
||||
}
|
||||
parser.read_handler = yaml_reader_read_handler
|
||||
parser.input_reader = r
|
||||
}
|
||||
|
||||
// Set the source encoding.
|
||||
func yaml_parser_set_encoding(parser *yaml_parser_t, encoding yaml_encoding_t) {
|
||||
if parser.encoding != yaml_ANY_ENCODING {
|
||||
panic("must set the encoding only once")
|
||||
}
|
||||
parser.encoding = encoding
|
||||
}
|
||||
|
||||
// Create a new emitter object.
|
||||
func yaml_emitter_initialize(emitter *yaml_emitter_t) {
|
||||
*emitter = yaml_emitter_t{
|
||||
buffer: make([]byte, output_buffer_size),
|
||||
raw_buffer: make([]byte, 0, output_raw_buffer_size),
|
||||
states: make([]yaml_emitter_state_t, 0, initial_stack_size),
|
||||
events: make([]yaml_event_t, 0, initial_queue_size),
|
||||
}
|
||||
}
|
||||
|
||||
// Destroy an emitter object.
|
||||
func yaml_emitter_delete(emitter *yaml_emitter_t) {
|
||||
*emitter = yaml_emitter_t{}
|
||||
}
|
||||
|
||||
// String write handler.
|
||||
func yaml_string_write_handler(emitter *yaml_emitter_t, buffer []byte) error {
|
||||
*emitter.output_buffer = append(*emitter.output_buffer, buffer...)
|
||||
return nil
|
||||
}
|
||||
|
||||
// yaml_writer_write_handler uses emitter.output_writer to write the
|
||||
// emitted text.
|
||||
func yaml_writer_write_handler(emitter *yaml_emitter_t, buffer []byte) error {
|
||||
_, err := emitter.output_writer.Write(buffer)
|
||||
return err
|
||||
}
|
||||
|
||||
// Set a string output.
|
||||
func yaml_emitter_set_output_string(emitter *yaml_emitter_t, output_buffer *[]byte) {
|
||||
if emitter.write_handler != nil {
|
||||
panic("must set the output target only once")
|
||||
}
|
||||
emitter.write_handler = yaml_string_write_handler
|
||||
emitter.output_buffer = output_buffer
|
||||
}
|
||||
|
||||
// Set a file output.
|
||||
func yaml_emitter_set_output_writer(emitter *yaml_emitter_t, w io.Writer) {
|
||||
if emitter.write_handler != nil {
|
||||
panic("must set the output target only once")
|
||||
}
|
||||
emitter.write_handler = yaml_writer_write_handler
|
||||
emitter.output_writer = w
|
||||
}
|
||||
|
||||
// Set the output encoding.
|
||||
func yaml_emitter_set_encoding(emitter *yaml_emitter_t, encoding yaml_encoding_t) {
|
||||
if emitter.encoding != yaml_ANY_ENCODING {
|
||||
panic("must set the output encoding only once")
|
||||
}
|
||||
emitter.encoding = encoding
|
||||
}
|
||||
|
||||
// Set the canonical output style.
|
||||
func yaml_emitter_set_canonical(emitter *yaml_emitter_t, canonical bool) {
|
||||
emitter.canonical = canonical
|
||||
}
|
||||
|
||||
//// Set the indentation increment.
|
||||
func yaml_emitter_set_indent(emitter *yaml_emitter_t, indent int) {
|
||||
if indent < 2 || indent > 9 {
|
||||
indent = 2
|
||||
}
|
||||
emitter.best_indent = indent
|
||||
}
|
||||
|
||||
// Set the preferred line width.
|
||||
func yaml_emitter_set_width(emitter *yaml_emitter_t, width int) {
|
||||
if width < 0 {
|
||||
width = -1
|
||||
}
|
||||
emitter.best_width = width
|
||||
}
|
||||
|
||||
// Set if unescaped non-ASCII characters are allowed.
|
||||
func yaml_emitter_set_unicode(emitter *yaml_emitter_t, unicode bool) {
|
||||
emitter.unicode = unicode
|
||||
}
|
||||
|
||||
// Set the preferred line break character.
|
||||
func yaml_emitter_set_break(emitter *yaml_emitter_t, line_break yaml_break_t) {
|
||||
emitter.line_break = line_break
|
||||
}
|
||||
|
||||
///*
|
||||
// * Destroy a token object.
|
||||
// */
|
||||
//
|
||||
//YAML_DECLARE(void)
|
||||
//yaml_token_delete(yaml_token_t *token)
|
||||
//{
|
||||
// assert(token); // Non-NULL token object expected.
|
||||
//
|
||||
// switch (token.type)
|
||||
// {
|
||||
// case YAML_TAG_DIRECTIVE_TOKEN:
|
||||
// yaml_free(token.data.tag_directive.handle);
|
||||
// yaml_free(token.data.tag_directive.prefix);
|
||||
// break;
|
||||
//
|
||||
// case YAML_ALIAS_TOKEN:
|
||||
// yaml_free(token.data.alias.value);
|
||||
// break;
|
||||
//
|
||||
// case YAML_ANCHOR_TOKEN:
|
||||
// yaml_free(token.data.anchor.value);
|
||||
// break;
|
||||
//
|
||||
// case YAML_TAG_TOKEN:
|
||||
// yaml_free(token.data.tag.handle);
|
||||
// yaml_free(token.data.tag.suffix);
|
||||
// break;
|
||||
//
|
||||
// case YAML_SCALAR_TOKEN:
|
||||
// yaml_free(token.data.scalar.value);
|
||||
// break;
|
||||
//
|
||||
// default:
|
||||
// break;
|
||||
// }
|
||||
//
|
||||
// memset(token, 0, sizeof(yaml_token_t));
|
||||
//}
|
||||
//
|
||||
///*
|
||||
// * Check if a string is a valid UTF-8 sequence.
|
||||
// *
|
||||
// * Check 'reader.c' for more details on UTF-8 encoding.
|
||||
// */
|
||||
//
|
||||
//static int
|
||||
//yaml_check_utf8(yaml_char_t *start, size_t length)
|
||||
//{
|
||||
// yaml_char_t *end = start+length;
|
||||
// yaml_char_t *pointer = start;
|
||||
//
|
||||
// while (pointer < end) {
|
||||
// unsigned char octet;
|
||||
// unsigned int width;
|
||||
// unsigned int value;
|
||||
// size_t k;
|
||||
//
|
||||
// octet = pointer[0];
|
||||
// width = (octet & 0x80) == 0x00 ? 1 :
|
||||
// (octet & 0xE0) == 0xC0 ? 2 :
|
||||
// (octet & 0xF0) == 0xE0 ? 3 :
|
||||
// (octet & 0xF8) == 0xF0 ? 4 : 0;
|
||||
// value = (octet & 0x80) == 0x00 ? octet & 0x7F :
|
||||
// (octet & 0xE0) == 0xC0 ? octet & 0x1F :
|
||||
// (octet & 0xF0) == 0xE0 ? octet & 0x0F :
|
||||
// (octet & 0xF8) == 0xF0 ? octet & 0x07 : 0;
|
||||
// if (!width) return 0;
|
||||
// if (pointer+width > end) return 0;
|
||||
// for (k = 1; k < width; k ++) {
|
||||
// octet = pointer[k];
|
||||
// if ((octet & 0xC0) != 0x80) return 0;
|
||||
// value = (value << 6) + (octet & 0x3F);
|
||||
// }
|
||||
// if (!((width == 1) ||
|
||||
// (width == 2 && value >= 0x80) ||
|
||||
// (width == 3 && value >= 0x800) ||
|
||||
// (width == 4 && value >= 0x10000))) return 0;
|
||||
//
|
||||
// pointer += width;
|
||||
// }
|
||||
//
|
||||
// return 1;
|
||||
//}
|
||||
//
|
||||
|
||||
// Create STREAM-START.
|
||||
func yaml_stream_start_event_initialize(event *yaml_event_t, encoding yaml_encoding_t) {
|
||||
*event = yaml_event_t{
|
||||
typ: yaml_STREAM_START_EVENT,
|
||||
encoding: encoding,
|
||||
}
|
||||
}
|
||||
|
||||
// Create STREAM-END.
|
||||
func yaml_stream_end_event_initialize(event *yaml_event_t) {
|
||||
*event = yaml_event_t{
|
||||
typ: yaml_STREAM_END_EVENT,
|
||||
}
|
||||
}
|
||||
|
||||
// Create DOCUMENT-START.
|
||||
func yaml_document_start_event_initialize(
|
||||
event *yaml_event_t,
|
||||
version_directive *yaml_version_directive_t,
|
||||
tag_directives []yaml_tag_directive_t,
|
||||
implicit bool,
|
||||
) {
|
||||
*event = yaml_event_t{
|
||||
typ: yaml_DOCUMENT_START_EVENT,
|
||||
version_directive: version_directive,
|
||||
tag_directives: tag_directives,
|
||||
implicit: implicit,
|
||||
}
|
||||
}
|
||||
|
||||
// Create DOCUMENT-END.
|
||||
func yaml_document_end_event_initialize(event *yaml_event_t, implicit bool) {
|
||||
*event = yaml_event_t{
|
||||
typ: yaml_DOCUMENT_END_EVENT,
|
||||
implicit: implicit,
|
||||
}
|
||||
}
|
||||
|
||||
///*
|
||||
// * Create ALIAS.
|
||||
// */
|
||||
//
|
||||
//YAML_DECLARE(int)
|
||||
//yaml_alias_event_initialize(event *yaml_event_t, anchor *yaml_char_t)
|
||||
//{
|
||||
// mark yaml_mark_t = { 0, 0, 0 }
|
||||
// anchor_copy *yaml_char_t = NULL
|
||||
//
|
||||
// assert(event) // Non-NULL event object is expected.
|
||||
// assert(anchor) // Non-NULL anchor is expected.
|
||||
//
|
||||
// if (!yaml_check_utf8(anchor, strlen((char *)anchor))) return 0
|
||||
//
|
||||
// anchor_copy = yaml_strdup(anchor)
|
||||
// if (!anchor_copy)
|
||||
// return 0
|
||||
//
|
||||
// ALIAS_EVENT_INIT(*event, anchor_copy, mark, mark)
|
||||
//
|
||||
// return 1
|
||||
//}
|
||||
|
||||
// Create SCALAR.
|
||||
func yaml_scalar_event_initialize(event *yaml_event_t, anchor, tag, value []byte, plain_implicit, quoted_implicit bool, style yaml_scalar_style_t) bool {
|
||||
*event = yaml_event_t{
|
||||
typ: yaml_SCALAR_EVENT,
|
||||
anchor: anchor,
|
||||
tag: tag,
|
||||
value: value,
|
||||
implicit: plain_implicit,
|
||||
quoted_implicit: quoted_implicit,
|
||||
style: yaml_style_t(style),
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Create SEQUENCE-START.
|
||||
func yaml_sequence_start_event_initialize(event *yaml_event_t, anchor, tag []byte, implicit bool, style yaml_sequence_style_t) bool {
|
||||
*event = yaml_event_t{
|
||||
typ: yaml_SEQUENCE_START_EVENT,
|
||||
anchor: anchor,
|
||||
tag: tag,
|
||||
implicit: implicit,
|
||||
style: yaml_style_t(style),
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Create SEQUENCE-END.
|
||||
func yaml_sequence_end_event_initialize(event *yaml_event_t) bool {
|
||||
*event = yaml_event_t{
|
||||
typ: yaml_SEQUENCE_END_EVENT,
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Create MAPPING-START.
|
||||
func yaml_mapping_start_event_initialize(event *yaml_event_t, anchor, tag []byte, implicit bool, style yaml_mapping_style_t) {
|
||||
*event = yaml_event_t{
|
||||
typ: yaml_MAPPING_START_EVENT,
|
||||
anchor: anchor,
|
||||
tag: tag,
|
||||
implicit: implicit,
|
||||
style: yaml_style_t(style),
|
||||
}
|
||||
}
|
||||
|
||||
// Create MAPPING-END.
|
||||
func yaml_mapping_end_event_initialize(event *yaml_event_t) {
|
||||
*event = yaml_event_t{
|
||||
typ: yaml_MAPPING_END_EVENT,
|
||||
}
|
||||
}
|
||||
|
||||
// Destroy an event object.
|
||||
func yaml_event_delete(event *yaml_event_t) {
|
||||
*event = yaml_event_t{}
|
||||
}
|
||||
|
||||
///*
|
||||
// * Create a document object.
|
||||
// */
|
||||
//
|
||||
//YAML_DECLARE(int)
|
||||
//yaml_document_initialize(document *yaml_document_t,
|
||||
// version_directive *yaml_version_directive_t,
|
||||
// tag_directives_start *yaml_tag_directive_t,
|
||||
// tag_directives_end *yaml_tag_directive_t,
|
||||
// start_implicit int, end_implicit int)
|
||||
//{
|
||||
// struct {
|
||||
// error yaml_error_type_t
|
||||
// } context
|
||||
// struct {
|
||||
// start *yaml_node_t
|
||||
// end *yaml_node_t
|
||||
// top *yaml_node_t
|
||||
// } nodes = { NULL, NULL, NULL }
|
||||
// version_directive_copy *yaml_version_directive_t = NULL
|
||||
// struct {
|
||||
// start *yaml_tag_directive_t
|
||||
// end *yaml_tag_directive_t
|
||||
// top *yaml_tag_directive_t
|
||||
// } tag_directives_copy = { NULL, NULL, NULL }
|
||||
// value yaml_tag_directive_t = { NULL, NULL }
|
||||
// mark yaml_mark_t = { 0, 0, 0 }
|
||||
//
|
||||
// assert(document) // Non-NULL document object is expected.
|
||||
// assert((tag_directives_start && tag_directives_end) ||
|
||||
// (tag_directives_start == tag_directives_end))
|
||||
// // Valid tag directives are expected.
|
||||
//
|
||||
// if (!STACK_INIT(&context, nodes, INITIAL_STACK_SIZE)) goto error
|
||||
//
|
||||
// if (version_directive) {
|
||||
// version_directive_copy = yaml_malloc(sizeof(yaml_version_directive_t))
|
||||
// if (!version_directive_copy) goto error
|
||||
// version_directive_copy.major = version_directive.major
|
||||
// version_directive_copy.minor = version_directive.minor
|
||||
// }
|
||||
//
|
||||
// if (tag_directives_start != tag_directives_end) {
|
||||
// tag_directive *yaml_tag_directive_t
|
||||
// if (!STACK_INIT(&context, tag_directives_copy, INITIAL_STACK_SIZE))
|
||||
// goto error
|
||||
// for (tag_directive = tag_directives_start
|
||||
// tag_directive != tag_directives_end; tag_directive ++) {
|
||||
// assert(tag_directive.handle)
|
||||
// assert(tag_directive.prefix)
|
||||
// if (!yaml_check_utf8(tag_directive.handle,
|
||||
// strlen((char *)tag_directive.handle)))
|
||||
// goto error
|
||||
// if (!yaml_check_utf8(tag_directive.prefix,
|
||||
// strlen((char *)tag_directive.prefix)))
|
||||
// goto error
|
||||
// value.handle = yaml_strdup(tag_directive.handle)
|
||||
// value.prefix = yaml_strdup(tag_directive.prefix)
|
||||
// if (!value.handle || !value.prefix) goto error
|
||||
// if (!PUSH(&context, tag_directives_copy, value))
|
||||
// goto error
|
||||
// value.handle = NULL
|
||||
// value.prefix = NULL
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// DOCUMENT_INIT(*document, nodes.start, nodes.end, version_directive_copy,
|
||||
// tag_directives_copy.start, tag_directives_copy.top,
|
||||
// start_implicit, end_implicit, mark, mark)
|
||||
//
|
||||
// return 1
|
||||
//
|
||||
//error:
|
||||
// STACK_DEL(&context, nodes)
|
||||
// yaml_free(version_directive_copy)
|
||||
// while (!STACK_EMPTY(&context, tag_directives_copy)) {
|
||||
// value yaml_tag_directive_t = POP(&context, tag_directives_copy)
|
||||
// yaml_free(value.handle)
|
||||
// yaml_free(value.prefix)
|
||||
// }
|
||||
// STACK_DEL(&context, tag_directives_copy)
|
||||
// yaml_free(value.handle)
|
||||
// yaml_free(value.prefix)
|
||||
//
|
||||
// return 0
|
||||
//}
|
||||
//
|
||||
///*
|
||||
// * Destroy a document object.
|
||||
// */
|
||||
//
|
||||
//YAML_DECLARE(void)
|
||||
//yaml_document_delete(document *yaml_document_t)
|
||||
//{
|
||||
// struct {
|
||||
// error yaml_error_type_t
|
||||
// } context
|
||||
// tag_directive *yaml_tag_directive_t
|
||||
//
|
||||
// context.error = YAML_NO_ERROR // Eliminate a compiler warning.
|
||||
//
|
||||
// assert(document) // Non-NULL document object is expected.
|
||||
//
|
||||
// while (!STACK_EMPTY(&context, document.nodes)) {
|
||||
// node yaml_node_t = POP(&context, document.nodes)
|
||||
// yaml_free(node.tag)
|
||||
// switch (node.type) {
|
||||
// case YAML_SCALAR_NODE:
|
||||
// yaml_free(node.data.scalar.value)
|
||||
// break
|
||||
// case YAML_SEQUENCE_NODE:
|
||||
// STACK_DEL(&context, node.data.sequence.items)
|
||||
// break
|
||||
// case YAML_MAPPING_NODE:
|
||||
// STACK_DEL(&context, node.data.mapping.pairs)
|
||||
// break
|
||||
// default:
|
||||
// assert(0) // Should not happen.
|
||||
// }
|
||||
// }
|
||||
// STACK_DEL(&context, document.nodes)
|
||||
//
|
||||
// yaml_free(document.version_directive)
|
||||
// for (tag_directive = document.tag_directives.start
|
||||
// tag_directive != document.tag_directives.end
|
||||
// tag_directive++) {
|
||||
// yaml_free(tag_directive.handle)
|
||||
// yaml_free(tag_directive.prefix)
|
||||
// }
|
||||
// yaml_free(document.tag_directives.start)
|
||||
//
|
||||
// memset(document, 0, sizeof(yaml_document_t))
|
||||
//}
|
||||
//
|
||||
///**
|
||||
// * Get a document node.
|
||||
// */
|
||||
//
|
||||
//YAML_DECLARE(yaml_node_t *)
|
||||
//yaml_document_get_node(document *yaml_document_t, index int)
|
||||
//{
|
||||
// assert(document) // Non-NULL document object is expected.
|
||||
//
|
||||
// if (index > 0 && document.nodes.start + index <= document.nodes.top) {
|
||||
// return document.nodes.start + index - 1
|
||||
// }
|
||||
// return NULL
|
||||
//}
|
||||
//
|
||||
///**
|
||||
// * Get the root object.
|
||||
// */
|
||||
//
|
||||
//YAML_DECLARE(yaml_node_t *)
|
||||
//yaml_document_get_root_node(document *yaml_document_t)
|
||||
//{
|
||||
// assert(document) // Non-NULL document object is expected.
|
||||
//
|
||||
// if (document.nodes.top != document.nodes.start) {
|
||||
// return document.nodes.start
|
||||
// }
|
||||
// return NULL
|
||||
//}
|
||||
//
|
||||
///*
|
||||
// * Add a scalar node to a document.
|
||||
// */
|
||||
//
|
||||
//YAML_DECLARE(int)
|
||||
//yaml_document_add_scalar(document *yaml_document_t,
|
||||
// tag *yaml_char_t, value *yaml_char_t, length int,
|
||||
// style yaml_scalar_style_t)
|
||||
//{
|
||||
// struct {
|
||||
// error yaml_error_type_t
|
||||
// } context
|
||||
// mark yaml_mark_t = { 0, 0, 0 }
|
||||
// tag_copy *yaml_char_t = NULL
|
||||
// value_copy *yaml_char_t = NULL
|
||||
// node yaml_node_t
|
||||
//
|
||||
// assert(document) // Non-NULL document object is expected.
|
||||
// assert(value) // Non-NULL value is expected.
|
||||
//
|
||||
// if (!tag) {
|
||||
// tag = (yaml_char_t *)YAML_DEFAULT_SCALAR_TAG
|
||||
// }
|
||||
//
|
||||
// if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error
|
||||
// tag_copy = yaml_strdup(tag)
|
||||
// if (!tag_copy) goto error
|
||||
//
|
||||
// if (length < 0) {
|
||||
// length = strlen((char *)value)
|
||||
// }
|
||||
//
|
||||
// if (!yaml_check_utf8(value, length)) goto error
|
||||
// value_copy = yaml_malloc(length+1)
|
||||
// if (!value_copy) goto error
|
||||
// memcpy(value_copy, value, length)
|
||||
// value_copy[length] = '\0'
|
||||
//
|
||||
// SCALAR_NODE_INIT(node, tag_copy, value_copy, length, style, mark, mark)
|
||||
// if (!PUSH(&context, document.nodes, node)) goto error
|
||||
//
|
||||
// return document.nodes.top - document.nodes.start
|
||||
//
|
||||
//error:
|
||||
// yaml_free(tag_copy)
|
||||
// yaml_free(value_copy)
|
||||
//
|
||||
// return 0
|
||||
//}
|
||||
//
|
||||
///*
|
||||
// * Add a sequence node to a document.
|
||||
// */
|
||||
//
|
||||
//YAML_DECLARE(int)
|
||||
//yaml_document_add_sequence(document *yaml_document_t,
|
||||
// tag *yaml_char_t, style yaml_sequence_style_t)
|
||||
//{
|
||||
// struct {
|
||||
// error yaml_error_type_t
|
||||
// } context
|
||||
// mark yaml_mark_t = { 0, 0, 0 }
|
||||
// tag_copy *yaml_char_t = NULL
|
||||
// struct {
|
||||
// start *yaml_node_item_t
|
||||
// end *yaml_node_item_t
|
||||
// top *yaml_node_item_t
|
||||
// } items = { NULL, NULL, NULL }
|
||||
// node yaml_node_t
|
||||
//
|
||||
// assert(document) // Non-NULL document object is expected.
|
||||
//
|
||||
// if (!tag) {
|
||||
// tag = (yaml_char_t *)YAML_DEFAULT_SEQUENCE_TAG
|
||||
// }
|
||||
//
|
||||
// if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error
|
||||
// tag_copy = yaml_strdup(tag)
|
||||
// if (!tag_copy) goto error
|
||||
//
|
||||
// if (!STACK_INIT(&context, items, INITIAL_STACK_SIZE)) goto error
|
||||
//
|
||||
// SEQUENCE_NODE_INIT(node, tag_copy, items.start, items.end,
|
||||
// style, mark, mark)
|
||||
// if (!PUSH(&context, document.nodes, node)) goto error
|
||||
//
|
||||
// return document.nodes.top - document.nodes.start
|
||||
//
|
||||
//error:
|
||||
// STACK_DEL(&context, items)
|
||||
// yaml_free(tag_copy)
|
||||
//
|
||||
// return 0
|
||||
//}
|
||||
//
|
||||
///*
|
||||
// * Add a mapping node to a document.
|
||||
// */
|
||||
//
|
||||
//YAML_DECLARE(int)
|
||||
//yaml_document_add_mapping(document *yaml_document_t,
|
||||
// tag *yaml_char_t, style yaml_mapping_style_t)
|
||||
//{
|
||||
// struct {
|
||||
// error yaml_error_type_t
|
||||
// } context
|
||||
// mark yaml_mark_t = { 0, 0, 0 }
|
||||
// tag_copy *yaml_char_t = NULL
|
||||
// struct {
|
||||
// start *yaml_node_pair_t
|
||||
// end *yaml_node_pair_t
|
||||
// top *yaml_node_pair_t
|
||||
// } pairs = { NULL, NULL, NULL }
|
||||
// node yaml_node_t
|
||||
//
|
||||
// assert(document) // Non-NULL document object is expected.
|
||||
//
|
||||
// if (!tag) {
|
||||
// tag = (yaml_char_t *)YAML_DEFAULT_MAPPING_TAG
|
||||
// }
|
||||
//
|
||||
// if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error
|
||||
// tag_copy = yaml_strdup(tag)
|
||||
// if (!tag_copy) goto error
|
||||
//
|
||||
// if (!STACK_INIT(&context, pairs, INITIAL_STACK_SIZE)) goto error
|
||||
//
|
||||
// MAPPING_NODE_INIT(node, tag_copy, pairs.start, pairs.end,
|
||||
// style, mark, mark)
|
||||
// if (!PUSH(&context, document.nodes, node)) goto error
|
||||
//
|
||||
// return document.nodes.top - document.nodes.start
|
||||
//
|
||||
//error:
|
||||
// STACK_DEL(&context, pairs)
|
||||
// yaml_free(tag_copy)
|
||||
//
|
||||
// return 0
|
||||
//}
|
||||
//
|
||||
///*
|
||||
// * Append an item to a sequence node.
|
||||
// */
|
||||
//
|
||||
//YAML_DECLARE(int)
|
||||
//yaml_document_append_sequence_item(document *yaml_document_t,
|
||||
// sequence int, item int)
|
||||
//{
|
||||
// struct {
|
||||
// error yaml_error_type_t
|
||||
// } context
|
||||
//
|
||||
// assert(document) // Non-NULL document is required.
|
||||
// assert(sequence > 0
|
||||
// && document.nodes.start + sequence <= document.nodes.top)
|
||||
// // Valid sequence id is required.
|
||||
// assert(document.nodes.start[sequence-1].type == YAML_SEQUENCE_NODE)
|
||||
// // A sequence node is required.
|
||||
// assert(item > 0 && document.nodes.start + item <= document.nodes.top)
|
||||
// // Valid item id is required.
|
||||
//
|
||||
// if (!PUSH(&context,
|
||||
// document.nodes.start[sequence-1].data.sequence.items, item))
|
||||
// return 0
|
||||
//
|
||||
// return 1
|
||||
//}
|
||||
//
|
||||
///*
|
||||
// * Append a pair of a key and a value to a mapping node.
|
||||
// */
|
||||
//
|
||||
//YAML_DECLARE(int)
|
||||
//yaml_document_append_mapping_pair(document *yaml_document_t,
|
||||
// mapping int, key int, value int)
|
||||
//{
|
||||
// struct {
|
||||
// error yaml_error_type_t
|
||||
// } context
|
||||
//
|
||||
// pair yaml_node_pair_t
|
||||
//
|
||||
// assert(document) // Non-NULL document is required.
|
||||
// assert(mapping > 0
|
||||
// && document.nodes.start + mapping <= document.nodes.top)
|
||||
// // Valid mapping id is required.
|
||||
// assert(document.nodes.start[mapping-1].type == YAML_MAPPING_NODE)
|
||||
// // A mapping node is required.
|
||||
// assert(key > 0 && document.nodes.start + key <= document.nodes.top)
|
||||
// // Valid key id is required.
|
||||
// assert(value > 0 && document.nodes.start + value <= document.nodes.top)
|
||||
// // Valid value id is required.
|
||||
//
|
||||
// pair.key = key
|
||||
// pair.value = value
|
||||
//
|
||||
// if (!PUSH(&context,
|
||||
// document.nodes.start[mapping-1].data.mapping.pairs, pair))
|
||||
// return 0
|
||||
//
|
||||
// return 1
|
||||
//}
|
||||
//
|
||||
//
|
775
vendor/gopkg.in/yaml.v2/decode.go
generated
vendored
Normal file
775
vendor/gopkg.in/yaml.v2/decode.go
generated
vendored
Normal file
@ -0,0 +1,775 @@
|
||||
package yaml
|
||||
|
||||
import (
|
||||
"encoding"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"io"
|
||||
"math"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
documentNode = 1 << iota
|
||||
mappingNode
|
||||
sequenceNode
|
||||
scalarNode
|
||||
aliasNode
|
||||
)
|
||||
|
||||
type node struct {
|
||||
kind int
|
||||
line, column int
|
||||
tag string
|
||||
// For an alias node, alias holds the resolved alias.
|
||||
alias *node
|
||||
value string
|
||||
implicit bool
|
||||
children []*node
|
||||
anchors map[string]*node
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Parser, produces a node tree out of a libyaml event stream.
|
||||
|
||||
type parser struct {
|
||||
parser yaml_parser_t
|
||||
event yaml_event_t
|
||||
doc *node
|
||||
doneInit bool
|
||||
}
|
||||
|
||||
func newParser(b []byte) *parser {
|
||||
p := parser{}
|
||||
if !yaml_parser_initialize(&p.parser) {
|
||||
panic("failed to initialize YAML emitter")
|
||||
}
|
||||
if len(b) == 0 {
|
||||
b = []byte{'\n'}
|
||||
}
|
||||
yaml_parser_set_input_string(&p.parser, b)
|
||||
return &p
|
||||
}
|
||||
|
||||
func newParserFromReader(r io.Reader) *parser {
|
||||
p := parser{}
|
||||
if !yaml_parser_initialize(&p.parser) {
|
||||
panic("failed to initialize YAML emitter")
|
||||
}
|
||||
yaml_parser_set_input_reader(&p.parser, r)
|
||||
return &p
|
||||
}
|
||||
|
||||
func (p *parser) init() {
|
||||
if p.doneInit {
|
||||
return
|
||||
}
|
||||
p.expect(yaml_STREAM_START_EVENT)
|
||||
p.doneInit = true
|
||||
}
|
||||
|
||||
func (p *parser) destroy() {
|
||||
if p.event.typ != yaml_NO_EVENT {
|
||||
yaml_event_delete(&p.event)
|
||||
}
|
||||
yaml_parser_delete(&p.parser)
|
||||
}
|
||||
|
||||
// expect consumes an event from the event stream and
|
||||
// checks that it's of the expected type.
|
||||
func (p *parser) expect(e yaml_event_type_t) {
|
||||
if p.event.typ == yaml_NO_EVENT {
|
||||
if !yaml_parser_parse(&p.parser, &p.event) {
|
||||
p.fail()
|
||||
}
|
||||
}
|
||||
if p.event.typ == yaml_STREAM_END_EVENT {
|
||||
failf("attempted to go past the end of stream; corrupted value?")
|
||||
}
|
||||
if p.event.typ != e {
|
||||
p.parser.problem = fmt.Sprintf("expected %s event but got %s", e, p.event.typ)
|
||||
p.fail()
|
||||
}
|
||||
yaml_event_delete(&p.event)
|
||||
p.event.typ = yaml_NO_EVENT
|
||||
}
|
||||
|
||||
// peek peeks at the next event in the event stream,
|
||||
// puts the results into p.event and returns the event type.
|
||||
func (p *parser) peek() yaml_event_type_t {
|
||||
if p.event.typ != yaml_NO_EVENT {
|
||||
return p.event.typ
|
||||
}
|
||||
if !yaml_parser_parse(&p.parser, &p.event) {
|
||||
p.fail()
|
||||
}
|
||||
return p.event.typ
|
||||
}
|
||||
|
||||
func (p *parser) fail() {
|
||||
var where string
|
||||
var line int
|
||||
if p.parser.problem_mark.line != 0 {
|
||||
line = p.parser.problem_mark.line
|
||||
// Scanner errors don't iterate line before returning error
|
||||
if p.parser.error == yaml_SCANNER_ERROR {
|
||||
line++
|
||||
}
|
||||
} else if p.parser.context_mark.line != 0 {
|
||||
line = p.parser.context_mark.line
|
||||
}
|
||||
if line != 0 {
|
||||
where = "line " + strconv.Itoa(line) + ": "
|
||||
}
|
||||
var msg string
|
||||
if len(p.parser.problem) > 0 {
|
||||
msg = p.parser.problem
|
||||
} else {
|
||||
msg = "unknown problem parsing YAML content"
|
||||
}
|
||||
failf("%s%s", where, msg)
|
||||
}
|
||||
|
||||
func (p *parser) anchor(n *node, anchor []byte) {
|
||||
if anchor != nil {
|
||||
p.doc.anchors[string(anchor)] = n
|
||||
}
|
||||
}
|
||||
|
||||
func (p *parser) parse() *node {
|
||||
p.init()
|
||||
switch p.peek() {
|
||||
case yaml_SCALAR_EVENT:
|
||||
return p.scalar()
|
||||
case yaml_ALIAS_EVENT:
|
||||
return p.alias()
|
||||
case yaml_MAPPING_START_EVENT:
|
||||
return p.mapping()
|
||||
case yaml_SEQUENCE_START_EVENT:
|
||||
return p.sequence()
|
||||
case yaml_DOCUMENT_START_EVENT:
|
||||
return p.document()
|
||||
case yaml_STREAM_END_EVENT:
|
||||
// Happens when attempting to decode an empty buffer.
|
||||
return nil
|
||||
default:
|
||||
panic("attempted to parse unknown event: " + p.event.typ.String())
|
||||
}
|
||||
}
|
||||
|
||||
func (p *parser) node(kind int) *node {
|
||||
return &node{
|
||||
kind: kind,
|
||||
line: p.event.start_mark.line,
|
||||
column: p.event.start_mark.column,
|
||||
}
|
||||
}
|
||||
|
||||
func (p *parser) document() *node {
|
||||
n := p.node(documentNode)
|
||||
n.anchors = make(map[string]*node)
|
||||
p.doc = n
|
||||
p.expect(yaml_DOCUMENT_START_EVENT)
|
||||
n.children = append(n.children, p.parse())
|
||||
p.expect(yaml_DOCUMENT_END_EVENT)
|
||||
return n
|
||||
}
|
||||
|
||||
func (p *parser) alias() *node {
|
||||
n := p.node(aliasNode)
|
||||
n.value = string(p.event.anchor)
|
||||
n.alias = p.doc.anchors[n.value]
|
||||
if n.alias == nil {
|
||||
failf("unknown anchor '%s' referenced", n.value)
|
||||
}
|
||||
p.expect(yaml_ALIAS_EVENT)
|
||||
return n
|
||||
}
|
||||
|
||||
func (p *parser) scalar() *node {
|
||||
n := p.node(scalarNode)
|
||||
n.value = string(p.event.value)
|
||||
n.tag = string(p.event.tag)
|
||||
n.implicit = p.event.implicit
|
||||
p.anchor(n, p.event.anchor)
|
||||
p.expect(yaml_SCALAR_EVENT)
|
||||
return n
|
||||
}
|
||||
|
||||
func (p *parser) sequence() *node {
|
||||
n := p.node(sequenceNode)
|
||||
p.anchor(n, p.event.anchor)
|
||||
p.expect(yaml_SEQUENCE_START_EVENT)
|
||||
for p.peek() != yaml_SEQUENCE_END_EVENT {
|
||||
n.children = append(n.children, p.parse())
|
||||
}
|
||||
p.expect(yaml_SEQUENCE_END_EVENT)
|
||||
return n
|
||||
}
|
||||
|
||||
func (p *parser) mapping() *node {
|
||||
n := p.node(mappingNode)
|
||||
p.anchor(n, p.event.anchor)
|
||||
p.expect(yaml_MAPPING_START_EVENT)
|
||||
for p.peek() != yaml_MAPPING_END_EVENT {
|
||||
n.children = append(n.children, p.parse(), p.parse())
|
||||
}
|
||||
p.expect(yaml_MAPPING_END_EVENT)
|
||||
return n
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Decoder, unmarshals a node into a provided value.
|
||||
|
||||
type decoder struct {
|
||||
doc *node
|
||||
aliases map[*node]bool
|
||||
mapType reflect.Type
|
||||
terrors []string
|
||||
strict bool
|
||||
}
|
||||
|
||||
var (
|
||||
mapItemType = reflect.TypeOf(MapItem{})
|
||||
durationType = reflect.TypeOf(time.Duration(0))
|
||||
defaultMapType = reflect.TypeOf(map[interface{}]interface{}{})
|
||||
ifaceType = defaultMapType.Elem()
|
||||
timeType = reflect.TypeOf(time.Time{})
|
||||
ptrTimeType = reflect.TypeOf(&time.Time{})
|
||||
)
|
||||
|
||||
func newDecoder(strict bool) *decoder {
|
||||
d := &decoder{mapType: defaultMapType, strict: strict}
|
||||
d.aliases = make(map[*node]bool)
|
||||
return d
|
||||
}
|
||||
|
||||
func (d *decoder) terror(n *node, tag string, out reflect.Value) {
|
||||
if n.tag != "" {
|
||||
tag = n.tag
|
||||
}
|
||||
value := n.value
|
||||
if tag != yaml_SEQ_TAG && tag != yaml_MAP_TAG {
|
||||
if len(value) > 10 {
|
||||
value = " `" + value[:7] + "...`"
|
||||
} else {
|
||||
value = " `" + value + "`"
|
||||
}
|
||||
}
|
||||
d.terrors = append(d.terrors, fmt.Sprintf("line %d: cannot unmarshal %s%s into %s", n.line+1, shortTag(tag), value, out.Type()))
|
||||
}
|
||||
|
||||
func (d *decoder) callUnmarshaler(n *node, u Unmarshaler) (good bool) {
|
||||
terrlen := len(d.terrors)
|
||||
err := u.UnmarshalYAML(func(v interface{}) (err error) {
|
||||
defer handleErr(&err)
|
||||
d.unmarshal(n, reflect.ValueOf(v))
|
||||
if len(d.terrors) > terrlen {
|
||||
issues := d.terrors[terrlen:]
|
||||
d.terrors = d.terrors[:terrlen]
|
||||
return &TypeError{issues}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if e, ok := err.(*TypeError); ok {
|
||||
d.terrors = append(d.terrors, e.Errors...)
|
||||
return false
|
||||
}
|
||||
if err != nil {
|
||||
fail(err)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// d.prepare initializes and dereferences pointers and calls UnmarshalYAML
|
||||
// if a value is found to implement it.
|
||||
// It returns the initialized and dereferenced out value, whether
|
||||
// unmarshalling was already done by UnmarshalYAML, and if so whether
|
||||
// its types unmarshalled appropriately.
|
||||
//
|
||||
// If n holds a null value, prepare returns before doing anything.
|
||||
func (d *decoder) prepare(n *node, out reflect.Value) (newout reflect.Value, unmarshaled, good bool) {
|
||||
if n.tag == yaml_NULL_TAG || n.kind == scalarNode && n.tag == "" && (n.value == "null" || n.value == "~" || n.value == "" && n.implicit) {
|
||||
return out, false, false
|
||||
}
|
||||
again := true
|
||||
for again {
|
||||
again = false
|
||||
if out.Kind() == reflect.Ptr {
|
||||
if out.IsNil() {
|
||||
out.Set(reflect.New(out.Type().Elem()))
|
||||
}
|
||||
out = out.Elem()
|
||||
again = true
|
||||
}
|
||||
if out.CanAddr() {
|
||||
if u, ok := out.Addr().Interface().(Unmarshaler); ok {
|
||||
good = d.callUnmarshaler(n, u)
|
||||
return out, true, good
|
||||
}
|
||||
}
|
||||
}
|
||||
return out, false, false
|
||||
}
|
||||
|
||||
func (d *decoder) unmarshal(n *node, out reflect.Value) (good bool) {
|
||||
switch n.kind {
|
||||
case documentNode:
|
||||
return d.document(n, out)
|
||||
case aliasNode:
|
||||
return d.alias(n, out)
|
||||
}
|
||||
out, unmarshaled, good := d.prepare(n, out)
|
||||
if unmarshaled {
|
||||
return good
|
||||
}
|
||||
switch n.kind {
|
||||
case scalarNode:
|
||||
good = d.scalar(n, out)
|
||||
case mappingNode:
|
||||
good = d.mapping(n, out)
|
||||
case sequenceNode:
|
||||
good = d.sequence(n, out)
|
||||
default:
|
||||
panic("internal error: unknown node kind: " + strconv.Itoa(n.kind))
|
||||
}
|
||||
return good
|
||||
}
|
||||
|
||||
func (d *decoder) document(n *node, out reflect.Value) (good bool) {
|
||||
if len(n.children) == 1 {
|
||||
d.doc = n
|
||||
d.unmarshal(n.children[0], out)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (d *decoder) alias(n *node, out reflect.Value) (good bool) {
|
||||
if d.aliases[n] {
|
||||
// TODO this could actually be allowed in some circumstances.
|
||||
failf("anchor '%s' value contains itself", n.value)
|
||||
}
|
||||
d.aliases[n] = true
|
||||
good = d.unmarshal(n.alias, out)
|
||||
delete(d.aliases, n)
|
||||
return good
|
||||
}
|
||||
|
||||
var zeroValue reflect.Value
|
||||
|
||||
func resetMap(out reflect.Value) {
|
||||
for _, k := range out.MapKeys() {
|
||||
out.SetMapIndex(k, zeroValue)
|
||||
}
|
||||
}
|
||||
|
||||
func (d *decoder) scalar(n *node, out reflect.Value) bool {
|
||||
var tag string
|
||||
var resolved interface{}
|
||||
if n.tag == "" && !n.implicit {
|
||||
tag = yaml_STR_TAG
|
||||
resolved = n.value
|
||||
} else {
|
||||
tag, resolved = resolve(n.tag, n.value)
|
||||
if tag == yaml_BINARY_TAG {
|
||||
data, err := base64.StdEncoding.DecodeString(resolved.(string))
|
||||
if err != nil {
|
||||
failf("!!binary value contains invalid base64 data")
|
||||
}
|
||||
resolved = string(data)
|
||||
}
|
||||
}
|
||||
if resolved == nil {
|
||||
if out.Kind() == reflect.Map && !out.CanAddr() {
|
||||
resetMap(out)
|
||||
} else {
|
||||
out.Set(reflect.Zero(out.Type()))
|
||||
}
|
||||
return true
|
||||
}
|
||||
if resolvedv := reflect.ValueOf(resolved); out.Type() == resolvedv.Type() {
|
||||
// We've resolved to exactly the type we want, so use that.
|
||||
out.Set(resolvedv)
|
||||
return true
|
||||
}
|
||||
// Perhaps we can use the value as a TextUnmarshaler to
|
||||
// set its value.
|
||||
if out.CanAddr() {
|
||||
u, ok := out.Addr().Interface().(encoding.TextUnmarshaler)
|
||||
if ok {
|
||||
var text []byte
|
||||
if tag == yaml_BINARY_TAG {
|
||||
text = []byte(resolved.(string))
|
||||
} else {
|
||||
// We let any value be unmarshaled into TextUnmarshaler.
|
||||
// That might be more lax than we'd like, but the
|
||||
// TextUnmarshaler itself should bowl out any dubious values.
|
||||
text = []byte(n.value)
|
||||
}
|
||||
err := u.UnmarshalText(text)
|
||||
if err != nil {
|
||||
fail(err)
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
switch out.Kind() {
|
||||
case reflect.String:
|
||||
if tag == yaml_BINARY_TAG {
|
||||
out.SetString(resolved.(string))
|
||||
return true
|
||||
}
|
||||
if resolved != nil {
|
||||
out.SetString(n.value)
|
||||
return true
|
||||
}
|
||||
case reflect.Interface:
|
||||
if resolved == nil {
|
||||
out.Set(reflect.Zero(out.Type()))
|
||||
} else if tag == yaml_TIMESTAMP_TAG {
|
||||
// It looks like a timestamp but for backward compatibility
|
||||
// reasons we set it as a string, so that code that unmarshals
|
||||
// timestamp-like values into interface{} will continue to
|
||||
// see a string and not a time.Time.
|
||||
// TODO(v3) Drop this.
|
||||
out.Set(reflect.ValueOf(n.value))
|
||||
} else {
|
||||
out.Set(reflect.ValueOf(resolved))
|
||||
}
|
||||
return true
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
switch resolved := resolved.(type) {
|
||||
case int:
|
||||
if !out.OverflowInt(int64(resolved)) {
|
||||
out.SetInt(int64(resolved))
|
||||
return true
|
||||
}
|
||||
case int64:
|
||||
if !out.OverflowInt(resolved) {
|
||||
out.SetInt(resolved)
|
||||
return true
|
||||
}
|
||||
case uint64:
|
||||
if resolved <= math.MaxInt64 && !out.OverflowInt(int64(resolved)) {
|
||||
out.SetInt(int64(resolved))
|
||||
return true
|
||||
}
|
||||
case float64:
|
||||
if resolved <= math.MaxInt64 && !out.OverflowInt(int64(resolved)) {
|
||||
out.SetInt(int64(resolved))
|
||||
return true
|
||||
}
|
||||
case string:
|
||||
if out.Type() == durationType {
|
||||
d, err := time.ParseDuration(resolved)
|
||||
if err == nil {
|
||||
out.SetInt(int64(d))
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||
switch resolved := resolved.(type) {
|
||||
case int:
|
||||
if resolved >= 0 && !out.OverflowUint(uint64(resolved)) {
|
||||
out.SetUint(uint64(resolved))
|
||||
return true
|
||||
}
|
||||
case int64:
|
||||
if resolved >= 0 && !out.OverflowUint(uint64(resolved)) {
|
||||
out.SetUint(uint64(resolved))
|
||||
return true
|
||||
}
|
||||
case uint64:
|
||||
if !out.OverflowUint(uint64(resolved)) {
|
||||
out.SetUint(uint64(resolved))
|
||||
return true
|
||||
}
|
||||
case float64:
|
||||
if resolved <= math.MaxUint64 && !out.OverflowUint(uint64(resolved)) {
|
||||
out.SetUint(uint64(resolved))
|
||||
return true
|
||||
}
|
||||
}
|
||||
case reflect.Bool:
|
||||
switch resolved := resolved.(type) {
|
||||
case bool:
|
||||
out.SetBool(resolved)
|
||||
return true
|
||||
}
|
||||
case reflect.Float32, reflect.Float64:
|
||||
switch resolved := resolved.(type) {
|
||||
case int:
|
||||
out.SetFloat(float64(resolved))
|
||||
return true
|
||||
case int64:
|
||||
out.SetFloat(float64(resolved))
|
||||
return true
|
||||
case uint64:
|
||||
out.SetFloat(float64(resolved))
|
||||
return true
|
||||
case float64:
|
||||
out.SetFloat(resolved)
|
||||
return true
|
||||
}
|
||||
case reflect.Struct:
|
||||
if resolvedv := reflect.ValueOf(resolved); out.Type() == resolvedv.Type() {
|
||||
out.Set(resolvedv)
|
||||
return true
|
||||
}
|
||||
case reflect.Ptr:
|
||||
if out.Type().Elem() == reflect.TypeOf(resolved) {
|
||||
// TODO DOes this make sense? When is out a Ptr except when decoding a nil value?
|
||||
elem := reflect.New(out.Type().Elem())
|
||||
elem.Elem().Set(reflect.ValueOf(resolved))
|
||||
out.Set(elem)
|
||||
return true
|
||||
}
|
||||
}
|
||||
d.terror(n, tag, out)
|
||||
return false
|
||||
}
|
||||
|
||||
func settableValueOf(i interface{}) reflect.Value {
|
||||
v := reflect.ValueOf(i)
|
||||
sv := reflect.New(v.Type()).Elem()
|
||||
sv.Set(v)
|
||||
return sv
|
||||
}
|
||||
|
||||
func (d *decoder) sequence(n *node, out reflect.Value) (good bool) {
|
||||
l := len(n.children)
|
||||
|
||||
var iface reflect.Value
|
||||
switch out.Kind() {
|
||||
case reflect.Slice:
|
||||
out.Set(reflect.MakeSlice(out.Type(), l, l))
|
||||
case reflect.Array:
|
||||
if l != out.Len() {
|
||||
failf("invalid array: want %d elements but got %d", out.Len(), l)
|
||||
}
|
||||
case reflect.Interface:
|
||||
// No type hints. Will have to use a generic sequence.
|
||||
iface = out
|
||||
out = settableValueOf(make([]interface{}, l))
|
||||
default:
|
||||
d.terror(n, yaml_SEQ_TAG, out)
|
||||
return false
|
||||
}
|
||||
et := out.Type().Elem()
|
||||
|
||||
j := 0
|
||||
for i := 0; i < l; i++ {
|
||||
e := reflect.New(et).Elem()
|
||||
if ok := d.unmarshal(n.children[i], e); ok {
|
||||
out.Index(j).Set(e)
|
||||
j++
|
||||
}
|
||||
}
|
||||
if out.Kind() != reflect.Array {
|
||||
out.Set(out.Slice(0, j))
|
||||
}
|
||||
if iface.IsValid() {
|
||||
iface.Set(out)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (d *decoder) mapping(n *node, out reflect.Value) (good bool) {
|
||||
switch out.Kind() {
|
||||
case reflect.Struct:
|
||||
return d.mappingStruct(n, out)
|
||||
case reflect.Slice:
|
||||
return d.mappingSlice(n, out)
|
||||
case reflect.Map:
|
||||
// okay
|
||||
case reflect.Interface:
|
||||
if d.mapType.Kind() == reflect.Map {
|
||||
iface := out
|
||||
out = reflect.MakeMap(d.mapType)
|
||||
iface.Set(out)
|
||||
} else {
|
||||
slicev := reflect.New(d.mapType).Elem()
|
||||
if !d.mappingSlice(n, slicev) {
|
||||
return false
|
||||
}
|
||||
out.Set(slicev)
|
||||
return true
|
||||
}
|
||||
default:
|
||||
d.terror(n, yaml_MAP_TAG, out)
|
||||
return false
|
||||
}
|
||||
outt := out.Type()
|
||||
kt := outt.Key()
|
||||
et := outt.Elem()
|
||||
|
||||
mapType := d.mapType
|
||||
if outt.Key() == ifaceType && outt.Elem() == ifaceType {
|
||||
d.mapType = outt
|
||||
}
|
||||
|
||||
if out.IsNil() {
|
||||
out.Set(reflect.MakeMap(outt))
|
||||
}
|
||||
l := len(n.children)
|
||||
for i := 0; i < l; i += 2 {
|
||||
if isMerge(n.children[i]) {
|
||||
d.merge(n.children[i+1], out)
|
||||
continue
|
||||
}
|
||||
k := reflect.New(kt).Elem()
|
||||
if d.unmarshal(n.children[i], k) {
|
||||
kkind := k.Kind()
|
||||
if kkind == reflect.Interface {
|
||||
kkind = k.Elem().Kind()
|
||||
}
|
||||
if kkind == reflect.Map || kkind == reflect.Slice {
|
||||
failf("invalid map key: %#v", k.Interface())
|
||||
}
|
||||
e := reflect.New(et).Elem()
|
||||
if d.unmarshal(n.children[i+1], e) {
|
||||
d.setMapIndex(n.children[i+1], out, k, e)
|
||||
}
|
||||
}
|
||||
}
|
||||
d.mapType = mapType
|
||||
return true
|
||||
}
|
||||
|
||||
func (d *decoder) setMapIndex(n *node, out, k, v reflect.Value) {
|
||||
if d.strict && out.MapIndex(k) != zeroValue {
|
||||
d.terrors = append(d.terrors, fmt.Sprintf("line %d: key %#v already set in map", n.line+1, k.Interface()))
|
||||
return
|
||||
}
|
||||
out.SetMapIndex(k, v)
|
||||
}
|
||||
|
||||
func (d *decoder) mappingSlice(n *node, out reflect.Value) (good bool) {
|
||||
outt := out.Type()
|
||||
if outt.Elem() != mapItemType {
|
||||
d.terror(n, yaml_MAP_TAG, out)
|
||||
return false
|
||||
}
|
||||
|
||||
mapType := d.mapType
|
||||
d.mapType = outt
|
||||
|
||||
var slice []MapItem
|
||||
var l = len(n.children)
|
||||
for i := 0; i < l; i += 2 {
|
||||
if isMerge(n.children[i]) {
|
||||
d.merge(n.children[i+1], out)
|
||||
continue
|
||||
}
|
||||
item := MapItem{}
|
||||
k := reflect.ValueOf(&item.Key).Elem()
|
||||
if d.unmarshal(n.children[i], k) {
|
||||
v := reflect.ValueOf(&item.Value).Elem()
|
||||
if d.unmarshal(n.children[i+1], v) {
|
||||
slice = append(slice, item)
|
||||
}
|
||||
}
|
||||
}
|
||||
out.Set(reflect.ValueOf(slice))
|
||||
d.mapType = mapType
|
||||
return true
|
||||
}
|
||||
|
||||
func (d *decoder) mappingStruct(n *node, out reflect.Value) (good bool) {
|
||||
sinfo, err := getStructInfo(out.Type())
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
name := settableValueOf("")
|
||||
l := len(n.children)
|
||||
|
||||
var inlineMap reflect.Value
|
||||
var elemType reflect.Type
|
||||
if sinfo.InlineMap != -1 {
|
||||
inlineMap = out.Field(sinfo.InlineMap)
|
||||
inlineMap.Set(reflect.New(inlineMap.Type()).Elem())
|
||||
elemType = inlineMap.Type().Elem()
|
||||
}
|
||||
|
||||
var doneFields []bool
|
||||
if d.strict {
|
||||
doneFields = make([]bool, len(sinfo.FieldsList))
|
||||
}
|
||||
for i := 0; i < l; i += 2 {
|
||||
ni := n.children[i]
|
||||
if isMerge(ni) {
|
||||
d.merge(n.children[i+1], out)
|
||||
continue
|
||||
}
|
||||
if !d.unmarshal(ni, name) {
|
||||
continue
|
||||
}
|
||||
if info, ok := sinfo.FieldsMap[name.String()]; ok {
|
||||
if d.strict {
|
||||
if doneFields[info.Id] {
|
||||
d.terrors = append(d.terrors, fmt.Sprintf("line %d: field %s already set in type %s", ni.line+1, name.String(), out.Type()))
|
||||
continue
|
||||
}
|
||||
doneFields[info.Id] = true
|
||||
}
|
||||
var field reflect.Value
|
||||
if info.Inline == nil {
|
||||
field = out.Field(info.Num)
|
||||
} else {
|
||||
field = out.FieldByIndex(info.Inline)
|
||||
}
|
||||
d.unmarshal(n.children[i+1], field)
|
||||
} else if sinfo.InlineMap != -1 {
|
||||
if inlineMap.IsNil() {
|
||||
inlineMap.Set(reflect.MakeMap(inlineMap.Type()))
|
||||
}
|
||||
value := reflect.New(elemType).Elem()
|
||||
d.unmarshal(n.children[i+1], value)
|
||||
d.setMapIndex(n.children[i+1], inlineMap, name, value)
|
||||
} else if d.strict {
|
||||
d.terrors = append(d.terrors, fmt.Sprintf("line %d: field %s not found in type %s", ni.line+1, name.String(), out.Type()))
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func failWantMap() {
|
||||
failf("map merge requires map or sequence of maps as the value")
|
||||
}
|
||||
|
||||
func (d *decoder) merge(n *node, out reflect.Value) {
|
||||
switch n.kind {
|
||||
case mappingNode:
|
||||
d.unmarshal(n, out)
|
||||
case aliasNode:
|
||||
an, ok := d.doc.anchors[n.value]
|
||||
if ok && an.kind != mappingNode {
|
||||
failWantMap()
|
||||
}
|
||||
d.unmarshal(n, out)
|
||||
case sequenceNode:
|
||||
// Step backwards as earlier nodes take precedence.
|
||||
for i := len(n.children) - 1; i >= 0; i-- {
|
||||
ni := n.children[i]
|
||||
if ni.kind == aliasNode {
|
||||
an, ok := d.doc.anchors[ni.value]
|
||||
if ok && an.kind != mappingNode {
|
||||
failWantMap()
|
||||
}
|
||||
} else if ni.kind != mappingNode {
|
||||
failWantMap()
|
||||
}
|
||||
d.unmarshal(ni, out)
|
||||
}
|
||||
default:
|
||||
failWantMap()
|
||||
}
|
||||
}
|
||||
|
||||
func isMerge(n *node) bool {
|
||||
return n.kind == scalarNode && n.value == "<<" && (n.implicit == true || n.tag == yaml_MERGE_TAG)
|
||||
}
|
1685
vendor/gopkg.in/yaml.v2/emitterc.go
generated
vendored
Normal file
1685
vendor/gopkg.in/yaml.v2/emitterc.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
362
vendor/gopkg.in/yaml.v2/encode.go
generated
vendored
Normal file
362
vendor/gopkg.in/yaml.v2/encode.go
generated
vendored
Normal file
@ -0,0 +1,362 @@
|
||||
package yaml
|
||||
|
||||
import (
|
||||
"encoding"
|
||||
"fmt"
|
||||
"io"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
type encoder struct {
|
||||
emitter yaml_emitter_t
|
||||
event yaml_event_t
|
||||
out []byte
|
||||
flow bool
|
||||
// doneInit holds whether the initial stream_start_event has been
|
||||
// emitted.
|
||||
doneInit bool
|
||||
}
|
||||
|
||||
func newEncoder() *encoder {
|
||||
e := &encoder{}
|
||||
yaml_emitter_initialize(&e.emitter)
|
||||
yaml_emitter_set_output_string(&e.emitter, &e.out)
|
||||
yaml_emitter_set_unicode(&e.emitter, true)
|
||||
return e
|
||||
}
|
||||
|
||||
func newEncoderWithWriter(w io.Writer) *encoder {
|
||||
e := &encoder{}
|
||||
yaml_emitter_initialize(&e.emitter)
|
||||
yaml_emitter_set_output_writer(&e.emitter, w)
|
||||
yaml_emitter_set_unicode(&e.emitter, true)
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *encoder) init() {
|
||||
if e.doneInit {
|
||||
return
|
||||
}
|
||||
yaml_stream_start_event_initialize(&e.event, yaml_UTF8_ENCODING)
|
||||
e.emit()
|
||||
e.doneInit = true
|
||||
}
|
||||
|
||||
func (e *encoder) finish() {
|
||||
e.emitter.open_ended = false
|
||||
yaml_stream_end_event_initialize(&e.event)
|
||||
e.emit()
|
||||
}
|
||||
|
||||
func (e *encoder) destroy() {
|
||||
yaml_emitter_delete(&e.emitter)
|
||||
}
|
||||
|
||||
func (e *encoder) emit() {
|
||||
// This will internally delete the e.event value.
|
||||
e.must(yaml_emitter_emit(&e.emitter, &e.event))
|
||||
}
|
||||
|
||||
func (e *encoder) must(ok bool) {
|
||||
if !ok {
|
||||
msg := e.emitter.problem
|
||||
if msg == "" {
|
||||
msg = "unknown problem generating YAML content"
|
||||
}
|
||||
failf("%s", msg)
|
||||
}
|
||||
}
|
||||
|
||||
func (e *encoder) marshalDoc(tag string, in reflect.Value) {
|
||||
e.init()
|
||||
yaml_document_start_event_initialize(&e.event, nil, nil, true)
|
||||
e.emit()
|
||||
e.marshal(tag, in)
|
||||
yaml_document_end_event_initialize(&e.event, true)
|
||||
e.emit()
|
||||
}
|
||||
|
||||
func (e *encoder) marshal(tag string, in reflect.Value) {
|
||||
if !in.IsValid() || in.Kind() == reflect.Ptr && in.IsNil() {
|
||||
e.nilv()
|
||||
return
|
||||
}
|
||||
iface := in.Interface()
|
||||
switch m := iface.(type) {
|
||||
case time.Time, *time.Time:
|
||||
// Although time.Time implements TextMarshaler,
|
||||
// we don't want to treat it as a string for YAML
|
||||
// purposes because YAML has special support for
|
||||
// timestamps.
|
||||
case Marshaler:
|
||||
v, err := m.MarshalYAML()
|
||||
if err != nil {
|
||||
fail(err)
|
||||
}
|
||||
if v == nil {
|
||||
e.nilv()
|
||||
return
|
||||
}
|
||||
in = reflect.ValueOf(v)
|
||||
case encoding.TextMarshaler:
|
||||
text, err := m.MarshalText()
|
||||
if err != nil {
|
||||
fail(err)
|
||||
}
|
||||
in = reflect.ValueOf(string(text))
|
||||
case nil:
|
||||
e.nilv()
|
||||
return
|
||||
}
|
||||
switch in.Kind() {
|
||||
case reflect.Interface:
|
||||
e.marshal(tag, in.Elem())
|
||||
case reflect.Map:
|
||||
e.mapv(tag, in)
|
||||
case reflect.Ptr:
|
||||
if in.Type() == ptrTimeType {
|
||||
e.timev(tag, in.Elem())
|
||||
} else {
|
||||
e.marshal(tag, in.Elem())
|
||||
}
|
||||
case reflect.Struct:
|
||||
if in.Type() == timeType {
|
||||
e.timev(tag, in)
|
||||
} else {
|
||||
e.structv(tag, in)
|
||||
}
|
||||
case reflect.Slice, reflect.Array:
|
||||
if in.Type().Elem() == mapItemType {
|
||||
e.itemsv(tag, in)
|
||||
} else {
|
||||
e.slicev(tag, in)
|
||||
}
|
||||
case reflect.String:
|
||||
e.stringv(tag, in)
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
if in.Type() == durationType {
|
||||
e.stringv(tag, reflect.ValueOf(iface.(time.Duration).String()))
|
||||
} else {
|
||||
e.intv(tag, in)
|
||||
}
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||
e.uintv(tag, in)
|
||||
case reflect.Float32, reflect.Float64:
|
||||
e.floatv(tag, in)
|
||||
case reflect.Bool:
|
||||
e.boolv(tag, in)
|
||||
default:
|
||||
panic("cannot marshal type: " + in.Type().String())
|
||||
}
|
||||
}
|
||||
|
||||
func (e *encoder) mapv(tag string, in reflect.Value) {
|
||||
e.mappingv(tag, func() {
|
||||
keys := keyList(in.MapKeys())
|
||||
sort.Sort(keys)
|
||||
for _, k := range keys {
|
||||
e.marshal("", k)
|
||||
e.marshal("", in.MapIndex(k))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func (e *encoder) itemsv(tag string, in reflect.Value) {
|
||||
e.mappingv(tag, func() {
|
||||
slice := in.Convert(reflect.TypeOf([]MapItem{})).Interface().([]MapItem)
|
||||
for _, item := range slice {
|
||||
e.marshal("", reflect.ValueOf(item.Key))
|
||||
e.marshal("", reflect.ValueOf(item.Value))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func (e *encoder) structv(tag string, in reflect.Value) {
|
||||
sinfo, err := getStructInfo(in.Type())
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
e.mappingv(tag, func() {
|
||||
for _, info := range sinfo.FieldsList {
|
||||
var value reflect.Value
|
||||
if info.Inline == nil {
|
||||
value = in.Field(info.Num)
|
||||
} else {
|
||||
value = in.FieldByIndex(info.Inline)
|
||||
}
|
||||
if info.OmitEmpty && isZero(value) {
|
||||
continue
|
||||
}
|
||||
e.marshal("", reflect.ValueOf(info.Key))
|
||||
e.flow = info.Flow
|
||||
e.marshal("", value)
|
||||
}
|
||||
if sinfo.InlineMap >= 0 {
|
||||
m := in.Field(sinfo.InlineMap)
|
||||
if m.Len() > 0 {
|
||||
e.flow = false
|
||||
keys := keyList(m.MapKeys())
|
||||
sort.Sort(keys)
|
||||
for _, k := range keys {
|
||||
if _, found := sinfo.FieldsMap[k.String()]; found {
|
||||
panic(fmt.Sprintf("Can't have key %q in inlined map; conflicts with struct field", k.String()))
|
||||
}
|
||||
e.marshal("", k)
|
||||
e.flow = false
|
||||
e.marshal("", m.MapIndex(k))
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func (e *encoder) mappingv(tag string, f func()) {
|
||||
implicit := tag == ""
|
||||
style := yaml_BLOCK_MAPPING_STYLE
|
||||
if e.flow {
|
||||
e.flow = false
|
||||
style = yaml_FLOW_MAPPING_STYLE
|
||||
}
|
||||
yaml_mapping_start_event_initialize(&e.event, nil, []byte(tag), implicit, style)
|
||||
e.emit()
|
||||
f()
|
||||
yaml_mapping_end_event_initialize(&e.event)
|
||||
e.emit()
|
||||
}
|
||||
|
||||
func (e *encoder) slicev(tag string, in reflect.Value) {
|
||||
implicit := tag == ""
|
||||
style := yaml_BLOCK_SEQUENCE_STYLE
|
||||
if e.flow {
|
||||
e.flow = false
|
||||
style = yaml_FLOW_SEQUENCE_STYLE
|
||||
}
|
||||
e.must(yaml_sequence_start_event_initialize(&e.event, nil, []byte(tag), implicit, style))
|
||||
e.emit()
|
||||
n := in.Len()
|
||||
for i := 0; i < n; i++ {
|
||||
e.marshal("", in.Index(i))
|
||||
}
|
||||
e.must(yaml_sequence_end_event_initialize(&e.event))
|
||||
e.emit()
|
||||
}
|
||||
|
||||
// isBase60 returns whether s is in base 60 notation as defined in YAML 1.1.
|
||||
//
|
||||
// The base 60 float notation in YAML 1.1 is a terrible idea and is unsupported
|
||||
// in YAML 1.2 and by this package, but these should be marshalled quoted for
|
||||
// the time being for compatibility with other parsers.
|
||||
func isBase60Float(s string) (result bool) {
|
||||
// Fast path.
|
||||
if s == "" {
|
||||
return false
|
||||
}
|
||||
c := s[0]
|
||||
if !(c == '+' || c == '-' || c >= '0' && c <= '9') || strings.IndexByte(s, ':') < 0 {
|
||||
return false
|
||||
}
|
||||
// Do the full match.
|
||||
return base60float.MatchString(s)
|
||||
}
|
||||
|
||||
// From http://yaml.org/type/float.html, except the regular expression there
|
||||
// is bogus. In practice parsers do not enforce the "\.[0-9_]*" suffix.
|
||||
var base60float = regexp.MustCompile(`^[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+(?:\.[0-9_]*)?$`)
|
||||
|
||||
func (e *encoder) stringv(tag string, in reflect.Value) {
|
||||
var style yaml_scalar_style_t
|
||||
s := in.String()
|
||||
canUsePlain := true
|
||||
switch {
|
||||
case !utf8.ValidString(s):
|
||||
if tag == yaml_BINARY_TAG {
|
||||
failf("explicitly tagged !!binary data must be base64-encoded")
|
||||
}
|
||||
if tag != "" {
|
||||
failf("cannot marshal invalid UTF-8 data as %s", shortTag(tag))
|
||||
}
|
||||
// It can't be encoded directly as YAML so use a binary tag
|
||||
// and encode it as base64.
|
||||
tag = yaml_BINARY_TAG
|
||||
s = encodeBase64(s)
|
||||
case tag == "":
|
||||
// Check to see if it would resolve to a specific
|
||||
// tag when encoded unquoted. If it doesn't,
|
||||
// there's no need to quote it.
|
||||
rtag, _ := resolve("", s)
|
||||
canUsePlain = rtag == yaml_STR_TAG && !isBase60Float(s)
|
||||
}
|
||||
// Note: it's possible for user code to emit invalid YAML
|
||||
// if they explicitly specify a tag and a string containing
|
||||
// text that's incompatible with that tag.
|
||||
switch {
|
||||
case strings.Contains(s, "\n"):
|
||||
style = yaml_LITERAL_SCALAR_STYLE
|
||||
case canUsePlain:
|
||||
style = yaml_PLAIN_SCALAR_STYLE
|
||||
default:
|
||||
style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
|
||||
}
|
||||
e.emitScalar(s, "", tag, style)
|
||||
}
|
||||
|
||||
func (e *encoder) boolv(tag string, in reflect.Value) {
|
||||
var s string
|
||||
if in.Bool() {
|
||||
s = "true"
|
||||
} else {
|
||||
s = "false"
|
||||
}
|
||||
e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE)
|
||||
}
|
||||
|
||||
func (e *encoder) intv(tag string, in reflect.Value) {
|
||||
s := strconv.FormatInt(in.Int(), 10)
|
||||
e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE)
|
||||
}
|
||||
|
||||
func (e *encoder) uintv(tag string, in reflect.Value) {
|
||||
s := strconv.FormatUint(in.Uint(), 10)
|
||||
e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE)
|
||||
}
|
||||
|
||||
func (e *encoder) timev(tag string, in reflect.Value) {
|
||||
t := in.Interface().(time.Time)
|
||||
s := t.Format(time.RFC3339Nano)
|
||||
e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE)
|
||||
}
|
||||
|
||||
func (e *encoder) floatv(tag string, in reflect.Value) {
|
||||
// Issue #352: When formatting, use the precision of the underlying value
|
||||
precision := 64
|
||||
if in.Kind() == reflect.Float32 {
|
||||
precision = 32
|
||||
}
|
||||
|
||||
s := strconv.FormatFloat(in.Float(), 'g', -1, precision)
|
||||
switch s {
|
||||
case "+Inf":
|
||||
s = ".inf"
|
||||
case "-Inf":
|
||||
s = "-.inf"
|
||||
case "NaN":
|
||||
s = ".nan"
|
||||
}
|
||||
e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE)
|
||||
}
|
||||
|
||||
func (e *encoder) nilv() {
|
||||
e.emitScalar("null", "", "", yaml_PLAIN_SCALAR_STYLE)
|
||||
}
|
||||
|
||||
func (e *encoder) emitScalar(value, anchor, tag string, style yaml_scalar_style_t) {
|
||||
implicit := tag == ""
|
||||
e.must(yaml_scalar_event_initialize(&e.event, []byte(anchor), []byte(tag), []byte(value), implicit, implicit, style))
|
||||
e.emit()
|
||||
}
|
5
vendor/gopkg.in/yaml.v2/go.mod
generated
vendored
Normal file
5
vendor/gopkg.in/yaml.v2/go.mod
generated
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
module "gopkg.in/yaml.v2"
|
||||
|
||||
require (
|
||||
"gopkg.in/check.v1" v0.0.0-20161208181325-20d25e280405
|
||||
)
|
1095
vendor/gopkg.in/yaml.v2/parserc.go
generated
vendored
Normal file
1095
vendor/gopkg.in/yaml.v2/parserc.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
412
vendor/gopkg.in/yaml.v2/readerc.go
generated
vendored
Normal file
412
vendor/gopkg.in/yaml.v2/readerc.go
generated
vendored
Normal file
@ -0,0 +1,412 @@
|
||||
package yaml
|
||||
|
||||
import (
|
||||
"io"
|
||||
)
|
||||
|
||||
// Set the reader error and return 0.
|
||||
func yaml_parser_set_reader_error(parser *yaml_parser_t, problem string, offset int, value int) bool {
|
||||
parser.error = yaml_READER_ERROR
|
||||
parser.problem = problem
|
||||
parser.problem_offset = offset
|
||||
parser.problem_value = value
|
||||
return false
|
||||
}
|
||||
|
||||
// Byte order marks.
|
||||
const (
|
||||
bom_UTF8 = "\xef\xbb\xbf"
|
||||
bom_UTF16LE = "\xff\xfe"
|
||||
bom_UTF16BE = "\xfe\xff"
|
||||
)
|
||||
|
||||
// Determine the input stream encoding by checking the BOM symbol. If no BOM is
|
||||
// found, the UTF-8 encoding is assumed. Return 1 on success, 0 on failure.
|
||||
func yaml_parser_determine_encoding(parser *yaml_parser_t) bool {
|
||||
// Ensure that we had enough bytes in the raw buffer.
|
||||
for !parser.eof && len(parser.raw_buffer)-parser.raw_buffer_pos < 3 {
|
||||
if !yaml_parser_update_raw_buffer(parser) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// Determine the encoding.
|
||||
buf := parser.raw_buffer
|
||||
pos := parser.raw_buffer_pos
|
||||
avail := len(buf) - pos
|
||||
if avail >= 2 && buf[pos] == bom_UTF16LE[0] && buf[pos+1] == bom_UTF16LE[1] {
|
||||
parser.encoding = yaml_UTF16LE_ENCODING
|
||||
parser.raw_buffer_pos += 2
|
||||
parser.offset += 2
|
||||
} else if avail >= 2 && buf[pos] == bom_UTF16BE[0] && buf[pos+1] == bom_UTF16BE[1] {
|
||||
parser.encoding = yaml_UTF16BE_ENCODING
|
||||
parser.raw_buffer_pos += 2
|
||||
parser.offset += 2
|
||||
} else if avail >= 3 && buf[pos] == bom_UTF8[0] && buf[pos+1] == bom_UTF8[1] && buf[pos+2] == bom_UTF8[2] {
|
||||
parser.encoding = yaml_UTF8_ENCODING
|
||||
parser.raw_buffer_pos += 3
|
||||
parser.offset += 3
|
||||
} else {
|
||||
parser.encoding = yaml_UTF8_ENCODING
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Update the raw buffer.
|
||||
func yaml_parser_update_raw_buffer(parser *yaml_parser_t) bool {
|
||||
size_read := 0
|
||||
|
||||
// Return if the raw buffer is full.
|
||||
if parser.raw_buffer_pos == 0 && len(parser.raw_buffer) == cap(parser.raw_buffer) {
|
||||
return true
|
||||
}
|
||||
|
||||
// Return on EOF.
|
||||
if parser.eof {
|
||||
return true
|
||||
}
|
||||
|
||||
// Move the remaining bytes in the raw buffer to the beginning.
|
||||
if parser.raw_buffer_pos > 0 && parser.raw_buffer_pos < len(parser.raw_buffer) {
|
||||
copy(parser.raw_buffer, parser.raw_buffer[parser.raw_buffer_pos:])
|
||||
}
|
||||
parser.raw_buffer = parser.raw_buffer[:len(parser.raw_buffer)-parser.raw_buffer_pos]
|
||||
parser.raw_buffer_pos = 0
|
||||
|
||||
// Call the read handler to fill the buffer.
|
||||
size_read, err := parser.read_handler(parser, parser.raw_buffer[len(parser.raw_buffer):cap(parser.raw_buffer)])
|
||||
parser.raw_buffer = parser.raw_buffer[:len(parser.raw_buffer)+size_read]
|
||||
if err == io.EOF {
|
||||
parser.eof = true
|
||||
} else if err != nil {
|
||||
return yaml_parser_set_reader_error(parser, "input error: "+err.Error(), parser.offset, -1)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Ensure that the buffer contains at least `length` characters.
|
||||
// Return true on success, false on failure.
|
||||
//
|
||||
// The length is supposed to be significantly less that the buffer size.
|
||||
func yaml_parser_update_buffer(parser *yaml_parser_t, length int) bool {
|
||||
if parser.read_handler == nil {
|
||||
panic("read handler must be set")
|
||||
}
|
||||
|
||||
// [Go] This function was changed to guarantee the requested length size at EOF.
|
||||
// The fact we need to do this is pretty awful, but the description above implies
|
||||
// for that to be the case, and there are tests
|
||||
|
||||
// If the EOF flag is set and the raw buffer is empty, do nothing.
|
||||
if parser.eof && parser.raw_buffer_pos == len(parser.raw_buffer) {
|
||||
// [Go] ACTUALLY! Read the documentation of this function above.
|
||||
// This is just broken. To return true, we need to have the
|
||||
// given length in the buffer. Not doing that means every single
|
||||
// check that calls this function to make sure the buffer has a
|
||||
// given length is Go) panicking; or C) accessing invalid memory.
|
||||
//return true
|
||||
}
|
||||
|
||||
// Return if the buffer contains enough characters.
|
||||
if parser.unread >= length {
|
||||
return true
|
||||
}
|
||||
|
||||
// Determine the input encoding if it is not known yet.
|
||||
if parser.encoding == yaml_ANY_ENCODING {
|
||||
if !yaml_parser_determine_encoding(parser) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// Move the unread characters to the beginning of the buffer.
|
||||
buffer_len := len(parser.buffer)
|
||||
if parser.buffer_pos > 0 && parser.buffer_pos < buffer_len {
|
||||
copy(parser.buffer, parser.buffer[parser.buffer_pos:])
|
||||
buffer_len -= parser.buffer_pos
|
||||
parser.buffer_pos = 0
|
||||
} else if parser.buffer_pos == buffer_len {
|
||||
buffer_len = 0
|
||||
parser.buffer_pos = 0
|
||||
}
|
||||
|
||||
// Open the whole buffer for writing, and cut it before returning.
|
||||
parser.buffer = parser.buffer[:cap(parser.buffer)]
|
||||
|
||||
// Fill the buffer until it has enough characters.
|
||||
first := true
|
||||
for parser.unread < length {
|
||||
|
||||
// Fill the raw buffer if necessary.
|
||||
if !first || parser.raw_buffer_pos == len(parser.raw_buffer) {
|
||||
if !yaml_parser_update_raw_buffer(parser) {
|
||||
parser.buffer = parser.buffer[:buffer_len]
|
||||
return false
|
||||
}
|
||||
}
|
||||
first = false
|
||||
|
||||
// Decode the raw buffer.
|
||||
inner:
|
||||
for parser.raw_buffer_pos != len(parser.raw_buffer) {
|
||||
var value rune
|
||||
var width int
|
||||
|
||||
raw_unread := len(parser.raw_buffer) - parser.raw_buffer_pos
|
||||
|
||||
// Decode the next character.
|
||||
switch parser.encoding {
|
||||
case yaml_UTF8_ENCODING:
|
||||
// Decode a UTF-8 character. Check RFC 3629
|
||||
// (http://www.ietf.org/rfc/rfc3629.txt) for more details.
|
||||
//
|
||||
// The following table (taken from the RFC) is used for
|
||||
// decoding.
|
||||
//
|
||||
// Char. number range | UTF-8 octet sequence
|
||||
// (hexadecimal) | (binary)
|
||||
// --------------------+------------------------------------
|
||||
// 0000 0000-0000 007F | 0xxxxxxx
|
||||
// 0000 0080-0000 07FF | 110xxxxx 10xxxxxx
|
||||
// 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
|
||||
// 0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
|
||||
//
|
||||
// Additionally, the characters in the range 0xD800-0xDFFF
|
||||
// are prohibited as they are reserved for use with UTF-16
|
||||
// surrogate pairs.
|
||||
|
||||
// Determine the length of the UTF-8 sequence.
|
||||
octet := parser.raw_buffer[parser.raw_buffer_pos]
|
||||
switch {
|
||||
case octet&0x80 == 0x00:
|
||||
width = 1
|
||||
case octet&0xE0 == 0xC0:
|
||||
width = 2
|
||||
case octet&0xF0 == 0xE0:
|
||||
width = 3
|
||||
case octet&0xF8 == 0xF0:
|
||||
width = 4
|
||||
default:
|
||||
// The leading octet is invalid.
|
||||
return yaml_parser_set_reader_error(parser,
|
||||
"invalid leading UTF-8 octet",
|
||||
parser.offset, int(octet))
|
||||
}
|
||||
|
||||
// Check if the raw buffer contains an incomplete character.
|
||||
if width > raw_unread {
|
||||
if parser.eof {
|
||||
return yaml_parser_set_reader_error(parser,
|
||||
"incomplete UTF-8 octet sequence",
|
||||
parser.offset, -1)
|
||||
}
|
||||
break inner
|
||||
}
|
||||
|
||||
// Decode the leading octet.
|
||||
switch {
|
||||
case octet&0x80 == 0x00:
|
||||
value = rune(octet & 0x7F)
|
||||
case octet&0xE0 == 0xC0:
|
||||
value = rune(octet & 0x1F)
|
||||
case octet&0xF0 == 0xE0:
|
||||
value = rune(octet & 0x0F)
|
||||
case octet&0xF8 == 0xF0:
|
||||
value = rune(octet & 0x07)
|
||||
default:
|
||||
value = 0
|
||||
}
|
||||
|
||||
// Check and decode the trailing octets.
|
||||
for k := 1; k < width; k++ {
|
||||
octet = parser.raw_buffer[parser.raw_buffer_pos+k]
|
||||
|
||||
// Check if the octet is valid.
|
||||
if (octet & 0xC0) != 0x80 {
|
||||
return yaml_parser_set_reader_error(parser,
|
||||
"invalid trailing UTF-8 octet",
|
||||
parser.offset+k, int(octet))
|
||||
}
|
||||
|
||||
// Decode the octet.
|
||||
value = (value << 6) + rune(octet&0x3F)
|
||||
}
|
||||
|
||||
// Check the length of the sequence against the value.
|
||||
switch {
|
||||
case width == 1:
|
||||
case width == 2 && value >= 0x80:
|
||||
case width == 3 && value >= 0x800:
|
||||
case width == 4 && value >= 0x10000:
|
||||
default:
|
||||
return yaml_parser_set_reader_error(parser,
|
||||
"invalid length of a UTF-8 sequence",
|
||||
parser.offset, -1)
|
||||
}
|
||||
|
||||
// Check the range of the value.
|
||||
if value >= 0xD800 && value <= 0xDFFF || value > 0x10FFFF {
|
||||
return yaml_parser_set_reader_error(parser,
|
||||
"invalid Unicode character",
|
||||
parser.offset, int(value))
|
||||
}
|
||||
|
||||
case yaml_UTF16LE_ENCODING, yaml_UTF16BE_ENCODING:
|
||||
var low, high int
|
||||
if parser.encoding == yaml_UTF16LE_ENCODING {
|
||||
low, high = 0, 1
|
||||
} else {
|
||||
low, high = 1, 0
|
||||
}
|
||||
|
||||
// The UTF-16 encoding is not as simple as one might
|
||||
// naively think. Check RFC 2781
|
||||
// (http://www.ietf.org/rfc/rfc2781.txt).
|
||||
//
|
||||
// Normally, two subsequent bytes describe a Unicode
|
||||
// character. However a special technique (called a
|
||||
// surrogate pair) is used for specifying character
|
||||
// values larger than 0xFFFF.
|
||||
//
|
||||
// A surrogate pair consists of two pseudo-characters:
|
||||
// high surrogate area (0xD800-0xDBFF)
|
||||
// low surrogate area (0xDC00-0xDFFF)
|
||||
//
|
||||
// The following formulas are used for decoding
|
||||
// and encoding characters using surrogate pairs:
|
||||
//
|
||||
// U = U' + 0x10000 (0x01 00 00 <= U <= 0x10 FF FF)
|
||||
// U' = yyyyyyyyyyxxxxxxxxxx (0 <= U' <= 0x0F FF FF)
|
||||
// W1 = 110110yyyyyyyyyy
|
||||
// W2 = 110111xxxxxxxxxx
|
||||
//
|
||||
// where U is the character value, W1 is the high surrogate
|
||||
// area, W2 is the low surrogate area.
|
||||
|
||||
// Check for incomplete UTF-16 character.
|
||||
if raw_unread < 2 {
|
||||
if parser.eof {
|
||||
return yaml_parser_set_reader_error(parser,
|
||||
"incomplete UTF-16 character",
|
||||
parser.offset, -1)
|
||||
}
|
||||
break inner
|
||||
}
|
||||
|
||||
// Get the character.
|
||||
value = rune(parser.raw_buffer[parser.raw_buffer_pos+low]) +
|
||||
(rune(parser.raw_buffer[parser.raw_buffer_pos+high]) << 8)
|
||||
|
||||
// Check for unexpected low surrogate area.
|
||||
if value&0xFC00 == 0xDC00 {
|
||||
return yaml_parser_set_reader_error(parser,
|
||||
"unexpected low surrogate area",
|
||||
parser.offset, int(value))
|
||||
}
|
||||
|
||||
// Check for a high surrogate area.
|
||||
if value&0xFC00 == 0xD800 {
|
||||
width = 4
|
||||
|
||||
// Check for incomplete surrogate pair.
|
||||
if raw_unread < 4 {
|
||||
if parser.eof {
|
||||
return yaml_parser_set_reader_error(parser,
|
||||
"incomplete UTF-16 surrogate pair",
|
||||
parser.offset, -1)
|
||||
}
|
||||
break inner
|
||||
}
|
||||
|
||||
// Get the next character.
|
||||
value2 := rune(parser.raw_buffer[parser.raw_buffer_pos+low+2]) +
|
||||
(rune(parser.raw_buffer[parser.raw_buffer_pos+high+2]) << 8)
|
||||
|
||||
// Check for a low surrogate area.
|
||||
if value2&0xFC00 != 0xDC00 {
|
||||
return yaml_parser_set_reader_error(parser,
|
||||
"expected low surrogate area",
|
||||
parser.offset+2, int(value2))
|
||||
}
|
||||
|
||||
// Generate the value of the surrogate pair.
|
||||
value = 0x10000 + ((value & 0x3FF) << 10) + (value2 & 0x3FF)
|
||||
} else {
|
||||
width = 2
|
||||
}
|
||||
|
||||
default:
|
||||
panic("impossible")
|
||||
}
|
||||
|
||||
// Check if the character is in the allowed range:
|
||||
// #x9 | #xA | #xD | [#x20-#x7E] (8 bit)
|
||||
// | #x85 | [#xA0-#xD7FF] | [#xE000-#xFFFD] (16 bit)
|
||||
// | [#x10000-#x10FFFF] (32 bit)
|
||||
switch {
|
||||
case value == 0x09:
|
||||
case value == 0x0A:
|
||||
case value == 0x0D:
|
||||
case value >= 0x20 && value <= 0x7E:
|
||||
case value == 0x85:
|
||||
case value >= 0xA0 && value <= 0xD7FF:
|
||||
case value >= 0xE000 && value <= 0xFFFD:
|
||||
case value >= 0x10000 && value <= 0x10FFFF:
|
||||
default:
|
||||
return yaml_parser_set_reader_error(parser,
|
||||
"control characters are not allowed",
|
||||
parser.offset, int(value))
|
||||
}
|
||||
|
||||
// Move the raw pointers.
|
||||
parser.raw_buffer_pos += width
|
||||
parser.offset += width
|
||||
|
||||
// Finally put the character into the buffer.
|
||||
if value <= 0x7F {
|
||||
// 0000 0000-0000 007F . 0xxxxxxx
|
||||
parser.buffer[buffer_len+0] = byte(value)
|
||||
buffer_len += 1
|
||||
} else if value <= 0x7FF {
|
||||
// 0000 0080-0000 07FF . 110xxxxx 10xxxxxx
|
||||
parser.buffer[buffer_len+0] = byte(0xC0 + (value >> 6))
|
||||
parser.buffer[buffer_len+1] = byte(0x80 + (value & 0x3F))
|
||||
buffer_len += 2
|
||||
} else if value <= 0xFFFF {
|
||||
// 0000 0800-0000 FFFF . 1110xxxx 10xxxxxx 10xxxxxx
|
||||
parser.buffer[buffer_len+0] = byte(0xE0 + (value >> 12))
|
||||
parser.buffer[buffer_len+1] = byte(0x80 + ((value >> 6) & 0x3F))
|
||||
parser.buffer[buffer_len+2] = byte(0x80 + (value & 0x3F))
|
||||
buffer_len += 3
|
||||
} else {
|
||||
// 0001 0000-0010 FFFF . 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
|
||||
parser.buffer[buffer_len+0] = byte(0xF0 + (value >> 18))
|
||||
parser.buffer[buffer_len+1] = byte(0x80 + ((value >> 12) & 0x3F))
|
||||
parser.buffer[buffer_len+2] = byte(0x80 + ((value >> 6) & 0x3F))
|
||||
parser.buffer[buffer_len+3] = byte(0x80 + (value & 0x3F))
|
||||
buffer_len += 4
|
||||
}
|
||||
|
||||
parser.unread++
|
||||
}
|
||||
|
||||
// On EOF, put NUL into the buffer and return.
|
||||
if parser.eof {
|
||||
parser.buffer[buffer_len] = 0
|
||||
buffer_len++
|
||||
parser.unread++
|
||||
break
|
||||
}
|
||||
}
|
||||
// [Go] Read the documentation of this function above. To return true,
|
||||
// we need to have the given length in the buffer. Not doing that means
|
||||
// every single check that calls this function to make sure the buffer
|
||||
// has a given length is Go) panicking; or C) accessing invalid memory.
|
||||
// This happens here due to the EOF above breaking early.
|
||||
for buffer_len < length {
|
||||
parser.buffer[buffer_len] = 0
|
||||
buffer_len++
|
||||
}
|
||||
parser.buffer = parser.buffer[:buffer_len]
|
||||
return true
|
||||
}
|
258
vendor/gopkg.in/yaml.v2/resolve.go
generated
vendored
Normal file
258
vendor/gopkg.in/yaml.v2/resolve.go
generated
vendored
Normal file
@ -0,0 +1,258 @@
|
||||
package yaml
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"math"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
type resolveMapItem struct {
|
||||
value interface{}
|
||||
tag string
|
||||
}
|
||||
|
||||
var resolveTable = make([]byte, 256)
|
||||
var resolveMap = make(map[string]resolveMapItem)
|
||||
|
||||
func init() {
|
||||
t := resolveTable
|
||||
t[int('+')] = 'S' // Sign
|
||||
t[int('-')] = 'S'
|
||||
for _, c := range "0123456789" {
|
||||
t[int(c)] = 'D' // Digit
|
||||
}
|
||||
for _, c := range "yYnNtTfFoO~" {
|
||||
t[int(c)] = 'M' // In map
|
||||
}
|
||||
t[int('.')] = '.' // Float (potentially in map)
|
||||
|
||||
var resolveMapList = []struct {
|
||||
v interface{}
|
||||
tag string
|
||||
l []string
|
||||
}{
|
||||
{true, yaml_BOOL_TAG, []string{"y", "Y", "yes", "Yes", "YES"}},
|
||||
{true, yaml_BOOL_TAG, []string{"true", "True", "TRUE"}},
|
||||
{true, yaml_BOOL_TAG, []string{"on", "On", "ON"}},
|
||||
{false, yaml_BOOL_TAG, []string{"n", "N", "no", "No", "NO"}},
|
||||
{false, yaml_BOOL_TAG, []string{"false", "False", "FALSE"}},
|
||||
{false, yaml_BOOL_TAG, []string{"off", "Off", "OFF"}},
|
||||
{nil, yaml_NULL_TAG, []string{"", "~", "null", "Null", "NULL"}},
|
||||
{math.NaN(), yaml_FLOAT_TAG, []string{".nan", ".NaN", ".NAN"}},
|
||||
{math.Inf(+1), yaml_FLOAT_TAG, []string{".inf", ".Inf", ".INF"}},
|
||||
{math.Inf(+1), yaml_FLOAT_TAG, []string{"+.inf", "+.Inf", "+.INF"}},
|
||||
{math.Inf(-1), yaml_FLOAT_TAG, []string{"-.inf", "-.Inf", "-.INF"}},
|
||||
{"<<", yaml_MERGE_TAG, []string{"<<"}},
|
||||
}
|
||||
|
||||
m := resolveMap
|
||||
for _, item := range resolveMapList {
|
||||
for _, s := range item.l {
|
||||
m[s] = resolveMapItem{item.v, item.tag}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const longTagPrefix = "tag:yaml.org,2002:"
|
||||
|
||||
func shortTag(tag string) string {
|
||||
// TODO This can easily be made faster and produce less garbage.
|
||||
if strings.HasPrefix(tag, longTagPrefix) {
|
||||
return "!!" + tag[len(longTagPrefix):]
|
||||
}
|
||||
return tag
|
||||
}
|
||||
|
||||
func longTag(tag string) string {
|
||||
if strings.HasPrefix(tag, "!!") {
|
||||
return longTagPrefix + tag[2:]
|
||||
}
|
||||
return tag
|
||||
}
|
||||
|
||||
func resolvableTag(tag string) bool {
|
||||
switch tag {
|
||||
case "", yaml_STR_TAG, yaml_BOOL_TAG, yaml_INT_TAG, yaml_FLOAT_TAG, yaml_NULL_TAG, yaml_TIMESTAMP_TAG:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
var yamlStyleFloat = regexp.MustCompile(`^[-+]?[0-9]*\.?[0-9]+([eE][-+][0-9]+)?$`)
|
||||
|
||||
func resolve(tag string, in string) (rtag string, out interface{}) {
|
||||
if !resolvableTag(tag) {
|
||||
return tag, in
|
||||
}
|
||||
|
||||
defer func() {
|
||||
switch tag {
|
||||
case "", rtag, yaml_STR_TAG, yaml_BINARY_TAG:
|
||||
return
|
||||
case yaml_FLOAT_TAG:
|
||||
if rtag == yaml_INT_TAG {
|
||||
switch v := out.(type) {
|
||||
case int64:
|
||||
rtag = yaml_FLOAT_TAG
|
||||
out = float64(v)
|
||||
return
|
||||
case int:
|
||||
rtag = yaml_FLOAT_TAG
|
||||
out = float64(v)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
failf("cannot decode %s `%s` as a %s", shortTag(rtag), in, shortTag(tag))
|
||||
}()
|
||||
|
||||
// Any data is accepted as a !!str or !!binary.
|
||||
// Otherwise, the prefix is enough of a hint about what it might be.
|
||||
hint := byte('N')
|
||||
if in != "" {
|
||||
hint = resolveTable[in[0]]
|
||||
}
|
||||
if hint != 0 && tag != yaml_STR_TAG && tag != yaml_BINARY_TAG {
|
||||
// Handle things we can lookup in a map.
|
||||
if item, ok := resolveMap[in]; ok {
|
||||
return item.tag, item.value
|
||||
}
|
||||
|
||||
// Base 60 floats are a bad idea, were dropped in YAML 1.2, and
|
||||
// are purposefully unsupported here. They're still quoted on
|
||||
// the way out for compatibility with other parser, though.
|
||||
|
||||
switch hint {
|
||||
case 'M':
|
||||
// We've already checked the map above.
|
||||
|
||||
case '.':
|
||||
// Not in the map, so maybe a normal float.
|
||||
floatv, err := strconv.ParseFloat(in, 64)
|
||||
if err == nil {
|
||||
return yaml_FLOAT_TAG, floatv
|
||||
}
|
||||
|
||||
case 'D', 'S':
|
||||
// Int, float, or timestamp.
|
||||
// Only try values as a timestamp if the value is unquoted or there's an explicit
|
||||
// !!timestamp tag.
|
||||
if tag == "" || tag == yaml_TIMESTAMP_TAG {
|
||||
t, ok := parseTimestamp(in)
|
||||
if ok {
|
||||
return yaml_TIMESTAMP_TAG, t
|
||||
}
|
||||
}
|
||||
|
||||
plain := strings.Replace(in, "_", "", -1)
|
||||
intv, err := strconv.ParseInt(plain, 0, 64)
|
||||
if err == nil {
|
||||
if intv == int64(int(intv)) {
|
||||
return yaml_INT_TAG, int(intv)
|
||||
} else {
|
||||
return yaml_INT_TAG, intv
|
||||
}
|
||||
}
|
||||
uintv, err := strconv.ParseUint(plain, 0, 64)
|
||||
if err == nil {
|
||||
return yaml_INT_TAG, uintv
|
||||
}
|
||||
if yamlStyleFloat.MatchString(plain) {
|
||||
floatv, err := strconv.ParseFloat(plain, 64)
|
||||
if err == nil {
|
||||
return yaml_FLOAT_TAG, floatv
|
||||
}
|
||||
}
|
||||
if strings.HasPrefix(plain, "0b") {
|
||||
intv, err := strconv.ParseInt(plain[2:], 2, 64)
|
||||
if err == nil {
|
||||
if intv == int64(int(intv)) {
|
||||
return yaml_INT_TAG, int(intv)
|
||||
} else {
|
||||
return yaml_INT_TAG, intv
|
||||
}
|
||||
}
|
||||
uintv, err := strconv.ParseUint(plain[2:], 2, 64)
|
||||
if err == nil {
|
||||
return yaml_INT_TAG, uintv
|
||||
}
|
||||
} else if strings.HasPrefix(plain, "-0b") {
|
||||
intv, err := strconv.ParseInt("-" + plain[3:], 2, 64)
|
||||
if err == nil {
|
||||
if true || intv == int64(int(intv)) {
|
||||
return yaml_INT_TAG, int(intv)
|
||||
} else {
|
||||
return yaml_INT_TAG, intv
|
||||
}
|
||||
}
|
||||
}
|
||||
default:
|
||||
panic("resolveTable item not yet handled: " + string(rune(hint)) + " (with " + in + ")")
|
||||
}
|
||||
}
|
||||
return yaml_STR_TAG, in
|
||||
}
|
||||
|
||||
// encodeBase64 encodes s as base64 that is broken up into multiple lines
|
||||
// as appropriate for the resulting length.
|
||||
func encodeBase64(s string) string {
|
||||
const lineLen = 70
|
||||
encLen := base64.StdEncoding.EncodedLen(len(s))
|
||||
lines := encLen/lineLen + 1
|
||||
buf := make([]byte, encLen*2+lines)
|
||||
in := buf[0:encLen]
|
||||
out := buf[encLen:]
|
||||
base64.StdEncoding.Encode(in, []byte(s))
|
||||
k := 0
|
||||
for i := 0; i < len(in); i += lineLen {
|
||||
j := i + lineLen
|
||||
if j > len(in) {
|
||||
j = len(in)
|
||||
}
|
||||
k += copy(out[k:], in[i:j])
|
||||
if lines > 1 {
|
||||
out[k] = '\n'
|
||||
k++
|
||||
}
|
||||
}
|
||||
return string(out[:k])
|
||||
}
|
||||
|
||||
// This is a subset of the formats allowed by the regular expression
|
||||
// defined at http://yaml.org/type/timestamp.html.
|
||||
var allowedTimestampFormats = []string{
|
||||
"2006-1-2T15:4:5.999999999Z07:00", // RCF3339Nano with short date fields.
|
||||
"2006-1-2t15:4:5.999999999Z07:00", // RFC3339Nano with short date fields and lower-case "t".
|
||||
"2006-1-2 15:4:5.999999999", // space separated with no time zone
|
||||
"2006-1-2", // date only
|
||||
// Notable exception: time.Parse cannot handle: "2001-12-14 21:59:43.10 -5"
|
||||
// from the set of examples.
|
||||
}
|
||||
|
||||
// parseTimestamp parses s as a timestamp string and
|
||||
// returns the timestamp and reports whether it succeeded.
|
||||
// Timestamp formats are defined at http://yaml.org/type/timestamp.html
|
||||
func parseTimestamp(s string) (time.Time, bool) {
|
||||
// TODO write code to check all the formats supported by
|
||||
// http://yaml.org/type/timestamp.html instead of using time.Parse.
|
||||
|
||||
// Quick check: all date formats start with YYYY-.
|
||||
i := 0
|
||||
for ; i < len(s); i++ {
|
||||
if c := s[i]; c < '0' || c > '9' {
|
||||
break
|
||||
}
|
||||
}
|
||||
if i != 4 || i == len(s) || s[i] != '-' {
|
||||
return time.Time{}, false
|
||||
}
|
||||
for _, format := range allowedTimestampFormats {
|
||||
if t, err := time.Parse(format, s); err == nil {
|
||||
return t, true
|
||||
}
|
||||
}
|
||||
return time.Time{}, false
|
||||
}
|
2696
vendor/gopkg.in/yaml.v2/scannerc.go
generated
vendored
Normal file
2696
vendor/gopkg.in/yaml.v2/scannerc.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
113
vendor/gopkg.in/yaml.v2/sorter.go
generated
vendored
Normal file
113
vendor/gopkg.in/yaml.v2/sorter.go
generated
vendored
Normal file
@ -0,0 +1,113 @@
|
||||
package yaml
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"unicode"
|
||||
)
|
||||
|
||||
type keyList []reflect.Value
|
||||
|
||||
func (l keyList) Len() int { return len(l) }
|
||||
func (l keyList) Swap(i, j int) { l[i], l[j] = l[j], l[i] }
|
||||
func (l keyList) Less(i, j int) bool {
|
||||
a := l[i]
|
||||
b := l[j]
|
||||
ak := a.Kind()
|
||||
bk := b.Kind()
|
||||
for (ak == reflect.Interface || ak == reflect.Ptr) && !a.IsNil() {
|
||||
a = a.Elem()
|
||||
ak = a.Kind()
|
||||
}
|
||||
for (bk == reflect.Interface || bk == reflect.Ptr) && !b.IsNil() {
|
||||
b = b.Elem()
|
||||
bk = b.Kind()
|
||||
}
|
||||
af, aok := keyFloat(a)
|
||||
bf, bok := keyFloat(b)
|
||||
if aok && bok {
|
||||
if af != bf {
|
||||
return af < bf
|
||||
}
|
||||
if ak != bk {
|
||||
return ak < bk
|
||||
}
|
||||
return numLess(a, b)
|
||||
}
|
||||
if ak != reflect.String || bk != reflect.String {
|
||||
return ak < bk
|
||||
}
|
||||
ar, br := []rune(a.String()), []rune(b.String())
|
||||
for i := 0; i < len(ar) && i < len(br); i++ {
|
||||
if ar[i] == br[i] {
|
||||
continue
|
||||
}
|
||||
al := unicode.IsLetter(ar[i])
|
||||
bl := unicode.IsLetter(br[i])
|
||||
if al && bl {
|
||||
return ar[i] < br[i]
|
||||
}
|
||||
if al || bl {
|
||||
return bl
|
||||
}
|
||||
var ai, bi int
|
||||
var an, bn int64
|
||||
if ar[i] == '0' || br[i] == '0' {
|
||||
for j := i-1; j >= 0 && unicode.IsDigit(ar[j]); j-- {
|
||||
if ar[j] != '0' {
|
||||
an = 1
|
||||
bn = 1
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
for ai = i; ai < len(ar) && unicode.IsDigit(ar[ai]); ai++ {
|
||||
an = an*10 + int64(ar[ai]-'0')
|
||||
}
|
||||
for bi = i; bi < len(br) && unicode.IsDigit(br[bi]); bi++ {
|
||||
bn = bn*10 + int64(br[bi]-'0')
|
||||
}
|
||||
if an != bn {
|
||||
return an < bn
|
||||
}
|
||||
if ai != bi {
|
||||
return ai < bi
|
||||
}
|
||||
return ar[i] < br[i]
|
||||
}
|
||||
return len(ar) < len(br)
|
||||
}
|
||||
|
||||
// keyFloat returns a float value for v if it is a number/bool
|
||||
// and whether it is a number/bool or not.
|
||||
func keyFloat(v reflect.Value) (f float64, ok bool) {
|
||||
switch v.Kind() {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
return float64(v.Int()), true
|
||||
case reflect.Float32, reflect.Float64:
|
||||
return v.Float(), true
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||
return float64(v.Uint()), true
|
||||
case reflect.Bool:
|
||||
if v.Bool() {
|
||||
return 1, true
|
||||
}
|
||||
return 0, true
|
||||
}
|
||||
return 0, false
|
||||
}
|
||||
|
||||
// numLess returns whether a < b.
|
||||
// a and b must necessarily have the same kind.
|
||||
func numLess(a, b reflect.Value) bool {
|
||||
switch a.Kind() {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
return a.Int() < b.Int()
|
||||
case reflect.Float32, reflect.Float64:
|
||||
return a.Float() < b.Float()
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||
return a.Uint() < b.Uint()
|
||||
case reflect.Bool:
|
||||
return !a.Bool() && b.Bool()
|
||||
}
|
||||
panic("not a number")
|
||||
}
|
26
vendor/gopkg.in/yaml.v2/writerc.go
generated
vendored
Normal file
26
vendor/gopkg.in/yaml.v2/writerc.go
generated
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
package yaml
|
||||
|
||||
// Set the writer error and return false.
|
||||
func yaml_emitter_set_writer_error(emitter *yaml_emitter_t, problem string) bool {
|
||||
emitter.error = yaml_WRITER_ERROR
|
||||
emitter.problem = problem
|
||||
return false
|
||||
}
|
||||
|
||||
// Flush the output buffer.
|
||||
func yaml_emitter_flush(emitter *yaml_emitter_t) bool {
|
||||
if emitter.write_handler == nil {
|
||||
panic("write handler not set")
|
||||
}
|
||||
|
||||
// Check if the buffer is empty.
|
||||
if emitter.buffer_pos == 0 {
|
||||
return true
|
||||
}
|
||||
|
||||
if err := emitter.write_handler(emitter, emitter.buffer[:emitter.buffer_pos]); err != nil {
|
||||
return yaml_emitter_set_writer_error(emitter, "write error: "+err.Error())
|
||||
}
|
||||
emitter.buffer_pos = 0
|
||||
return true
|
||||
}
|
466
vendor/gopkg.in/yaml.v2/yaml.go
generated
vendored
Normal file
466
vendor/gopkg.in/yaml.v2/yaml.go
generated
vendored
Normal file
@ -0,0 +1,466 @@
|
||||
// Package yaml implements YAML support for the Go language.
|
||||
//
|
||||
// Source code and other details for the project are available at GitHub:
|
||||
//
|
||||
// https://github.com/go-yaml/yaml
|
||||
//
|
||||
package yaml
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"reflect"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// MapSlice encodes and decodes as a YAML map.
|
||||
// The order of keys is preserved when encoding and decoding.
|
||||
type MapSlice []MapItem
|
||||
|
||||
// MapItem is an item in a MapSlice.
|
||||
type MapItem struct {
|
||||
Key, Value interface{}
|
||||
}
|
||||
|
||||
// The Unmarshaler interface may be implemented by types to customize their
|
||||
// behavior when being unmarshaled from a YAML document. The UnmarshalYAML
|
||||
// method receives a function that may be called to unmarshal the original
|
||||
// YAML value into a field or variable. It is safe to call the unmarshal
|
||||
// function parameter more than once if necessary.
|
||||
type Unmarshaler interface {
|
||||
UnmarshalYAML(unmarshal func(interface{}) error) error
|
||||
}
|
||||
|
||||
// The Marshaler interface may be implemented by types to customize their
|
||||
// behavior when being marshaled into a YAML document. The returned value
|
||||
// is marshaled in place of the original value implementing Marshaler.
|
||||
//
|
||||
// If an error is returned by MarshalYAML, the marshaling procedure stops
|
||||
// and returns with the provided error.
|
||||
type Marshaler interface {
|
||||
MarshalYAML() (interface{}, error)
|
||||
}
|
||||
|
||||
// Unmarshal decodes the first document found within the in byte slice
|
||||
// and assigns decoded values into the out value.
|
||||
//
|
||||
// Maps and pointers (to a struct, string, int, etc) are accepted as out
|
||||
// values. If an internal pointer within a struct is not initialized,
|
||||
// the yaml package will initialize it if necessary for unmarshalling
|
||||
// the provided data. The out parameter must not be nil.
|
||||
//
|
||||
// The type of the decoded values should be compatible with the respective
|
||||
// values in out. If one or more values cannot be decoded due to a type
|
||||
// mismatches, decoding continues partially until the end of the YAML
|
||||
// content, and a *yaml.TypeError is returned with details for all
|
||||
// missed values.
|
||||
//
|
||||
// Struct fields are only unmarshalled if they are exported (have an
|
||||
// upper case first letter), and are unmarshalled using the field name
|
||||
// lowercased as the default key. Custom keys may be defined via the
|
||||
// "yaml" name in the field tag: the content preceding the first comma
|
||||
// is used as the key, and the following comma-separated options are
|
||||
// used to tweak the marshalling process (see Marshal).
|
||||
// Conflicting names result in a runtime error.
|
||||
//
|
||||
// For example:
|
||||
//
|
||||
// type T struct {
|
||||
// F int `yaml:"a,omitempty"`
|
||||
// B int
|
||||
// }
|
||||
// var t T
|
||||
// yaml.Unmarshal([]byte("a: 1\nb: 2"), &t)
|
||||
//
|
||||
// See the documentation of Marshal for the format of tags and a list of
|
||||
// supported tag options.
|
||||
//
|
||||
func Unmarshal(in []byte, out interface{}) (err error) {
|
||||
return unmarshal(in, out, false)
|
||||
}
|
||||
|
||||
// UnmarshalStrict is like Unmarshal except that any fields that are found
|
||||
// in the data that do not have corresponding struct members, or mapping
|
||||
// keys that are duplicates, will result in
|
||||
// an error.
|
||||
func UnmarshalStrict(in []byte, out interface{}) (err error) {
|
||||
return unmarshal(in, out, true)
|
||||
}
|
||||
|
||||
// A Decorder reads and decodes YAML values from an input stream.
|
||||
type Decoder struct {
|
||||
strict bool
|
||||
parser *parser
|
||||
}
|
||||
|
||||
// NewDecoder returns a new decoder that reads from r.
|
||||
//
|
||||
// The decoder introduces its own buffering and may read
|
||||
// data from r beyond the YAML values requested.
|
||||
func NewDecoder(r io.Reader) *Decoder {
|
||||
return &Decoder{
|
||||
parser: newParserFromReader(r),
|
||||
}
|
||||
}
|
||||
|
||||
// SetStrict sets whether strict decoding behaviour is enabled when
|
||||
// decoding items in the data (see UnmarshalStrict). By default, decoding is not strict.
|
||||
func (dec *Decoder) SetStrict(strict bool) {
|
||||
dec.strict = strict
|
||||
}
|
||||
|
||||
// Decode reads the next YAML-encoded value from its input
|
||||
// and stores it in the value pointed to by v.
|
||||
//
|
||||
// See the documentation for Unmarshal for details about the
|
||||
// conversion of YAML into a Go value.
|
||||
func (dec *Decoder) Decode(v interface{}) (err error) {
|
||||
d := newDecoder(dec.strict)
|
||||
defer handleErr(&err)
|
||||
node := dec.parser.parse()
|
||||
if node == nil {
|
||||
return io.EOF
|
||||
}
|
||||
out := reflect.ValueOf(v)
|
||||
if out.Kind() == reflect.Ptr && !out.IsNil() {
|
||||
out = out.Elem()
|
||||
}
|
||||
d.unmarshal(node, out)
|
||||
if len(d.terrors) > 0 {
|
||||
return &TypeError{d.terrors}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func unmarshal(in []byte, out interface{}, strict bool) (err error) {
|
||||
defer handleErr(&err)
|
||||
d := newDecoder(strict)
|
||||
p := newParser(in)
|
||||
defer p.destroy()
|
||||
node := p.parse()
|
||||
if node != nil {
|
||||
v := reflect.ValueOf(out)
|
||||
if v.Kind() == reflect.Ptr && !v.IsNil() {
|
||||
v = v.Elem()
|
||||
}
|
||||
d.unmarshal(node, v)
|
||||
}
|
||||
if len(d.terrors) > 0 {
|
||||
return &TypeError{d.terrors}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Marshal serializes the value provided into a YAML document. The structure
|
||||
// of the generated document will reflect the structure of the value itself.
|
||||
// Maps and pointers (to struct, string, int, etc) are accepted as the in value.
|
||||
//
|
||||
// Struct fields are only marshalled if they are exported (have an upper case
|
||||
// first letter), and are marshalled using the field name lowercased as the
|
||||
// default key. Custom keys may be defined via the "yaml" name in the field
|
||||
// tag: the content preceding the first comma is used as the key, and the
|
||||
// following comma-separated options are used to tweak the marshalling process.
|
||||
// Conflicting names result in a runtime error.
|
||||
//
|
||||
// The field tag format accepted is:
|
||||
//
|
||||
// `(...) yaml:"[<key>][,<flag1>[,<flag2>]]" (...)`
|
||||
//
|
||||
// The following flags are currently supported:
|
||||
//
|
||||
// omitempty Only include the field if it's not set to the zero
|
||||
// value for the type or to empty slices or maps.
|
||||
// Zero valued structs will be omitted if all their public
|
||||
// fields are zero, unless they implement an IsZero
|
||||
// method (see the IsZeroer interface type), in which
|
||||
// case the field will be included if that method returns true.
|
||||
//
|
||||
// flow Marshal using a flow style (useful for structs,
|
||||
// sequences and maps).
|
||||
//
|
||||
// inline Inline the field, which must be a struct or a map,
|
||||
// causing all of its fields or keys to be processed as if
|
||||
// they were part of the outer struct. For maps, keys must
|
||||
// not conflict with the yaml keys of other struct fields.
|
||||
//
|
||||
// In addition, if the key is "-", the field is ignored.
|
||||
//
|
||||
// For example:
|
||||
//
|
||||
// type T struct {
|
||||
// F int `yaml:"a,omitempty"`
|
||||
// B int
|
||||
// }
|
||||
// yaml.Marshal(&T{B: 2}) // Returns "b: 2\n"
|
||||
// yaml.Marshal(&T{F: 1}} // Returns "a: 1\nb: 0\n"
|
||||
//
|
||||
func Marshal(in interface{}) (out []byte, err error) {
|
||||
defer handleErr(&err)
|
||||
e := newEncoder()
|
||||
defer e.destroy()
|
||||
e.marshalDoc("", reflect.ValueOf(in))
|
||||
e.finish()
|
||||
out = e.out
|
||||
return
|
||||
}
|
||||
|
||||
// An Encoder writes YAML values to an output stream.
|
||||
type Encoder struct {
|
||||
encoder *encoder
|
||||
}
|
||||
|
||||
// NewEncoder returns a new encoder that writes to w.
|
||||
// The Encoder should be closed after use to flush all data
|
||||
// to w.
|
||||
func NewEncoder(w io.Writer) *Encoder {
|
||||
return &Encoder{
|
||||
encoder: newEncoderWithWriter(w),
|
||||
}
|
||||
}
|
||||
|
||||
// Encode writes the YAML encoding of v to the stream.
|
||||
// If multiple items are encoded to the stream, the
|
||||
// second and subsequent document will be preceded
|
||||
// with a "---" document separator, but the first will not.
|
||||
//
|
||||
// See the documentation for Marshal for details about the conversion of Go
|
||||
// values to YAML.
|
||||
func (e *Encoder) Encode(v interface{}) (err error) {
|
||||
defer handleErr(&err)
|
||||
e.encoder.marshalDoc("", reflect.ValueOf(v))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Close closes the encoder by writing any remaining data.
|
||||
// It does not write a stream terminating string "...".
|
||||
func (e *Encoder) Close() (err error) {
|
||||
defer handleErr(&err)
|
||||
e.encoder.finish()
|
||||
return nil
|
||||
}
|
||||
|
||||
func handleErr(err *error) {
|
||||
if v := recover(); v != nil {
|
||||
if e, ok := v.(yamlError); ok {
|
||||
*err = e.err
|
||||
} else {
|
||||
panic(v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type yamlError struct {
|
||||
err error
|
||||
}
|
||||
|
||||
func fail(err error) {
|
||||
panic(yamlError{err})
|
||||
}
|
||||
|
||||
func failf(format string, args ...interface{}) {
|
||||
panic(yamlError{fmt.Errorf("yaml: "+format, args...)})
|
||||
}
|
||||
|
||||
// A TypeError is returned by Unmarshal when one or more fields in
|
||||
// the YAML document cannot be properly decoded into the requested
|
||||
// types. When this error is returned, the value is still
|
||||
// unmarshaled partially.
|
||||
type TypeError struct {
|
||||
Errors []string
|
||||
}
|
||||
|
||||
func (e *TypeError) Error() string {
|
||||
return fmt.Sprintf("yaml: unmarshal errors:\n %s", strings.Join(e.Errors, "\n "))
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Maintain a mapping of keys to structure field indexes
|
||||
|
||||
// The code in this section was copied from mgo/bson.
|
||||
|
||||
// structInfo holds details for the serialization of fields of
|
||||
// a given struct.
|
||||
type structInfo struct {
|
||||
FieldsMap map[string]fieldInfo
|
||||
FieldsList []fieldInfo
|
||||
|
||||
// InlineMap is the number of the field in the struct that
|
||||
// contains an ,inline map, or -1 if there's none.
|
||||
InlineMap int
|
||||
}
|
||||
|
||||
type fieldInfo struct {
|
||||
Key string
|
||||
Num int
|
||||
OmitEmpty bool
|
||||
Flow bool
|
||||
// Id holds the unique field identifier, so we can cheaply
|
||||
// check for field duplicates without maintaining an extra map.
|
||||
Id int
|
||||
|
||||
// Inline holds the field index if the field is part of an inlined struct.
|
||||
Inline []int
|
||||
}
|
||||
|
||||
var structMap = make(map[reflect.Type]*structInfo)
|
||||
var fieldMapMutex sync.RWMutex
|
||||
|
||||
func getStructInfo(st reflect.Type) (*structInfo, error) {
|
||||
fieldMapMutex.RLock()
|
||||
sinfo, found := structMap[st]
|
||||
fieldMapMutex.RUnlock()
|
||||
if found {
|
||||
return sinfo, nil
|
||||
}
|
||||
|
||||
n := st.NumField()
|
||||
fieldsMap := make(map[string]fieldInfo)
|
||||
fieldsList := make([]fieldInfo, 0, n)
|
||||
inlineMap := -1
|
||||
for i := 0; i != n; i++ {
|
||||
field := st.Field(i)
|
||||
if field.PkgPath != "" && !field.Anonymous {
|
||||
continue // Private field
|
||||
}
|
||||
|
||||
info := fieldInfo{Num: i}
|
||||
|
||||
tag := field.Tag.Get("yaml")
|
||||
if tag == "" && strings.Index(string(field.Tag), ":") < 0 {
|
||||
tag = string(field.Tag)
|
||||
}
|
||||
if tag == "-" {
|
||||
continue
|
||||
}
|
||||
|
||||
inline := false
|
||||
fields := strings.Split(tag, ",")
|
||||
if len(fields) > 1 {
|
||||
for _, flag := range fields[1:] {
|
||||
switch flag {
|
||||
case "omitempty":
|
||||
info.OmitEmpty = true
|
||||
case "flow":
|
||||
info.Flow = true
|
||||
case "inline":
|
||||
inline = true
|
||||
default:
|
||||
return nil, errors.New(fmt.Sprintf("Unsupported flag %q in tag %q of type %s", flag, tag, st))
|
||||
}
|
||||
}
|
||||
tag = fields[0]
|
||||
}
|
||||
|
||||
if inline {
|
||||
switch field.Type.Kind() {
|
||||
case reflect.Map:
|
||||
if inlineMap >= 0 {
|
||||
return nil, errors.New("Multiple ,inline maps in struct " + st.String())
|
||||
}
|
||||
if field.Type.Key() != reflect.TypeOf("") {
|
||||
return nil, errors.New("Option ,inline needs a map with string keys in struct " + st.String())
|
||||
}
|
||||
inlineMap = info.Num
|
||||
case reflect.Struct:
|
||||
sinfo, err := getStructInfo(field.Type)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, finfo := range sinfo.FieldsList {
|
||||
if _, found := fieldsMap[finfo.Key]; found {
|
||||
msg := "Duplicated key '" + finfo.Key + "' in struct " + st.String()
|
||||
return nil, errors.New(msg)
|
||||
}
|
||||
if finfo.Inline == nil {
|
||||
finfo.Inline = []int{i, finfo.Num}
|
||||
} else {
|
||||
finfo.Inline = append([]int{i}, finfo.Inline...)
|
||||
}
|
||||
finfo.Id = len(fieldsList)
|
||||
fieldsMap[finfo.Key] = finfo
|
||||
fieldsList = append(fieldsList, finfo)
|
||||
}
|
||||
default:
|
||||
//return nil, errors.New("Option ,inline needs a struct value or map field")
|
||||
return nil, errors.New("Option ,inline needs a struct value field")
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if tag != "" {
|
||||
info.Key = tag
|
||||
} else {
|
||||
info.Key = strings.ToLower(field.Name)
|
||||
}
|
||||
|
||||
if _, found = fieldsMap[info.Key]; found {
|
||||
msg := "Duplicated key '" + info.Key + "' in struct " + st.String()
|
||||
return nil, errors.New(msg)
|
||||
}
|
||||
|
||||
info.Id = len(fieldsList)
|
||||
fieldsList = append(fieldsList, info)
|
||||
fieldsMap[info.Key] = info
|
||||
}
|
||||
|
||||
sinfo = &structInfo{
|
||||
FieldsMap: fieldsMap,
|
||||
FieldsList: fieldsList,
|
||||
InlineMap: inlineMap,
|
||||
}
|
||||
|
||||
fieldMapMutex.Lock()
|
||||
structMap[st] = sinfo
|
||||
fieldMapMutex.Unlock()
|
||||
return sinfo, nil
|
||||
}
|
||||
|
||||
// IsZeroer is used to check whether an object is zero to
|
||||
// determine whether it should be omitted when marshaling
|
||||
// with the omitempty flag. One notable implementation
|
||||
// is time.Time.
|
||||
type IsZeroer interface {
|
||||
IsZero() bool
|
||||
}
|
||||
|
||||
func isZero(v reflect.Value) bool {
|
||||
kind := v.Kind()
|
||||
if z, ok := v.Interface().(IsZeroer); ok {
|
||||
if (kind == reflect.Ptr || kind == reflect.Interface) && v.IsNil() {
|
||||
return true
|
||||
}
|
||||
return z.IsZero()
|
||||
}
|
||||
switch kind {
|
||||
case reflect.String:
|
||||
return len(v.String()) == 0
|
||||
case reflect.Interface, reflect.Ptr:
|
||||
return v.IsNil()
|
||||
case reflect.Slice:
|
||||
return v.Len() == 0
|
||||
case reflect.Map:
|
||||
return v.Len() == 0
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
return v.Int() == 0
|
||||
case reflect.Float32, reflect.Float64:
|
||||
return v.Float() == 0
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||
return v.Uint() == 0
|
||||
case reflect.Bool:
|
||||
return !v.Bool()
|
||||
case reflect.Struct:
|
||||
vt := v.Type()
|
||||
for i := v.NumField() - 1; i >= 0; i-- {
|
||||
if vt.Field(i).PkgPath != "" {
|
||||
continue // Private field
|
||||
}
|
||||
if !isZero(v.Field(i)) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
738
vendor/gopkg.in/yaml.v2/yamlh.go
generated
vendored
Normal file
738
vendor/gopkg.in/yaml.v2/yamlh.go
generated
vendored
Normal file
@ -0,0 +1,738 @@
|
||||
package yaml
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
|
||||
// The version directive data.
|
||||
type yaml_version_directive_t struct {
|
||||
major int8 // The major version number.
|
||||
minor int8 // The minor version number.
|
||||
}
|
||||
|
||||
// The tag directive data.
|
||||
type yaml_tag_directive_t struct {
|
||||
handle []byte // The tag handle.
|
||||
prefix []byte // The tag prefix.
|
||||
}
|
||||
|
||||
type yaml_encoding_t int
|
||||
|
||||
// The stream encoding.
|
||||
const (
|
||||
// Let the parser choose the encoding.
|
||||
yaml_ANY_ENCODING yaml_encoding_t = iota
|
||||
|
||||
yaml_UTF8_ENCODING // The default UTF-8 encoding.
|
||||
yaml_UTF16LE_ENCODING // The UTF-16-LE encoding with BOM.
|
||||
yaml_UTF16BE_ENCODING // The UTF-16-BE encoding with BOM.
|
||||
)
|
||||
|
||||
type yaml_break_t int
|
||||
|
||||
// Line break types.
|
||||
const (
|
||||
// Let the parser choose the break type.
|
||||
yaml_ANY_BREAK yaml_break_t = iota
|
||||
|
||||
yaml_CR_BREAK // Use CR for line breaks (Mac style).
|
||||
yaml_LN_BREAK // Use LN for line breaks (Unix style).
|
||||
yaml_CRLN_BREAK // Use CR LN for line breaks (DOS style).
|
||||
)
|
||||
|
||||
type yaml_error_type_t int
|
||||
|
||||
// Many bad things could happen with the parser and emitter.
|
||||
const (
|
||||
// No error is produced.
|
||||
yaml_NO_ERROR yaml_error_type_t = iota
|
||||
|
||||
yaml_MEMORY_ERROR // Cannot allocate or reallocate a block of memory.
|
||||
yaml_READER_ERROR // Cannot read or decode the input stream.
|
||||
yaml_SCANNER_ERROR // Cannot scan the input stream.
|
||||
yaml_PARSER_ERROR // Cannot parse the input stream.
|
||||
yaml_COMPOSER_ERROR // Cannot compose a YAML document.
|
||||
yaml_WRITER_ERROR // Cannot write to the output stream.
|
||||
yaml_EMITTER_ERROR // Cannot emit a YAML stream.
|
||||
)
|
||||
|
||||
// The pointer position.
|
||||
type yaml_mark_t struct {
|
||||
index int // The position index.
|
||||
line int // The position line.
|
||||
column int // The position column.
|
||||
}
|
||||
|
||||
// Node Styles
|
||||
|
||||
type yaml_style_t int8
|
||||
|
||||
type yaml_scalar_style_t yaml_style_t
|
||||
|
||||
// Scalar styles.
|
||||
const (
|
||||
// Let the emitter choose the style.
|
||||
yaml_ANY_SCALAR_STYLE yaml_scalar_style_t = iota
|
||||
|
||||
yaml_PLAIN_SCALAR_STYLE // The plain scalar style.
|
||||
yaml_SINGLE_QUOTED_SCALAR_STYLE // The single-quoted scalar style.
|
||||
yaml_DOUBLE_QUOTED_SCALAR_STYLE // The double-quoted scalar style.
|
||||
yaml_LITERAL_SCALAR_STYLE // The literal scalar style.
|
||||
yaml_FOLDED_SCALAR_STYLE // The folded scalar style.
|
||||
)
|
||||
|
||||
type yaml_sequence_style_t yaml_style_t
|
||||
|
||||
// Sequence styles.
|
||||
const (
|
||||
// Let the emitter choose the style.
|
||||
yaml_ANY_SEQUENCE_STYLE yaml_sequence_style_t = iota
|
||||
|
||||
yaml_BLOCK_SEQUENCE_STYLE // The block sequence style.
|
||||
yaml_FLOW_SEQUENCE_STYLE // The flow sequence style.
|
||||
)
|
||||
|
||||
type yaml_mapping_style_t yaml_style_t
|
||||
|
||||
// Mapping styles.
|
||||
const (
|
||||
// Let the emitter choose the style.
|
||||
yaml_ANY_MAPPING_STYLE yaml_mapping_style_t = iota
|
||||
|
||||
yaml_BLOCK_MAPPING_STYLE // The block mapping style.
|
||||
yaml_FLOW_MAPPING_STYLE // The flow mapping style.
|
||||
)
|
||||
|
||||
// Tokens
|
||||
|
||||
type yaml_token_type_t int
|
||||
|
||||
// Token types.
|
||||
const (
|
||||
// An empty token.
|
||||
yaml_NO_TOKEN yaml_token_type_t = iota
|
||||
|
||||
yaml_STREAM_START_TOKEN // A STREAM-START token.
|
||||
yaml_STREAM_END_TOKEN // A STREAM-END token.
|
||||
|
||||
yaml_VERSION_DIRECTIVE_TOKEN // A VERSION-DIRECTIVE token.
|
||||
yaml_TAG_DIRECTIVE_TOKEN // A TAG-DIRECTIVE token.
|
||||
yaml_DOCUMENT_START_TOKEN // A DOCUMENT-START token.
|
||||
yaml_DOCUMENT_END_TOKEN // A DOCUMENT-END token.
|
||||
|
||||
yaml_BLOCK_SEQUENCE_START_TOKEN // A BLOCK-SEQUENCE-START token.
|
||||
yaml_BLOCK_MAPPING_START_TOKEN // A BLOCK-SEQUENCE-END token.
|
||||
yaml_BLOCK_END_TOKEN // A BLOCK-END token.
|
||||
|
||||
yaml_FLOW_SEQUENCE_START_TOKEN // A FLOW-SEQUENCE-START token.
|
||||
yaml_FLOW_SEQUENCE_END_TOKEN // A FLOW-SEQUENCE-END token.
|
||||
yaml_FLOW_MAPPING_START_TOKEN // A FLOW-MAPPING-START token.
|
||||
yaml_FLOW_MAPPING_END_TOKEN // A FLOW-MAPPING-END token.
|
||||
|
||||
yaml_BLOCK_ENTRY_TOKEN // A BLOCK-ENTRY token.
|
||||
yaml_FLOW_ENTRY_TOKEN // A FLOW-ENTRY token.
|
||||
yaml_KEY_TOKEN // A KEY token.
|
||||
yaml_VALUE_TOKEN // A VALUE token.
|
||||
|
||||
yaml_ALIAS_TOKEN // An ALIAS token.
|
||||
yaml_ANCHOR_TOKEN // An ANCHOR token.
|
||||
yaml_TAG_TOKEN // A TAG token.
|
||||
yaml_SCALAR_TOKEN // A SCALAR token.
|
||||
)
|
||||
|
||||
func (tt yaml_token_type_t) String() string {
|
||||
switch tt {
|
||||
case yaml_NO_TOKEN:
|
||||
return "yaml_NO_TOKEN"
|
||||
case yaml_STREAM_START_TOKEN:
|
||||
return "yaml_STREAM_START_TOKEN"
|
||||
case yaml_STREAM_END_TOKEN:
|
||||
return "yaml_STREAM_END_TOKEN"
|
||||
case yaml_VERSION_DIRECTIVE_TOKEN:
|
||||
return "yaml_VERSION_DIRECTIVE_TOKEN"
|
||||
case yaml_TAG_DIRECTIVE_TOKEN:
|
||||
return "yaml_TAG_DIRECTIVE_TOKEN"
|
||||
case yaml_DOCUMENT_START_TOKEN:
|
||||
return "yaml_DOCUMENT_START_TOKEN"
|
||||
case yaml_DOCUMENT_END_TOKEN:
|
||||
return "yaml_DOCUMENT_END_TOKEN"
|
||||
case yaml_BLOCK_SEQUENCE_START_TOKEN:
|
||||
return "yaml_BLOCK_SEQUENCE_START_TOKEN"
|
||||
case yaml_BLOCK_MAPPING_START_TOKEN:
|
||||
return "yaml_BLOCK_MAPPING_START_TOKEN"
|
||||
case yaml_BLOCK_END_TOKEN:
|
||||
return "yaml_BLOCK_END_TOKEN"
|
||||
case yaml_FLOW_SEQUENCE_START_TOKEN:
|
||||
return "yaml_FLOW_SEQUENCE_START_TOKEN"
|
||||
case yaml_FLOW_SEQUENCE_END_TOKEN:
|
||||
return "yaml_FLOW_SEQUENCE_END_TOKEN"
|
||||
case yaml_FLOW_MAPPING_START_TOKEN:
|
||||
return "yaml_FLOW_MAPPING_START_TOKEN"
|
||||
case yaml_FLOW_MAPPING_END_TOKEN:
|
||||
return "yaml_FLOW_MAPPING_END_TOKEN"
|
||||
case yaml_BLOCK_ENTRY_TOKEN:
|
||||
return "yaml_BLOCK_ENTRY_TOKEN"
|
||||
case yaml_FLOW_ENTRY_TOKEN:
|
||||
return "yaml_FLOW_ENTRY_TOKEN"
|
||||
case yaml_KEY_TOKEN:
|
||||
return "yaml_KEY_TOKEN"
|
||||
case yaml_VALUE_TOKEN:
|
||||
return "yaml_VALUE_TOKEN"
|
||||
case yaml_ALIAS_TOKEN:
|
||||
return "yaml_ALIAS_TOKEN"
|
||||
case yaml_ANCHOR_TOKEN:
|
||||
return "yaml_ANCHOR_TOKEN"
|
||||
case yaml_TAG_TOKEN:
|
||||
return "yaml_TAG_TOKEN"
|
||||
case yaml_SCALAR_TOKEN:
|
||||
return "yaml_SCALAR_TOKEN"
|
||||
}
|
||||
return "<unknown token>"
|
||||
}
|
||||
|
||||
// The token structure.
|
||||
type yaml_token_t struct {
|
||||
// The token type.
|
||||
typ yaml_token_type_t
|
||||
|
||||
// The start/end of the token.
|
||||
start_mark, end_mark yaml_mark_t
|
||||
|
||||
// The stream encoding (for yaml_STREAM_START_TOKEN).
|
||||
encoding yaml_encoding_t
|
||||
|
||||
// The alias/anchor/scalar value or tag/tag directive handle
|
||||
// (for yaml_ALIAS_TOKEN, yaml_ANCHOR_TOKEN, yaml_SCALAR_TOKEN, yaml_TAG_TOKEN, yaml_TAG_DIRECTIVE_TOKEN).
|
||||
value []byte
|
||||
|
||||
// The tag suffix (for yaml_TAG_TOKEN).
|
||||
suffix []byte
|
||||
|
||||
// The tag directive prefix (for yaml_TAG_DIRECTIVE_TOKEN).
|
||||
prefix []byte
|
||||
|
||||
// The scalar style (for yaml_SCALAR_TOKEN).
|
||||
style yaml_scalar_style_t
|
||||
|
||||
// The version directive major/minor (for yaml_VERSION_DIRECTIVE_TOKEN).
|
||||
major, minor int8
|
||||
}
|
||||
|
||||
// Events
|
||||
|
||||
type yaml_event_type_t int8
|
||||
|
||||
// Event types.
|
||||
const (
|
||||
// An empty event.
|
||||
yaml_NO_EVENT yaml_event_type_t = iota
|
||||
|
||||
yaml_STREAM_START_EVENT // A STREAM-START event.
|
||||
yaml_STREAM_END_EVENT // A STREAM-END event.
|
||||
yaml_DOCUMENT_START_EVENT // A DOCUMENT-START event.
|
||||
yaml_DOCUMENT_END_EVENT // A DOCUMENT-END event.
|
||||
yaml_ALIAS_EVENT // An ALIAS event.
|
||||
yaml_SCALAR_EVENT // A SCALAR event.
|
||||
yaml_SEQUENCE_START_EVENT // A SEQUENCE-START event.
|
||||
yaml_SEQUENCE_END_EVENT // A SEQUENCE-END event.
|
||||
yaml_MAPPING_START_EVENT // A MAPPING-START event.
|
||||
yaml_MAPPING_END_EVENT // A MAPPING-END event.
|
||||
)
|
||||
|
||||
var eventStrings = []string{
|
||||
yaml_NO_EVENT: "none",
|
||||
yaml_STREAM_START_EVENT: "stream start",
|
||||
yaml_STREAM_END_EVENT: "stream end",
|
||||
yaml_DOCUMENT_START_EVENT: "document start",
|
||||
yaml_DOCUMENT_END_EVENT: "document end",
|
||||
yaml_ALIAS_EVENT: "alias",
|
||||
yaml_SCALAR_EVENT: "scalar",
|
||||
yaml_SEQUENCE_START_EVENT: "sequence start",
|
||||
yaml_SEQUENCE_END_EVENT: "sequence end",
|
||||
yaml_MAPPING_START_EVENT: "mapping start",
|
||||
yaml_MAPPING_END_EVENT: "mapping end",
|
||||
}
|
||||
|
||||
func (e yaml_event_type_t) String() string {
|
||||
if e < 0 || int(e) >= len(eventStrings) {
|
||||
return fmt.Sprintf("unknown event %d", e)
|
||||
}
|
||||
return eventStrings[e]
|
||||
}
|
||||
|
||||
// The event structure.
|
||||
type yaml_event_t struct {
|
||||
|
||||
// The event type.
|
||||
typ yaml_event_type_t
|
||||
|
||||
// The start and end of the event.
|
||||
start_mark, end_mark yaml_mark_t
|
||||
|
||||
// The document encoding (for yaml_STREAM_START_EVENT).
|
||||
encoding yaml_encoding_t
|
||||
|
||||
// The version directive (for yaml_DOCUMENT_START_EVENT).
|
||||
version_directive *yaml_version_directive_t
|
||||
|
||||
// The list of tag directives (for yaml_DOCUMENT_START_EVENT).
|
||||
tag_directives []yaml_tag_directive_t
|
||||
|
||||
// The anchor (for yaml_SCALAR_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT, yaml_ALIAS_EVENT).
|
||||
anchor []byte
|
||||
|
||||
// The tag (for yaml_SCALAR_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT).
|
||||
tag []byte
|
||||
|
||||
// The scalar value (for yaml_SCALAR_EVENT).
|
||||
value []byte
|
||||
|
||||
// Is the document start/end indicator implicit, or the tag optional?
|
||||
// (for yaml_DOCUMENT_START_EVENT, yaml_DOCUMENT_END_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT, yaml_SCALAR_EVENT).
|
||||
implicit bool
|
||||
|
||||
// Is the tag optional for any non-plain style? (for yaml_SCALAR_EVENT).
|
||||
quoted_implicit bool
|
||||
|
||||
// The style (for yaml_SCALAR_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT).
|
||||
style yaml_style_t
|
||||
}
|
||||
|
||||
func (e *yaml_event_t) scalar_style() yaml_scalar_style_t { return yaml_scalar_style_t(e.style) }
|
||||
func (e *yaml_event_t) sequence_style() yaml_sequence_style_t { return yaml_sequence_style_t(e.style) }
|
||||
func (e *yaml_event_t) mapping_style() yaml_mapping_style_t { return yaml_mapping_style_t(e.style) }
|
||||
|
||||
// Nodes
|
||||
|
||||
const (
|
||||
yaml_NULL_TAG = "tag:yaml.org,2002:null" // The tag !!null with the only possible value: null.
|
||||
yaml_BOOL_TAG = "tag:yaml.org,2002:bool" // The tag !!bool with the values: true and false.
|
||||
yaml_STR_TAG = "tag:yaml.org,2002:str" // The tag !!str for string values.
|
||||
yaml_INT_TAG = "tag:yaml.org,2002:int" // The tag !!int for integer values.
|
||||
yaml_FLOAT_TAG = "tag:yaml.org,2002:float" // The tag !!float for float values.
|
||||
yaml_TIMESTAMP_TAG = "tag:yaml.org,2002:timestamp" // The tag !!timestamp for date and time values.
|
||||
|
||||
yaml_SEQ_TAG = "tag:yaml.org,2002:seq" // The tag !!seq is used to denote sequences.
|
||||
yaml_MAP_TAG = "tag:yaml.org,2002:map" // The tag !!map is used to denote mapping.
|
||||
|
||||
// Not in original libyaml.
|
||||
yaml_BINARY_TAG = "tag:yaml.org,2002:binary"
|
||||
yaml_MERGE_TAG = "tag:yaml.org,2002:merge"
|
||||
|
||||
yaml_DEFAULT_SCALAR_TAG = yaml_STR_TAG // The default scalar tag is !!str.
|
||||
yaml_DEFAULT_SEQUENCE_TAG = yaml_SEQ_TAG // The default sequence tag is !!seq.
|
||||
yaml_DEFAULT_MAPPING_TAG = yaml_MAP_TAG // The default mapping tag is !!map.
|
||||
)
|
||||
|
||||
type yaml_node_type_t int
|
||||
|
||||
// Node types.
|
||||
const (
|
||||
// An empty node.
|
||||
yaml_NO_NODE yaml_node_type_t = iota
|
||||
|
||||
yaml_SCALAR_NODE // A scalar node.
|
||||
yaml_SEQUENCE_NODE // A sequence node.
|
||||
yaml_MAPPING_NODE // A mapping node.
|
||||
)
|
||||
|
||||
// An element of a sequence node.
|
||||
type yaml_node_item_t int
|
||||
|
||||
// An element of a mapping node.
|
||||
type yaml_node_pair_t struct {
|
||||
key int // The key of the element.
|
||||
value int // The value of the element.
|
||||
}
|
||||
|
||||
// The node structure.
|
||||
type yaml_node_t struct {
|
||||
typ yaml_node_type_t // The node type.
|
||||
tag []byte // The node tag.
|
||||
|
||||
// The node data.
|
||||
|
||||
// The scalar parameters (for yaml_SCALAR_NODE).
|
||||
scalar struct {
|
||||
value []byte // The scalar value.
|
||||
length int // The length of the scalar value.
|
||||
style yaml_scalar_style_t // The scalar style.
|
||||
}
|
||||
|
||||
// The sequence parameters (for YAML_SEQUENCE_NODE).
|
||||
sequence struct {
|
||||
items_data []yaml_node_item_t // The stack of sequence items.
|
||||
style yaml_sequence_style_t // The sequence style.
|
||||
}
|
||||
|
||||
// The mapping parameters (for yaml_MAPPING_NODE).
|
||||
mapping struct {
|
||||
pairs_data []yaml_node_pair_t // The stack of mapping pairs (key, value).
|
||||
pairs_start *yaml_node_pair_t // The beginning of the stack.
|
||||
pairs_end *yaml_node_pair_t // The end of the stack.
|
||||
pairs_top *yaml_node_pair_t // The top of the stack.
|
||||
style yaml_mapping_style_t // The mapping style.
|
||||
}
|
||||
|
||||
start_mark yaml_mark_t // The beginning of the node.
|
||||
end_mark yaml_mark_t // The end of the node.
|
||||
|
||||
}
|
||||
|
||||
// The document structure.
|
||||
type yaml_document_t struct {
|
||||
|
||||
// The document nodes.
|
||||
nodes []yaml_node_t
|
||||
|
||||
// The version directive.
|
||||
version_directive *yaml_version_directive_t
|
||||
|
||||
// The list of tag directives.
|
||||
tag_directives_data []yaml_tag_directive_t
|
||||
tag_directives_start int // The beginning of the tag directives list.
|
||||
tag_directives_end int // The end of the tag directives list.
|
||||
|
||||
start_implicit int // Is the document start indicator implicit?
|
||||
end_implicit int // Is the document end indicator implicit?
|
||||
|
||||
// The start/end of the document.
|
||||
start_mark, end_mark yaml_mark_t
|
||||
}
|
||||
|
||||
// The prototype of a read handler.
|
||||
//
|
||||
// The read handler is called when the parser needs to read more bytes from the
|
||||
// source. The handler should write not more than size bytes to the buffer.
|
||||
// The number of written bytes should be set to the size_read variable.
|
||||
//
|
||||
// [in,out] data A pointer to an application data specified by
|
||||
// yaml_parser_set_input().
|
||||
// [out] buffer The buffer to write the data from the source.
|
||||
// [in] size The size of the buffer.
|
||||
// [out] size_read The actual number of bytes read from the source.
|
||||
//
|
||||
// On success, the handler should return 1. If the handler failed,
|
||||
// the returned value should be 0. On EOF, the handler should set the
|
||||
// size_read to 0 and return 1.
|
||||
type yaml_read_handler_t func(parser *yaml_parser_t, buffer []byte) (n int, err error)
|
||||
|
||||
// This structure holds information about a potential simple key.
|
||||
type yaml_simple_key_t struct {
|
||||
possible bool // Is a simple key possible?
|
||||
required bool // Is a simple key required?
|
||||
token_number int // The number of the token.
|
||||
mark yaml_mark_t // The position mark.
|
||||
}
|
||||
|
||||
// The states of the parser.
|
||||
type yaml_parser_state_t int
|
||||
|
||||
const (
|
||||
yaml_PARSE_STREAM_START_STATE yaml_parser_state_t = iota
|
||||
|
||||
yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE // Expect the beginning of an implicit document.
|
||||
yaml_PARSE_DOCUMENT_START_STATE // Expect DOCUMENT-START.
|
||||
yaml_PARSE_DOCUMENT_CONTENT_STATE // Expect the content of a document.
|
||||
yaml_PARSE_DOCUMENT_END_STATE // Expect DOCUMENT-END.
|
||||
yaml_PARSE_BLOCK_NODE_STATE // Expect a block node.
|
||||
yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE // Expect a block node or indentless sequence.
|
||||
yaml_PARSE_FLOW_NODE_STATE // Expect a flow node.
|
||||
yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE // Expect the first entry of a block sequence.
|
||||
yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE // Expect an entry of a block sequence.
|
||||
yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE // Expect an entry of an indentless sequence.
|
||||
yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE // Expect the first key of a block mapping.
|
||||
yaml_PARSE_BLOCK_MAPPING_KEY_STATE // Expect a block mapping key.
|
||||
yaml_PARSE_BLOCK_MAPPING_VALUE_STATE // Expect a block mapping value.
|
||||
yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE // Expect the first entry of a flow sequence.
|
||||
yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE // Expect an entry of a flow sequence.
|
||||
yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE // Expect a key of an ordered mapping.
|
||||
yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE // Expect a value of an ordered mapping.
|
||||
yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE // Expect the and of an ordered mapping entry.
|
||||
yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE // Expect the first key of a flow mapping.
|
||||
yaml_PARSE_FLOW_MAPPING_KEY_STATE // Expect a key of a flow mapping.
|
||||
yaml_PARSE_FLOW_MAPPING_VALUE_STATE // Expect a value of a flow mapping.
|
||||
yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE // Expect an empty value of a flow mapping.
|
||||
yaml_PARSE_END_STATE // Expect nothing.
|
||||
)
|
||||
|
||||
func (ps yaml_parser_state_t) String() string {
|
||||
switch ps {
|
||||
case yaml_PARSE_STREAM_START_STATE:
|
||||
return "yaml_PARSE_STREAM_START_STATE"
|
||||
case yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE:
|
||||
return "yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE"
|
||||
case yaml_PARSE_DOCUMENT_START_STATE:
|
||||
return "yaml_PARSE_DOCUMENT_START_STATE"
|
||||
case yaml_PARSE_DOCUMENT_CONTENT_STATE:
|
||||
return "yaml_PARSE_DOCUMENT_CONTENT_STATE"
|
||||
case yaml_PARSE_DOCUMENT_END_STATE:
|
||||
return "yaml_PARSE_DOCUMENT_END_STATE"
|
||||
case yaml_PARSE_BLOCK_NODE_STATE:
|
||||
return "yaml_PARSE_BLOCK_NODE_STATE"
|
||||
case yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE:
|
||||
return "yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE"
|
||||
case yaml_PARSE_FLOW_NODE_STATE:
|
||||
return "yaml_PARSE_FLOW_NODE_STATE"
|
||||
case yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE:
|
||||
return "yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE"
|
||||
case yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE:
|
||||
return "yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE"
|
||||
case yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE:
|
||||
return "yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE"
|
||||
case yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE:
|
||||
return "yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE"
|
||||
case yaml_PARSE_BLOCK_MAPPING_KEY_STATE:
|
||||
return "yaml_PARSE_BLOCK_MAPPING_KEY_STATE"
|
||||
case yaml_PARSE_BLOCK_MAPPING_VALUE_STATE:
|
||||
return "yaml_PARSE_BLOCK_MAPPING_VALUE_STATE"
|
||||
case yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE:
|
||||
return "yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE"
|
||||
case yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE:
|
||||
return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE"
|
||||
case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE:
|
||||
return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE"
|
||||
case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE:
|
||||
return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE"
|
||||
case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE:
|
||||
return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE"
|
||||
case yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE:
|
||||
return "yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE"
|
||||
case yaml_PARSE_FLOW_MAPPING_KEY_STATE:
|
||||
return "yaml_PARSE_FLOW_MAPPING_KEY_STATE"
|
||||
case yaml_PARSE_FLOW_MAPPING_VALUE_STATE:
|
||||
return "yaml_PARSE_FLOW_MAPPING_VALUE_STATE"
|
||||
case yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE:
|
||||
return "yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE"
|
||||
case yaml_PARSE_END_STATE:
|
||||
return "yaml_PARSE_END_STATE"
|
||||
}
|
||||
return "<unknown parser state>"
|
||||
}
|
||||
|
||||
// This structure holds aliases data.
|
||||
type yaml_alias_data_t struct {
|
||||
anchor []byte // The anchor.
|
||||
index int // The node id.
|
||||
mark yaml_mark_t // The anchor mark.
|
||||
}
|
||||
|
||||
// The parser structure.
|
||||
//
|
||||
// All members are internal. Manage the structure using the
|
||||
// yaml_parser_ family of functions.
|
||||
type yaml_parser_t struct {
|
||||
|
||||
// Error handling
|
||||
|
||||
error yaml_error_type_t // Error type.
|
||||
|
||||
problem string // Error description.
|
||||
|
||||
// The byte about which the problem occurred.
|
||||
problem_offset int
|
||||
problem_value int
|
||||
problem_mark yaml_mark_t
|
||||
|
||||
// The error context.
|
||||
context string
|
||||
context_mark yaml_mark_t
|
||||
|
||||
// Reader stuff
|
||||
|
||||
read_handler yaml_read_handler_t // Read handler.
|
||||
|
||||
input_reader io.Reader // File input data.
|
||||
input []byte // String input data.
|
||||
input_pos int
|
||||
|
||||
eof bool // EOF flag
|
||||
|
||||
buffer []byte // The working buffer.
|
||||
buffer_pos int // The current position of the buffer.
|
||||
|
||||
unread int // The number of unread characters in the buffer.
|
||||
|
||||
raw_buffer []byte // The raw buffer.
|
||||
raw_buffer_pos int // The current position of the buffer.
|
||||
|
||||
encoding yaml_encoding_t // The input encoding.
|
||||
|
||||
offset int // The offset of the current position (in bytes).
|
||||
mark yaml_mark_t // The mark of the current position.
|
||||
|
||||
// Scanner stuff
|
||||
|
||||
stream_start_produced bool // Have we started to scan the input stream?
|
||||
stream_end_produced bool // Have we reached the end of the input stream?
|
||||
|
||||
flow_level int // The number of unclosed '[' and '{' indicators.
|
||||
|
||||
tokens []yaml_token_t // The tokens queue.
|
||||
tokens_head int // The head of the tokens queue.
|
||||
tokens_parsed int // The number of tokens fetched from the queue.
|
||||
token_available bool // Does the tokens queue contain a token ready for dequeueing.
|
||||
|
||||
indent int // The current indentation level.
|
||||
indents []int // The indentation levels stack.
|
||||
|
||||
simple_key_allowed bool // May a simple key occur at the current position?
|
||||
simple_keys []yaml_simple_key_t // The stack of simple keys.
|
||||
|
||||
// Parser stuff
|
||||
|
||||
state yaml_parser_state_t // The current parser state.
|
||||
states []yaml_parser_state_t // The parser states stack.
|
||||
marks []yaml_mark_t // The stack of marks.
|
||||
tag_directives []yaml_tag_directive_t // The list of TAG directives.
|
||||
|
||||
// Dumper stuff
|
||||
|
||||
aliases []yaml_alias_data_t // The alias data.
|
||||
|
||||
document *yaml_document_t // The currently parsed document.
|
||||
}
|
||||
|
||||
// Emitter Definitions
|
||||
|
||||
// The prototype of a write handler.
|
||||
//
|
||||
// The write handler is called when the emitter needs to flush the accumulated
|
||||
// characters to the output. The handler should write @a size bytes of the
|
||||
// @a buffer to the output.
|
||||
//
|
||||
// @param[in,out] data A pointer to an application data specified by
|
||||
// yaml_emitter_set_output().
|
||||
// @param[in] buffer The buffer with bytes to be written.
|
||||
// @param[in] size The size of the buffer.
|
||||
//
|
||||
// @returns On success, the handler should return @c 1. If the handler failed,
|
||||
// the returned value should be @c 0.
|
||||
//
|
||||
type yaml_write_handler_t func(emitter *yaml_emitter_t, buffer []byte) error
|
||||
|
||||
type yaml_emitter_state_t int
|
||||
|
||||
// The emitter states.
|
||||
const (
|
||||
// Expect STREAM-START.
|
||||
yaml_EMIT_STREAM_START_STATE yaml_emitter_state_t = iota
|
||||
|
||||
yaml_EMIT_FIRST_DOCUMENT_START_STATE // Expect the first DOCUMENT-START or STREAM-END.
|
||||
yaml_EMIT_DOCUMENT_START_STATE // Expect DOCUMENT-START or STREAM-END.
|
||||
yaml_EMIT_DOCUMENT_CONTENT_STATE // Expect the content of a document.
|
||||
yaml_EMIT_DOCUMENT_END_STATE // Expect DOCUMENT-END.
|
||||
yaml_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE // Expect the first item of a flow sequence.
|
||||
yaml_EMIT_FLOW_SEQUENCE_ITEM_STATE // Expect an item of a flow sequence.
|
||||
yaml_EMIT_FLOW_MAPPING_FIRST_KEY_STATE // Expect the first key of a flow mapping.
|
||||
yaml_EMIT_FLOW_MAPPING_KEY_STATE // Expect a key of a flow mapping.
|
||||
yaml_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE // Expect a value for a simple key of a flow mapping.
|
||||
yaml_EMIT_FLOW_MAPPING_VALUE_STATE // Expect a value of a flow mapping.
|
||||
yaml_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE // Expect the first item of a block sequence.
|
||||
yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE // Expect an item of a block sequence.
|
||||
yaml_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE // Expect the first key of a block mapping.
|
||||
yaml_EMIT_BLOCK_MAPPING_KEY_STATE // Expect the key of a block mapping.
|
||||
yaml_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE // Expect a value for a simple key of a block mapping.
|
||||
yaml_EMIT_BLOCK_MAPPING_VALUE_STATE // Expect a value of a block mapping.
|
||||
yaml_EMIT_END_STATE // Expect nothing.
|
||||
)
|
||||
|
||||
// The emitter structure.
|
||||
//
|
||||
// All members are internal. Manage the structure using the @c yaml_emitter_
|
||||
// family of functions.
|
||||
type yaml_emitter_t struct {
|
||||
|
||||
// Error handling
|
||||
|
||||
error yaml_error_type_t // Error type.
|
||||
problem string // Error description.
|
||||
|
||||
// Writer stuff
|
||||
|
||||
write_handler yaml_write_handler_t // Write handler.
|
||||
|
||||
output_buffer *[]byte // String output data.
|
||||
output_writer io.Writer // File output data.
|
||||
|
||||
buffer []byte // The working buffer.
|
||||
buffer_pos int // The current position of the buffer.
|
||||
|
||||
raw_buffer []byte // The raw buffer.
|
||||
raw_buffer_pos int // The current position of the buffer.
|
||||
|
||||
encoding yaml_encoding_t // The stream encoding.
|
||||
|
||||
// Emitter stuff
|
||||
|
||||
canonical bool // If the output is in the canonical style?
|
||||
best_indent int // The number of indentation spaces.
|
||||
best_width int // The preferred width of the output lines.
|
||||
unicode bool // Allow unescaped non-ASCII characters?
|
||||
line_break yaml_break_t // The preferred line break.
|
||||
|
||||
state yaml_emitter_state_t // The current emitter state.
|
||||
states []yaml_emitter_state_t // The stack of states.
|
||||
|
||||
events []yaml_event_t // The event queue.
|
||||
events_head int // The head of the event queue.
|
||||
|
||||
indents []int // The stack of indentation levels.
|
||||
|
||||
tag_directives []yaml_tag_directive_t // The list of tag directives.
|
||||
|
||||
indent int // The current indentation level.
|
||||
|
||||
flow_level int // The current flow level.
|
||||
|
||||
root_context bool // Is it the document root context?
|
||||
sequence_context bool // Is it a sequence context?
|
||||
mapping_context bool // Is it a mapping context?
|
||||
simple_key_context bool // Is it a simple mapping key context?
|
||||
|
||||
line int // The current line.
|
||||
column int // The current column.
|
||||
whitespace bool // If the last character was a whitespace?
|
||||
indention bool // If the last character was an indentation character (' ', '-', '?', ':')?
|
||||
open_ended bool // If an explicit document end is required?
|
||||
|
||||
// Anchor analysis.
|
||||
anchor_data struct {
|
||||
anchor []byte // The anchor value.
|
||||
alias bool // Is it an alias?
|
||||
}
|
||||
|
||||
// Tag analysis.
|
||||
tag_data struct {
|
||||
handle []byte // The tag handle.
|
||||
suffix []byte // The tag suffix.
|
||||
}
|
||||
|
||||
// Scalar analysis.
|
||||
scalar_data struct {
|
||||
value []byte // The scalar value.
|
||||
multiline bool // Does the scalar contain line breaks?
|
||||
flow_plain_allowed bool // Can the scalar be expessed in the flow plain style?
|
||||
block_plain_allowed bool // Can the scalar be expressed in the block plain style?
|
||||
single_quoted_allowed bool // Can the scalar be expressed in the single quoted style?
|
||||
block_allowed bool // Can the scalar be expressed in the literal or folded styles?
|
||||
style yaml_scalar_style_t // The output style.
|
||||
}
|
||||
|
||||
// Dumper stuff
|
||||
|
||||
opened bool // If the stream was already opened?
|
||||
closed bool // If the stream was already closed?
|
||||
|
||||
// The information associated with the document nodes.
|
||||
anchors *struct {
|
||||
references int // The number of references.
|
||||
anchor int // The anchor id.
|
||||
serialized bool // If the node has been emitted?
|
||||
}
|
||||
|
||||
last_anchor_id int // The last assigned anchor id.
|
||||
|
||||
document *yaml_document_t // The currently emitted document.
|
||||
}
|
173
vendor/gopkg.in/yaml.v2/yamlprivateh.go
generated
vendored
Normal file
173
vendor/gopkg.in/yaml.v2/yamlprivateh.go
generated
vendored
Normal file
@ -0,0 +1,173 @@
|
||||
package yaml
|
||||
|
||||
const (
|
||||
// The size of the input raw buffer.
|
||||
input_raw_buffer_size = 512
|
||||
|
||||
// The size of the input buffer.
|
||||
// It should be possible to decode the whole raw buffer.
|
||||
input_buffer_size = input_raw_buffer_size * 3
|
||||
|
||||
// The size of the output buffer.
|
||||
output_buffer_size = 128
|
||||
|
||||
// The size of the output raw buffer.
|
||||
// It should be possible to encode the whole output buffer.
|
||||
output_raw_buffer_size = (output_buffer_size*2 + 2)
|
||||
|
||||
// The size of other stacks and queues.
|
||||
initial_stack_size = 16
|
||||
initial_queue_size = 16
|
||||
initial_string_size = 16
|
||||
)
|
||||
|
||||
// Check if the character at the specified position is an alphabetical
|
||||
// character, a digit, '_', or '-'.
|
||||
func is_alpha(b []byte, i int) bool {
|
||||
return b[i] >= '0' && b[i] <= '9' || b[i] >= 'A' && b[i] <= 'Z' || b[i] >= 'a' && b[i] <= 'z' || b[i] == '_' || b[i] == '-'
|
||||
}
|
||||
|
||||
// Check if the character at the specified position is a digit.
|
||||
func is_digit(b []byte, i int) bool {
|
||||
return b[i] >= '0' && b[i] <= '9'
|
||||
}
|
||||
|
||||
// Get the value of a digit.
|
||||
func as_digit(b []byte, i int) int {
|
||||
return int(b[i]) - '0'
|
||||
}
|
||||
|
||||
// Check if the character at the specified position is a hex-digit.
|
||||
func is_hex(b []byte, i int) bool {
|
||||
return b[i] >= '0' && b[i] <= '9' || b[i] >= 'A' && b[i] <= 'F' || b[i] >= 'a' && b[i] <= 'f'
|
||||
}
|
||||
|
||||
// Get the value of a hex-digit.
|
||||
func as_hex(b []byte, i int) int {
|
||||
bi := b[i]
|
||||
if bi >= 'A' && bi <= 'F' {
|
||||
return int(bi) - 'A' + 10
|
||||
}
|
||||
if bi >= 'a' && bi <= 'f' {
|
||||
return int(bi) - 'a' + 10
|
||||
}
|
||||
return int(bi) - '0'
|
||||
}
|
||||
|
||||
// Check if the character is ASCII.
|
||||
func is_ascii(b []byte, i int) bool {
|
||||
return b[i] <= 0x7F
|
||||
}
|
||||
|
||||
// Check if the character at the start of the buffer can be printed unescaped.
|
||||
func is_printable(b []byte, i int) bool {
|
||||
return ((b[i] == 0x0A) || // . == #x0A
|
||||
(b[i] >= 0x20 && b[i] <= 0x7E) || // #x20 <= . <= #x7E
|
||||
(b[i] == 0xC2 && b[i+1] >= 0xA0) || // #0xA0 <= . <= #xD7FF
|
||||
(b[i] > 0xC2 && b[i] < 0xED) ||
|
||||
(b[i] == 0xED && b[i+1] < 0xA0) ||
|
||||
(b[i] == 0xEE) ||
|
||||
(b[i] == 0xEF && // #xE000 <= . <= #xFFFD
|
||||
!(b[i+1] == 0xBB && b[i+2] == 0xBF) && // && . != #xFEFF
|
||||
!(b[i+1] == 0xBF && (b[i+2] == 0xBE || b[i+2] == 0xBF))))
|
||||
}
|
||||
|
||||
// Check if the character at the specified position is NUL.
|
||||
func is_z(b []byte, i int) bool {
|
||||
return b[i] == 0x00
|
||||
}
|
||||
|
||||
// Check if the beginning of the buffer is a BOM.
|
||||
func is_bom(b []byte, i int) bool {
|
||||
return b[0] == 0xEF && b[1] == 0xBB && b[2] == 0xBF
|
||||
}
|
||||
|
||||
// Check if the character at the specified position is space.
|
||||
func is_space(b []byte, i int) bool {
|
||||
return b[i] == ' '
|
||||
}
|
||||
|
||||
// Check if the character at the specified position is tab.
|
||||
func is_tab(b []byte, i int) bool {
|
||||
return b[i] == '\t'
|
||||
}
|
||||
|
||||
// Check if the character at the specified position is blank (space or tab).
|
||||
func is_blank(b []byte, i int) bool {
|
||||
//return is_space(b, i) || is_tab(b, i)
|
||||
return b[i] == ' ' || b[i] == '\t'
|
||||
}
|
||||
|
||||
// Check if the character at the specified position is a line break.
|
||||
func is_break(b []byte, i int) bool {
|
||||
return (b[i] == '\r' || // CR (#xD)
|
||||
b[i] == '\n' || // LF (#xA)
|
||||
b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85)
|
||||
b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028)
|
||||
b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9) // PS (#x2029)
|
||||
}
|
||||
|
||||
func is_crlf(b []byte, i int) bool {
|
||||
return b[i] == '\r' && b[i+1] == '\n'
|
||||
}
|
||||
|
||||
// Check if the character is a line break or NUL.
|
||||
func is_breakz(b []byte, i int) bool {
|
||||
//return is_break(b, i) || is_z(b, i)
|
||||
return ( // is_break:
|
||||
b[i] == '\r' || // CR (#xD)
|
||||
b[i] == '\n' || // LF (#xA)
|
||||
b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85)
|
||||
b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028)
|
||||
b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029)
|
||||
// is_z:
|
||||
b[i] == 0)
|
||||
}
|
||||
|
||||
// Check if the character is a line break, space, or NUL.
|
||||
func is_spacez(b []byte, i int) bool {
|
||||
//return is_space(b, i) || is_breakz(b, i)
|
||||
return ( // is_space:
|
||||
b[i] == ' ' ||
|
||||
// is_breakz:
|
||||
b[i] == '\r' || // CR (#xD)
|
||||
b[i] == '\n' || // LF (#xA)
|
||||
b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85)
|
||||
b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028)
|
||||
b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029)
|
||||
b[i] == 0)
|
||||
}
|
||||
|
||||
// Check if the character is a line break, space, tab, or NUL.
|
||||
func is_blankz(b []byte, i int) bool {
|
||||
//return is_blank(b, i) || is_breakz(b, i)
|
||||
return ( // is_blank:
|
||||
b[i] == ' ' || b[i] == '\t' ||
|
||||
// is_breakz:
|
||||
b[i] == '\r' || // CR (#xD)
|
||||
b[i] == '\n' || // LF (#xA)
|
||||
b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85)
|
||||
b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028)
|
||||
b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029)
|
||||
b[i] == 0)
|
||||
}
|
||||
|
||||
// Determine the width of the character.
|
||||
func width(b byte) int {
|
||||
// Don't replace these by a switch without first
|
||||
// confirming that it is being inlined.
|
||||
if b&0x80 == 0x00 {
|
||||
return 1
|
||||
}
|
||||
if b&0xE0 == 0xC0 {
|
||||
return 2
|
||||
}
|
||||
if b&0xF0 == 0xE0 {
|
||||
return 3
|
||||
}
|
||||
if b&0xF8 == 0xF0 {
|
||||
return 4
|
||||
}
|
||||
return 0
|
||||
|
||||
}
|
118
vendor/vendor.json
vendored
118
vendor/vendor.json
vendored
@ -694,112 +694,106 @@
|
||||
"revisionTime": "2015-01-27T13:39:51Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "QTqcF26Y2e0SHe2Z+2wj+fedud4=",
|
||||
"checksumSHA1": "qduT9GZUhXc00XoHEwLx16Xn9gM=",
|
||||
"path": "github.com/gophercloud/gophercloud",
|
||||
"revision": "95a28eb606def6aaaed082b6b82d3244b0552184",
|
||||
"revisionTime": "2017-06-23T01:44:30Z"
|
||||
"revision": "7112fcd50da4ea27e8d4d499b30f04eea143bec2",
|
||||
"revisionTime": "2018-05-31T02:06:30Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "b7g9TcU1OmW7e2UySYeOAmcfHpY=",
|
||||
"path": "github.com/gophercloud/gophercloud/internal",
|
||||
"revision": "95a28eb606def6aaaed082b6b82d3244b0552184",
|
||||
"revisionTime": "2017-06-23T01:44:30Z"
|
||||
"revision": "7112fcd50da4ea27e8d4d499b30f04eea143bec2",
|
||||
"revisionTime": "2018-05-31T02:06:30Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "24DO5BEQdFKNl1rfWgI2b4+ry5U=",
|
||||
"checksumSHA1": "YDNvjFNQS+UxqZMLm/shFs7aLNU=",
|
||||
"path": "github.com/gophercloud/gophercloud/openstack",
|
||||
"revision": "95a28eb606def6aaaed082b6b82d3244b0552184",
|
||||
"revisionTime": "2017-06-23T01:44:30Z"
|
||||
"revision": "7112fcd50da4ea27e8d4d499b30f04eea143bec2",
|
||||
"revisionTime": "2018-05-31T02:06:30Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "Au6MAsI90lewLByg9n+Yjtdqdh8=",
|
||||
"path": "github.com/gophercloud/gophercloud/openstack/common/extensions",
|
||||
"revision": "95a28eb606def6aaaed082b6b82d3244b0552184",
|
||||
"revisionTime": "2017-06-23T01:44:30Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "4XWDCGMYqipwJymi9xJo9UffD7g=",
|
||||
"path": "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions",
|
||||
"revision": "95a28eb606def6aaaed082b6b82d3244b0552184",
|
||||
"revisionTime": "2017-06-23T01:44:30Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "e7AW3YDVYJPKUjpqsB4AL9RRlTw=",
|
||||
"checksumSHA1": "vFS5BwnCdQIfKm1nNWrR+ijsAZA=",
|
||||
"path": "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/floatingips",
|
||||
"revision": "95a28eb606def6aaaed082b6b82d3244b0552184",
|
||||
"revisionTime": "2017-06-23T01:44:30Z"
|
||||
"revision": "7112fcd50da4ea27e8d4d499b30f04eea143bec2",
|
||||
"revisionTime": "2018-05-31T02:06:30Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "bx6QnHtpgB6nKmN4QRVKa5PszqY=",
|
||||
"checksumSHA1": "lAQuKIqTuQ9JuMgN0pPkNtRH2RM=",
|
||||
"path": "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/keypairs",
|
||||
"revision": "95a28eb606def6aaaed082b6b82d3244b0552184",
|
||||
"revisionTime": "2017-06-23T01:44:30Z"
|
||||
"revision": "7112fcd50da4ea27e8d4d499b30f04eea143bec2",
|
||||
"revisionTime": "2018-05-31T02:06:30Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "qBpGbX7LQMPATdO8XyQmU7IXDiI=",
|
||||
"checksumSHA1": "qfVZltu1fYTYXS97WbjeLuLPgUc=",
|
||||
"path": "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/startstop",
|
||||
"revision": "95a28eb606def6aaaed082b6b82d3244b0552184",
|
||||
"revisionTime": "2017-06-23T01:44:30Z"
|
||||
"revision": "7112fcd50da4ea27e8d4d499b30f04eea143bec2",
|
||||
"revisionTime": "2018-05-31T02:06:30Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "vTyXSR+Znw7/o/70UBOWG0F09r8=",
|
||||
"checksumSHA1": "1/1G6O0CUVYyTFF/IqzWThGyuPQ=",
|
||||
"path": "github.com/gophercloud/gophercloud/openstack/compute/v2/flavors",
|
||||
"revision": "95a28eb606def6aaaed082b6b82d3244b0552184",
|
||||
"revisionTime": "2017-06-23T01:44:30Z"
|
||||
"revision": "7112fcd50da4ea27e8d4d499b30f04eea143bec2",
|
||||
"revisionTime": "2018-05-31T02:06:30Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "Rnzx2YgOD41k8KoPA08tR992PxQ=",
|
||||
"checksumSHA1": "CSnfH01hSas0bdc/3m/f5Rt6SFY=",
|
||||
"path": "github.com/gophercloud/gophercloud/openstack/compute/v2/images",
|
||||
"revision": "95a28eb606def6aaaed082b6b82d3244b0552184",
|
||||
"revisionTime": "2017-06-23T01:44:30Z"
|
||||
"revision": "7112fcd50da4ea27e8d4d499b30f04eea143bec2",
|
||||
"revisionTime": "2018-05-31T02:06:30Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "IjCvcaNnRW++hclt21WUkMYinaA=",
|
||||
"checksumSHA1": "FKVrvZnE/223fpKVGPqaIX4JP9I=",
|
||||
"path": "github.com/gophercloud/gophercloud/openstack/compute/v2/servers",
|
||||
"revision": "95a28eb606def6aaaed082b6b82d3244b0552184",
|
||||
"revisionTime": "2017-06-23T01:44:30Z"
|
||||
"revision": "7112fcd50da4ea27e8d4d499b30f04eea143bec2",
|
||||
"revisionTime": "2018-05-31T02:06:30Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "S8bHmOP+NjtlYioJC89zIBVvhYc=",
|
||||
"checksumSHA1": "oOJkelRgWx0NzUmxuI3kTS27gM0=",
|
||||
"path": "github.com/gophercloud/gophercloud/openstack/identity/v2/tenants",
|
||||
"revision": "95a28eb606def6aaaed082b6b82d3244b0552184",
|
||||
"revisionTime": "2017-06-23T01:44:30Z"
|
||||
"revision": "7112fcd50da4ea27e8d4d499b30f04eea143bec2",
|
||||
"revisionTime": "2018-05-31T02:06:30Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "AvUU5En9YpG25iLlcAPDgcQODjI=",
|
||||
"checksumSHA1": "z5NsqMZX3TLMzpmwzOOXE4M5D9w=",
|
||||
"path": "github.com/gophercloud/gophercloud/openstack/identity/v2/tokens",
|
||||
"revision": "95a28eb606def6aaaed082b6b82d3244b0552184",
|
||||
"revisionTime": "2017-06-23T01:44:30Z"
|
||||
"revision": "7112fcd50da4ea27e8d4d499b30f04eea143bec2",
|
||||
"revisionTime": "2018-05-31T02:06:30Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "rqE0NwmQ9qhXADXxg3DcuZ4A3wk=",
|
||||
"checksumSHA1": "2PYxD2MOrbp4JCWy5794sEtDYD4=",
|
||||
"path": "github.com/gophercloud/gophercloud/openstack/identity/v3/tokens",
|
||||
"revision": "95a28eb606def6aaaed082b6b82d3244b0552184",
|
||||
"revisionTime": "2017-06-23T01:44:30Z"
|
||||
"revision": "7112fcd50da4ea27e8d4d499b30f04eea143bec2",
|
||||
"revisionTime": "2018-05-31T02:06:30Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "p2ivHupXGBmyHkusnob2NsbsCQk=",
|
||||
"checksumSHA1": "Pop8rylL583hCZ0RjO+9TkrScCo=",
|
||||
"path": "github.com/gophercloud/gophercloud/openstack/imageservice/v2/images",
|
||||
"revision": "95a28eb606def6aaaed082b6b82d3244b0552184",
|
||||
"revisionTime": "2017-06-23T01:44:30Z"
|
||||
"revision": "7112fcd50da4ea27e8d4d499b30f04eea143bec2",
|
||||
"revisionTime": "2018-05-31T02:06:30Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "KA5YKF9TwIsTy9KssO27y+wk/6U=",
|
||||
"checksumSHA1": "GFqX1Y5SpZvvyx0LPaP9D9Xp5k0=",
|
||||
"path": "github.com/gophercloud/gophercloud/openstack/imageservice/v2/members",
|
||||
"revision": "95a28eb606def6aaaed082b6b82d3244b0552184",
|
||||
"revisionTime": "2017-06-23T01:44:30Z"
|
||||
"revision": "7112fcd50da4ea27e8d4d499b30f04eea143bec2",
|
||||
"revisionTime": "2018-05-31T02:06:30Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "TDOZnaS0TO0NirpxV1QwPerAQTY=",
|
||||
"checksumSHA1": "8KE4bJzhbFZKsYMxcRg6xLqqfTg=",
|
||||
"path": "github.com/gophercloud/gophercloud/openstack/utils",
|
||||
"revision": "95a28eb606def6aaaed082b6b82d3244b0552184",
|
||||
"revisionTime": "2017-06-23T01:44:30Z"
|
||||
"revision": "7112fcd50da4ea27e8d4d499b30f04eea143bec2",
|
||||
"revisionTime": "2018-05-31T02:06:30Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "YspETi3tOMvawKIT91HyuqaA5lM=",
|
||||
"checksumSHA1": "jWdt1lN75UC0GrLG5Tmng+qP+ZI=",
|
||||
"path": "github.com/gophercloud/gophercloud/pagination",
|
||||
"revision": "95a28eb606def6aaaed082b6b82d3244b0552184",
|
||||
"revisionTime": "2017-06-23T01:44:30Z"
|
||||
"revision": "7112fcd50da4ea27e8d4d499b30f04eea143bec2",
|
||||
"revisionTime": "2018-05-31T02:06:30Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "ujo1JDey6cxwnGs4HXVCJNVrhHw=",
|
||||
"path": "github.com/gophercloud/utils/openstack/clientconfig",
|
||||
"revision": "afce78e977c56ca5407957bf67e8ecc56aab601d",
|
||||
"revisionTime": "2018-05-22T20:53:45Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "xSmii71kfQASGNG2C8ttmHx9KTE=",
|
||||
@ -1684,6 +1678,12 @@
|
||||
"checksumSHA1": "U7dGDNwEHORvJFMoNSXErKE7ITg=",
|
||||
"path": "google.golang.org/cloud/internal",
|
||||
"revision": "5a3b06f8b5da3b7c3a93da43163b872c86c509ef"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "ZSWoOPUNRr5+3dhkLK3C4cZAQPk=",
|
||||
"path": "gopkg.in/yaml.v2",
|
||||
"revision": "5420a8b6744d3b0345ab293f6fcba19c978f1183",
|
||||
"revisionTime": "2018-03-28T19:50:20Z"
|
||||
}
|
||||
],
|
||||
"rootPath": "github.com/hashicorp/packer"
|
||||
|
@ -25,7 +25,7 @@ created. This simplifies configuration quite a bit.
|
||||
The builder does *not* manage images. Once it creates an image, it is up to you
|
||||
to use it or delete it.
|
||||
|
||||
~> **Note:** To use OpenStack builder with the OpenStack Newton (Oct 2016)
|
||||
~> **Note:** To use OpenStack builder with the OpenStack Newton (Oct 2016)
|
||||
or earlier, we recommend you use Packer v1.1.2 or earlier version.
|
||||
|
||||
~> **OpenStack Liberty or later requires OpenSSL!** To use the OpenStack
|
||||
@ -33,7 +33,8 @@ builder with OpenStack Liberty (Oct 2015) or later you need to have OpenSSL
|
||||
installed *if you are using temporary key pairs*, i.e. don't use
|
||||
[`ssh_keypair_name`](openstack.html#ssh_keypair_name) nor
|
||||
[`ssh_password`](/docs/templates/communicator.html#ssh_password). All major
|
||||
OS'es have OpenSSL installed by default except Windows.
|
||||
OS'es have OpenSSL installed by default except Windows. This have been
|
||||
resolved in OpenStack Ocata(Feb 2017).
|
||||
|
||||
|
||||
## Configuration Reference
|
||||
@ -55,7 +56,7 @@ builder.
|
||||
|
||||
- `identity_endpoint` (string) - The URL to the OpenStack Identity service.
|
||||
If not specified, Packer will use the environment variables `OS_AUTH_URL`,
|
||||
if set.
|
||||
if set. This is not required if using `cloud.yaml`.
|
||||
|
||||
- `source_image` (string) - The ID or full URL to the base image to use. This
|
||||
is the image that will be used to launch a new server and provision it.
|
||||
@ -68,11 +69,14 @@ builder.
|
||||
|
||||
- `username` or `user_id` (string) - The username or id used to connect to
|
||||
the OpenStack service. If not specified, Packer will use the environment
|
||||
variable `OS_USERNAME` or `OS_USERID`, if set.
|
||||
variable `OS_USERNAME` or `OS_USERID`, if set. This is not required if
|
||||
using access token instead of password or if using `cloud.yaml`.
|
||||
|
||||
- `password` (string) - The password used to connect to the OpenStack service.
|
||||
If not specified, Packer will use the environment variables `OS_PASSWORD`,
|
||||
if set.
|
||||
if set. This is not required if using access token instead of password or
|
||||
if using `cloud.yaml`.
|
||||
|
||||
|
||||
### Optional:
|
||||
|
||||
@ -81,14 +85,20 @@ builder.
|
||||
cluster will be used. This may be required for some OpenStack clusters.
|
||||
|
||||
- `cacert` (string) - Custom CA certificate file path.
|
||||
If omitted the OS\_CACERT environment variable can be used.
|
||||
If omitted the `OS_CACERT` environment variable can be used.
|
||||
|
||||
- `cert` (string) - Client certificate file path for SSL client authentication.
|
||||
If omitted the `OS_CERT` environment variable can be used.
|
||||
|
||||
- `cloud` (string) - An entry in a `clouds.yaml` file. See the OpenStack
|
||||
os-client-config
|
||||
[documentation](https://docs.openstack.org/os-client-config/latest/user/configuration.html)
|
||||
for more information about `clouds.yaml` files. If omitted, the `OS_CLOUD`
|
||||
environment variable is used.
|
||||
|
||||
- `config_drive` (boolean) - Whether or not nova should use ConfigDrive for
|
||||
cloud-init metadata.
|
||||
|
||||
- `cert` (string) - Client certificate file path for SSL client authentication.
|
||||
If omitted the OS\_CERT environment variable can be used.
|
||||
|
||||
- `domain_name` or `domain_id` (string) - The Domain name or ID you are
|
||||
authenticating with. OpenStack installations require this if identity v3 is used.
|
||||
Packer will use the environment variable `OS_DOMAIN_NAME` or `OS_DOMAIN_ID`, if set.
|
||||
@ -104,7 +114,7 @@ builder.
|
||||
|
||||
- `image_members` (array of strings) - List of members to add to the image
|
||||
after creation. An image member is usually a project (also called the
|
||||
“tenant”) with whom the image is shared.
|
||||
"tenant") with whom the image is shared.
|
||||
|
||||
- `image_visibility` (string) - One of "public", "private", "shared", or
|
||||
"community".
|
||||
@ -113,7 +123,7 @@ builder.
|
||||
done over an insecure connection. By default this is false.
|
||||
|
||||
- `key` (string) - Client private key file path for SSL client authentication.
|
||||
If omitted the OS\_KEY environment variable can be used.
|
||||
If omitted the `OS_KEY` environment variable can be used.
|
||||
|
||||
- `metadata` (object of key/value strings) - Glance metadata that will be
|
||||
applied to the image.
|
||||
@ -177,8 +187,11 @@ builder.
|
||||
|
||||
- `tenant_id` or `tenant_name` (string) - The tenant ID or name to boot the
|
||||
instance into. Some OpenStack installations require this. If not specified,
|
||||
Packer will use the environment variable `OS_TENANT_NAME`, if set. Tenant
|
||||
is also called Project in later versions of OpenStack.
|
||||
Packer will use the environment variable `OS_TENANT_NAME` or `OS_TENANT_ID`,
|
||||
if set. Tenant is also called Project in later versions of OpenStack.
|
||||
|
||||
- `token` (string) - the token (id) to use with token based authorization.
|
||||
Packer will use the environment variable `OS_TOKEN`, if set.
|
||||
|
||||
- `use_floating_ip` (boolean) - *Deprecated* use `floating_ip` or `floating_ip_pool`
|
||||
instead.
|
||||
@ -279,11 +292,12 @@ export OS_PROJECT_DOMAIN_NAME="mydomain"
|
||||
|
||||
## Notes on OpenStack Authorization
|
||||
|
||||
The simplest way to get all settings for authorization agains OpenStack is to
|
||||
The simplest way to get all settings for authorization against OpenStack is to
|
||||
go into the OpenStack Dashboard (Horizon) select your *Project* and navigate
|
||||
*Project, Access & Security*, select *API Access* and *Download OpenStack RC
|
||||
File v3*. Source the file, and select your wanted region by setting
|
||||
environment variable `OS_REGION_NAME` or `OS_REGION_ID` and `export OS_TENANT_NAME=$OS_PROJECT_NAME` or `export OS_TENANT_ID=$OS_PROJECT_ID`.
|
||||
File v3*. Source the file, and select your wanted region
|
||||
by setting environment variable `OS_REGION_NAME` or `OS_REGION_ID` and
|
||||
`export OS_TENANT_NAME=$OS_PROJECT_NAME` or `export OS_TENANT_ID=$OS_PROJECT_ID`.
|
||||
|
||||
~> `OS_TENANT_NAME` or `OS_TENANT_ID` must be used even with Identity v3,
|
||||
`OS_PROJECT_NAME` and `OS_PROJECT_ID` has no effect in Packer.
|
||||
@ -292,3 +306,13 @@ To troubleshoot authorization issues test you environment variables with the
|
||||
OpenStack cli. It can be installed with
|
||||
|
||||
$ pip install --user python-openstackclient
|
||||
|
||||
### Authorize Using Tokens
|
||||
|
||||
To authorize with a access token only `identity_endpoint` and `token` is needed,
|
||||
and possibly `tenant_name` or `tenant_id` depending on your token type. Or use
|
||||
the following environment variables:
|
||||
|
||||
- `OS_AUTH_URL`
|
||||
- `OS_TOKEN`
|
||||
- One of `OS_TENANT_NAME` or `OS_TENANT_ID`
|
||||
|
Loading…
x
Reference in New Issue
Block a user