Merge pull request #10556 from zetaab/feature/updatedeps

update gophercloud dependency
This commit is contained in:
Kubernetes Prow Robot 2021-01-11 06:13:08 -08:00 committed by GitHub
commit f94539f6f6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
48 changed files with 703 additions and 238 deletions

4
go.mod
View File

@ -47,8 +47,6 @@ replace k8s.io/kube-controller-manager => k8s.io/kube-controller-manager v0.20.0
// This should match hack/go.mod
replace k8s.io/code-generator => k8s.io/code-generator v0.20.0
replace github.com/gophercloud/gophercloud => github.com/gophercloud/gophercloud v0.11.0
require (
cloud.google.com/go v0.54.0
github.com/Azure/azure-pipeline-go v0.2.3
@ -75,7 +73,7 @@ require (
github.com/gogo/protobuf v1.3.1
github.com/google/go-cmp v0.5.2
github.com/google/uuid v1.1.2
github.com/gophercloud/gophercloud v0.11.1-0.20200518183226-7aec46f32c19
github.com/gophercloud/gophercloud v0.15.0
github.com/gorilla/mux v1.7.3
github.com/hashicorp/hcl/v2 v2.7.0
github.com/hashicorp/vault/api v1.0.4

12
go.sum
View File

@ -501,8 +501,12 @@ github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5m
github.com/googleapis/gnostic v0.3.1/go.mod h1:on+2t9HRStVgn95RSsFWFz+6Q0Snyqv1awfrALZdbtU=
github.com/googleapis/gnostic v0.4.1 h1:DLJCy1n/vrD4HPjOvYcT8aYQXpPIzoRZONaYwyycI+I=
github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg=
github.com/gophercloud/gophercloud v0.11.0 h1:pYMP9UZBdQa3lsfIZ1tZor4EbtxiuB6BHhocenkiH/E=
github.com/gophercloud/gophercloud v0.11.0/go.mod h1:gmC5oQqMDOMO1t1gq5DquX/yAU808e/4mzjjDA76+Ss=
github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8=
github.com/gophercloud/gophercloud v0.6.1-0.20191122030953-d8ac278c1c9d/go.mod h1:ozGNgr9KYOVATV5jsgHl/ceCDXGuguqOZAzoQ/2vcNM=
github.com/gophercloud/gophercloud v0.11.1-0.20200518183226-7aec46f32c19 h1:Amaxs7PsvtzbahUHadno+OZI0IrMqwbPhoGUVLdM1NA=
github.com/gophercloud/gophercloud v0.11.1-0.20200518183226-7aec46f32c19/go.mod h1:gmC5oQqMDOMO1t1gq5DquX/yAU808e/4mzjjDA76+Ss=
github.com/gophercloud/gophercloud v0.15.0 h1:jQeAWj0s1p83+TrUXhJhEOK4oe2g6YcBcFwEyMNIjEk=
github.com/gophercloud/gophercloud v0.15.0/go.mod h1:VX0Ibx85B60B5XOrZr6kaNwrmPUzcmMpwxvQ1WQIIWM=
github.com/gophercloud/utils v0.0.0-20200423144003-7c72efc7435d/go.mod h1:ehWUbLQJPqS0Ep+CxeD559hsm9pthPXadJNKwZkp43w=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
@ -646,6 +650,8 @@ github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFB
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs=
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
@ -1043,6 +1049,7 @@ golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnf
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190123085648-057139ce5d2b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190228161510-8dd112bcdc25/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190320223903-b7391e95e576/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
@ -1165,6 +1172,7 @@ golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190124100055-b90733256f2e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190129075346-302c3dd5f1cc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190228124157-a34e9553db1e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=

View File

@ -57,6 +57,7 @@ go_test(
"//vendor/github.com/aws/aws-sdk-go/service/autoscaling/autoscalingiface:go_default_library",
"//vendor/github.com/aws/aws-sdk-go/service/ec2:go_default_library",
"//vendor/github.com/aws/aws-sdk-go/service/ec2/ec2iface:go_default_library",
"//vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/servergroups:go_default_library",
"//vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/servers:go_default_library",
"//vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/ports:go_default_library",
"//vendor/github.com/stretchr/testify/assert:go_default_library",

View File

@ -22,14 +22,9 @@ import (
"testing"
"time"
"k8s.io/kops/upup/pkg/fi"
"github.com/gophercloud/gophercloud/openstack/networking/v2/ports"
"k8s.io/kops/util/pkg/vfs"
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/servergroups"
"github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
"github.com/gophercloud/gophercloud/openstack/networking/v2/ports"
"github.com/stretchr/testify/assert"
v1 "k8s.io/api/core/v1"
v1meta "k8s.io/apimachinery/pkg/apis/meta/v1"
@ -39,8 +34,10 @@ import (
"k8s.io/kops/pkg/client/simple/vfsclientset"
"k8s.io/kops/pkg/cloudinstances"
"k8s.io/kops/pkg/testutils"
"k8s.io/kops/upup/pkg/fi"
"k8s.io/kops/upup/pkg/fi/cloudup"
"k8s.io/kops/upup/pkg/fi/cloudup/openstack"
"k8s.io/kops/util/pkg/vfs"
)
func getTestSetupOS(t *testing.T) (*RollingUpdateCluster, *openstack.MockCloud) {
@ -211,7 +208,7 @@ func getGroupsAllNeedUpdateOS(t *testing.T, c *RollingUpdateCluster) (map[string
func assertGroupInstanceCountOS(t *testing.T, cloud *openstack.MockCloud, groupName string, expected int) {
groups, _ := cloud.ListServerGroups()
groups, _ := cloud.ListServerGroups(servergroups.ListOpts{})
for _, g := range groups {
if g.Name == groupName {
assert.Lenf(t, g.Members, expected, "%s instances", groupName)

View File

@ -23,6 +23,7 @@ go_library(
"//upup/pkg/fi:go_default_library",
"//upup/pkg/fi/cloudup/openstack:go_default_library",
"//vendor/github.com/gophercloud/gophercloud/openstack/blockstorage/v3/volumes:go_default_library",
"//vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/servergroups:go_default_library",
"//vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/servers:go_default_library",
"//vendor/github.com/gophercloud/gophercloud/openstack/dns/v2/recordsets:go_default_library",
"//vendor/github.com/gophercloud/gophercloud/openstack/dns/v2/zones:go_default_library",

View File

@ -19,6 +19,7 @@ package openstack
import (
"strings"
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/servergroups"
"k8s.io/kops/pkg/resources"
"k8s.io/kops/upup/pkg/fi"
"k8s.io/kops/upup/pkg/fi/cloudup/openstack"
@ -30,7 +31,7 @@ const (
func (os *clusterDiscoveryOS) ListServerGroups() ([]*resources.Resource, error) {
var resourceTrackers []*resources.Resource
servergroups, err := os.osCloud.ListServerGroups()
servergroups, err := os.osCloud.ListServerGroups(servergroups.ListOpts{})
if err != nil {
return resourceTrackers, err
}

View File

@ -235,7 +235,7 @@ type OpenstackCloud interface {
CreateServerGroup(opt servergroups.CreateOptsBuilder) (*servergroups.ServerGroup, error)
// ListServerGroups will list available server groups
ListServerGroups() ([]servergroups.ServerGroup, error)
ListServerGroups(opts servergroups.ListOptsBuilder) ([]servergroups.ServerGroup, error)
// DeleteServerGroup will delete a nova server group
DeleteServerGroup(groupID string) error
@ -617,7 +617,7 @@ func getCloudGroups(c OpenstackCloud, cluster *kops.Cluster, instancegroups []*k
nodeMap := cloudinstances.GetNodeMap(nodes, cluster)
groups := make(map[string]*cloudinstances.CloudInstanceGroup)
serverGrps, err := c.ListServerGroups()
serverGrps, err := c.ListServerGroups(servergroups.ListOpts{})
if err != nil {
return nil, fmt.Errorf("unable to list servergroups: %v", err)
}

View File

@ -423,8 +423,8 @@ func (c *MockCloud) ListSecurityGroupRules(opt sgr.ListOpts) ([]sgr.SecGroupRule
func (c *MockCloud) ListServerFloatingIPs(instanceID string) ([]*string, error) {
return listServerFloatingIPs(c, instanceID, true)
}
func (c *MockCloud) ListServerGroups() ([]servergroups.ServerGroup, error) {
return listServerGroups(c)
func (c *MockCloud) ListServerGroups(opts servergroups.ListOptsBuilder) ([]servergroups.ServerGroup, error) {
return listServerGroups(c, opts)
}
func (c *MockCloud) ListSubnets(opt subnets.ListOptsBuilder) ([]subnets.Subnet, error) {
return listSubnets(c, opt)

View File

@ -55,14 +55,14 @@ func createServerGroup(c OpenstackCloud, opt servergroups.CreateOptsBuilder) (*s
}
}
func (c *openstackCloud) ListServerGroups() ([]servergroups.ServerGroup, error) {
return listServerGroups(c)
func (c *openstackCloud) ListServerGroups(opts servergroups.ListOptsBuilder) ([]servergroups.ServerGroup, error) {
return listServerGroups(c, opts)
}
func listServerGroups(c OpenstackCloud) ([]servergroups.ServerGroup, error) {
func listServerGroups(c OpenstackCloud, opts servergroups.ListOptsBuilder) ([]servergroups.ServerGroup, error) {
var sgs []servergroups.ServerGroup
done, err := vfs.RetryWithBackoff(readBackoff, func() (bool, error) {
allPages, err := servergroups.List(c.ComputeClient()).AllPages()
allPages, err := servergroups.List(c.ComputeClient(), opts).AllPages()
if err != nil {
return false, fmt.Errorf("error listing server groups: %v", err)
}

View File

@ -262,7 +262,6 @@ func (_ *Instance) RenderOpenstack(t *openstack.OpenstackAPITarget, a, e, change
},
},
Metadata: e.Metadata,
ServiceClient: t.Cloud.ComputeClient(),
SecurityGroups: e.SecurityGroups,
}
if e.UserData != nil {

View File

@ -62,7 +62,7 @@ func (s *ServerGroup) Find(context *fi.Context) (*ServerGroup, error) {
cloud := context.Cloud.(openstack.OpenstackCloud)
//TODO: move to cloud, add vfs backoff
page, err := servergroups.List(cloud.ComputeClient()).AllPages()
page, err := servergroups.List(cloud.ComputeClient(), servergroups.ListOpts{}).AllPages()
if err != nil {
return nil, fmt.Errorf("Failed to list server groups: %v", err)
}

View File

@ -1,25 +0,0 @@
language: go
sudo: false
install:
- GO111MODULE=off go get golang.org/x/crypto/ssh
- GO111MODULE=off go get -v -tags 'fixtures acceptance' ./...
- GO111MODULE=off go get github.com/wadey/gocovmerge
- GO111MODULE=off go get github.com/mattn/goveralls
- GO111MODULE=off go get golang.org/x/tools/cmd/goimports
go:
- "1.11"
- "1.12"
- "1.13"
- "tip"
env:
global:
- secure: "xSQsAG5wlL9emjbCdxzz/hYQsSpJ/bABO1kkbwMSISVcJ3Nk0u4ywF+LS4bgeOnwPfmFvNTOqVDu3RwEvMeWXSI76t1piCPcObutb2faKLVD/hLoAS76gYX+Z8yGWGHrSB7Do5vTPj1ERe2UljdrnsSeOXzoDwFxYRaZLX4bBOB4AyoGvRniil5QXPATiA1tsWX1VMicj8a4F8X+xeESzjt1Q5Iy31e7vkptu71bhvXCaoo5QhYwT+pLR9dN0S1b7Ro0KVvkRefmr1lUOSYd2e74h6Lc34tC1h3uYZCS4h47t7v5cOXvMNxinEj2C51RvbjvZI1RLVdkuAEJD1Iz4+Ote46nXbZ//6XRZMZz/YxQ13l7ux1PFjgEB6HAapmF5Xd8PRsgeTU9LRJxpiTJ3P5QJ3leS1va8qnziM5kYipj/Rn+V8g2ad/rgkRox9LSiR9VYZD2Pe45YCb1mTKSl2aIJnV7nkOqsShY5LNB4JZSg7xIffA+9YVDktw8dJlATjZqt7WvJJ49g6A61mIUV4C15q2JPGKTkZzDiG81NtmS7hFa7k0yaE2ELgYocbcuyUcAahhxntYTC0i23nJmEHVNiZmBO3u7EgpWe4KGVfumU+lt12tIn5b3dZRBBUk3QakKKozSK1QPHGpk/AZGrhu7H6l8to6IICKWtDcyMPQ="
- GO111MODULE=on
before_script:
- go vet ./...
script:
- ./script/coverage
- ./script/unittest
- ./script/format
after_success:
- $HOME/gopath/bin/goveralls -service=travis-ci -coverprofile=cover.out

View File

@ -12,6 +12,7 @@
description: |
Run gophercloud acceptance test on master branch
run: .zuul/playbooks/gophercloud-acceptance-test/run.yaml
timeout: 18000 # 5 hours
nodeset: ubuntu-bionic
- job:
@ -22,6 +23,24 @@
run: .zuul/playbooks/gophercloud-acceptance-test-ironic/run.yaml
nodeset: ubuntu-bionic
- job:
name: gophercloud-acceptance-test-ussuri
parent: gophercloud-acceptance-test
description: |
Run gophercloud acceptance test on ussuri branch
vars:
global_env:
OS_BRANCH: stable/ussuri
- job:
name: gophercloud-acceptance-test-train
parent: gophercloud-acceptance-test
description: |
Run gophercloud acceptance test on train branch
vars:
global_env:
OS_BRANCH: stable/train
- job:
name: gophercloud-acceptance-test-stein
parent: gophercloud-acceptance-test
@ -45,15 +64,19 @@
parent: gophercloud-acceptance-test
description: |
Run gophercloud acceptance test on queens branch
nodeset: ubuntu-xenial
vars:
global_env:
OS_BRANCH: stable/queens
# NOTE: A Pike-based devstack environment is currently
# not building correctly. This might be a temporary issue.
- job:
name: gophercloud-acceptance-test-pike
parent: gophercloud-acceptance-test
description: |
Run gophercloud acceptance test on pike branch
nodeset: ubuntu-xenial
vars:
global_env:
OS_BRANCH: stable/pike
@ -63,15 +86,19 @@
parent: gophercloud-acceptance-test
description: |
Run gophercloud acceptance test on ocata branch
nodeset: ubuntu-xenial
vars:
global_env:
OS_BRANCH: stable/ocata
# NOTE: A Newton-based devstack environment is currently
# not building correctly. This might be a temporary issue.
- job:
name: gophercloud-acceptance-test-newton
parent: gophercloud-acceptance-test
description: |
Run gophercloud acceptance test on newton branch
nodeset: ubuntu-xenial
vars:
global_env:
OS_BRANCH: stable/newton
@ -101,3 +128,9 @@
recheck-stein:
jobs:
- gophercloud-acceptance-test-stein
recheck-train:
jobs:
- gophercloud-acceptance-test-train
recheck-ussuri:
jobs:
- gophercloud-acceptance-test-ussuri

View File

@ -1,4 +1,123 @@
## 0.12.0 (Unreleased)
## 0.16.0 (Unreleased)
## 0.15.0 (December 27, 2020)
BREAKING CHANGES
* `compute/v2/extensions/servergroups.List` now takes a `ListOpts` parameter. You can pass `nil` if you don't need to use this.
IMPROVEMENTS
* Added `loadbalancer/v2/pools.CreateMemberOpts.Tags` [GH-2056](https://github.com/gophercloud/gophercloud/pull/2056)
* Added `loadbalancer/v2/pools.UpdateMemberOpts.Backup` [GH-2056](https://github.com/gophercloud/gophercloud/pull/2056)
* Added `loadbalancer/v2/pools.UpdateMemberOpts.MonitorAddress` [GH-2056](https://github.com/gophercloud/gophercloud/pull/2056)
* Added `loadbalancer/v2/pools.UpdateMemberOpts.MonitorPort` [GH-2056](https://github.com/gophercloud/gophercloud/pull/2056)
* Added `loadbalancer/v2/pools.UpdateMemberOpts.Tags` [GH-2056](https://github.com/gophercloud/gophercloud/pull/2056)
* Added `loadbalancer/v2/pools.BatchUpdateMemberOpts.Backup` [GH-2056](https://github.com/gophercloud/gophercloud/pull/2056)
* Added `loadbalancer/v2/pools.BatchUpdateMemberOpts.MonitorAddress` [GH-2056](https://github.com/gophercloud/gophercloud/pull/2056)
* Added `loadbalancer/v2/pools.BatchUpdateMemberOpts.MonitorPort` [GH-2056](https://github.com/gophercloud/gophercloud/pull/2056)
* Added `loadbalancer/v2/pools.BatchUpdateMemberOpts.Tags` [GH-2056](https://github.com/gophercloud/gophercloud/pull/2056)
* Added `networking/v2/extensions/quotas.GetDetail` [GH-2061](https://github.com/gophercloud/gophercloud/pull/2061)
* Added `networking/v2/extensions/quotas.UpdateOpts.Trunk` [GH-2061](https://github.com/gophercloud/gophercloud/pull/2061)
* Added `objectstorage/v1/accounts.UpdateOpts.RemoveMetadata` [GH-2063](https://github.com/gophercloud/gophercloud/pull/2063)
* Added `objectstorage/v1/objects.UpdateOpts.RemoveMetadata` [GH-2063](https://github.com/gophercloud/gophercloud/pull/2063)
* Added `identity/v3/catalog.List` [GH-2067](https://github.com/gophercloud/gophercloud/pull/2067)
* Added `networking/v2/extensions/fwaas_v2/policies.List` [GH-2057](https://github.com/gophercloud/gophercloud/pull/2057)
* Added `networking/v2/extensions/fwaas_v2/policies.Create` [GH-2057](https://github.com/gophercloud/gophercloud/pull/2057)
* Added `networking/v2/extensions/fwaas_v2/policies.Get` [GH-2057](https://github.com/gophercloud/gophercloud/pull/2057)
* Added `networking/v2/extensions/fwaas_v2/policies.Update` [GH-2057](https://github.com/gophercloud/gophercloud/pull/2057)
* Added `networking/v2/extensions/fwaas_v2/policies.Delete` [GH-2057](https://github.com/gophercloud/gophercloud/pull/2057)
* Added `compute/v2/extensions/servergroups.ListOpts.AllProjects` [GH-2070](https://github.com/gophercloud/gophercloud/pull/2070)
* Added `objectstorage/v1/containers.CreateOpts.StoragePolicy` [GH-2075](https://github.com/gophercloud/gophercloud/pull/2075)
* Added `blockstorage/v3/snapshots.Update` [GH-2081](https://github.com/gophercloud/gophercloud/pull/2081)
* Added `loadbalancer/v2/l7policies.CreateOpts.Rules` [GH-2077](https://github.com/gophercloud/gophercloud/pull/2077)
* Added `loadbalancer/v2/listeners.CreateOpts.DefaultPool` [GH-2077](https://github.com/gophercloud/gophercloud/pull/2077)
* Added `loadbalancer/v2/listeners.CreateOpts.L7Policies` [GH-2077](https://github.com/gophercloud/gophercloud/pull/2077)
* Added `loadbalancer/v2/listeners.Listener.DefaultPool` [GH-2077](https://github.com/gophercloud/gophercloud/pull/2077)
* Added `loadbalancer/v2/loadbalancers.CreateOpts.Listeners` [GH-2077](https://github.com/gophercloud/gophercloud/pull/2077)
* Added `loadbalancer/v2/loadbalancers.CreateOpts.Pools` [GH-2077](https://github.com/gophercloud/gophercloud/pull/2077)
* Added `loadbalancer/v2/pools.CreateOpts.Members` [GH-2077](https://github.com/gophercloud/gophercloud/pull/2077)
* Added `loadbalancer/v2/pools.CreateOpts.Monitor` [GH-2077](https://github.com/gophercloud/gophercloud/pull/2077)
## 0.14.0 (November 11, 2020)
IMPROVEMENTS
* Added `identity/v3/endpoints.Endpoint.Enabled` [GH-2030](https://github.com/gophercloud/gophercloud/pull/2030)
* Added `containerinfra/v1/clusters.Upgrade` [GH-2032](https://github.com/gophercloud/gophercloud/pull/2032)
* Added `compute/apiversions.List` [GH-2037](https://github.com/gophercloud/gophercloud/pull/2037)
* Added `compute/apiversions.Get` [GH-2037](https://github.com/gophercloud/gophercloud/pull/2037)
* Added `compute/v2/servers.ListOpts.IP` [GH-2038](https://github.com/gophercloud/gophercloud/pull/2038)
* Added `compute/v2/servers.ListOpts.IP6` [GH-2038](https://github.com/gophercloud/gophercloud/pull/2038)
* Added `compute/v2/servers.ListOpts.UserID` [GH-2038](https://github.com/gophercloud/gophercloud/pull/2038)
* Added `dns/v2/transfer/accept.List` [GH-2041](https://github.com/gophercloud/gophercloud/pull/2041)
* Added `dns/v2/transfer/accept.Get` [GH-2041](https://github.com/gophercloud/gophercloud/pull/2041)
* Added `dns/v2/transfer/accept.Create` [GH-2041](https://github.com/gophercloud/gophercloud/pull/2041)
* Added `dns/v2/transfer/requests.List` [GH-2041](https://github.com/gophercloud/gophercloud/pull/2041)
* Added `dns/v2/transfer/requests.Get` [GH-2041](https://github.com/gophercloud/gophercloud/pull/2041)
* Added `dns/v2/transfer/requests.Update` [GH-2041](https://github.com/gophercloud/gophercloud/pull/2041)
* Added `dns/v2/transfer/requests.Delete` [GH-2041](https://github.com/gophercloud/gophercloud/pull/2041)
* Added `baremetal/v1/nodes.RescueWait` [GH-2052](https://github.com/gophercloud/gophercloud/pull/2052)
* Added `baremetal/v1/nodes.Unrescuing` [GH-2052](https://github.com/gophercloud/gophercloud/pull/2052)
* Added `networking/v2/extensions/fwaas_v2/groups.List` [GH-2050](https://github.com/gophercloud/gophercloud/pull/2050)
* Added `networking/v2/extensions/fwaas_v2/groups.Get` [GH-2050](https://github.com/gophercloud/gophercloud/pull/2050)
* Added `networking/v2/extensions/fwaas_v2/groups.Create` [GH-2050](https://github.com/gophercloud/gophercloud/pull/2050)
* Added `networking/v2/extensions/fwaas_v2/groups.Update` [GH-2050](https://github.com/gophercloud/gophercloud/pull/2050)
* Added `networking/v2/extensions/fwaas_v2/groups.Delete` [GH-2050](https://github.com/gophercloud/gophercloud/pull/2050)
BUG FIXES
* Changed `networking/v2/extensions/layer3/routers.Routes` from `[]Route` to `*[]Route` [GH-2043](https://github.com/gophercloud/gophercloud/pull/2043)
## 0.13.0 (September 27, 2020)
IMPROVEMENTS
* Added `ProtocolTerminatedHTTPS` as a valid listener protocol to `loadbalancer/v2/listeners` [GH-1992](https://github.com/gophercloud/gophercloud/pull/1992)
* Added `objectstorage/v1/objects.CreateTempURLOpts.Timestamp` [GH-1994](https://github.com/gophercloud/gophercloud/pull/1994)
* Added `compute/v2/extensions/schedulerhints.SchedulerHints.DifferentCell` [GH-2012](https://github.com/gophercloud/gophercloud/pull/2012)
* Added `loadbalancer/v2/quotas.Get` [GH-2010](https://github.com/gophercloud/gophercloud/pull/2010)
* Added `messaging/v2/queues.CreateOpts.EnableEncryptMessages` [GH-2016](https://github.com/gophercloud/gophercloud/pull/2016)
* Added `messaging/v2/queues.ListOpts.Name` [GH-2018](https://github.com/gophercloud/gophercloud/pull/2018)
* Added `messaging/v2/queues.ListOpts.WithCount` [GH-2018](https://github.com/gophercloud/gophercloud/pull/2018)
* Added `loadbalancer/v2/quotas.Update` [GH-2023](https://github.com/gophercloud/gophercloud/pull/2023)
* Added `loadbalancer/v2/loadbalancers.ListOpts.AvailabilityZone` [GH-2026](https://github.com/gophercloud/gophercloud/pull/2026)
* Added `loadbalancer/v2/loadbalancers.CreateOpts.AvailabilityZone` [GH-2026](https://github.com/gophercloud/gophercloud/pull/2026)
* Added `loadbalancer/v2/loadbalancers.LoadBalancer.AvailabilityZone` [GH-2026](https://github.com/gophercloud/gophercloud/pull/2026)
* Added `networking/v2/extensions/layer3/routers.ListL3Agents` [GH-2025](https://github.com/gophercloud/gophercloud/pull/2025)
BUG FIXES
* Fixed URL escaping in `objectstorage/v1/objects.CreateTempURL` [GH-1994](https://github.com/gophercloud/gophercloud/pull/1994)
* Remove unused `ServiceClient` from `compute/v2/servers.CreateOpts` [GH-2004](https://github.com/gophercloud/gophercloud/pull/2004)
* Changed `objectstorage/v1/objects.CreateOpts.DeleteAfter` from `int` to `int64` [GH-2014](https://github.com/gophercloud/gophercloud/pull/2014)
* Changed `objectstorage/v1/objects.CreateOpts.DeleteAt` from `int` to `int64` [GH-2014](https://github.com/gophercloud/gophercloud/pull/2014)
* Changed `objectstorage/v1/objects.UpdateOpts.DeleteAfter` from `int` to `int64` [GH-2014](https://github.com/gophercloud/gophercloud/pull/2014)
* Changed `objectstorage/v1/objects.UpdateOpts.DeleteAt` from `int` to `int64` [GH-2014](https://github.com/gophercloud/gophercloud/pull/2014)
## 0.12.0 (June 25, 2020)
UPGRADE NOTES
* The URL used in the `compute/v2/extensions/bootfromvolume` package has been changed from `os-volumes_boot` to `servers`.
IMPROVEMENTS
* The URL used in the `compute/v2/extensions/bootfromvolume` package has been changed from `os-volumes_boot` to `servers` [GH-1973](https://github.com/gophercloud/gophercloud/pull/1973)
* Modify `baremetal/v1/nodes.LogicalDisk.PhysicalDisks` type to support physical disks hints [GH-1982](https://github.com/gophercloud/gophercloud/pull/1982)
* Added `baremetalintrospection/httpbasic` which provides an HTTP Basic Auth client [GH-1986](https://github.com/gophercloud/gophercloud/pull/1986)
* Added `baremetal/httpbasic` which provides an HTTP Basic Auth client [GH-1983](https://github.com/gophercloud/gophercloud/pull/1983)
* Added `containerinfra/v1/clusters.CreateOpts.MergeLabels` [GH-1985](https://github.com/gophercloud/gophercloud/pull/1985)
BUG FIXES
* Changed `containerinfra/v1/clusters.Cluster.HealthStatusReason` from `string` to `map[string]interface{}` [GH-1968](https://github.com/gophercloud/gophercloud/pull/1968)
* Fixed marshalling of `blockstorage/extensions/backups.ImportBackup.Metadata` [GH-1967](https://github.com/gophercloud/gophercloud/pull/1967)
* Fixed typo of "OAUth" to "OAuth" in `identity/v3/extensions/oauth1` [GH-1969](https://github.com/gophercloud/gophercloud/pull/1969)
* Fixed goroutine leak during reauthentication [GH-1978](https://github.com/gophercloud/gophercloud/pull/1978)
* Changed `baremetalintrospection/v1/introspection.RootDiskType.Size` from `int` to `int64` [GH-1988](https://github.com/gophercloud/gophercloud/pull/1988)
## 0.11.0 (May 14, 2020)
@ -176,7 +295,7 @@ IMPROVEMENTS
* Added `MonitorAddress` to `loadbalancer/v2/pools.CreateMemberOpts` [GH-1824](https://github.com/gophercloud/gophercloud/pull/1824)
* Added `MonitorPort` to `loadbalancer/v2/pools.CreateMemberOpts` [GH-1824](https://github.com/gophercloud/gophercloud/pull/1824)
* Changed `Impersonation` to a non-required field in `identity/v3/extensions/trusts.CreateOpts` [GH-1818](https://github.com/gophercloud/gophercloud/pull/1818)
* Added `InsertHeaders` to `loadbalancer/v2/listeners.UpdateOpts` [GH-1835]
* Added `InsertHeaders` to `loadbalancer/v2/listeners.UpdateOpts` [GH-1835](https://github.com/gophercloud/gophercloud/pull/1835)
* Added `NUMATopology` to `baremetalintrospection/v1/introspection.Data` [GH-1842](https://github.com/gophercloud/gophercloud/pull/1842)
* Added `placement/v1/resourceproviders.Create` [GH-1841](https://github.com/gophercloud/gophercloud/pull/1841)
* Added `blockstorage/extensions/volumeactions.UploadImageOpts.Visibility` [GH-1873](https://github.com/gophercloud/gophercloud/pull/1873)

View File

@ -60,6 +60,13 @@ prompted for your password.
### Authentication
> NOTE: It is now recommended to use the `clientconfig` package found at
> https://github.com/gophercloud/utils/tree/master/openstack/clientconfig
> for all authentication purposes.
>
> The below documentation is still relevant. clientconfig simply implements
> the below and presents it in an easier and more flexible way.
Once you have access to your credentials, you can begin plugging them into
Gophercloud. The next step is authentication, and this is handled by a base
"Provider" struct. To get one, you can either pass in your credentials

View File

@ -1,13 +1,11 @@
module github.com/gophercloud/gophercloud
go 1.13
require (
github.com/kr/pretty v0.2.1 // indirect
golang.org/x/crypto v0.0.0-20191202143827-86a70503ff7e
golang.org/x/net v0.0.0-20191126235420-ef20fe5d7933 // indirect
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e // indirect
golang.org/x/sys v0.0.0-20191128015809-6d18c012aee9 // indirect
golang.org/x/text v0.3.2 // indirect
golang.org/x/tools v0.0.0-20191203134012-c197fd4bf371 // indirect
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898 // indirect
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
gopkg.in/yaml.v2 v2.2.7
gopkg.in/yaml.v2 v2.3.0
)

View File

@ -1,26 +1,19 @@
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191202143827-86a70503ff7e h1:egKlR8l7Nu9vHGWbcUV8lqR4987UfUbBd7GbhqGzNYU=
golang.org/x/crypto v0.0.0-20191202143827-86a70503ff7e/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191126235420-ef20fe5d7933/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191128015809-6d18c012aee9 h1:ZBzSG/7F4eNKz2L3GE9o300RX0Az1Bw5HF7PDraD+qU=
golang.org/x/sys v0.0.0-20191128015809-6d18c012aee9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191203134012-c197fd4bf371/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.7 h1:VUgggvou5XRW9mHwD/yXxIYSMtY0zoKQf/v226p2nyo=
gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

View File

@ -1,12 +0,0 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = [
"pkg.go",
"util.go",
],
importmap = "k8s.io/kops/vendor/github.com/gophercloud/gophercloud/internal",
importpath = "github.com/gophercloud/gophercloud/internal",
visibility = ["//vendor/github.com/gophercloud/gophercloud:__subpackages__"],
)

View File

@ -1 +0,0 @@
package internal

View File

@ -1,34 +0,0 @@
package internal
import (
"reflect"
"strings"
)
// RemainingKeys will inspect a struct and compare it to a map. Any struct
// field that does not have a JSON tag that matches a key in the map or
// a matching lower-case field in the map will be returned as an extra.
//
// This is useful for determining the extra fields returned in response bodies
// for resources that can contain an arbitrary or dynamic number of fields.
func RemainingKeys(s interface{}, m map[string]interface{}) (extras map[string]interface{}) {
extras = make(map[string]interface{})
for k, v := range m {
extras[k] = v
}
valueOf := reflect.ValueOf(s)
typeOf := reflect.TypeOf(s)
for i := 0; i < valueOf.NumField(); i++ {
field := typeOf.Field(i)
lowerField := strings.ToLower(field.Name)
delete(extras, lowerField)
if tagValue := field.Tag.Get("json"); tagValue != "" && tagValue != "-" {
delete(extras, tagValue)
}
}
return
}

View File

@ -3,5 +3,5 @@ package bootfromvolume
import "github.com/gophercloud/gophercloud"
func createURL(c *gophercloud.ServiceClient) string {
return c.ServiceURL("os-volumes_boot")
return c.ServiceURL("servers")
}

View File

@ -31,6 +31,9 @@ type SchedulerHints struct {
// TargetCell specifies a cell name where the instance will be placed.
TargetCell string `json:"target_cell,omitempty"`
// DifferentCell specifies cells names where an instance should not be placed.
DifferentCell []string `json:"different_cell,omitempty"`
// BuildNearHostIP specifies a subnet of compute nodes to host the instance.
BuildNearHostIP string
@ -124,6 +127,10 @@ func (opts SchedulerHints) ToServerSchedulerHintsCreateMap() (map[string]interfa
sh["target_cell"] = opts.TargetCell
}
if len(opts.DifferentCell) > 0 {
sh["different_cell"] = opts.DifferentCell
}
if opts.BuildNearHostIP != "" {
if _, _, err := net.ParseCIDR(opts.BuildNearHostIP); err != nil {
err := gophercloud.ErrInvalidInput{}

View File

@ -5,10 +5,34 @@ import (
"github.com/gophercloud/gophercloud/pagination"
)
type ListOptsBuilder interface {
ToServerListQuery() (string, error)
}
type ListOpts struct {
// AllProjects is a bool to show all projects.
AllProjects bool `q:"all_projects"`
}
// ToServerListQuery formats a ListOpts into a query string.
func (opts ListOpts) ToServerListQuery() (string, error) {
q, err := gophercloud.BuildQueryString(opts)
return q.String(), err
}
// List returns a Pager that allows you to iterate over a collection of
// ServerGroups.
func List(client *gophercloud.ServiceClient) pagination.Pager {
return pagination.NewPager(client, listURL(client), func(r pagination.PageResult) pagination.Page {
func List(client *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager {
url := listURL(client)
if opts != nil {
query, err := opts.ToServerListQuery()
if err != nil {
return pagination.Pager{Err: err}
}
url += query
}
return pagination.NewPager(client, url, func(r pagination.PageResult) pagination.Page {
return ServerGroupPage{pagination.SinglePageBase(r)}
})
}

View File

@ -29,6 +29,14 @@ type ListOpts struct {
// Flavor is the name of the flavor in URL format.
Flavor string `q:"flavor"`
// IP is a regular expression to match the IPv4 address of the server.
IP string `q:"ip"`
// This requires the client to be set to microversion 2.5 or later, unless
// the user is an admin.
// IP is a regular expression to match the IPv6 address of the server.
IP6 string `q:"ip6"`
// Name of the server as a string; can be queried with regular expressions.
// Realize that ?name=bob returns both bob and bobb. If you need to match bob
// only, you can use a regular expression matching the syntax of the
@ -55,6 +63,11 @@ type ListOpts struct {
// Setting "AllTenants = true" is required.
TenantID string `q:"tenant_id"`
// This requires the client to be set to microversion 2.83 or later, unless
// the user is an admin.
// UserID lists servers for a particular user.
UserID string `q:"user_id"`
// This requires the client to be set to microversion 2.26 or later.
// Tags filters on specific server tags. All tags must be present for the server.
Tags string `q:"tags"`
@ -199,10 +212,6 @@ type CreateOpts struct {
// Max specifies Maximum number of servers to launch.
Max int `json:"max_count,omitempty"`
// ServiceClient will allow calls to be made to retrieve an image or
// flavor ID by name.
ServiceClient *gophercloud.ServiceClient `json:"-"`
// Tags allows a server to be tagged with single-word metadata.
// Requires microversion 2.52 or later.
Tags []string `json:"tags,omitempty"`
@ -211,7 +220,6 @@ type CreateOpts struct {
// ToServerCreateMap assembles a request body based on the contents of a
// CreateOpts.
func (opts CreateOpts) ToServerCreateMap() (map[string]interface{}, error) {
opts.ServiceClient = nil
b, err := gophercloud.BuildRequestBody(opts, "")
if err != nil {
return nil, err
@ -447,10 +455,6 @@ type RebuildOpts struct {
// Personality [optional] includes files to inject into the server at launch.
// Rebuild will base64-encode file contents for you.
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:"-"`
}
// ToServerRebuildMap formats a RebuildOpts struct into a map for use in JSON

View File

@ -8,7 +8,7 @@ for more information.
Example to List Tenants
listOpts := tenants.ListOpts{
listOpts := &tenants.ListOpts{
Limit: 2,
}

View File

@ -96,8 +96,8 @@ type Token struct {
OAuthToken string `q:"oauth_token"`
// OAuthTokenSecret is the secret value associated with the OAuth Token.
OAuthTokenSecret string `q:"oauth_token_secret"`
// OAUthExpiresAt is the date and time when an OAuth token expires.
OAUthExpiresAt *time.Time `q:"-"`
// OAuthExpiresAt is the date and time when an OAuth token expires.
OAuthExpiresAt *time.Time `q:"-"`
}
// TokenResult is a struct to handle
@ -127,7 +127,7 @@ func (r TokenResult) Extract() (*Token, error) {
if t, err := time.Parse(gophercloud.RFC3339Milli, v); err != nil {
return nil, err
} else {
token.OAUthExpiresAt = &t
token.OAuthExpiresAt = &t
}
}

View File

@ -14,7 +14,6 @@ go_library(
visibility = ["//visibility:public"],
deps = [
"//vendor/github.com/gophercloud/gophercloud:go_default_library",
"//vendor/github.com/gophercloud/gophercloud/internal:go_default_library",
"//vendor/github.com/gophercloud/gophercloud/openstack/utils:go_default_library",
"//vendor/github.com/gophercloud/gophercloud/pagination:go_default_library",
],

View File

@ -8,7 +8,6 @@ import (
"time"
"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/internal"
"github.com/gophercloud/gophercloud/pagination"
)
@ -132,7 +131,7 @@ func (r *Image) UnmarshalJSON(b []byte) error {
delete(resultMap, "size")
delete(resultMap, "openstack-image-import-methods")
delete(resultMap, "openstack-image-store-ids")
r.Properties = internal.RemainingKeys(Image{}, resultMap)
r.Properties = gophercloud.RemainingKeys(Image{}, resultMap)
}
if v := strings.FieldsFunc(strings.TrimSpace(s.OpenStackImageImportMethods), splitFunc); len(v) > 0 {

View File

@ -40,7 +40,7 @@ type CreateOpts struct {
Name string `json:"name,omitempty"`
// The ID of the listener.
ListenerID string `json:"listener_id" required:"true"`
ListenerID string `json:"listener_id,omitempty"`
// The L7 policy action. One of REDIRECT_TO_POOL, REDIRECT_TO_URL, or REJECT.
Action Action `json:"action" required:"true"`
@ -66,6 +66,13 @@ type CreateOpts struct {
// The administrative state of the Loadbalancer. A valid value is true (UP)
// or false (DOWN).
AdminStateUp *bool `json:"admin_state_up,omitempty"`
// Rules is a slice of CreateRuleOpts which allows a set of rules
// to be created at the same time the policy is created.
//
// This is only possible to use when creating a fully populated
// Loadbalancer.
Rules []CreateRuleOpts `json:"rules,omitempty" xor:"ListenerID"`
}
// ToL7PolicyCreateMap builds a request body from CreateOpts.

View File

@ -2,6 +2,8 @@ package listeners
import (
"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/l7policies"
"github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/pools"
"github.com/gophercloud/gophercloud/pagination"
)
@ -10,11 +12,12 @@ type Protocol string
// Supported attributes for create/update operations.
const (
ProtocolTCP Protocol = "TCP"
ProtocolUDP Protocol = "UDP"
ProtocolPROXY Protocol = "PROXY"
ProtocolHTTP Protocol = "HTTP"
ProtocolHTTPS Protocol = "HTTPS"
ProtocolTCP Protocol = "TCP"
ProtocolUDP Protocol = "UDP"
ProtocolPROXY Protocol = "PROXY"
ProtocolHTTP Protocol = "HTTP"
ProtocolHTTPS Protocol = "HTTPS"
ProtocolTerminatedHTTPS Protocol = "TERMINATED_HTTPS"
)
// ListOptsBuilder allows extensions to add additional parameters to the
@ -83,9 +86,9 @@ type CreateOptsBuilder interface {
// CreateOpts represents options for creating a listener.
type CreateOpts struct {
// The load balancer on which to provision this listener.
LoadbalancerID string `json:"loadbalancer_id" required:"true"`
LoadbalancerID string `json:"loadbalancer_id,omitempty"`
// The protocol - can either be TCP, HTTP or HTTPS.
// The protocol - can either be TCP, HTTP, HTTPS or TERMINATED_HTTPS.
Protocol Protocol `json:"protocol" required:"true"`
// The port on which to listen for client traffic.
@ -101,6 +104,13 @@ type CreateOpts struct {
// The ID of the default pool with which the Listener is associated.
DefaultPoolID string `json:"default_pool_id,omitempty"`
// DefaultPool an instance of pools.CreateOpts which allows a
// (default) pool to be created at the same time the listener is created.
//
// This is only possible to use when creating a fully populated
// load balancer.
DefaultPool *pools.CreateOpts `json:"default_pool,omitempty" xor:"LoadbalancerID"`
// Human-readable description for the Listener.
Description string `json:"description,omitempty"`
@ -117,6 +127,13 @@ type CreateOpts struct {
// or false (DOWN).
AdminStateUp *bool `json:"admin_state_up,omitempty"`
// L7Policies is a slice of l7policies.CreateOpts which allows a set
// of policies to be created at the same time the listener is created.
//
// This is only possible to use when creating a fully populated
// Loadbalancer.
L7Policies []l7policies.CreateOpts `json:"l7policies,omitempty" xor:"LoadbalancerID"`
// Frontend client inactivity timeout in milliseconds
TimeoutClientData *int `json:"timeout_client_data,omitempty"`

View File

@ -37,6 +37,9 @@ type Listener struct {
// The UUID of default pool. Must have compatible protocol with listener.
DefaultPoolID string `json:"default_pool_id"`
// The default pool with which the Listener is associated.
DefaultPool *pools.Pool `json:"default_pool"`
// A list of load balancer IDs.
Loadbalancers []LoadBalancerID `json:"loadbalancers"`

View File

@ -39,6 +39,54 @@ Example to Create a Load Balancer
panic(err)
}
Example to Create a fully populated Load Balancer
createOpts := loadbalancers.CreateOpts{
Name: "db_lb",
AdminStateUp: gophercloud.Enabled,
VipSubnetID: "9cedb85d-0759-4898-8a4b-fa5a5ea10086",
VipAddress: "10.30.176.48",
FlavorID: "60df399a-ee85-11e9-81b4-2a2ae2dbcce4",
Provider: "haproxy",
Tags: []string{"test", "stage"},
Listeners: []listeners.CreateOpts{{
Protocol: "HTTP",
ProtocolPort: 8080,
Name: "redirect_listener",
L7Policies: []l7policies.CreateOpts{{
Name: "redirect-example.com",
Action: l7policies.ActionRedirectToURL,
RedirectURL: "http://www.example.com",
Rules: []l7policies.CreateRuleOpts{{
RuleType: l7policies.TypePath,
CompareType: l7policies.CompareTypeRegex,
Value: "/images*",
}},
}},
DefaultPool: &pools.CreateOpts{
LBMethod: pools.LBMethodRoundRobin,
Protocol: "HTTP",
Name: "example pool",
Members: []pools.BatchUpdateMemberOpts{{
Address: "192.0.2.51",
ProtocolPort: 80,
},},
Monitor: &monitors.CreateOpts{
Name: "db",
Type: "HTTP",
Delay: 3,
MaxRetries: 2,
Timeout: 1,
},
},
}},
}
lb, err := loadbalancers.Create(networkClient, createOpts).Extract()
if err != nil {
panic(err)
}
Example to Update a Load Balancer
lbID := "d67d56a6-4a86-4688-a282-f46444705c64"

View File

@ -2,6 +2,8 @@ package loadbalancers
import (
"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/listeners"
"github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/pools"
"github.com/gophercloud/gophercloud/pagination"
)
@ -29,6 +31,7 @@ type ListOpts struct {
OperatingStatus string `q:"operating_status"`
Name string `q:"name"`
FlavorID string `q:"flavor_id"`
AvailabilityZone string `q:"availability_zone"`
Provider string `q:"provider"`
Limit int `q:"limit"`
Marker string `q:"marker"`
@ -111,9 +114,27 @@ type CreateOpts struct {
// The UUID of a flavor.
FlavorID string `json:"flavor_id,omitempty"`
// The name of an Octavia availability zone.
// Requires Octavia API version 2.14 or later.
AvailabilityZone string `json:"availability_zone,omitempty"`
// The name of the provider.
Provider string `json:"provider,omitempty"`
// Listeners is a slice of listeners.CreateOpts which allows a set
// of listeners to be created at the same time the Loadbalancer is created.
//
// This is only possible to use when creating a fully populated
// load balancer.
Listeners []listeners.CreateOpts `json:"listeners,omitempty"`
// Pools is a slice of pools.CreateOpts which allows a set of pools
// to be created at the same time the Loadbalancer is created.
//
// This is only possible to use when creating a fully populated
// load balancer.
Pools []pools.CreateOpts `json:"pools,omitempty"`
// Tags is a set of resource tags.
Tags []string `json:"tags,omitempty"`
}

View File

@ -59,6 +59,9 @@ type LoadBalancer struct {
// The UUID of a flavor if set.
FlavorID string `json:"flavor_id"`
// The name of an Octavia availability zone if set.
AvailabilityZone string `json:"availability_zone"`
// The name of the provider.
Provider string `json:"provider"`

View File

@ -91,7 +91,7 @@ type CreateOptsBuilder interface {
// operation.
type CreateOpts struct {
// The Pool to Monitor.
PoolID string `json:"pool_id" required:"true"`
PoolID string `json:"pool_id,omitempty"`
// The type of probe, which is PING, TCP, HTTP, or HTTPS, that is
// sent by the load balancer to verify the member state.

View File

@ -2,6 +2,7 @@ package pools
import (
"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/monitors"
"github.com/gophercloud/gophercloud/pagination"
)
@ -92,11 +93,11 @@ type CreateOpts struct {
// The Loadbalancer on which the members of the pool will be associated with.
// Note: one of LoadbalancerID or ListenerID must be provided.
LoadbalancerID string `json:"loadbalancer_id,omitempty" xor:"ListenerID"`
LoadbalancerID string `json:"loadbalancer_id,omitempty"`
// The Listener on which the members of the pool will be associated with.
// Note: one of LoadbalancerID or ListenerID must be provided.
ListenerID string `json:"listener_id,omitempty" xor:"LoadbalancerID"`
ListenerID string `json:"listener_id,omitempty"`
// ProjectID is the UUID of the project who owns the Pool.
// Only administrative users can specify a project UUID other than their own.
@ -115,6 +116,20 @@ type CreateOpts struct {
// The administrative state of the Pool. A valid value is true (UP)
// or false (DOWN).
AdminStateUp *bool `json:"admin_state_up,omitempty"`
// Members is a slice of BatchUpdateMemberOpts which allows a set of
// members to be created at the same time the pool is created.
//
// This is only possible to use when creating a fully populated
// Loadbalancer.
Members []BatchUpdateMemberOpts `json:"members,omitempty"`
// Monitor is an instance of monitors.CreateOpts which allows a monitor
// to be created at the same time the pool is created.
//
// This is only possible to use when creating a fully populated
// Loadbalancer.
Monitor *monitors.CreateOpts `json:"healthmonitor,omitempty"`
}
// ToPoolCreateMap builds a request body from CreateOpts.
@ -280,7 +295,9 @@ type CreateMemberOpts struct {
// or false (DOWN).
AdminStateUp *bool `json:"admin_state_up,omitempty"`
// Is the member a backup? Backup members only receive traffic when all non-backup members are down.
// Is the member a backup? Backup members only receive traffic when all
// non-backup members are down.
// Requires microversion 2.1 or later.
Backup *bool `json:"backup,omitempty"`
// An alternate IP address used for health monitoring a backend member.
@ -288,6 +305,10 @@ type CreateMemberOpts struct {
// An alternate protocol port used for health monitoring a backend member.
MonitorPort *int `json:"monitor_port,omitempty"`
// A list of simple strings assigned to the resource.
// Requires microversion 2.5 or later.
Tags []string `json:"tags,omitempty"`
}
// ToMemberCreateMap builds a request body from CreateMemberOpts.
@ -335,6 +356,21 @@ type UpdateMemberOpts struct {
// The administrative state of the Pool. A valid value is true (UP)
// or false (DOWN).
AdminStateUp *bool `json:"admin_state_up,omitempty"`
// Is the member a backup? Backup members only receive traffic when all
// non-backup members are down.
// Requires microversion 2.1 or later.
Backup *bool `json:"backup,omitempty"`
// An alternate IP address used for health monitoring a backend member.
MonitorAddress *string `json:"monitor_address,omitempty"`
// An alternate protocol port used for health monitoring a backend member.
MonitorPort *int `json:"monitor_port,omitempty"`
// A list of simple strings assigned to the resource.
// Requires microversion 2.5 or later.
Tags []string `json:"tags,omitempty"`
}
// ToMemberUpdateMap builds a request body from UpdateMemberOpts.
@ -390,6 +426,21 @@ type BatchUpdateMemberOpts struct {
// The administrative state of the Pool. A valid value is true (UP)
// or false (DOWN).
AdminStateUp *bool `json:"admin_state_up,omitempty"`
// Is the member a backup? Backup members only receive traffic when all
// non-backup members are down.
// Requires microversion 2.1 or later.
Backup *bool `json:"backup,omitempty"`
// An alternate IP address used for health monitoring a backend member.
MonitorAddress *string `json:"monitor_address,omitempty"`
// An alternate protocol port used for health monitoring a backend member.
MonitorPort *int `json:"monitor_port,omitempty"`
// A list of simple strings assigned to the resource.
// Requires microversion 2.5 or later.
Tags []string `json:"tags,omitempty"`
}
// ToBatchMemberUpdateMap builds a request body from BatchUpdateMemberOpts.
@ -425,8 +476,7 @@ func BatchUpdateMembers(c *gophercloud.ServiceClient, poolID string, opts []Batc
return
}
// DisassociateMember will remove and disassociate a Member from a particular
// Pool.
// DeleteMember will remove and disassociate a Member from a particular Pool.
func DeleteMember(c *gophercloud.ServiceClient, poolID string, memberID string) (r DeleteMemberResult) {
resp, err := c.Delete(memberResourceURL(c, poolID, memberID), nil)
_, r.Header, r.Err = gophercloud.ParseResponse(resp, err)

View File

@ -228,6 +228,10 @@ type Member struct {
// An alternate protocol port used for health monitoring a backend member.
MonitorPort int `json:"monitor_port"`
// A list of simple strings assigned to the resource.
// Requires microversion 2.5 or later.
Tags []string `json:"tags"`
}
// MemberPage is the page returned by a pager when traversing over a

View File

@ -48,7 +48,20 @@ Example to Update a Router
updateOpts := routers.UpdateOpts{
Name: "new_name",
Routes: routes,
Routes: &routes,
}
router, err := routers.Update(networkClient, routerID, updateOpts).Extract()
if err != nil {
panic(err)
}
Example to Update just the Router name, keeping everything else as-is
routerID := "4e8e5957-649f-477b-9e5b-f1f75b21c03c"
updateOpts := routers.UpdateOpts{
Name: "new_name",
}
router, err := routers.Update(networkClient, routerID, updateOpts).Extract()
@ -63,7 +76,7 @@ Example to Remove all Routes from a Router
routes := []routers.Route{}
updateOpts := routers.UpdateOpts{
Routes: routes,
Routes: &routes,
}
router, err := routers.Update(networkClient, routerID, updateOpts).Extract()
@ -104,5 +117,23 @@ Example to Remove an Interface from a Router
if err != nil {
panic(err)
}
Example to List an L3 agents for a Router
routerID := "4e8e5957-649f-477b-9e5b-f1f75b21c03c"
allPages, err := routers.ListL3Agents(networkClient, routerID).AllPages()
if err != nil {
panic(err)
}
allL3Agents, err := routers.ExtractL3Agents(allPages)
if err != nil {
panic(err)
}
for _, agent := range allL3Agents {
fmt.Printf("%+v\n", agent)
}
*/
package routers

View File

@ -109,7 +109,7 @@ type UpdateOpts struct {
AdminStateUp *bool `json:"admin_state_up,omitempty"`
Distributed *bool `json:"distributed,omitempty"`
GatewayInfo *GatewayInfo `json:"external_gateway_info,omitempty"`
Routes []Route `json:"routes"`
Routes *[]Route `json:"routes,omitempty"`
}
// ToRouterUpdateMap builds an update body based on UpdateOpts.
@ -237,3 +237,10 @@ func RemoveInterface(c *gophercloud.ServiceClient, id string, opts RemoveInterfa
_, r.Header, r.Err = gophercloud.ParseResponse(resp, err)
return
}
// ListL3Agents returns a list of l3-agents scheduled for a specific router.
func ListL3Agents(c *gophercloud.ServiceClient, id string) (result pagination.Pager) {
return pagination.NewPager(c, listl3AgentsURL(c, id), func(r pagination.PageResult) pagination.Page {
return ListL3AgentsPage{pagination.SinglePageBase(r)}
})
}

View File

@ -1,6 +1,9 @@
package routers
import (
"encoding/json"
"time"
"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/pagination"
)
@ -179,3 +182,96 @@ func (r InterfaceResult) Extract() (*InterfaceInfo, error) {
err := r.ExtractInto(&s)
return &s, err
}
// L3Agent represents a Neutron agent for routers.
type L3Agent struct {
// ID is the id of the agent.
ID string `json:"id"`
// AdminStateUp is an administrative state of the agent.
AdminStateUp bool `json:"admin_state_up"`
// AgentType is a type of the agent.
AgentType string `json:"agent_type"`
// Alive indicates whether agent is alive or not.
Alive bool `json:"alive"`
// ResourcesSynced indicates whether agent is synced or not.
// Not all agent types track resources via Placement.
ResourcesSynced bool `json:"resources_synced"`
// AvailabilityZone is a zone of the agent.
AvailabilityZone string `json:"availability_zone"`
// Binary is an executable binary of the agent.
Binary string `json:"binary"`
// Configurations is a configuration specific key/value pairs that are
// determined by the agent binary and type.
Configurations map[string]interface{} `json:"configurations"`
// CreatedAt is a creation timestamp.
CreatedAt time.Time `json:"-"`
// StartedAt is a starting timestamp.
StartedAt time.Time `json:"-"`
// HeartbeatTimestamp is a last heartbeat timestamp.
HeartbeatTimestamp time.Time `json:"-"`
// Description contains agent description.
Description string `json:"description"`
// Host is a hostname of the agent system.
Host string `json:"host"`
// Topic contains name of AMQP topic.
Topic string `json:"topic"`
// HAState is a ha state of agent(active/standby) for router
HAState string `json:"ha_state"`
// ResourceVersions is a list agent known objects and version numbers
ResourceVersions map[string]interface{} `json:"resource_versions"`
}
// UnmarshalJSON helps to convert the timestamps into the time.Time type.
func (r *L3Agent) UnmarshalJSON(b []byte) error {
type tmp L3Agent
var s struct {
tmp
CreatedAt gophercloud.JSONRFC3339ZNoTNoZ `json:"created_at"`
StartedAt gophercloud.JSONRFC3339ZNoTNoZ `json:"started_at"`
HeartbeatTimestamp gophercloud.JSONRFC3339ZNoTNoZ `json:"heartbeat_timestamp"`
}
err := json.Unmarshal(b, &s)
if err != nil {
return err
}
*r = L3Agent(s.tmp)
r.CreatedAt = time.Time(s.CreatedAt)
r.StartedAt = time.Time(s.StartedAt)
r.HeartbeatTimestamp = time.Time(s.HeartbeatTimestamp)
return nil
}
type ListL3AgentsPage struct {
pagination.SinglePageBase
}
func (r ListL3AgentsPage) IsEmpty() (bool, error) {
v, err := ExtractL3Agents(r)
return len(v) == 0, err
}
func ExtractL3Agents(r pagination.Page) ([]L3Agent, error) {
var s struct {
L3Agents []L3Agent `json:"agents"`
}
err := (r.(ListL3AgentsPage)).ExtractInto(&s)
return s.L3Agents, err
}

View File

@ -19,3 +19,7 @@ func addInterfaceURL(c *gophercloud.ServiceClient, id string) string {
func removeInterfaceURL(c *gophercloud.ServiceClient, id string) string {
return c.ServiceURL(resourcePath, id, "remove_router_interface")
}
func listl3AgentsURL(c *gophercloud.ServiceClient, id string) string {
return c.ServiceURL(resourcePath, id, "l3-agents")
}

View File

@ -53,6 +53,7 @@ type UpdateOptsBuilder interface {
// deleting an account's metadata.
type UpdateOpts struct {
Metadata map[string]string
RemoveMetadata []string
ContentType string `h:"Content-Type"`
DetectContentType bool `h:"X-Detect-Content-Type"`
TempURLKey string `h:"X-Account-Meta-Temp-URL-Key"`
@ -65,9 +66,15 @@ func (opts UpdateOpts) ToAccountUpdateMap() (map[string]string, error) {
if err != nil {
return nil, err
}
for k, v := range opts.Metadata {
headers["X-Account-Meta-"+k] = v
}
for _, k := range opts.RemoveMetadata {
headers["X-Remove-Account-Meta-"+k] = "remove"
}
return headers, err
}

View File

@ -80,6 +80,7 @@ type CreateOpts struct {
HistoryLocation string `h:"X-History-Location"`
TempURLKey string `h:"X-Container-Meta-Temp-URL-Key"`
TempURLKey2 string `h:"X-Container-Meta-Temp-URL-Key-2"`
StoragePolicy string `h:"X-Storage-Policy"`
}
// ToContainerCreateMap formats a CreateOpts into a map of headers.

View File

@ -153,8 +153,8 @@ type CreateOpts struct {
ContentLength int64 `h:"Content-Length"`
ContentType string `h:"Content-Type"`
CopyFrom string `h:"X-Copy-From"`
DeleteAfter int `h:"X-Delete-After"`
DeleteAt int `h:"X-Delete-At"`
DeleteAfter int64 `h:"X-Delete-After"`
DeleteAt int64 `h:"X-Delete-At"`
DetectContentType string `h:"X-Detect-Content-Type"`
ETag string `h:"ETag"`
IfNoneMatch string `h:"If-None-Match"`
@ -388,11 +388,12 @@ type UpdateOptsBuilder interface {
// deleting an object's metadata.
type UpdateOpts struct {
Metadata map[string]string
RemoveMetadata []string
ContentDisposition string `h:"Content-Disposition"`
ContentEncoding string `h:"Content-Encoding"`
ContentType string `h:"Content-Type"`
DeleteAfter int `h:"X-Delete-After"`
DeleteAt int `h:"X-Delete-At"`
DeleteAfter int64 `h:"X-Delete-After"`
DeleteAt int64 `h:"X-Delete-At"`
DetectContentType bool `h:"X-Detect-Content-Type"`
}
@ -402,9 +403,14 @@ func (opts UpdateOpts) ToObjectUpdateMap() (map[string]string, error) {
if err != nil {
return nil, err
}
for k, v := range opts.Metadata {
h["X-Object-Meta-"+k] = v
}
for _, k := range opts.RemoveMetadata {
h["X-Remove-Object-Meta-"+k] = "remove"
}
return h, nil
}
@ -454,6 +460,9 @@ type CreateTempURLOpts struct {
// the object path is used in the hash, the object URL needs to be parsed. If
// empty, the default OpenStack URL split point will be used ("/v1/").
Split string
// Timestamp is a timestamp to calculate Temp URL signature. Optional.
Timestamp time.Time
}
// CreateTempURL is a function for creating a temporary URL for an object. It
@ -463,8 +472,17 @@ func CreateTempURL(c *gophercloud.ServiceClient, containerName, objectName strin
if opts.Split == "" {
opts.Split = "/v1/"
}
// Initialize time if it was not passed as opts
var date time.Time
if opts.Timestamp.IsZero() {
date = time.Now().UTC()
} else {
date = opts.Timestamp
}
duration := time.Duration(opts.TTL) * time.Second
expiry := time.Now().Add(duration).Unix()
expiry := date.Add(duration).Unix()
getHeader, err := containers.Get(c, url.QueryEscape(containerName), nil).Extract()
if err != nil {
return "", err
@ -479,7 +497,7 @@ func CreateTempURL(c *gophercloud.ServiceClient, containerName, objectName strin
tempURLKey = getHeader.TempURLKey
}
secretKey := []byte(tempURLKey)
url := getURL(c, url.QueryEscape(containerName), url.QueryEscape(objectName))
url := getURL(c, containerName, objectName)
splitPath := strings.Split(url, opts.Split)
baseURL, objectPath := splitPath[0], splitPath[1]
objectPath = opts.Split + objectPath

View File

@ -40,7 +40,7 @@ func (current LinkedPageBase) NextPageURL() (string, error) {
}
for {
key, path = path[0], path[1:len(path)]
key, path = path[0], path[1:]
value, ok := submap[key]
if !ok {

View File

@ -94,10 +94,32 @@ type ProviderClient struct {
// reauthlock represents a set of attributes used to help in the reauthentication process.
type reauthlock struct {
sync.RWMutex
// This channel is non-nil during reauthentication. It can be used to ask the
// goroutine doing Reauthenticate() for its result. Look at the implementation
// of Reauthenticate() for details.
ongoing chan<- (chan<- error)
ongoing *reauthFuture
}
// reauthFuture represents future result of the reauthentication process.
// while done channel is not closed, reauthentication is in progress.
// when done channel is closed, err contains the result of reauthentication.
type reauthFuture struct {
done chan struct{}
err error
}
func newReauthFuture() *reauthFuture {
return &reauthFuture{
make(chan struct{}),
nil,
}
}
func (f *reauthFuture) Set(err error) {
f.err = err
close(f.done)
}
func (f *reauthFuture) Get() error {
<-f.done
return f.err
}
// AuthenticatedHeaders returns a map of HTTP headers that are common for all
@ -112,9 +134,7 @@ func (client *ProviderClient) AuthenticatedHeaders() (m map[string]string) {
ongoing := client.reauthmut.ongoing
client.reauthmut.Unlock()
if ongoing != nil {
responseChannel := make(chan error)
ongoing <- responseChannel
_ = <-responseChannel
_ = ongoing.Get()
}
}
t := client.Token()
@ -237,21 +257,19 @@ func (client *ProviderClient) Reauthenticate(previousToken string) error {
return client.ReauthFunc()
}
messages := make(chan (chan<- error))
future := newReauthFuture()
// Check if a Reauthenticate is in progress, or start one if not.
client.reauthmut.Lock()
ongoing := client.reauthmut.ongoing
if ongoing == nil {
client.reauthmut.ongoing = messages
client.reauthmut.ongoing = future
}
client.reauthmut.Unlock()
// If Reauthenticate is running elsewhere, wait for its result.
if ongoing != nil {
responseChannel := make(chan error)
ongoing <- responseChannel
return <-responseChannel
return ongoing.Get()
}
// Perform the actual reauthentication.
@ -264,22 +282,10 @@ func (client *ProviderClient) Reauthenticate(previousToken string) error {
// Mark Reauthenticate as finished.
client.reauthmut.Lock()
client.reauthmut.ongoing.Set(err)
client.reauthmut.ongoing = nil
client.reauthmut.Unlock()
// Report result to all other interested goroutines.
//
// This happens in a separate goroutine because another goroutine might have
// acquired a copy of `client.reauthmut.ongoing` before we cleared it, but not
// have come around to sending its request. By answering in a goroutine, we
// can have that goroutine linger until all responseChannels have been sent.
// When GC has collected all sendings ends of the channel, our receiving end
// will be closed and the goroutine will end.
go func() {
for responseChannel := range messages {
responseChannel <- err
}
}()
return err
}

View File

@ -4,10 +4,85 @@ import (
"fmt"
"net/url"
"path/filepath"
"reflect"
"strings"
"time"
)
// NormalizePathURL is used to convert rawPath to a fqdn, using basePath as
// a reference in the filesystem, if necessary. basePath is assumed to contain
// either '.' when first used, or the file:// type fqdn of the parent resource.
// e.g. myFavScript.yaml => file://opt/lib/myFavScript.yaml
func NormalizePathURL(basePath, rawPath string) (string, error) {
u, err := url.Parse(rawPath)
if err != nil {
return "", err
}
// if a scheme is defined, it must be a fqdn already
if u.Scheme != "" {
return u.String(), nil
}
// if basePath is a url, then child resources are assumed to be relative to it
bu, err := url.Parse(basePath)
if err != nil {
return "", err
}
var basePathSys, absPathSys string
if bu.Scheme != "" {
basePathSys = filepath.FromSlash(bu.Path)
absPathSys = filepath.Join(basePathSys, rawPath)
bu.Path = filepath.ToSlash(absPathSys)
return bu.String(), nil
}
absPathSys = filepath.Join(basePath, rawPath)
u.Path = filepath.ToSlash(absPathSys)
if err != nil {
return "", err
}
u.Scheme = "file"
return u.String(), nil
}
// NormalizeURL is an internal function to be used by provider clients.
//
// It ensures that each endpoint URL has a closing `/`, as expected by
// ServiceClient's methods.
func NormalizeURL(url string) string {
if !strings.HasSuffix(url, "/") {
return url + "/"
}
return url
}
// RemainingKeys will inspect a struct and compare it to a map. Any struct
// field that does not have a JSON tag that matches a key in the map or
// a matching lower-case field in the map will be returned as an extra.
//
// This is useful for determining the extra fields returned in response bodies
// for resources that can contain an arbitrary or dynamic number of fields.
func RemainingKeys(s interface{}, m map[string]interface{}) (extras map[string]interface{}) {
extras = make(map[string]interface{})
for k, v := range m {
extras[k] = v
}
valueOf := reflect.ValueOf(s)
typeOf := reflect.TypeOf(s)
for i := 0; i < valueOf.NumField(); i++ {
field := typeOf.Field(i)
lowerField := strings.ToLower(field.Name)
delete(extras, lowerField)
if tagValue := field.Tag.Get("json"); tagValue != "" && tagValue != "-" {
delete(extras, tagValue)
}
}
return
}
// WaitFor polls a predicate function, once per second, up to a timeout limit.
// This is useful to wait for a resource to transition to a certain state.
// To handle situations when the predicate might hang indefinitely, the
@ -53,50 +128,3 @@ func WaitFor(timeout int, predicate func() (bool, error)) error {
}
}
}
// NormalizeURL is an internal function to be used by provider clients.
//
// It ensures that each endpoint URL has a closing `/`, as expected by
// ServiceClient's methods.
func NormalizeURL(url string) string {
if !strings.HasSuffix(url, "/") {
return url + "/"
}
return url
}
// NormalizePathURL is used to convert rawPath to a fqdn, using basePath as
// a reference in the filesystem, if necessary. basePath is assumed to contain
// either '.' when first used, or the file:// type fqdn of the parent resource.
// e.g. myFavScript.yaml => file://opt/lib/myFavScript.yaml
func NormalizePathURL(basePath, rawPath string) (string, error) {
u, err := url.Parse(rawPath)
if err != nil {
return "", err
}
// if a scheme is defined, it must be a fqdn already
if u.Scheme != "" {
return u.String(), nil
}
// if basePath is a url, then child resources are assumed to be relative to it
bu, err := url.Parse(basePath)
if err != nil {
return "", err
}
var basePathSys, absPathSys string
if bu.Scheme != "" {
basePathSys = filepath.FromSlash(bu.Path)
absPathSys = filepath.Join(basePathSys, rawPath)
bu.Path = filepath.ToSlash(absPathSys)
return bu.String(), nil
}
absPathSys = filepath.Join(basePath, rawPath)
u.Path = filepath.ToSlash(absPathSys)
if err != nil {
return "", err
}
u.Scheme = "file"
return u.String(), nil
}

4
vendor/modules.txt vendored
View File

@ -300,10 +300,9 @@ github.com/googleapis/gax-go/v2
github.com/googleapis/gnostic/compiler
github.com/googleapis/gnostic/extensions
github.com/googleapis/gnostic/openapiv2
# github.com/gophercloud/gophercloud v0.11.1-0.20200518183226-7aec46f32c19 => github.com/gophercloud/gophercloud v0.11.0
# github.com/gophercloud/gophercloud v0.15.0
## explicit
github.com/gophercloud/gophercloud
github.com/gophercloud/gophercloud/internal
github.com/gophercloud/gophercloud/openstack
github.com/gophercloud/gophercloud/openstack/blockstorage/v3/volumes
github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/availabilityzones
@ -1393,4 +1392,3 @@ sigs.k8s.io/yaml
# k8s.io/cli-runtime => k8s.io/cli-runtime v0.20.0
# k8s.io/kube-controller-manager => k8s.io/kube-controller-manager v0.20.0
# k8s.io/code-generator => k8s.io/code-generator v0.20.0
# github.com/gophercloud/gophercloud => github.com/gophercloud/gophercloud v0.11.0