mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-03 19:58:17 +00:00 
			
		
		
		
	Merge pull request #36344 from anguslees/gophercloud
Automatic merge from submit-queue (batch tested with PRs 41756, 36344, 34259, 40843, 41526) Migrate rackspace/gophercloud -> gophercloud/gophercloud `gophercloud` is the go library we use to interact with openstack. It has recently been renamed and incorporated a number of breaking code cleanups. This change migrates the Kubernetes openstack code (openstack provider, keystone auth, cinder volumes) to the new library. Fixes #30404 ```release-note The openstack cloud provider config no longer supports the deprecated `api-key` option. ``` Note this PR doesn't change the rackspace provider. It uses some rackspace-specific APIs and continues to use the older rackspace/gophercloud library.
This commit is contained in:
		
							
								
								
									
										194
									
								
								Godeps/Godeps.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										194
									
								
								Godeps/Godeps.json
									
									
									
										generated
									
									
									
								
							@@ -1,7 +1,7 @@
 | 
			
		||||
{
 | 
			
		||||
	"ImportPath": "k8s.io/kubernetes",
 | 
			
		||||
	"GoVersion": "go1.7",
 | 
			
		||||
	"GodepVersion": "v74",
 | 
			
		||||
	"GodepVersion": "v75",
 | 
			
		||||
	"Packages": [
 | 
			
		||||
		"github.com/ugorji/go/codec/codecgen",
 | 
			
		||||
		"github.com/onsi/ginkgo/ginkgo",
 | 
			
		||||
@@ -1400,6 +1400,118 @@
 | 
			
		||||
			"ImportPath": "github.com/google/gofuzz",
 | 
			
		||||
			"Rev": "44d81051d367757e1c7c6a5a86423ece9afcf63c"
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"ImportPath": "github.com/gophercloud/gophercloud",
 | 
			
		||||
			"Rev": "12f19e5e04d617182cffa5c11f189ef0013b9791"
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"ImportPath": "github.com/gophercloud/gophercloud/openstack",
 | 
			
		||||
			"Rev": "12f19e5e04d617182cffa5c11f189ef0013b9791"
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"ImportPath": "github.com/gophercloud/gophercloud/openstack/blockstorage/v1/volumes",
 | 
			
		||||
			"Rev": "12f19e5e04d617182cffa5c11f189ef0013b9791"
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"ImportPath": "github.com/gophercloud/gophercloud/openstack/common/extensions",
 | 
			
		||||
			"Rev": "12f19e5e04d617182cffa5c11f189ef0013b9791"
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"ImportPath": "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/volumeattach",
 | 
			
		||||
			"Rev": "12f19e5e04d617182cffa5c11f189ef0013b9791"
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"ImportPath": "github.com/gophercloud/gophercloud/openstack/compute/v2/flavors",
 | 
			
		||||
			"Rev": "12f19e5e04d617182cffa5c11f189ef0013b9791"
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"ImportPath": "github.com/gophercloud/gophercloud/openstack/compute/v2/images",
 | 
			
		||||
			"Rev": "12f19e5e04d617182cffa5c11f189ef0013b9791"
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"ImportPath": "github.com/gophercloud/gophercloud/openstack/compute/v2/servers",
 | 
			
		||||
			"Rev": "12f19e5e04d617182cffa5c11f189ef0013b9791"
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"ImportPath": "github.com/gophercloud/gophercloud/openstack/identity/v2/tenants",
 | 
			
		||||
			"Rev": "12f19e5e04d617182cffa5c11f189ef0013b9791"
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"ImportPath": "github.com/gophercloud/gophercloud/openstack/identity/v2/tokens",
 | 
			
		||||
			"Rev": "12f19e5e04d617182cffa5c11f189ef0013b9791"
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"ImportPath": "github.com/gophercloud/gophercloud/openstack/identity/v3/extensions/trusts",
 | 
			
		||||
			"Rev": "12f19e5e04d617182cffa5c11f189ef0013b9791"
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"ImportPath": "github.com/gophercloud/gophercloud/openstack/identity/v3/tokens",
 | 
			
		||||
			"Rev": "12f19e5e04d617182cffa5c11f189ef0013b9791"
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"ImportPath": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions",
 | 
			
		||||
			"Rev": "12f19e5e04d617182cffa5c11f189ef0013b9791"
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"ImportPath": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/floatingips",
 | 
			
		||||
			"Rev": "12f19e5e04d617182cffa5c11f189ef0013b9791"
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"ImportPath": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/routers",
 | 
			
		||||
			"Rev": "12f19e5e04d617182cffa5c11f189ef0013b9791"
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"ImportPath": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas/members",
 | 
			
		||||
			"Rev": "12f19e5e04d617182cffa5c11f189ef0013b9791"
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"ImportPath": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas/monitors",
 | 
			
		||||
			"Rev": "12f19e5e04d617182cffa5c11f189ef0013b9791"
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"ImportPath": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas/pools",
 | 
			
		||||
			"Rev": "12f19e5e04d617182cffa5c11f189ef0013b9791"
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"ImportPath": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas/vips",
 | 
			
		||||
			"Rev": "12f19e5e04d617182cffa5c11f189ef0013b9791"
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"ImportPath": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/listeners",
 | 
			
		||||
			"Rev": "12f19e5e04d617182cffa5c11f189ef0013b9791"
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"ImportPath": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/loadbalancers",
 | 
			
		||||
			"Rev": "12f19e5e04d617182cffa5c11f189ef0013b9791"
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"ImportPath": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/monitors",
 | 
			
		||||
			"Rev": "12f19e5e04d617182cffa5c11f189ef0013b9791"
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"ImportPath": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/pools",
 | 
			
		||||
			"Rev": "12f19e5e04d617182cffa5c11f189ef0013b9791"
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"ImportPath": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/groups",
 | 
			
		||||
			"Rev": "12f19e5e04d617182cffa5c11f189ef0013b9791"
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"ImportPath": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/rules",
 | 
			
		||||
			"Rev": "12f19e5e04d617182cffa5c11f189ef0013b9791"
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"ImportPath": "github.com/gophercloud/gophercloud/openstack/networking/v2/ports",
 | 
			
		||||
			"Rev": "12f19e5e04d617182cffa5c11f189ef0013b9791"
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"ImportPath": "github.com/gophercloud/gophercloud/openstack/utils",
 | 
			
		||||
			"Rev": "12f19e5e04d617182cffa5c11f189ef0013b9791"
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"ImportPath": "github.com/gophercloud/gophercloud/pagination",
 | 
			
		||||
			"Rev": "12f19e5e04d617182cffa5c11f189ef0013b9791"
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"ImportPath": "github.com/gorilla/context",
 | 
			
		||||
			"Rev": "215affda49addc4c8ef7e2534915df2c8c35c6cd"
 | 
			
		||||
@@ -1964,11 +2076,6 @@
 | 
			
		||||
			"Comment": "v1.0.0-1012-ge00690e8",
 | 
			
		||||
			"Rev": "e00690e87603abe613e9f02c816c7c4bef82e063"
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"ImportPath": "github.com/rackspace/gophercloud/openstack/common/extensions",
 | 
			
		||||
			"Comment": "v1.0.0-1012-ge00690e8",
 | 
			
		||||
			"Rev": "e00690e87603abe613e9f02c816c7c4bef82e063"
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"ImportPath": "github.com/rackspace/gophercloud/openstack/compute/v2/extensions/bootfromvolume",
 | 
			
		||||
			"Comment": "v1.0.0-1012-ge00690e8",
 | 
			
		||||
@@ -2009,86 +2116,11 @@
 | 
			
		||||
			"Comment": "v1.0.0-1012-ge00690e8",
 | 
			
		||||
			"Rev": "e00690e87603abe613e9f02c816c7c4bef82e063"
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"ImportPath": "github.com/rackspace/gophercloud/openstack/identity/v3/extensions/trust",
 | 
			
		||||
			"Comment": "v1.0.0-1012-ge00690e8",
 | 
			
		||||
			"Rev": "e00690e87603abe613e9f02c816c7c4bef82e063"
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"ImportPath": "github.com/rackspace/gophercloud/openstack/identity/v3/tokens",
 | 
			
		||||
			"Comment": "v1.0.0-1012-ge00690e8",
 | 
			
		||||
			"Rev": "e00690e87603abe613e9f02c816c7c4bef82e063"
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"ImportPath": "github.com/rackspace/gophercloud/openstack/networking/v2/extensions",
 | 
			
		||||
			"Comment": "v1.0.0-1012-ge00690e8",
 | 
			
		||||
			"Rev": "e00690e87603abe613e9f02c816c7c4bef82e063"
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"ImportPath": "github.com/rackspace/gophercloud/openstack/networking/v2/extensions/layer3/floatingips",
 | 
			
		||||
			"Comment": "v1.0.0-1012-ge00690e8",
 | 
			
		||||
			"Rev": "e00690e87603abe613e9f02c816c7c4bef82e063"
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"ImportPath": "github.com/rackspace/gophercloud/openstack/networking/v2/extensions/layer3/routers",
 | 
			
		||||
			"Comment": "v1.0.0-1012-ge00690e8",
 | 
			
		||||
			"Rev": "e00690e87603abe613e9f02c816c7c4bef82e063"
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"ImportPath": "github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/members",
 | 
			
		||||
			"Comment": "v1.0.0-1012-ge00690e8",
 | 
			
		||||
			"Rev": "e00690e87603abe613e9f02c816c7c4bef82e063"
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"ImportPath": "github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/monitors",
 | 
			
		||||
			"Comment": "v1.0.0-1012-ge00690e8",
 | 
			
		||||
			"Rev": "e00690e87603abe613e9f02c816c7c4bef82e063"
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"ImportPath": "github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/pools",
 | 
			
		||||
			"Comment": "v1.0.0-1012-ge00690e8",
 | 
			
		||||
			"Rev": "e00690e87603abe613e9f02c816c7c4bef82e063"
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"ImportPath": "github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/vips",
 | 
			
		||||
			"Comment": "v1.0.0-1012-ge00690e8",
 | 
			
		||||
			"Rev": "e00690e87603abe613e9f02c816c7c4bef82e063"
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"ImportPath": "github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas_v2/listeners",
 | 
			
		||||
			"Comment": "v1.0.0-1012-ge00690e8",
 | 
			
		||||
			"Rev": "e00690e87603abe613e9f02c816c7c4bef82e063"
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"ImportPath": "github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas_v2/loadbalancers",
 | 
			
		||||
			"Comment": "v1.0.0-1012-ge00690e8",
 | 
			
		||||
			"Rev": "e00690e87603abe613e9f02c816c7c4bef82e063"
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"ImportPath": "github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas_v2/monitors",
 | 
			
		||||
			"Comment": "v1.0.0-1012-ge00690e8",
 | 
			
		||||
			"Rev": "e00690e87603abe613e9f02c816c7c4bef82e063"
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"ImportPath": "github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas_v2/pools",
 | 
			
		||||
			"Comment": "v1.0.0-1012-ge00690e8",
 | 
			
		||||
			"Rev": "e00690e87603abe613e9f02c816c7c4bef82e063"
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"ImportPath": "github.com/rackspace/gophercloud/openstack/networking/v2/extensions/security/groups",
 | 
			
		||||
			"Comment": "v1.0.0-1012-ge00690e8",
 | 
			
		||||
			"Rev": "e00690e87603abe613e9f02c816c7c4bef82e063"
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"ImportPath": "github.com/rackspace/gophercloud/openstack/networking/v2/extensions/security/rules",
 | 
			
		||||
			"Comment": "v1.0.0-1012-ge00690e8",
 | 
			
		||||
			"Rev": "e00690e87603abe613e9f02c816c7c4bef82e063"
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"ImportPath": "github.com/rackspace/gophercloud/openstack/networking/v2/ports",
 | 
			
		||||
			"Comment": "v1.0.0-1012-ge00690e8",
 | 
			
		||||
			"Rev": "e00690e87603abe613e9f02c816c7c4bef82e063"
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"ImportPath": "github.com/rackspace/gophercloud/openstack/utils",
 | 
			
		||||
			"Comment": "v1.0.0-1012-ge00690e8",
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										8756
									
								
								Godeps/LICENSES
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										8756
									
								
								Godeps/LICENSES
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -27,30 +27,30 @@ go_library(
 | 
			
		||||
        "//pkg/util/mount:go_default_library",
 | 
			
		||||
        "//pkg/volume:go_default_library",
 | 
			
		||||
        "//vendor:github.com/golang/glog",
 | 
			
		||||
        "//vendor:github.com/gophercloud/gophercloud",
 | 
			
		||||
        "//vendor:github.com/gophercloud/gophercloud/openstack",
 | 
			
		||||
        "//vendor:github.com/gophercloud/gophercloud/openstack/blockstorage/v1/volumes",
 | 
			
		||||
        "//vendor:github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/volumeattach",
 | 
			
		||||
        "//vendor:github.com/gophercloud/gophercloud/openstack/compute/v2/flavors",
 | 
			
		||||
        "//vendor:github.com/gophercloud/gophercloud/openstack/compute/v2/servers",
 | 
			
		||||
        "//vendor:github.com/gophercloud/gophercloud/openstack/identity/v3/extensions/trusts",
 | 
			
		||||
        "//vendor:github.com/gophercloud/gophercloud/openstack/identity/v3/tokens",
 | 
			
		||||
        "//vendor:github.com/gophercloud/gophercloud/openstack/networking/v2/extensions",
 | 
			
		||||
        "//vendor:github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/floatingips",
 | 
			
		||||
        "//vendor:github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/routers",
 | 
			
		||||
        "//vendor:github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas/members",
 | 
			
		||||
        "//vendor:github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas/monitors",
 | 
			
		||||
        "//vendor:github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas/pools",
 | 
			
		||||
        "//vendor:github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas/vips",
 | 
			
		||||
        "//vendor:github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/listeners",
 | 
			
		||||
        "//vendor:github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/loadbalancers",
 | 
			
		||||
        "//vendor:github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/monitors",
 | 
			
		||||
        "//vendor:github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/pools",
 | 
			
		||||
        "//vendor:github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/groups",
 | 
			
		||||
        "//vendor:github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/rules",
 | 
			
		||||
        "//vendor:github.com/gophercloud/gophercloud/openstack/networking/v2/ports",
 | 
			
		||||
        "//vendor:github.com/gophercloud/gophercloud/pagination",
 | 
			
		||||
        "//vendor:github.com/mitchellh/mapstructure",
 | 
			
		||||
        "//vendor:github.com/rackspace/gophercloud",
 | 
			
		||||
        "//vendor:github.com/rackspace/gophercloud/openstack",
 | 
			
		||||
        "//vendor:github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumes",
 | 
			
		||||
        "//vendor:github.com/rackspace/gophercloud/openstack/compute/v2/extensions/volumeattach",
 | 
			
		||||
        "//vendor:github.com/rackspace/gophercloud/openstack/compute/v2/flavors",
 | 
			
		||||
        "//vendor:github.com/rackspace/gophercloud/openstack/compute/v2/servers",
 | 
			
		||||
        "//vendor:github.com/rackspace/gophercloud/openstack/identity/v3/extensions/trust",
 | 
			
		||||
        "//vendor:github.com/rackspace/gophercloud/openstack/identity/v3/tokens",
 | 
			
		||||
        "//vendor:github.com/rackspace/gophercloud/openstack/networking/v2/extensions",
 | 
			
		||||
        "//vendor:github.com/rackspace/gophercloud/openstack/networking/v2/extensions/layer3/floatingips",
 | 
			
		||||
        "//vendor:github.com/rackspace/gophercloud/openstack/networking/v2/extensions/layer3/routers",
 | 
			
		||||
        "//vendor:github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/members",
 | 
			
		||||
        "//vendor:github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/monitors",
 | 
			
		||||
        "//vendor:github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/pools",
 | 
			
		||||
        "//vendor:github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/vips",
 | 
			
		||||
        "//vendor:github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas_v2/listeners",
 | 
			
		||||
        "//vendor:github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas_v2/loadbalancers",
 | 
			
		||||
        "//vendor:github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas_v2/monitors",
 | 
			
		||||
        "//vendor:github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas_v2/pools",
 | 
			
		||||
        "//vendor:github.com/rackspace/gophercloud/openstack/networking/v2/extensions/security/groups",
 | 
			
		||||
        "//vendor:github.com/rackspace/gophercloud/openstack/networking/v2/extensions/security/rules",
 | 
			
		||||
        "//vendor:github.com/rackspace/gophercloud/openstack/networking/v2/ports",
 | 
			
		||||
        "//vendor:github.com/rackspace/gophercloud/pagination",
 | 
			
		||||
        "//vendor:gopkg.in/gcfg.v1",
 | 
			
		||||
        "//vendor:k8s.io/apimachinery/pkg/api/resource",
 | 
			
		||||
        "//vendor:k8s.io/apimachinery/pkg/types",
 | 
			
		||||
@@ -69,8 +69,8 @@ go_test(
 | 
			
		||||
    deps = [
 | 
			
		||||
        "//pkg/api/v1:go_default_library",
 | 
			
		||||
        "//pkg/cloudprovider:go_default_library",
 | 
			
		||||
        "//vendor:github.com/rackspace/gophercloud",
 | 
			
		||||
        "//vendor:github.com/rackspace/gophercloud/openstack/compute/v2/servers",
 | 
			
		||||
        "//vendor:github.com/gophercloud/gophercloud",
 | 
			
		||||
        "//vendor:github.com/gophercloud/gophercloud/openstack/compute/v2/servers",
 | 
			
		||||
        "//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
 | 
			
		||||
        "//vendor:k8s.io/apimachinery/pkg/types",
 | 
			
		||||
        "//vendor:k8s.io/apimachinery/pkg/util/rand",
 | 
			
		||||
 
 | 
			
		||||
@@ -26,13 +26,13 @@ import (
 | 
			
		||||
	"strings"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/gophercloud/gophercloud"
 | 
			
		||||
	"github.com/gophercloud/gophercloud/openstack"
 | 
			
		||||
	"github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
 | 
			
		||||
	"github.com/gophercloud/gophercloud/openstack/identity/v3/extensions/trusts"
 | 
			
		||||
	tokens3 "github.com/gophercloud/gophercloud/openstack/identity/v3/tokens"
 | 
			
		||||
	"github.com/gophercloud/gophercloud/pagination"
 | 
			
		||||
	"github.com/mitchellh/mapstructure"
 | 
			
		||||
	"github.com/rackspace/gophercloud"
 | 
			
		||||
	"github.com/rackspace/gophercloud/openstack"
 | 
			
		||||
	"github.com/rackspace/gophercloud/openstack/compute/v2/servers"
 | 
			
		||||
	"github.com/rackspace/gophercloud/openstack/identity/v3/extensions/trust"
 | 
			
		||||
	token3 "github.com/rackspace/gophercloud/openstack/identity/v3/tokens"
 | 
			
		||||
	"github.com/rackspace/gophercloud/pagination"
 | 
			
		||||
	"gopkg.in/gcfg.v1"
 | 
			
		||||
 | 
			
		||||
	"github.com/golang/glog"
 | 
			
		||||
@@ -110,7 +110,6 @@ type Config struct {
 | 
			
		||||
		Username   string
 | 
			
		||||
		UserId     string `gcfg:"user-id"`
 | 
			
		||||
		Password   string
 | 
			
		||||
		ApiKey     string `gcfg:"api-key"`
 | 
			
		||||
		TenantId   string `gcfg:"tenant-id"`
 | 
			
		||||
		TenantName string `gcfg:"tenant-name"`
 | 
			
		||||
		TrustId    string `gcfg:"trust-id"`
 | 
			
		||||
@@ -139,7 +138,6 @@ func (cfg Config) toAuthOptions() gophercloud.AuthOptions {
 | 
			
		||||
		Username:         cfg.Global.Username,
 | 
			
		||||
		UserID:           cfg.Global.UserId,
 | 
			
		||||
		Password:         cfg.Global.Password,
 | 
			
		||||
		APIKey:           cfg.Global.ApiKey,
 | 
			
		||||
		TenantID:         cfg.Global.TenantId,
 | 
			
		||||
		TenantName:       cfg.Global.TenantName,
 | 
			
		||||
		DomainID:         cfg.Global.DomainId,
 | 
			
		||||
@@ -150,6 +148,18 @@ func (cfg Config) toAuthOptions() gophercloud.AuthOptions {
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (cfg Config) toAuth3Options() tokens3.AuthOptions {
 | 
			
		||||
	return tokens3.AuthOptions{
 | 
			
		||||
		IdentityEndpoint: cfg.Global.AuthUrl,
 | 
			
		||||
		Username:         cfg.Global.Username,
 | 
			
		||||
		UserID:           cfg.Global.UserId,
 | 
			
		||||
		Password:         cfg.Global.Password,
 | 
			
		||||
		DomainID:         cfg.Global.DomainId,
 | 
			
		||||
		DomainName:       cfg.Global.DomainName,
 | 
			
		||||
		AllowReauth:      true,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func readConfig(config io.Reader) (Config, error) {
 | 
			
		||||
	if config == nil {
 | 
			
		||||
		err := fmt.Errorf("no OpenStack cloud provider config file given")
 | 
			
		||||
@@ -205,11 +215,12 @@ func newOpenStack(cfg Config) (*OpenStack, error) {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	if cfg.Global.TrustId != "" {
 | 
			
		||||
		authOptionsExt := trust.AuthOptionsExt{
 | 
			
		||||
		opts := cfg.toAuth3Options()
 | 
			
		||||
		authOptsExt := trusts.AuthOptsExt{
 | 
			
		||||
			TrustID:            cfg.Global.TrustId,
 | 
			
		||||
			AuthOptions: token3.AuthOptions{AuthOptions: cfg.toAuthOptions()},
 | 
			
		||||
			AuthOptionsBuilder: &opts,
 | 
			
		||||
		}
 | 
			
		||||
		err = trust.AuthenticateV3Trust(provider, authOptionsExt)
 | 
			
		||||
		err = openstack.AuthenticateV3(provider, authOptsExt, gophercloud.EndpointOpts{})
 | 
			
		||||
	} else {
 | 
			
		||||
		err = openstack.Authenticate(provider, cfg.toAuthOptions())
 | 
			
		||||
	}
 | 
			
		||||
@@ -446,7 +457,7 @@ func (os *OpenStack) LoadBalancer() (cloudprovider.LoadBalancer, bool) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func isNotFound(err error) bool {
 | 
			
		||||
	e, ok := err.(*gophercloud.UnexpectedResponseCodeError)
 | 
			
		||||
	e, ok := err.(*gophercloud.ErrUnexpectedResponseCode)
 | 
			
		||||
	return ok && e.Actual == http.StatusNotFound
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -20,11 +20,11 @@ import (
 | 
			
		||||
	"errors"
 | 
			
		||||
 | 
			
		||||
	"github.com/golang/glog"
 | 
			
		||||
	"github.com/rackspace/gophercloud"
 | 
			
		||||
	"github.com/rackspace/gophercloud/openstack"
 | 
			
		||||
	"github.com/rackspace/gophercloud/openstack/compute/v2/flavors"
 | 
			
		||||
	"github.com/rackspace/gophercloud/openstack/compute/v2/servers"
 | 
			
		||||
	"github.com/rackspace/gophercloud/pagination"
 | 
			
		||||
	"github.com/gophercloud/gophercloud"
 | 
			
		||||
	"github.com/gophercloud/gophercloud/openstack"
 | 
			
		||||
	"github.com/gophercloud/gophercloud/openstack/compute/v2/flavors"
 | 
			
		||||
	"github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
 | 
			
		||||
	"github.com/gophercloud/gophercloud/pagination"
 | 
			
		||||
 | 
			
		||||
	"k8s.io/apimachinery/pkg/api/resource"
 | 
			
		||||
	"k8s.io/apimachinery/pkg/types"
 | 
			
		||||
 
 | 
			
		||||
@@ -23,21 +23,21 @@ import (
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/golang/glog"
 | 
			
		||||
	"github.com/rackspace/gophercloud"
 | 
			
		||||
	"github.com/rackspace/gophercloud/openstack/networking/v2/extensions"
 | 
			
		||||
	"github.com/rackspace/gophercloud/openstack/networking/v2/extensions/layer3/floatingips"
 | 
			
		||||
	"github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/members"
 | 
			
		||||
	"github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/monitors"
 | 
			
		||||
	"github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/pools"
 | 
			
		||||
	"github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/vips"
 | 
			
		||||
	"github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas_v2/listeners"
 | 
			
		||||
	"github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas_v2/loadbalancers"
 | 
			
		||||
	v2monitors "github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas_v2/monitors"
 | 
			
		||||
	v2pools "github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas_v2/pools"
 | 
			
		||||
	"github.com/rackspace/gophercloud/openstack/networking/v2/extensions/security/groups"
 | 
			
		||||
	"github.com/rackspace/gophercloud/openstack/networking/v2/extensions/security/rules"
 | 
			
		||||
	neutronports "github.com/rackspace/gophercloud/openstack/networking/v2/ports"
 | 
			
		||||
	"github.com/rackspace/gophercloud/pagination"
 | 
			
		||||
	"github.com/gophercloud/gophercloud"
 | 
			
		||||
	"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions"
 | 
			
		||||
	"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/floatingips"
 | 
			
		||||
	"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas/members"
 | 
			
		||||
	"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas/monitors"
 | 
			
		||||
	"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas/pools"
 | 
			
		||||
	"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas/vips"
 | 
			
		||||
	"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/listeners"
 | 
			
		||||
	"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/loadbalancers"
 | 
			
		||||
	v2monitors "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/monitors"
 | 
			
		||||
	v2pools "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/pools"
 | 
			
		||||
	"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/groups"
 | 
			
		||||
	"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/rules"
 | 
			
		||||
	neutronports "github.com/gophercloud/gophercloud/openstack/networking/v2/ports"
 | 
			
		||||
	"github.com/gophercloud/gophercloud/pagination"
 | 
			
		||||
 | 
			
		||||
	"k8s.io/kubernetes/pkg/api/v1"
 | 
			
		||||
	"k8s.io/kubernetes/pkg/api/v1/service"
 | 
			
		||||
@@ -221,7 +221,7 @@ func getLoadbalancerByName(client *gophercloud.ServiceClient, name string) (*loa
 | 
			
		||||
	loadbalancerList := make([]loadbalancers.LoadBalancer, 0, 1)
 | 
			
		||||
 | 
			
		||||
	err := pager.EachPage(func(page pagination.Page) (bool, error) {
 | 
			
		||||
		v, err := loadbalancers.ExtractLoadbalancers(page)
 | 
			
		||||
		v, err := loadbalancers.ExtractLoadBalancers(page)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return false, err
 | 
			
		||||
		}
 | 
			
		||||
@@ -275,7 +275,7 @@ func getListenersByLoadBalancerID(client *gophercloud.ServiceClient, id string)
 | 
			
		||||
// get listener for a port or nil if does not exist
 | 
			
		||||
func getListenerForPort(existingListeners []listeners.Listener, port v1.ServicePort) *listeners.Listener {
 | 
			
		||||
	for _, l := range existingListeners {
 | 
			
		||||
		if l.Protocol == string(port.Protocol) && l.ProtocolPort == int(port.Port) {
 | 
			
		||||
		if listeners.Protocol(l.Protocol) == toListenersProtocol(port.Protocol) && l.ProtocolPort == int(port.Port) {
 | 
			
		||||
			return &l
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
@@ -321,7 +321,7 @@ func getPoolByListenerID(client *gophercloud.ServiceClient, loadbalancerID strin
 | 
			
		||||
 | 
			
		||||
func getMembersByPoolID(client *gophercloud.ServiceClient, id string) ([]v2pools.Member, error) {
 | 
			
		||||
	var members []v2pools.Member
 | 
			
		||||
	err := v2pools.ListAssociateMembers(client, id, v2pools.MemberListOpts{}).EachPage(func(page pagination.Page) (bool, error) {
 | 
			
		||||
	err := v2pools.ListMembers(client, id, v2pools.ListMembersOpts{}).EachPage(func(page pagination.Page) (bool, error) {
 | 
			
		||||
		membersList, err := v2pools.ExtractMembers(page)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return false, err
 | 
			
		||||
@@ -477,25 +477,45 @@ func waitLoadbalancerDeleted(client *gophercloud.ServiceClient, loadbalancerID s
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func createNodeSecurityGroup(client *gophercloud.ServiceClient, nodeSecurityGroupID string, port int, protocol string, lbSecGroup string) error {
 | 
			
		||||
func toRuleProtocol(protocol v1.Protocol) rules.RuleProtocol {
 | 
			
		||||
	switch protocol {
 | 
			
		||||
	case v1.ProtocolTCP:
 | 
			
		||||
		return rules.ProtocolTCP
 | 
			
		||||
	case v1.ProtocolUDP:
 | 
			
		||||
		return rules.ProtocolUDP
 | 
			
		||||
	default:
 | 
			
		||||
		return rules.RuleProtocol(strings.ToLower(string(protocol)))
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func toListenersProtocol(protocol v1.Protocol) listeners.Protocol {
 | 
			
		||||
	switch protocol {
 | 
			
		||||
	case v1.ProtocolTCP:
 | 
			
		||||
		return listeners.ProtocolTCP
 | 
			
		||||
	default:
 | 
			
		||||
		return listeners.Protocol(string(protocol))
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func createNodeSecurityGroup(client *gophercloud.ServiceClient, nodeSecurityGroupID string, port int, protocol v1.Protocol, lbSecGroup string) error {
 | 
			
		||||
	v4NodeSecGroupRuleCreateOpts := rules.CreateOpts{
 | 
			
		||||
		Direction:     "ingress",
 | 
			
		||||
		Direction:     rules.DirIngress,
 | 
			
		||||
		PortRangeMax:  port,
 | 
			
		||||
		PortRangeMin:  port,
 | 
			
		||||
		Protocol:      strings.ToLower(protocol),
 | 
			
		||||
		Protocol:      toRuleProtocol(protocol),
 | 
			
		||||
		RemoteGroupID: lbSecGroup,
 | 
			
		||||
		SecGroupID:    nodeSecurityGroupID,
 | 
			
		||||
		EtherType:     "IPv4",
 | 
			
		||||
		EtherType:     rules.EtherType4,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	v6NodeSecGroupRuleCreateOpts := rules.CreateOpts{
 | 
			
		||||
		Direction:     "ingress",
 | 
			
		||||
		Direction:     rules.DirIngress,
 | 
			
		||||
		PortRangeMax:  port,
 | 
			
		||||
		PortRangeMin:  port,
 | 
			
		||||
		Protocol:      strings.ToLower(protocol),
 | 
			
		||||
		Protocol:      toRuleProtocol(protocol),
 | 
			
		||||
		RemoteGroupID: lbSecGroup,
 | 
			
		||||
		SecGroupID:    nodeSecurityGroupID,
 | 
			
		||||
		EtherType:     "IPv6",
 | 
			
		||||
		EtherType:     rules.EtherType6,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	_, err := rules.Create(client, v4NodeSecGroupRuleCreateOpts).Extract()
 | 
			
		||||
@@ -705,7 +725,7 @@ func (lbaas *LbaasV2) EnsureLoadBalancer(clusterName string, apiService *v1.Serv
 | 
			
		||||
 | 
			
		||||
			if !memberExists(members, addr, int(port.NodePort)) {
 | 
			
		||||
				glog.V(4).Infof("Creating member for pool %s", pool.ID)
 | 
			
		||||
				_, err := v2pools.CreateAssociateMember(lbaas.network, pool.ID, v2pools.MemberCreateOpts{
 | 
			
		||||
				_, err := v2pools.CreateMember(lbaas.network, pool.ID, v2pools.CreateMemberOpts{
 | 
			
		||||
					ProtocolPort: int(port.NodePort),
 | 
			
		||||
					Address:      addr,
 | 
			
		||||
					SubnetID:     lbaas.opts.SubnetId,
 | 
			
		||||
@@ -848,7 +868,7 @@ func (lbaas *LbaasV2) EnsureLoadBalancer(clusterName string, apiService *v1.Serv
 | 
			
		||||
		for _, port := range ports {
 | 
			
		||||
 | 
			
		||||
			for _, sourceRange := range sourceRanges.StringSlice() {
 | 
			
		||||
				ethertype := "IPv4"
 | 
			
		||||
				ethertype := rules.EtherType4
 | 
			
		||||
				network, _, err := net.ParseCIDR(sourceRange)
 | 
			
		||||
 | 
			
		||||
				if err != nil {
 | 
			
		||||
@@ -859,14 +879,14 @@ func (lbaas *LbaasV2) EnsureLoadBalancer(clusterName string, apiService *v1.Serv
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				if network.To4() == nil {
 | 
			
		||||
					ethertype = "IPv6"
 | 
			
		||||
					ethertype = rules.EtherType6
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				lbSecGroupRuleCreateOpts := rules.CreateOpts{
 | 
			
		||||
					Direction:      "ingress",
 | 
			
		||||
					Direction:      rules.DirIngress,
 | 
			
		||||
					PortRangeMax:   int(port.Port),
 | 
			
		||||
					PortRangeMin:   int(port.Port),
 | 
			
		||||
					Protocol:       strings.ToLower(string(port.Protocol)),
 | 
			
		||||
					Protocol:       toRuleProtocol(port.Protocol),
 | 
			
		||||
					RemoteIPPrefix: sourceRange,
 | 
			
		||||
					SecGroupID:     lbSecGroup.ID,
 | 
			
		||||
					EtherType:      ethertype,
 | 
			
		||||
@@ -881,7 +901,7 @@ func (lbaas *LbaasV2) EnsureLoadBalancer(clusterName string, apiService *v1.Serv
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			err := createNodeSecurityGroup(lbaas.network, lbaas.opts.NodeSecurityGroupID, int(port.NodePort), string(port.Protocol), lbSecGroup.ID)
 | 
			
		||||
			err := createNodeSecurityGroup(lbaas.network, lbaas.opts.NodeSecurityGroupID, int(port.NodePort), port.Protocol, lbSecGroup.ID)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				glog.Errorf("Error occured creating security group for loadbalancer %s:", loadbalancer.ID)
 | 
			
		||||
				_ = lbaas.EnsureLoadBalancerDeleted(clusterName, apiService)
 | 
			
		||||
@@ -890,13 +910,13 @@ func (lbaas *LbaasV2) EnsureLoadBalancer(clusterName string, apiService *v1.Serv
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		lbSecGroupRuleCreateOpts := rules.CreateOpts{
 | 
			
		||||
			Direction:      "ingress",
 | 
			
		||||
			Direction:      rules.DirIngress,
 | 
			
		||||
			PortRangeMax:   4, // ICMP: Code -  Values for ICMP  "Destination Unreachable: Fragmentation Needed and Don't Fragment was Set"
 | 
			
		||||
			PortRangeMin:   3, // ICMP: Type
 | 
			
		||||
			Protocol:       "icmp",
 | 
			
		||||
			Protocol:       rules.ProtocolICMP,
 | 
			
		||||
			RemoteIPPrefix: "0.0.0.0/0", // The Fragmentation packet can come from anywhere along the path back to the sourceRange - we need to all this from all
 | 
			
		||||
			SecGroupID:     lbSecGroup.ID,
 | 
			
		||||
			EtherType:      "IPv4",
 | 
			
		||||
			EtherType:      rules.EtherType4,
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		_, err = rules.Create(lbaas.network, lbSecGroupRuleCreateOpts).Extract()
 | 
			
		||||
@@ -908,13 +928,13 @@ func (lbaas *LbaasV2) EnsureLoadBalancer(clusterName string, apiService *v1.Serv
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		lbSecGroupRuleCreateOpts = rules.CreateOpts{
 | 
			
		||||
			Direction:      "ingress",
 | 
			
		||||
			Direction:      rules.DirIngress,
 | 
			
		||||
			PortRangeMax:   0, // ICMP: Code - Values for ICMP "Packet Too Big"
 | 
			
		||||
			PortRangeMin:   2, // ICMP: Type
 | 
			
		||||
			Protocol:       "icmp",
 | 
			
		||||
			Protocol:       rules.ProtocolICMP,
 | 
			
		||||
			RemoteIPPrefix: "::/0", // The Fragmentation packet can come from anywhere along the path back to the sourceRange - we need to all this from all
 | 
			
		||||
			SecGroupID:     lbSecGroup.ID,
 | 
			
		||||
			EtherType:      "IPv6",
 | 
			
		||||
			EtherType:      rules.EtherType6,
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		_, err = rules.Create(lbaas.network, lbSecGroupRuleCreateOpts).Extract()
 | 
			
		||||
@@ -968,7 +988,7 @@ func (lbaas *LbaasV2) UpdateLoadBalancer(clusterName string, service *v1.Service
 | 
			
		||||
 | 
			
		||||
	// Get all listeners for this loadbalancer, by "port key".
 | 
			
		||||
	type portKey struct {
 | 
			
		||||
		Protocol string
 | 
			
		||||
		Protocol listeners.Protocol
 | 
			
		||||
		Port     int
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -983,7 +1003,7 @@ func (lbaas *LbaasV2) UpdateLoadBalancer(clusterName string, service *v1.Service
 | 
			
		||||
				// Double check this Listener belongs to the LB we're updating. Neutron's API filtering
 | 
			
		||||
				// can't be counted on in older releases (i.e Liberty).
 | 
			
		||||
				if loadbalancer.ID == lb.ID {
 | 
			
		||||
					key := portKey{Protocol: l.Protocol, Port: l.ProtocolPort}
 | 
			
		||||
					key := portKey{Protocol: listeners.Protocol(l.Protocol), Port: l.ProtocolPort}
 | 
			
		||||
					lbListeners[key] = l
 | 
			
		||||
					break
 | 
			
		||||
				}
 | 
			
		||||
@@ -1034,7 +1054,7 @@ func (lbaas *LbaasV2) UpdateLoadBalancer(clusterName string, service *v1.Service
 | 
			
		||||
	for _, port := range ports {
 | 
			
		||||
		// Get listener associated with this port
 | 
			
		||||
		listener, ok := lbListeners[portKey{
 | 
			
		||||
			Protocol: string(port.Protocol),
 | 
			
		||||
			Protocol: toListenersProtocol(port.Protocol),
 | 
			
		||||
			Port:     int(port.Port),
 | 
			
		||||
		}]
 | 
			
		||||
		if !ok {
 | 
			
		||||
@@ -1049,7 +1069,7 @@ func (lbaas *LbaasV2) UpdateLoadBalancer(clusterName string, service *v1.Service
 | 
			
		||||
 | 
			
		||||
		// Find existing pool members (by address) for this port
 | 
			
		||||
		members := make(map[string]v2pools.Member)
 | 
			
		||||
		err := v2pools.ListAssociateMembers(lbaas.network, pool.ID, v2pools.MemberListOpts{}).EachPage(func(page pagination.Page) (bool, error) {
 | 
			
		||||
		err := v2pools.ListMembers(lbaas.network, pool.ID, v2pools.ListMembersOpts{}).EachPage(func(page pagination.Page) (bool, error) {
 | 
			
		||||
			membersList, err := v2pools.ExtractMembers(page)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return false, err
 | 
			
		||||
@@ -1069,7 +1089,7 @@ func (lbaas *LbaasV2) UpdateLoadBalancer(clusterName string, service *v1.Service
 | 
			
		||||
				// Already exists, do not create member
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
			_, err := v2pools.CreateAssociateMember(lbaas.network, pool.ID, v2pools.MemberCreateOpts{
 | 
			
		||||
			_, err := v2pools.CreateMember(lbaas.network, pool.ID, v2pools.CreateMemberOpts{
 | 
			
		||||
				Address:      addr,
 | 
			
		||||
				ProtocolPort: int(port.NodePort),
 | 
			
		||||
				SubnetID:     lbaas.opts.SubnetId,
 | 
			
		||||
@@ -1167,7 +1187,7 @@ func (lbaas *LbaasV2) EnsureLoadBalancerDeleted(clusterName string, service *v1.
 | 
			
		||||
	// get all members associated with each poolIDs
 | 
			
		||||
	var memberIDs []string
 | 
			
		||||
	for _, poolID := range poolIDs {
 | 
			
		||||
		err := v2pools.ListAssociateMembers(lbaas.network, poolID, v2pools.MemberListOpts{}).EachPage(func(page pagination.Page) (bool, error) {
 | 
			
		||||
		err := v2pools.ListMembers(lbaas.network, poolID, v2pools.ListMembersOpts{}).EachPage(func(page pagination.Page) (bool, error) {
 | 
			
		||||
			membersList, err := v2pools.ExtractMembers(page)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return false, err
 | 
			
		||||
@@ -1338,7 +1358,7 @@ func (lb *LbaasV1) EnsureLoadBalancer(clusterName string, apiService *v1.Service
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	lbmethod := lb.opts.LBMethod
 | 
			
		||||
	lbmethod := pools.LBMethod(lb.opts.LBMethod)
 | 
			
		||||
	if lbmethod == "" {
 | 
			
		||||
		lbmethod = pools.LBMethodRoundRobin
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -19,10 +19,10 @@ package openstack
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
 | 
			
		||||
	"github.com/rackspace/gophercloud"
 | 
			
		||||
	"github.com/rackspace/gophercloud/openstack/compute/v2/servers"
 | 
			
		||||
	"github.com/rackspace/gophercloud/openstack/networking/v2/extensions/layer3/routers"
 | 
			
		||||
	neutronports "github.com/rackspace/gophercloud/openstack/networking/v2/ports"
 | 
			
		||||
	"github.com/gophercloud/gophercloud"
 | 
			
		||||
	"github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
 | 
			
		||||
	"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/routers"
 | 
			
		||||
	neutronports "github.com/gophercloud/gophercloud/openstack/networking/v2/ports"
 | 
			
		||||
 | 
			
		||||
	"github.com/golang/glog"
 | 
			
		||||
	"k8s.io/apimachinery/pkg/types"
 | 
			
		||||
 
 | 
			
		||||
@@ -24,8 +24,8 @@ import (
 | 
			
		||||
	"testing"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/rackspace/gophercloud"
 | 
			
		||||
	"github.com/rackspace/gophercloud/openstack/compute/v2/servers"
 | 
			
		||||
	"github.com/gophercloud/gophercloud"
 | 
			
		||||
	"github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
 | 
			
		||||
 | 
			
		||||
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
			
		||||
	"k8s.io/apimachinery/pkg/util/rand"
 | 
			
		||||
@@ -247,14 +247,13 @@ func configFromEnv() (cfg Config, ok bool) {
 | 
			
		||||
 | 
			
		||||
	cfg.Global.Username = os.Getenv("OS_USERNAME")
 | 
			
		||||
	cfg.Global.Password = os.Getenv("OS_PASSWORD")
 | 
			
		||||
	cfg.Global.ApiKey = os.Getenv("OS_API_KEY")
 | 
			
		||||
	cfg.Global.Region = os.Getenv("OS_REGION_NAME")
 | 
			
		||||
	cfg.Global.DomainId = os.Getenv("OS_DOMAIN_ID")
 | 
			
		||||
	cfg.Global.DomainName = os.Getenv("OS_DOMAIN_NAME")
 | 
			
		||||
 | 
			
		||||
	ok = (cfg.Global.AuthUrl != "" &&
 | 
			
		||||
		cfg.Global.Username != "" &&
 | 
			
		||||
		(cfg.Global.Password != "" || cfg.Global.ApiKey != "") &&
 | 
			
		||||
		cfg.Global.Password != "" &&
 | 
			
		||||
		(cfg.Global.TenantId != "" || cfg.Global.TenantName != "" ||
 | 
			
		||||
			cfg.Global.DomainId != "" || cfg.Global.DomainName != ""))
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -25,11 +25,11 @@ import (
 | 
			
		||||
 | 
			
		||||
	"k8s.io/kubernetes/pkg/volume"
 | 
			
		||||
 | 
			
		||||
	"github.com/rackspace/gophercloud"
 | 
			
		||||
	"github.com/rackspace/gophercloud/openstack"
 | 
			
		||||
	"github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumes"
 | 
			
		||||
	"github.com/rackspace/gophercloud/openstack/compute/v2/extensions/volumeattach"
 | 
			
		||||
	"github.com/rackspace/gophercloud/pagination"
 | 
			
		||||
	"github.com/gophercloud/gophercloud"
 | 
			
		||||
	"github.com/gophercloud/gophercloud/openstack"
 | 
			
		||||
	"github.com/gophercloud/gophercloud/openstack/blockstorage/v1/volumes"
 | 
			
		||||
	"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/volumeattach"
 | 
			
		||||
	"github.com/gophercloud/gophercloud/pagination"
 | 
			
		||||
 | 
			
		||||
	"github.com/golang/glog"
 | 
			
		||||
)
 | 
			
		||||
 
 | 
			
		||||
@@ -23,8 +23,8 @@ import (
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"github.com/golang/glog"
 | 
			
		||||
	"github.com/rackspace/gophercloud"
 | 
			
		||||
	"github.com/rackspace/gophercloud/openstack"
 | 
			
		||||
	"github.com/gophercloud/gophercloud"
 | 
			
		||||
	"github.com/gophercloud/gophercloud/openstack"
 | 
			
		||||
 | 
			
		||||
	netutil "k8s.io/apimachinery/pkg/util/net"
 | 
			
		||||
	"k8s.io/apiserver/pkg/authentication/user"
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										10422
									
								
								vendor/BUILD
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										10422
									
								
								vendor/BUILD
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										1
									
								
								vendor/github.com/gophercloud/gophercloud/.gitignore
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								vendor/github.com/gophercloud/gophercloud/.gitignore
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
**/*.swp
 | 
			
		||||
							
								
								
									
										17
									
								
								vendor/github.com/gophercloud/gophercloud/.travis.yml
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								vendor/github.com/gophercloud/gophercloud/.travis.yml
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,17 @@
 | 
			
		||||
language: go
 | 
			
		||||
sudo: false
 | 
			
		||||
install:
 | 
			
		||||
- go get golang.org/x/crypto/ssh
 | 
			
		||||
- go get -v -tags 'fixtures acceptance' ./...
 | 
			
		||||
- go get github.com/wadey/gocovmerge
 | 
			
		||||
- go get github.com/mattn/goveralls
 | 
			
		||||
go:
 | 
			
		||||
- 1.7
 | 
			
		||||
- tip
 | 
			
		||||
env:
 | 
			
		||||
  global:
 | 
			
		||||
  - secure: "xSQsAG5wlL9emjbCdxzz/hYQsSpJ/bABO1kkbwMSISVcJ3Nk0u4ywF+LS4bgeOnwPfmFvNTOqVDu3RwEvMeWXSI76t1piCPcObutb2faKLVD/hLoAS76gYX+Z8yGWGHrSB7Do5vTPj1ERe2UljdrnsSeOXzoDwFxYRaZLX4bBOB4AyoGvRniil5QXPATiA1tsWX1VMicj8a4F8X+xeESzjt1Q5Iy31e7vkptu71bhvXCaoo5QhYwT+pLR9dN0S1b7Ro0KVvkRefmr1lUOSYd2e74h6Lc34tC1h3uYZCS4h47t7v5cOXvMNxinEj2C51RvbjvZI1RLVdkuAEJD1Iz4+Ote46nXbZ//6XRZMZz/YxQ13l7ux1PFjgEB6HAapmF5Xd8PRsgeTU9LRJxpiTJ3P5QJ3leS1va8qnziM5kYipj/Rn+V8g2ad/rgkRox9LSiR9VYZD2Pe45YCb1mTKSl2aIJnV7nkOqsShY5LNB4JZSg7xIffA+9YVDktw8dJlATjZqt7WvJJ49g6A61mIUV4C15q2JPGKTkZzDiG81NtmS7hFa7k0yaE2ELgYocbcuyUcAahhxntYTC0i23nJmEHVNiZmBO3u7EgpWe4KGVfumU+lt12tIn5b3dZRBBUk3QakKKozSK1QPHGpk/AZGrhu7H6l8to6IICKWtDcyMPQ="
 | 
			
		||||
script:
 | 
			
		||||
- ./script/coverage
 | 
			
		||||
after_success:
 | 
			
		||||
- $HOME/gopath/bin/goveralls -service=travis-ci -coverprofile=cover.out
 | 
			
		||||
							
								
								
									
										0
									
								
								vendor/github.com/gophercloud/gophercloud/CHANGELOG.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								vendor/github.com/gophercloud/gophercloud/CHANGELOG.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
								
								
									
										191
									
								
								vendor/github.com/gophercloud/gophercloud/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										191
									
								
								vendor/github.com/gophercloud/gophercloud/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,191 @@
 | 
			
		||||
Copyright 2012-2013 Rackspace, Inc.
 | 
			
		||||
 | 
			
		||||
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.                                
 | 
			
		||||
 | 
			
		||||
------
 | 
			
		||||
 
 | 
			
		||||
				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
 | 
			
		||||
							
								
								
									
										32
									
								
								vendor/github.com/gophercloud/gophercloud/MIGRATING.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								vendor/github.com/gophercloud/gophercloud/MIGRATING.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,32 @@
 | 
			
		||||
# 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`
 | 
			
		||||
							
								
								
									
										139
									
								
								vendor/github.com/gophercloud/gophercloud/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										139
									
								
								vendor/github.com/gophercloud/gophercloud/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,139 @@
 | 
			
		||||
# Gophercloud: an OpenStack SDK for Go
 | 
			
		||||
[](https://travis-ci.org/gophercloud/gophercloud)
 | 
			
		||||
[](https://coveralls.io/github/gophercloud/gophercloud?branch=master)
 | 
			
		||||
 | 
			
		||||
Gophercloud is an OpenStack Go SDK.
 | 
			
		||||
 | 
			
		||||
## Useful links
 | 
			
		||||
 | 
			
		||||
* [Reference documentation](http://godoc.org/github.com/gophercloud/gophercloud)
 | 
			
		||||
* [Effective Go](https://golang.org/doc/effective_go.html)
 | 
			
		||||
 | 
			
		||||
## How to install
 | 
			
		||||
 | 
			
		||||
Before installing, you need to ensure that your [GOPATH environment variable](https://golang.org/doc/code.html#GOPATH)
 | 
			
		||||
is pointing to an appropriate directory where you want to install Gophercloud:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
mkdir $HOME/go
 | 
			
		||||
export GOPATH=$HOME/go
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
To protect yourself against changes in your dependencies, we highly recommend choosing a
 | 
			
		||||
[dependency management solution](https://github.com/golang/go/wiki/PackageManagementTools) for
 | 
			
		||||
your projects, such as [godep](https://github.com/tools/godep). Once this is set up, you can install
 | 
			
		||||
Gophercloud as a dependency like so:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
go get github.com/gophercloud/gophercloud
 | 
			
		||||
 | 
			
		||||
# Edit your code to import relevant packages from "github.com/gophercloud/gophercloud"
 | 
			
		||||
 | 
			
		||||
godep save ./...
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
This will install all the source files you need into a `Godeps/_workspace` directory, which is
 | 
			
		||||
referenceable from your own source files when you use the `godep go` command.
 | 
			
		||||
 | 
			
		||||
## Getting started
 | 
			
		||||
 | 
			
		||||
### Credentials
 | 
			
		||||
 | 
			
		||||
Because you'll be hitting an API, you will need to retrieve your OpenStack
 | 
			
		||||
credentials and either store them as environment variables or in your local Go
 | 
			
		||||
files. The first method is recommended because it decouples credential
 | 
			
		||||
information from source code, allowing you to push the latter to your version
 | 
			
		||||
control system without any security risk.
 | 
			
		||||
 | 
			
		||||
You will need to retrieve the following:
 | 
			
		||||
 | 
			
		||||
* username
 | 
			
		||||
* password
 | 
			
		||||
* a valid Keystone identity URL
 | 
			
		||||
 | 
			
		||||
For users that have the OpenStack dashboard installed, there's a shortcut. If
 | 
			
		||||
you visit the `project/access_and_security` path in Horizon and click on the
 | 
			
		||||
"Download OpenStack RC File" button at the top right hand corner, you will
 | 
			
		||||
download a bash file that exports all of your access details to environment
 | 
			
		||||
variables. To execute the file, run `source admin-openrc.sh` and you will be
 | 
			
		||||
prompted for your password.
 | 
			
		||||
 | 
			
		||||
### Authentication
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
explicitly, or tell Gophercloud to use environment variables:
 | 
			
		||||
 | 
			
		||||
```go
 | 
			
		||||
import (
 | 
			
		||||
  "github.com/gophercloud/gophercloud"
 | 
			
		||||
  "github.com/gophercloud/gophercloud/openstack"
 | 
			
		||||
  "github.com/gophercloud/gophercloud/openstack/utils"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Option 1: Pass in the values yourself
 | 
			
		||||
opts := gophercloud.AuthOptions{
 | 
			
		||||
  IdentityEndpoint: "https://my-openstack.com:5000/v2.0",
 | 
			
		||||
  Username: "{username}",
 | 
			
		||||
  Password: "{password}",
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Option 2: Use a utility function to retrieve all your environment variables
 | 
			
		||||
opts, err := openstack.AuthOptionsFromEnv()
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Once you have the `opts` variable, you can pass it in and get back a
 | 
			
		||||
`ProviderClient` struct:
 | 
			
		||||
 | 
			
		||||
```go
 | 
			
		||||
provider, err := openstack.AuthenticatedClient(opts)
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
The `ProviderClient` is the top-level client that all of your OpenStack services
 | 
			
		||||
derive from. The provider contains all of the authentication details that allow
 | 
			
		||||
your Go code to access the API - such as the base URL and token ID.
 | 
			
		||||
 | 
			
		||||
### Provision a server
 | 
			
		||||
 | 
			
		||||
Once we have a base Provider, we inject it as a dependency into each OpenStack
 | 
			
		||||
service. In order to work with the Compute API, we need a Compute service
 | 
			
		||||
client; which can be created like so:
 | 
			
		||||
 | 
			
		||||
```go
 | 
			
		||||
client, err := openstack.NewComputeV2(provider, gophercloud.EndpointOpts{
 | 
			
		||||
  Region: os.Getenv("OS_REGION_NAME"),
 | 
			
		||||
})
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
We then use this `client` for any Compute API operation we want. In our case,
 | 
			
		||||
we want to provision a new server - so we invoke the `Create` method and pass
 | 
			
		||||
in the flavor ID (hardware specification) and image ID (operating system) we're
 | 
			
		||||
interested in:
 | 
			
		||||
 | 
			
		||||
```go
 | 
			
		||||
import "github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
 | 
			
		||||
 | 
			
		||||
server, err := servers.Create(client, servers.CreateOpts{
 | 
			
		||||
  Name:      "My new server!",
 | 
			
		||||
  FlavorRef: "flavor_id",
 | 
			
		||||
  ImageRef:  "image_id",
 | 
			
		||||
}).Extract()
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
The above code sample creates a new server with the parameters, and embodies the
 | 
			
		||||
new resource in the `server` variable (a
 | 
			
		||||
[`servers.Server`](http://godoc.org/github.com/gophercloud/gophercloud) struct).
 | 
			
		||||
 | 
			
		||||
## Backwards-Compatibility Guarantees
 | 
			
		||||
 | 
			
		||||
None. Vendor it and write tests covering the parts you use.
 | 
			
		||||
 | 
			
		||||
## Contributing
 | 
			
		||||
 | 
			
		||||
See the [contributing guide](./.github/CONTRIBUTING.md).
 | 
			
		||||
 | 
			
		||||
## Help and feedback
 | 
			
		||||
 | 
			
		||||
If you're struggling with something or have spotted a potential bug, feel free
 | 
			
		||||
to submit an issue to our [bug tracker](/issues).
 | 
			
		||||
							
								
								
									
										68
									
								
								vendor/github.com/gophercloud/gophercloud/STYLEGUIDE.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								vendor/github.com/gophercloud/gophercloud/STYLEGUIDE.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,68 @@
 | 
			
		||||
 | 
			
		||||
## 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 `@`.
 | 
			
		||||
 | 
			
		||||
- 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 `response.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`).
 | 
			
		||||
							
								
								
									
										331
									
								
								vendor/github.com/gophercloud/gophercloud/auth_options.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										331
									
								
								vendor/github.com/gophercloud/gophercloud/auth_options.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,331 @@
 | 
			
		||||
package gophercloud
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
AuthOptions stores information needed to authenticate to an OpenStack cluster.
 | 
			
		||||
You can populate one manually, or use a provider's AuthOptionsFromEnv() function
 | 
			
		||||
to read relevant information from the standard environment variables. Pass one
 | 
			
		||||
to a provider's AuthenticatedClient function to authenticate and obtain a
 | 
			
		||||
ProviderClient representing an active session on that provider.
 | 
			
		||||
 | 
			
		||||
Its fields are the union of those recognized by each identity implementation and
 | 
			
		||||
provider.
 | 
			
		||||
*/
 | 
			
		||||
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.
 | 
			
		||||
	IdentityEndpoint string `json:"-"`
 | 
			
		||||
 | 
			
		||||
	// Username is required if using Identity V2 API. Consult with your provider's
 | 
			
		||||
	// control panel to discover your account's username. In Identity V3, either
 | 
			
		||||
	// UserID or a combination of Username and DomainID or DomainName are needed.
 | 
			
		||||
	Username string `json:"username,omitempty"`
 | 
			
		||||
	UserID   string `json:"id,omitempty"`
 | 
			
		||||
 | 
			
		||||
	Password string `json:"password,omitempty"`
 | 
			
		||||
 | 
			
		||||
	// At most one of DomainID and DomainName must be provided if using Username
 | 
			
		||||
	// with Identity V3. Otherwise, either are optional.
 | 
			
		||||
	DomainID   string `json:"id,omitempty"`
 | 
			
		||||
	DomainName string `json:"name,omitempty"`
 | 
			
		||||
 | 
			
		||||
	// The TenantID and TenantName fields are optional for the Identity V2 API.
 | 
			
		||||
	// Some providers allow you to specify a TenantName instead of the TenantId.
 | 
			
		||||
	// Some require both. Your provider's authentication policies will determine
 | 
			
		||||
	// how these fields influence authentication.
 | 
			
		||||
	TenantID   string `json:"tenantId,omitempty"`
 | 
			
		||||
	TenantName string `json:"tenantName,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.
 | 
			
		||||
	//
 | 
			
		||||
	// 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:"-"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ToTokenV2CreateMap allows AuthOptions to satisfy the AuthOptionsBuilder
 | 
			
		||||
// interface in the v2 tokens package
 | 
			
		||||
func (opts AuthOptions) ToTokenV2CreateMap() (map[string]interface{}, error) {
 | 
			
		||||
	// Populate the request map.
 | 
			
		||||
	authMap := make(map[string]interface{})
 | 
			
		||||
 | 
			
		||||
	if opts.Username != "" {
 | 
			
		||||
		if opts.Password != "" {
 | 
			
		||||
			authMap["passwordCredentials"] = map[string]interface{}{
 | 
			
		||||
				"username": opts.Username,
 | 
			
		||||
				"password": opts.Password,
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
			return nil, ErrMissingInput{Argument: "Password"}
 | 
			
		||||
		}
 | 
			
		||||
	} else if opts.TokenID != "" {
 | 
			
		||||
		authMap["token"] = map[string]interface{}{
 | 
			
		||||
			"id": opts.TokenID,
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		return nil, ErrMissingInput{Argument: "Username"}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if opts.TenantID != "" {
 | 
			
		||||
		authMap["tenantId"] = opts.TenantID
 | 
			
		||||
	}
 | 
			
		||||
	if opts.TenantName != "" {
 | 
			
		||||
		authMap["tenantName"] = opts.TenantName
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return map[string]interface{}{"auth": authMap}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (opts *AuthOptions) ToTokenV3CreateMap(scope map[string]interface{}) (map[string]interface{}, error) {
 | 
			
		||||
	type domainReq struct {
 | 
			
		||||
		ID   *string `json:"id,omitempty"`
 | 
			
		||||
		Name *string `json:"name,omitempty"`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	type projectReq struct {
 | 
			
		||||
		Domain *domainReq `json:"domain,omitempty"`
 | 
			
		||||
		Name   *string    `json:"name,omitempty"`
 | 
			
		||||
		ID     *string    `json:"id,omitempty"`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	type userReq struct {
 | 
			
		||||
		ID       *string    `json:"id,omitempty"`
 | 
			
		||||
		Name     *string    `json:"name,omitempty"`
 | 
			
		||||
		Password string     `json:"password"`
 | 
			
		||||
		Domain   *domainReq `json:"domain,omitempty"`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	type passwordReq struct {
 | 
			
		||||
		User userReq `json:"user"`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	type tokenReq struct {
 | 
			
		||||
		ID string `json:"id"`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	type identityReq struct {
 | 
			
		||||
		Methods  []string     `json:"methods"`
 | 
			
		||||
		Password *passwordReq `json:"password,omitempty"`
 | 
			
		||||
		Token    *tokenReq    `json:"token,omitempty"`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	type authReq struct {
 | 
			
		||||
		Identity identityReq `json:"identity"`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	type request struct {
 | 
			
		||||
		Auth authReq `json:"auth"`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Populate the request structure based on the provided arguments. Create and return an error
 | 
			
		||||
	// if insufficient or incompatible information is present.
 | 
			
		||||
	var req request
 | 
			
		||||
 | 
			
		||||
	// Test first for unrecognized arguments.
 | 
			
		||||
	if opts.TenantID != "" {
 | 
			
		||||
		return nil, ErrTenantIDProvided{}
 | 
			
		||||
	}
 | 
			
		||||
	if opts.TenantName != "" {
 | 
			
		||||
		return nil, ErrTenantNameProvided{}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if opts.Password == "" {
 | 
			
		||||
		if opts.TokenID != "" {
 | 
			
		||||
			// Because we aren't using password authentication, it's an error to also provide any of the user-based authentication
 | 
			
		||||
			// parameters.
 | 
			
		||||
			if opts.Username != "" {
 | 
			
		||||
				return nil, ErrUsernameWithToken{}
 | 
			
		||||
			}
 | 
			
		||||
			if opts.UserID != "" {
 | 
			
		||||
				return nil, ErrUserIDWithToken{}
 | 
			
		||||
			}
 | 
			
		||||
			if opts.DomainID != "" {
 | 
			
		||||
				return nil, ErrDomainIDWithToken{}
 | 
			
		||||
			}
 | 
			
		||||
			if opts.DomainName != "" {
 | 
			
		||||
				return nil, ErrDomainNameWithToken{}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// Configure the request for Token authentication.
 | 
			
		||||
			req.Auth.Identity.Methods = []string{"token"}
 | 
			
		||||
			req.Auth.Identity.Token = &tokenReq{
 | 
			
		||||
				ID: opts.TokenID,
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
			// If no password or token ID are available, authentication can't continue.
 | 
			
		||||
			return nil, ErrMissingPassword{}
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		// Password authentication.
 | 
			
		||||
		req.Auth.Identity.Methods = []string{"password"}
 | 
			
		||||
 | 
			
		||||
		// At least one of Username and UserID must be specified.
 | 
			
		||||
		if opts.Username == "" && opts.UserID == "" {
 | 
			
		||||
			return nil, ErrUsernameOrUserID{}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if opts.Username != "" {
 | 
			
		||||
			// If Username is provided, UserID may not be provided.
 | 
			
		||||
			if opts.UserID != "" {
 | 
			
		||||
				return nil, ErrUsernameOrUserID{}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// Either DomainID or DomainName must also be specified.
 | 
			
		||||
			if opts.DomainID == "" && opts.DomainName == "" {
 | 
			
		||||
				return nil, ErrDomainIDOrDomainName{}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if opts.DomainID != "" {
 | 
			
		||||
				if opts.DomainName != "" {
 | 
			
		||||
					return nil, ErrDomainIDOrDomainName{}
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				// Configure the request for Username and Password authentication with a DomainID.
 | 
			
		||||
				req.Auth.Identity.Password = &passwordReq{
 | 
			
		||||
					User: userReq{
 | 
			
		||||
						Name:     &opts.Username,
 | 
			
		||||
						Password: opts.Password,
 | 
			
		||||
						Domain:   &domainReq{ID: &opts.DomainID},
 | 
			
		||||
					},
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if opts.DomainName != "" {
 | 
			
		||||
				// Configure the request for Username and Password authentication with a DomainName.
 | 
			
		||||
				req.Auth.Identity.Password = &passwordReq{
 | 
			
		||||
					User: userReq{
 | 
			
		||||
						Name:     &opts.Username,
 | 
			
		||||
						Password: opts.Password,
 | 
			
		||||
						Domain:   &domainReq{Name: &opts.DomainName},
 | 
			
		||||
					},
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if opts.UserID != "" {
 | 
			
		||||
			// If UserID is specified, neither DomainID nor DomainName may be.
 | 
			
		||||
			if opts.DomainID != "" {
 | 
			
		||||
				return nil, ErrDomainIDWithUserID{}
 | 
			
		||||
			}
 | 
			
		||||
			if opts.DomainName != "" {
 | 
			
		||||
				return nil, ErrDomainNameWithUserID{}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// Configure the request for UserID and Password authentication.
 | 
			
		||||
			req.Auth.Identity.Password = &passwordReq{
 | 
			
		||||
				User: userReq{ID: &opts.UserID, Password: opts.Password},
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	b, err := BuildRequestBody(req, "")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(scope) != 0 {
 | 
			
		||||
		b["auth"].(map[string]interface{})["scope"] = scope
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return b, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
		opts.TenantID = ""
 | 
			
		||||
		opts.TenantName = ""
 | 
			
		||||
	} else {
 | 
			
		||||
		if opts.TenantName != "" {
 | 
			
		||||
			scope.ProjectName = opts.TenantName
 | 
			
		||||
			scope.DomainID = opts.DomainID
 | 
			
		||||
			scope.DomainName = opts.DomainName
 | 
			
		||||
		}
 | 
			
		||||
		opts.TenantName = ""
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if scope.ProjectName != "" {
 | 
			
		||||
		// ProjectName provided: either DomainID or DomainName must also be supplied.
 | 
			
		||||
		// ProjectID may not be supplied.
 | 
			
		||||
		if scope.DomainID == "" && scope.DomainName == "" {
 | 
			
		||||
			return nil, ErrScopeDomainIDOrDomainName{}
 | 
			
		||||
		}
 | 
			
		||||
		if scope.ProjectID != "" {
 | 
			
		||||
			return nil, ErrScopeProjectIDOrProjectName{}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if scope.DomainID != "" {
 | 
			
		||||
			// ProjectName + DomainID
 | 
			
		||||
			return map[string]interface{}{
 | 
			
		||||
				"project": map[string]interface{}{
 | 
			
		||||
					"name":   &scope.ProjectName,
 | 
			
		||||
					"domain": map[string]interface{}{"id": &scope.DomainID},
 | 
			
		||||
				},
 | 
			
		||||
			}, nil
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if scope.DomainName != "" {
 | 
			
		||||
			// ProjectName + DomainName
 | 
			
		||||
			return map[string]interface{}{
 | 
			
		||||
				"project": map[string]interface{}{
 | 
			
		||||
					"name":   &scope.ProjectName,
 | 
			
		||||
					"domain": map[string]interface{}{"name": &scope.DomainName},
 | 
			
		||||
				},
 | 
			
		||||
			}, nil
 | 
			
		||||
		}
 | 
			
		||||
	} else if scope.ProjectID != "" {
 | 
			
		||||
		// ProjectID provided. ProjectName, DomainID, and DomainName may not be provided.
 | 
			
		||||
		if scope.DomainID != "" {
 | 
			
		||||
			return nil, ErrScopeProjectIDAlone{}
 | 
			
		||||
		}
 | 
			
		||||
		if scope.DomainName != "" {
 | 
			
		||||
			return nil, ErrScopeProjectIDAlone{}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// ProjectID
 | 
			
		||||
		return map[string]interface{}{
 | 
			
		||||
			"project": map[string]interface{}{
 | 
			
		||||
				"id": &scope.ProjectID,
 | 
			
		||||
			},
 | 
			
		||||
		}, nil
 | 
			
		||||
	} else if scope.DomainID != "" {
 | 
			
		||||
		// DomainID provided. ProjectID, ProjectName, and DomainName may not be provided.
 | 
			
		||||
		if scope.DomainName != "" {
 | 
			
		||||
			return nil, ErrScopeDomainIDOrDomainName{}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// DomainID
 | 
			
		||||
		return map[string]interface{}{
 | 
			
		||||
			"domain": map[string]interface{}{
 | 
			
		||||
				"id": &scope.DomainID,
 | 
			
		||||
			},
 | 
			
		||||
		}, nil
 | 
			
		||||
	} else if scope.DomainName != "" {
 | 
			
		||||
		return nil, ErrScopeDomainName{}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (opts AuthOptions) CanReauth() bool {
 | 
			
		||||
	return opts.AllowReauth
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										67
									
								
								vendor/github.com/gophercloud/gophercloud/doc.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								vendor/github.com/gophercloud/gophercloud/doc.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,67 @@
 | 
			
		||||
/*
 | 
			
		||||
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. Examples of providers include: OpenStack, Rackspace,
 | 
			
		||||
HP. These are defined like so:
 | 
			
		||||
 | 
			
		||||
  opts := gophercloud.AuthOptions{
 | 
			
		||||
    IdentityEndpoint: "https://my-openstack.com:5000/v2.0",
 | 
			
		||||
    Username: "{username}",
 | 
			
		||||
    Password: "{password}",
 | 
			
		||||
    TenantID: "{tenant_id}",
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  provider, err := openstack.AuthenticatedClient(opts)
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
pass in the parent provider, like so:
 | 
			
		||||
 | 
			
		||||
  opts := gophercloud.EndpointOpts{Region: "RegionOne"}
 | 
			
		||||
 | 
			
		||||
  client := openstack.NewComputeV2(provider, opts)
 | 
			
		||||
 | 
			
		||||
Resource structs are the domain models that services make use of in order
 | 
			
		||||
to work with and represent the state of API resources:
 | 
			
		||||
 | 
			
		||||
  server, err := servers.Get(client, "{serverId}").Extract()
 | 
			
		||||
 | 
			
		||||
Intermediate Result structs are returned for API operations, which allow
 | 
			
		||||
generic access to the HTTP headers, response body, and any errors associated
 | 
			
		||||
with the network transaction. To turn a result into a usable resource struct,
 | 
			
		||||
you must call the Extract method which is chained to the response, or an
 | 
			
		||||
Extract function from an applicable extension:
 | 
			
		||||
 | 
			
		||||
  result := servers.Get(client, "{serverId}")
 | 
			
		||||
 | 
			
		||||
  // Attempt to extract the disk configuration from the OS-DCF disk config
 | 
			
		||||
  // extension:
 | 
			
		||||
  config, err := diskconfig.ExtractGet(result)
 | 
			
		||||
 | 
			
		||||
All requests that enumerate a collection return a Pager struct that is used to
 | 
			
		||||
iterate through the results one page at a time. Use the EachPage method on that
 | 
			
		||||
Pager to handle each successive Page in a closure, then use the appropriate
 | 
			
		||||
extraction method from that request's package to interpret that Page as a slice
 | 
			
		||||
of results:
 | 
			
		||||
 | 
			
		||||
  err := servers.List(client, nil).EachPage(func (page pagination.Page) (bool, error) {
 | 
			
		||||
    s, err := servers.ExtractServers(page)
 | 
			
		||||
    if err != nil {
 | 
			
		||||
      return false, err
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Handle the []servers.Server slice.
 | 
			
		||||
 | 
			
		||||
    // Return "false" or an error to prematurely stop fetching new pages.
 | 
			
		||||
    return true, nil
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
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.
 | 
			
		||||
*/
 | 
			
		||||
package gophercloud
 | 
			
		||||
							
								
								
									
										76
									
								
								vendor/github.com/gophercloud/gophercloud/endpoint_search.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								vendor/github.com/gophercloud/gophercloud/endpoint_search.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,76 @@
 | 
			
		||||
package gophercloud
 | 
			
		||||
 | 
			
		||||
// Availability indicates to whom a specific service endpoint is accessible:
 | 
			
		||||
// the internet at large, internal networks only, or only to administrators.
 | 
			
		||||
// Different identity services use different terminology for these. Identity v2
 | 
			
		||||
// lists them as different kinds of URLs within the service catalog ("adminURL",
 | 
			
		||||
// "internalURL", and "publicURL"), while v3 lists them as "Interfaces" in an
 | 
			
		||||
// endpoint's response.
 | 
			
		||||
type Availability string
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	// AvailabilityAdmin indicates that an endpoint is only available to
 | 
			
		||||
	// administrators.
 | 
			
		||||
	AvailabilityAdmin Availability = "admin"
 | 
			
		||||
 | 
			
		||||
	// AvailabilityPublic indicates that an endpoint is available to everyone on
 | 
			
		||||
	// the internet.
 | 
			
		||||
	AvailabilityPublic Availability = "public"
 | 
			
		||||
 | 
			
		||||
	// AvailabilityInternal indicates that an endpoint is only available within
 | 
			
		||||
	// the cluster's internal network.
 | 
			
		||||
	AvailabilityInternal Availability = "internal"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// EndpointOpts specifies search criteria used by queries against an
 | 
			
		||||
// OpenStack service catalog. The options must contain enough information to
 | 
			
		||||
// 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()".
 | 
			
		||||
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
 | 
			
		||||
	// function, but a user-given value will be honored if provided.
 | 
			
		||||
	Type string
 | 
			
		||||
 | 
			
		||||
	// Name [optional] is the service name for the client (e.g., "nova") as it
 | 
			
		||||
	// appears in the service catalog. Services can have the same Type but a
 | 
			
		||||
	// different Name, which is why both Type and Name are sometimes needed.
 | 
			
		||||
	Name string
 | 
			
		||||
 | 
			
		||||
	// Region [required] is the geographic region in which the endpoint resides,
 | 
			
		||||
	// generally specifying which datacenter should house your resources.
 | 
			
		||||
	// Required only for services that span multiple regions.
 | 
			
		||||
	Region string
 | 
			
		||||
 | 
			
		||||
	// Availability [optional] is the visibility of the endpoint to be returned.
 | 
			
		||||
	// Valid types include the constants AvailabilityPublic, AvailabilityInternal,
 | 
			
		||||
	// or AvailabilityAdmin from this package.
 | 
			
		||||
	//
 | 
			
		||||
	// Availability is not required, and defaults to AvailabilityPublic. Not all
 | 
			
		||||
	// providers or services offer all Availability options.
 | 
			
		||||
	Availability Availability
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
EndpointLocator is an internal function to be used by provider implementations.
 | 
			
		||||
 | 
			
		||||
It provides an implementation that locates a single endpoint from a service
 | 
			
		||||
catalog for a specific ProviderClient based on user-provided EndpointOpts. The
 | 
			
		||||
provider then uses it to discover related ServiceClients.
 | 
			
		||||
*/
 | 
			
		||||
type EndpointLocator func(EndpointOpts) (string, error)
 | 
			
		||||
 | 
			
		||||
// ApplyDefaults is an internal method to be used by provider implementations.
 | 
			
		||||
//
 | 
			
		||||
// It sets EndpointOpts fields if not already set, including a default type.
 | 
			
		||||
// Currently, EndpointOpts.Availability defaults to the public endpoint.
 | 
			
		||||
func (eo *EndpointOpts) ApplyDefaults(t string) {
 | 
			
		||||
	if eo.Type == "" {
 | 
			
		||||
		eo.Type = t
 | 
			
		||||
	}
 | 
			
		||||
	if eo.Availability == "" {
 | 
			
		||||
		eo.Availability = AvailabilityPublic
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										408
									
								
								vendor/github.com/gophercloud/gophercloud/errors.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										408
									
								
								vendor/github.com/gophercloud/gophercloud/errors.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,408 @@
 | 
			
		||||
package gophercloud
 | 
			
		||||
 | 
			
		||||
import "fmt"
 | 
			
		||||
 | 
			
		||||
// BaseError is an error type that all other error types embed.
 | 
			
		||||
type BaseError struct {
 | 
			
		||||
	DefaultErrString string
 | 
			
		||||
	Info             string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e BaseError) Error() string {
 | 
			
		||||
	e.DefaultErrString = "An error occurred while executing a Gophercloud request."
 | 
			
		||||
	return e.choseErrString()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e BaseError) choseErrString() string {
 | 
			
		||||
	if e.Info != "" {
 | 
			
		||||
		return e.Info
 | 
			
		||||
	}
 | 
			
		||||
	return e.DefaultErrString
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ErrMissingInput is the error when input is required in a particular
 | 
			
		||||
// situation but not provided by the user
 | 
			
		||||
type ErrMissingInput struct {
 | 
			
		||||
	BaseError
 | 
			
		||||
	Argument string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e ErrMissingInput) Error() string {
 | 
			
		||||
	e.DefaultErrString = fmt.Sprintf("Missing input for argument [%s]", e.Argument)
 | 
			
		||||
	return e.choseErrString()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ErrInvalidInput is an error type used for most non-HTTP Gophercloud errors.
 | 
			
		||||
type ErrInvalidInput struct {
 | 
			
		||||
	ErrMissingInput
 | 
			
		||||
	Value interface{}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e ErrInvalidInput) Error() string {
 | 
			
		||||
	e.DefaultErrString = fmt.Sprintf("Invalid input provided for argument [%s]: [%+v]", e.Argument, e.Value)
 | 
			
		||||
	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 {
 | 
			
		||||
	BaseError
 | 
			
		||||
	URL      string
 | 
			
		||||
	Method   string
 | 
			
		||||
	Expected []int
 | 
			
		||||
	Actual   int
 | 
			
		||||
	Body     []byte
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e ErrUnexpectedResponseCode) Error() string {
 | 
			
		||||
	e.DefaultErrString = fmt.Sprintf(
 | 
			
		||||
		"Expected HTTP response code %v when accessing [%s %s], but got %d instead\n%s",
 | 
			
		||||
		e.Expected, e.Method, e.URL, e.Actual, e.Body,
 | 
			
		||||
	)
 | 
			
		||||
	return e.choseErrString()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ErrDefault400 is the default error type returned on a 400 HTTP response code.
 | 
			
		||||
type ErrDefault400 struct {
 | 
			
		||||
	ErrUnexpectedResponseCode
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ErrDefault401 is the default error type returned on a 401 HTTP response code.
 | 
			
		||||
type ErrDefault401 struct {
 | 
			
		||||
	ErrUnexpectedResponseCode
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ErrDefault404 is the default error type returned on a 404 HTTP response code.
 | 
			
		||||
type ErrDefault404 struct {
 | 
			
		||||
	ErrUnexpectedResponseCode
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ErrDefault405 is the default error type returned on a 405 HTTP response code.
 | 
			
		||||
type ErrDefault405 struct {
 | 
			
		||||
	ErrUnexpectedResponseCode
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ErrDefault408 is the default error type returned on a 408 HTTP response code.
 | 
			
		||||
type ErrDefault408 struct {
 | 
			
		||||
	ErrUnexpectedResponseCode
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ErrDefault429 is the default error type returned on a 429 HTTP response code.
 | 
			
		||||
type ErrDefault429 struct {
 | 
			
		||||
	ErrUnexpectedResponseCode
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ErrDefault500 is the default error type returned on a 500 HTTP response code.
 | 
			
		||||
type ErrDefault500 struct {
 | 
			
		||||
	ErrUnexpectedResponseCode
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ErrDefault503 is the default error type returned on a 503 HTTP response code.
 | 
			
		||||
type ErrDefault503 struct {
 | 
			
		||||
	ErrUnexpectedResponseCode
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e ErrDefault400) Error() string {
 | 
			
		||||
	return "Invalid request due to incorrect syntax or missing required parameters."
 | 
			
		||||
}
 | 
			
		||||
func (e ErrDefault401) Error() string {
 | 
			
		||||
	return "Authentication failed"
 | 
			
		||||
}
 | 
			
		||||
func (e ErrDefault404) Error() string {
 | 
			
		||||
	return "Resource not found"
 | 
			
		||||
}
 | 
			
		||||
func (e ErrDefault405) Error() string {
 | 
			
		||||
	return "Method not allowed"
 | 
			
		||||
}
 | 
			
		||||
func (e ErrDefault408) Error() string {
 | 
			
		||||
	return "The server timed out waiting for the request"
 | 
			
		||||
}
 | 
			
		||||
func (e ErrDefault429) Error() string {
 | 
			
		||||
	return "Too many requests have been sent in a given amount of time. Pause" +
 | 
			
		||||
		" requests, wait up to one minute, and try again."
 | 
			
		||||
}
 | 
			
		||||
func (e ErrDefault500) Error() string {
 | 
			
		||||
	return "Internal Server Error"
 | 
			
		||||
}
 | 
			
		||||
func (e ErrDefault503) Error() string {
 | 
			
		||||
	return "The service is currently unable to handle the request due to a temporary" +
 | 
			
		||||
		" overloading or maintenance. This is a temporary condition. Try again later."
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Err400er is the interface resource error types implement to override the error message
 | 
			
		||||
// from a 400 error.
 | 
			
		||||
type Err400er interface {
 | 
			
		||||
	Error400(ErrUnexpectedResponseCode) error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Err401er is the interface resource error types implement to override the error message
 | 
			
		||||
// from a 401 error.
 | 
			
		||||
type Err401er interface {
 | 
			
		||||
	Error401(ErrUnexpectedResponseCode) error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Err404er is the interface resource error types implement to override the error message
 | 
			
		||||
// from a 404 error.
 | 
			
		||||
type Err404er interface {
 | 
			
		||||
	Error404(ErrUnexpectedResponseCode) error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Err405er is the interface resource error types implement to override the error message
 | 
			
		||||
// from a 405 error.
 | 
			
		||||
type Err405er interface {
 | 
			
		||||
	Error405(ErrUnexpectedResponseCode) error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Err408er is the interface resource error types implement to override the error message
 | 
			
		||||
// from a 408 error.
 | 
			
		||||
type Err408er interface {
 | 
			
		||||
	Error408(ErrUnexpectedResponseCode) error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Err429er is the interface resource error types implement to override the error message
 | 
			
		||||
// from a 429 error.
 | 
			
		||||
type Err429er interface {
 | 
			
		||||
	Error429(ErrUnexpectedResponseCode) error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Err500er is the interface resource error types implement to override the error message
 | 
			
		||||
// from a 500 error.
 | 
			
		||||
type Err500er interface {
 | 
			
		||||
	Error500(ErrUnexpectedResponseCode) error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Err503er is the interface resource error types implement to override the error message
 | 
			
		||||
// from a 503 error.
 | 
			
		||||
type Err503er interface {
 | 
			
		||||
	Error503(ErrUnexpectedResponseCode) error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ErrTimeOut is the error type returned when an operations times out.
 | 
			
		||||
type ErrTimeOut struct {
 | 
			
		||||
	BaseError
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e ErrTimeOut) Error() string {
 | 
			
		||||
	e.DefaultErrString = "A time out occurred"
 | 
			
		||||
	return e.choseErrString()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ErrUnableToReauthenticate is the error type returned when reauthentication fails.
 | 
			
		||||
type ErrUnableToReauthenticate struct {
 | 
			
		||||
	BaseError
 | 
			
		||||
	ErrOriginal error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e ErrUnableToReauthenticate) Error() string {
 | 
			
		||||
	e.DefaultErrString = fmt.Sprintf("Unable to re-authenticate: %s", e.ErrOriginal)
 | 
			
		||||
	return e.choseErrString()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ErrErrorAfterReauthentication is the error type returned when reauthentication
 | 
			
		||||
// succeeds, but an error occurs afterword (usually an HTTP error).
 | 
			
		||||
type ErrErrorAfterReauthentication struct {
 | 
			
		||||
	BaseError
 | 
			
		||||
	ErrOriginal error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e ErrErrorAfterReauthentication) Error() string {
 | 
			
		||||
	e.DefaultErrString = fmt.Sprintf("Successfully re-authenticated, but got error executing request: %s", e.ErrOriginal)
 | 
			
		||||
	return e.choseErrString()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ErrServiceNotFound is returned when no service in a service catalog matches
 | 
			
		||||
// the provided EndpointOpts. This is generally returned by provider service
 | 
			
		||||
// factory methods like "NewComputeV2()" and can mean that a service is not
 | 
			
		||||
// enabled for your account.
 | 
			
		||||
type ErrServiceNotFound struct {
 | 
			
		||||
	BaseError
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e ErrServiceNotFound) Error() string {
 | 
			
		||||
	e.DefaultErrString = "No suitable service could be found in the service catalog."
 | 
			
		||||
	return e.choseErrString()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ErrEndpointNotFound is returned when no available endpoints match the
 | 
			
		||||
// provided EndpointOpts. This is also generally returned by provider service
 | 
			
		||||
// factory methods, and usually indicates that a region was specified
 | 
			
		||||
// incorrectly.
 | 
			
		||||
type ErrEndpointNotFound struct {
 | 
			
		||||
	BaseError
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e ErrEndpointNotFound) Error() string {
 | 
			
		||||
	e.DefaultErrString = "No suitable endpoint could be found in the service catalog."
 | 
			
		||||
	return e.choseErrString()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ErrResourceNotFound is the error when trying to retrieve a resource's
 | 
			
		||||
// ID by name and the resource doesn't exist.
 | 
			
		||||
type ErrResourceNotFound struct {
 | 
			
		||||
	BaseError
 | 
			
		||||
	Name         string
 | 
			
		||||
	ResourceType string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e ErrResourceNotFound) Error() string {
 | 
			
		||||
	e.DefaultErrString = fmt.Sprintf("Unable to find %s with name %s", e.ResourceType, e.Name)
 | 
			
		||||
	return e.choseErrString()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ErrMultipleResourcesFound is the error when trying to retrieve a resource's
 | 
			
		||||
// ID by name and multiple resources have the user-provided name.
 | 
			
		||||
type ErrMultipleResourcesFound struct {
 | 
			
		||||
	BaseError
 | 
			
		||||
	Name         string
 | 
			
		||||
	Count        int
 | 
			
		||||
	ResourceType string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e ErrMultipleResourcesFound) Error() string {
 | 
			
		||||
	e.DefaultErrString = fmt.Sprintf("Found %d %ss matching %s", e.Count, e.ResourceType, e.Name)
 | 
			
		||||
	return e.choseErrString()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ErrUnexpectedType is the error when an unexpected type is encountered
 | 
			
		||||
type ErrUnexpectedType struct {
 | 
			
		||||
	BaseError
 | 
			
		||||
	Expected string
 | 
			
		||||
	Actual   string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e ErrUnexpectedType) Error() string {
 | 
			
		||||
	e.DefaultErrString = fmt.Sprintf("Expected %s but got %s", e.Expected, e.Actual)
 | 
			
		||||
	return e.choseErrString()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func unacceptedAttributeErr(attribute string) string {
 | 
			
		||||
	return fmt.Sprintf("The base Identity V3 API does not accept authentication by %s", attribute)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func redundantWithTokenErr(attribute string) string {
 | 
			
		||||
	return fmt.Sprintf("%s may not be provided when authenticating with a TokenID", attribute)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func redundantWithUserID(attribute string) string {
 | 
			
		||||
	return fmt.Sprintf("%s may not be provided when authenticating with a UserID", attribute)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ErrAPIKeyProvided indicates that an APIKey was provided but can't be used.
 | 
			
		||||
type ErrAPIKeyProvided struct{ BaseError }
 | 
			
		||||
 | 
			
		||||
func (e ErrAPIKeyProvided) Error() string {
 | 
			
		||||
	return unacceptedAttributeErr("APIKey")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ErrTenantIDProvided indicates that a TenantID was provided but can't be used.
 | 
			
		||||
type ErrTenantIDProvided struct{ BaseError }
 | 
			
		||||
 | 
			
		||||
func (e ErrTenantIDProvided) Error() string {
 | 
			
		||||
	return unacceptedAttributeErr("TenantID")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ErrTenantNameProvided indicates that a TenantName was provided but can't be used.
 | 
			
		||||
type ErrTenantNameProvided struct{ BaseError }
 | 
			
		||||
 | 
			
		||||
func (e ErrTenantNameProvided) Error() string {
 | 
			
		||||
	return unacceptedAttributeErr("TenantName")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ErrUsernameWithToken indicates that a Username was provided, but token authentication is being used instead.
 | 
			
		||||
type ErrUsernameWithToken struct{ BaseError }
 | 
			
		||||
 | 
			
		||||
func (e ErrUsernameWithToken) Error() string {
 | 
			
		||||
	return redundantWithTokenErr("Username")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ErrUserIDWithToken indicates that a UserID was provided, but token authentication is being used instead.
 | 
			
		||||
type ErrUserIDWithToken struct{ BaseError }
 | 
			
		||||
 | 
			
		||||
func (e ErrUserIDWithToken) Error() string {
 | 
			
		||||
	return redundantWithTokenErr("UserID")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ErrDomainIDWithToken indicates that a DomainID was provided, but token authentication is being used instead.
 | 
			
		||||
type ErrDomainIDWithToken struct{ BaseError }
 | 
			
		||||
 | 
			
		||||
func (e ErrDomainIDWithToken) Error() string {
 | 
			
		||||
	return redundantWithTokenErr("DomainID")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ErrDomainNameWithToken indicates that a DomainName was provided, but token authentication is being used instead.s
 | 
			
		||||
type ErrDomainNameWithToken struct{ BaseError }
 | 
			
		||||
 | 
			
		||||
func (e ErrDomainNameWithToken) Error() string {
 | 
			
		||||
	return redundantWithTokenErr("DomainName")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ErrUsernameOrUserID indicates that neither username nor userID are specified, or both are at once.
 | 
			
		||||
type ErrUsernameOrUserID struct{ BaseError }
 | 
			
		||||
 | 
			
		||||
func (e ErrUsernameOrUserID) Error() string {
 | 
			
		||||
	return "Exactly one of Username and UserID must be provided for password authentication"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ErrDomainIDWithUserID indicates that a DomainID was provided, but unnecessary because a UserID is being used.
 | 
			
		||||
type ErrDomainIDWithUserID struct{ BaseError }
 | 
			
		||||
 | 
			
		||||
func (e ErrDomainIDWithUserID) Error() string {
 | 
			
		||||
	return redundantWithUserID("DomainID")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ErrDomainNameWithUserID indicates that a DomainName was provided, but unnecessary because a UserID is being used.
 | 
			
		||||
type ErrDomainNameWithUserID struct{ BaseError }
 | 
			
		||||
 | 
			
		||||
func (e ErrDomainNameWithUserID) Error() string {
 | 
			
		||||
	return redundantWithUserID("DomainName")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ErrDomainIDOrDomainName indicates that a username was provided, but no domain to scope it.
 | 
			
		||||
// It may also indicate that both a DomainID and a DomainName were provided at once.
 | 
			
		||||
type ErrDomainIDOrDomainName struct{ BaseError }
 | 
			
		||||
 | 
			
		||||
func (e ErrDomainIDOrDomainName) Error() string {
 | 
			
		||||
	return "You must provide exactly one of DomainID or DomainName to authenticate by Username"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ErrMissingPassword indicates that no password was provided and no token is available.
 | 
			
		||||
type ErrMissingPassword struct{ BaseError }
 | 
			
		||||
 | 
			
		||||
func (e ErrMissingPassword) Error() string {
 | 
			
		||||
	return "You must provide a password to authenticate"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ErrScopeDomainIDOrDomainName indicates that a domain ID or Name was required in a Scope, but not present.
 | 
			
		||||
type ErrScopeDomainIDOrDomainName struct{ BaseError }
 | 
			
		||||
 | 
			
		||||
func (e ErrScopeDomainIDOrDomainName) Error() string {
 | 
			
		||||
	return "You must provide exactly one of DomainID or DomainName in a Scope with ProjectName"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ErrScopeProjectIDOrProjectName indicates that both a ProjectID and a ProjectName were provided in a Scope.
 | 
			
		||||
type ErrScopeProjectIDOrProjectName struct{ BaseError }
 | 
			
		||||
 | 
			
		||||
func (e ErrScopeProjectIDOrProjectName) Error() string {
 | 
			
		||||
	return "You must provide at most one of ProjectID or ProjectName in a Scope"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ErrScopeProjectIDAlone indicates that a ProjectID was provided with other constraints in a Scope.
 | 
			
		||||
type ErrScopeProjectIDAlone struct{ BaseError }
 | 
			
		||||
 | 
			
		||||
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 }
 | 
			
		||||
 | 
			
		||||
func (e ErrScopeEmpty) Error() string {
 | 
			
		||||
	return "You must provide either a Project or Domain in a Scope"
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										52
									
								
								vendor/github.com/gophercloud/gophercloud/openstack/auth_env.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								vendor/github.com/gophercloud/gophercloud/openstack/auth_env.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,52 @@
 | 
			
		||||
package openstack
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"os"
 | 
			
		||||
 | 
			
		||||
	"github.com/gophercloud/gophercloud"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
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.
 | 
			
		||||
func AuthOptionsFromEnv() (gophercloud.AuthOptions, error) {
 | 
			
		||||
	authURL := os.Getenv("OS_AUTH_URL")
 | 
			
		||||
	username := os.Getenv("OS_USERNAME")
 | 
			
		||||
	userID := os.Getenv("OS_USERID")
 | 
			
		||||
	password := os.Getenv("OS_PASSWORD")
 | 
			
		||||
	tenantID := os.Getenv("OS_TENANT_ID")
 | 
			
		||||
	tenantName := os.Getenv("OS_TENANT_NAME")
 | 
			
		||||
	domainID := os.Getenv("OS_DOMAIN_ID")
 | 
			
		||||
	domainName := os.Getenv("OS_DOMAIN_NAME")
 | 
			
		||||
 | 
			
		||||
	if authURL == "" {
 | 
			
		||||
		err := gophercloud.ErrMissingInput{Argument: "authURL"}
 | 
			
		||||
		return nilOptions, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if username == "" && userID == "" {
 | 
			
		||||
		err := gophercloud.ErrMissingInput{Argument: "username"}
 | 
			
		||||
		return nilOptions, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if password == "" {
 | 
			
		||||
		err := gophercloud.ErrMissingInput{Argument: "password"}
 | 
			
		||||
		return nilOptions, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ao := gophercloud.AuthOptions{
 | 
			
		||||
		IdentityEndpoint: authURL,
 | 
			
		||||
		UserID:           userID,
 | 
			
		||||
		Username:         username,
 | 
			
		||||
		Password:         password,
 | 
			
		||||
		TenantID:         tenantID,
 | 
			
		||||
		TenantName:       tenantName,
 | 
			
		||||
		DomainID:         domainID,
 | 
			
		||||
		DomainName:       domainName,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return ao, nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										5
									
								
								vendor/github.com/gophercloud/gophercloud/openstack/blockstorage/v1/volumes/doc.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								vendor/github.com/gophercloud/gophercloud/openstack/blockstorage/v1/volumes/doc.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
			
		||||
// Package volumes provides information and interaction with volumes in the
 | 
			
		||||
// OpenStack Block Storage service. A volume is a detachable block storage
 | 
			
		||||
// device, akin to a USB hard drive. It can only be attached to one instance at
 | 
			
		||||
// a time.
 | 
			
		||||
package volumes
 | 
			
		||||
							
								
								
									
										167
									
								
								vendor/github.com/gophercloud/gophercloud/openstack/blockstorage/v1/volumes/requests.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										167
									
								
								vendor/github.com/gophercloud/gophercloud/openstack/blockstorage/v1/volumes/requests.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,167 @@
 | 
			
		||||
package volumes
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/gophercloud/gophercloud"
 | 
			
		||||
	"github.com/gophercloud/gophercloud/pagination"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// CreateOptsBuilder allows extensions to add additional parameters to the
 | 
			
		||||
// Create request.
 | 
			
		||||
type CreateOptsBuilder interface {
 | 
			
		||||
	ToVolumeCreateMap() (map[string]interface{}, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CreateOpts contains options for creating a Volume. This object is passed to
 | 
			
		||||
// the volumes.Create function. For more information about these parameters,
 | 
			
		||||
// see the Volume object.
 | 
			
		||||
type CreateOpts struct {
 | 
			
		||||
	Size         int               `json:"size" required:"true"`
 | 
			
		||||
	Availability string            `json:"availability,omitempty"`
 | 
			
		||||
	Description  string            `json:"display_description,omitempty"`
 | 
			
		||||
	Metadata     map[string]string `json:"metadata,omitempty"`
 | 
			
		||||
	Name         string            `json:"display_name,omitempty"`
 | 
			
		||||
	SnapshotID   string            `json:"snapshot_id,omitempty"`
 | 
			
		||||
	SourceVolID  string            `json:"source_volid,omitempty"`
 | 
			
		||||
	ImageID      string            `json:"imageRef,omitempty"`
 | 
			
		||||
	VolumeType   string            `json:"volume_type,omitempty"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ToVolumeCreateMap assembles a request body based on the contents of a
 | 
			
		||||
// CreateOpts.
 | 
			
		||||
func (opts CreateOpts) ToVolumeCreateMap() (map[string]interface{}, error) {
 | 
			
		||||
	return gophercloud.BuildRequestBody(opts, "volume")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Create will create a new Volume based on the values in CreateOpts. To extract
 | 
			
		||||
// the Volume object from the response, call the Extract method on the
 | 
			
		||||
// CreateResult.
 | 
			
		||||
func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) (r CreateResult) {
 | 
			
		||||
	b, err := opts.ToVolumeCreateMap()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		r.Err = err
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	_, r.Err = client.Post(createURL(client), b, &r.Body, &gophercloud.RequestOpts{
 | 
			
		||||
		OkCodes: []int{200, 201},
 | 
			
		||||
	})
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Delete will delete the existing Volume with the provided ID.
 | 
			
		||||
func Delete(client *gophercloud.ServiceClient, id string) (r DeleteResult) {
 | 
			
		||||
	_, r.Err = client.Delete(deleteURL(client, id), nil)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Get retrieves the Volume with the provided ID. To extract the Volume object
 | 
			
		||||
// from the response, call the Extract method on the GetResult.
 | 
			
		||||
func Get(client *gophercloud.ServiceClient, id string) (r GetResult) {
 | 
			
		||||
	_, r.Err = client.Get(getURL(client, id), &r.Body, nil)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ListOptsBuilder allows extensions to add additional parameters to the List
 | 
			
		||||
// request.
 | 
			
		||||
type ListOptsBuilder interface {
 | 
			
		||||
	ToVolumeListQuery() (string, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ListOpts holds options for listing Volumes. It is passed to the volumes.List
 | 
			
		||||
// function.
 | 
			
		||||
type ListOpts struct {
 | 
			
		||||
	// admin-only option. Set it to true to see all tenant volumes.
 | 
			
		||||
	AllTenants bool `q:"all_tenants"`
 | 
			
		||||
	// List only volumes that contain Metadata.
 | 
			
		||||
	Metadata map[string]string `q:"metadata"`
 | 
			
		||||
	// List only volumes that have Name as the display name.
 | 
			
		||||
	Name string `q:"display_name"`
 | 
			
		||||
	// List only volumes that have a status of Status.
 | 
			
		||||
	Status string `q:"status"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ToVolumeListQuery formats a ListOpts into a query string.
 | 
			
		||||
func (opts ListOpts) ToVolumeListQuery() (string, error) {
 | 
			
		||||
	q, err := gophercloud.BuildQueryString(opts)
 | 
			
		||||
	return q.String(), err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// List returns Volumes optionally limited by the conditions provided in ListOpts.
 | 
			
		||||
func List(client *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager {
 | 
			
		||||
	url := listURL(client)
 | 
			
		||||
	if opts != nil {
 | 
			
		||||
		query, err := opts.ToVolumeListQuery()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return pagination.Pager{Err: err}
 | 
			
		||||
		}
 | 
			
		||||
		url += query
 | 
			
		||||
	}
 | 
			
		||||
	return pagination.NewPager(client, url, func(r pagination.PageResult) pagination.Page {
 | 
			
		||||
		return VolumePage{pagination.SinglePageBase(r)}
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UpdateOptsBuilder allows extensions to add additional parameters to the
 | 
			
		||||
// Update request.
 | 
			
		||||
type UpdateOptsBuilder interface {
 | 
			
		||||
	ToVolumeUpdateMap() (map[string]interface{}, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UpdateOpts contain options for updating an existing Volume. This object is passed
 | 
			
		||||
// to the volumes.Update function. For more information about the parameters, see
 | 
			
		||||
// the Volume object.
 | 
			
		||||
type UpdateOpts struct {
 | 
			
		||||
	Name        string            `json:"display_name,omitempty"`
 | 
			
		||||
	Description string            `json:"display_description,omitempty"`
 | 
			
		||||
	Metadata    map[string]string `json:"metadata,omitempty"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ToVolumeUpdateMap assembles a request body based on the contents of an
 | 
			
		||||
// UpdateOpts.
 | 
			
		||||
func (opts UpdateOpts) ToVolumeUpdateMap() (map[string]interface{}, error) {
 | 
			
		||||
	return gophercloud.BuildRequestBody(opts, "volume")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Update will update the Volume with provided information. To extract the updated
 | 
			
		||||
// Volume from the response, call the Extract method on the UpdateResult.
 | 
			
		||||
func Update(client *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) (r UpdateResult) {
 | 
			
		||||
	b, err := opts.ToVolumeUpdateMap()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		r.Err = err
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	_, r.Err = client.Put(updateURL(client, id), b, &r.Body, &gophercloud.RequestOpts{
 | 
			
		||||
		OkCodes: []int{200},
 | 
			
		||||
	})
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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 := ""
 | 
			
		||||
	pages, err := List(client, nil).AllPages()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	all, err := ExtractVolumes(pages)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, s := range all {
 | 
			
		||||
		if s.Name == name {
 | 
			
		||||
			count++
 | 
			
		||||
			id = s.ID
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	switch count {
 | 
			
		||||
	case 0:
 | 
			
		||||
		return "", gophercloud.ErrResourceNotFound{Name: name, ResourceType: "volume"}
 | 
			
		||||
	case 1:
 | 
			
		||||
		return id, nil
 | 
			
		||||
	default:
 | 
			
		||||
		return "", gophercloud.ErrMultipleResourcesFound{Name: name, Count: count, ResourceType: "volume"}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										89
									
								
								vendor/github.com/gophercloud/gophercloud/openstack/blockstorage/v1/volumes/results.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								vendor/github.com/gophercloud/gophercloud/openstack/blockstorage/v1/volumes/results.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,89 @@
 | 
			
		||||
package volumes
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/gophercloud/gophercloud"
 | 
			
		||||
	"github.com/gophercloud/gophercloud/pagination"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Volume contains all the information associated with an OpenStack Volume.
 | 
			
		||||
type Volume struct {
 | 
			
		||||
	// Current status of the volume.
 | 
			
		||||
	Status string `json:"status"`
 | 
			
		||||
	// Human-readable display name for the volume.
 | 
			
		||||
	Name string `json:"display_name"`
 | 
			
		||||
	// Instances onto which the volume is attached.
 | 
			
		||||
	Attachments []map[string]interface{} `json:"attachments"`
 | 
			
		||||
	// This parameter is no longer used.
 | 
			
		||||
	AvailabilityZone string `json:"availability_zone"`
 | 
			
		||||
	// Indicates whether this is a bootable volume.
 | 
			
		||||
	Bootable string `json:"bootable"`
 | 
			
		||||
	// The date when this volume was created.
 | 
			
		||||
	CreatedAt gophercloud.JSONRFC3339MilliNoZ `json:"created_at"`
 | 
			
		||||
	// Human-readable description for the volume.
 | 
			
		||||
	Description string `json:"display_description"`
 | 
			
		||||
	// The type of volume to create, either SATA or SSD.
 | 
			
		||||
	VolumeType string `json:"volume_type"`
 | 
			
		||||
	// The ID of the snapshot from which the volume was created
 | 
			
		||||
	SnapshotID string `json:"snapshot_id"`
 | 
			
		||||
	// The ID of another block storage volume from which the current volume was created
 | 
			
		||||
	SourceVolID string `json:"source_volid"`
 | 
			
		||||
	// Arbitrary key-value pairs defined by the user.
 | 
			
		||||
	Metadata map[string]string `json:"metadata"`
 | 
			
		||||
	// Unique identifier for the volume.
 | 
			
		||||
	ID string `json:"id"`
 | 
			
		||||
	// Size of the volume in GB.
 | 
			
		||||
	Size int `json:"size"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CreateResult contains the response body and error from a Create request.
 | 
			
		||||
type CreateResult struct {
 | 
			
		||||
	commonResult
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetResult contains the response body and error from a Get request.
 | 
			
		||||
type GetResult struct {
 | 
			
		||||
	commonResult
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeleteResult contains the response body and error from a Delete request.
 | 
			
		||||
type DeleteResult struct {
 | 
			
		||||
	gophercloud.ErrResult
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// VolumePage is a pagination.pager that is returned from a call to the List function.
 | 
			
		||||
type VolumePage struct {
 | 
			
		||||
	pagination.SinglePageBase
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IsEmpty returns true if a VolumePage contains no Volumes.
 | 
			
		||||
func (r VolumePage) IsEmpty() (bool, error) {
 | 
			
		||||
	volumes, err := ExtractVolumes(r)
 | 
			
		||||
	return len(volumes) == 0, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ExtractVolumes extracts and returns Volumes. It is used while iterating over a volumes.List call.
 | 
			
		||||
func ExtractVolumes(r pagination.Page) ([]Volume, error) {
 | 
			
		||||
	var s struct {
 | 
			
		||||
		Volumes []Volume `json:"volumes"`
 | 
			
		||||
	}
 | 
			
		||||
	err := (r.(VolumePage)).ExtractInto(&s)
 | 
			
		||||
	return s.Volumes, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UpdateResult contains the response body and error from an Update request.
 | 
			
		||||
type UpdateResult struct {
 | 
			
		||||
	commonResult
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type commonResult struct {
 | 
			
		||||
	gophercloud.Result
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Extract will get the Volume object out of the commonResult object.
 | 
			
		||||
func (r commonResult) Extract() (*Volume, error) {
 | 
			
		||||
	var s struct {
 | 
			
		||||
		Volume *Volume `json:"volume"`
 | 
			
		||||
	}
 | 
			
		||||
	err := r.ExtractInto(&s)
 | 
			
		||||
	return s.Volume, err
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										23
									
								
								vendor/github.com/gophercloud/gophercloud/openstack/blockstorage/v1/volumes/urls.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								vendor/github.com/gophercloud/gophercloud/openstack/blockstorage/v1/volumes/urls.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,23 @@
 | 
			
		||||
package volumes
 | 
			
		||||
 | 
			
		||||
import "github.com/gophercloud/gophercloud"
 | 
			
		||||
 | 
			
		||||
func createURL(c *gophercloud.ServiceClient) string {
 | 
			
		||||
	return c.ServiceURL("volumes")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func listURL(c *gophercloud.ServiceClient) string {
 | 
			
		||||
	return createURL(c)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func deleteURL(c *gophercloud.ServiceClient, id string) string {
 | 
			
		||||
	return c.ServiceURL("volumes", id)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func getURL(c *gophercloud.ServiceClient, id string) string {
 | 
			
		||||
	return deleteURL(c, id)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func updateURL(c *gophercloud.ServiceClient, id string) string {
 | 
			
		||||
	return deleteURL(c, id)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										22
									
								
								vendor/github.com/gophercloud/gophercloud/openstack/blockstorage/v1/volumes/util.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								vendor/github.com/gophercloud/gophercloud/openstack/blockstorage/v1/volumes/util.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,22 @@
 | 
			
		||||
package volumes
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/gophercloud/gophercloud"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// WaitForStatus will continually poll the resource, checking for a particular
 | 
			
		||||
// status. It will do this for the amount of seconds defined.
 | 
			
		||||
func WaitForStatus(c *gophercloud.ServiceClient, id, status string, secs int) error {
 | 
			
		||||
	return gophercloud.WaitFor(secs, func() (bool, error) {
 | 
			
		||||
		current, err := Get(c, id).Extract()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return false, err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if current.Status == status {
 | 
			
		||||
			return true, nil
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return false, nil
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										323
									
								
								vendor/github.com/gophercloud/gophercloud/openstack/client.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										323
									
								
								vendor/github.com/gophercloud/gophercloud/openstack/client.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,323 @@
 | 
			
		||||
package openstack
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"net/url"
 | 
			
		||||
	"reflect"
 | 
			
		||||
 | 
			
		||||
	"github.com/gophercloud/gophercloud"
 | 
			
		||||
	tokens2 "github.com/gophercloud/gophercloud/openstack/identity/v2/tokens"
 | 
			
		||||
	tokens3 "github.com/gophercloud/gophercloud/openstack/identity/v3/tokens"
 | 
			
		||||
	"github.com/gophercloud/gophercloud/openstack/utils"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	v20 = "v2.0"
 | 
			
		||||
	v30 = "v3.0"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// 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.
 | 
			
		||||
func NewClient(endpoint string) (*gophercloud.ProviderClient, error) {
 | 
			
		||||
	u, err := url.Parse(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
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return &gophercloud.ProviderClient{
 | 
			
		||||
		IdentityBase:     base,
 | 
			
		||||
		IdentityEndpoint: "",
 | 
			
		||||
	}, 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.
 | 
			
		||||
func AuthenticatedClient(options gophercloud.AuthOptions) (*gophercloud.ProviderClient, error) {
 | 
			
		||||
	client, err := NewClient(options.IdentityEndpoint)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err = Authenticate(client, options)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return client, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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/"},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	chosen, endpoint, err := utils.ChooseVersion(client, versions)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	switch chosen.ID {
 | 
			
		||||
	case v20:
 | 
			
		||||
		return v2auth(client, endpoint, options, gophercloud.EndpointOpts{})
 | 
			
		||||
	case v30:
 | 
			
		||||
		return v3auth(client, endpoint, &options, gophercloud.EndpointOpts{})
 | 
			
		||||
	default:
 | 
			
		||||
		// The switch statement must be out of date from the versions list.
 | 
			
		||||
		return fmt.Errorf("Unrecognized identity version: %s", chosen.ID)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// AuthenticateV2 explicitly authenticates against the identity v2 endpoint.
 | 
			
		||||
func AuthenticateV2(client *gophercloud.ProviderClient, options gophercloud.AuthOptions, eo gophercloud.EndpointOpts) error {
 | 
			
		||||
	return v2auth(client, "", options, eo)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func v2auth(client *gophercloud.ProviderClient, endpoint string, options gophercloud.AuthOptions, eo gophercloud.EndpointOpts) error {
 | 
			
		||||
	v2Client, err := NewIdentityV2(client, eo)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if endpoint != "" {
 | 
			
		||||
		v2Client.Endpoint = endpoint
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	v2Opts := tokens2.AuthOptions{
 | 
			
		||||
		IdentityEndpoint: options.IdentityEndpoint,
 | 
			
		||||
		Username:         options.Username,
 | 
			
		||||
		Password:         options.Password,
 | 
			
		||||
		TenantID:         options.TenantID,
 | 
			
		||||
		TenantName:       options.TenantName,
 | 
			
		||||
		AllowReauth:      options.AllowReauth,
 | 
			
		||||
		TokenID:          options.TokenID,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	result := tokens2.Create(v2Client, v2Opts)
 | 
			
		||||
 | 
			
		||||
	token, err := result.ExtractToken()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	catalog, err := result.ExtractServiceCatalog()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if options.AllowReauth {
 | 
			
		||||
		client.ReauthFunc = func() error {
 | 
			
		||||
			client.TokenID = ""
 | 
			
		||||
			return v2auth(client, endpoint, options, eo)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	client.TokenID = token.ID
 | 
			
		||||
	client.EndpointLocator = func(opts gophercloud.EndpointOpts) (string, error) {
 | 
			
		||||
		return V2EndpointURL(catalog, opts)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// AuthenticateV3 explicitly authenticates against the identity v3 service.
 | 
			
		||||
func AuthenticateV3(client *gophercloud.ProviderClient, options tokens3.AuthOptionsBuilder, eo gophercloud.EndpointOpts) error {
 | 
			
		||||
	return v3auth(client, "", options, eo)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func v3auth(client *gophercloud.ProviderClient, endpoint string, opts tokens3.AuthOptionsBuilder, eo gophercloud.EndpointOpts) error {
 | 
			
		||||
	// Override the generated service endpoint with the one returned by the version endpoint.
 | 
			
		||||
	v3Client, err := NewIdentityV3(client, eo)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if endpoint != "" {
 | 
			
		||||
		v3Client.Endpoint = endpoint
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	result := tokens3.Create(v3Client, opts)
 | 
			
		||||
 | 
			
		||||
	token, err := result.ExtractToken()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	catalog, err := result.ExtractServiceCatalog()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	client.TokenID = token.ID
 | 
			
		||||
 | 
			
		||||
	if opts.CanReauth() {
 | 
			
		||||
		client.ReauthFunc = func() error {
 | 
			
		||||
			client.TokenID = ""
 | 
			
		||||
			return v3auth(client, endpoint, opts, eo)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	client.EndpointLocator = func(opts gophercloud.EndpointOpts) (string, error) {
 | 
			
		||||
		return V3EndpointURL(catalog, opts)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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/"
 | 
			
		||||
	var err error
 | 
			
		||||
	if !reflect.DeepEqual(eo, gophercloud.EndpointOpts{}) {
 | 
			
		||||
		eo.ApplyDefaults("identity")
 | 
			
		||||
		endpoint, err = client.EndpointLocator(eo)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return &gophercloud.ServiceClient{
 | 
			
		||||
		ProviderClient: client,
 | 
			
		||||
		Endpoint:       endpoint,
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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/"
 | 
			
		||||
	var err error
 | 
			
		||||
	if !reflect.DeepEqual(eo, gophercloud.EndpointOpts{}) {
 | 
			
		||||
		eo.ApplyDefaults("identity")
 | 
			
		||||
		endpoint, err = client.EndpointLocator(eo)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return &gophercloud.ServiceClient{
 | 
			
		||||
		ProviderClient: client,
 | 
			
		||||
		Endpoint:       endpoint,
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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) {
 | 
			
		||||
	eo.ApplyDefaults("object-store")
 | 
			
		||||
	url, err := client.EndpointLocator(eo)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewComputeV2 creates a ServiceClient that may be used with the v2 compute package.
 | 
			
		||||
func NewComputeV2(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
 | 
			
		||||
	eo.ApplyDefaults("compute")
 | 
			
		||||
	url, err := client.EndpointLocator(eo)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewNetworkV2 creates a ServiceClient that may be used with the v2 network package.
 | 
			
		||||
func NewNetworkV2(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
 | 
			
		||||
	eo.ApplyDefaults("network")
 | 
			
		||||
	url, err := client.EndpointLocator(eo)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return &gophercloud.ServiceClient{
 | 
			
		||||
		ProviderClient: client,
 | 
			
		||||
		Endpoint:       url,
 | 
			
		||||
		ResourceBase:   url + "v2.0/",
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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) {
 | 
			
		||||
	eo.ApplyDefaults("volume")
 | 
			
		||||
	url, err := client.EndpointLocator(eo)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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) {
 | 
			
		||||
	eo.ApplyDefaults("volumev2")
 | 
			
		||||
	url, err := client.EndpointLocator(eo)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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) {
 | 
			
		||||
	eo.ApplyDefaults("sharev2")
 | 
			
		||||
	url, err := client.EndpointLocator(eo)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewCDNV1 creates a ServiceClient that may be used to access the OpenStack v1
 | 
			
		||||
// CDN service.
 | 
			
		||||
func NewCDNV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
 | 
			
		||||
	eo.ApplyDefaults("cdn")
 | 
			
		||||
	url, err := client.EndpointLocator(eo)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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) {
 | 
			
		||||
	eo.ApplyDefaults("orchestration")
 | 
			
		||||
	url, err := client.EndpointLocator(eo)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewDBV1 creates a ServiceClient that may be used to access the v1 DB service.
 | 
			
		||||
func NewDBV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
 | 
			
		||||
	eo.ApplyDefaults("database")
 | 
			
		||||
	url, err := client.EndpointLocator(eo)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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) {
 | 
			
		||||
	eo.ApplyDefaults("image")
 | 
			
		||||
	url, err := client.EndpointLocator(eo)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return &gophercloud.ServiceClient{ProviderClient: client,
 | 
			
		||||
		Endpoint:     url,
 | 
			
		||||
		ResourceBase: url + "v2/"}, nil
 | 
			
		||||
}
 | 
			
		||||
@@ -1,15 +1,14 @@
 | 
			
		||||
package extensions
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/rackspace/gophercloud"
 | 
			
		||||
	"github.com/rackspace/gophercloud/pagination"
 | 
			
		||||
	"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) GetResult {
 | 
			
		||||
	var res GetResult
 | 
			
		||||
	_, res.Err = c.Get(ExtensionURL(c, alias), &res.Body, nil)
 | 
			
		||||
	return res
 | 
			
		||||
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.
 | 
			
		||||
@@ -1,9 +1,8 @@
 | 
			
		||||
package extensions
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/mitchellh/mapstructure"
 | 
			
		||||
	"github.com/rackspace/gophercloud"
 | 
			
		||||
	"github.com/rackspace/gophercloud/pagination"
 | 
			
		||||
	"github.com/gophercloud/gophercloud"
 | 
			
		||||
	"github.com/gophercloud/gophercloud/pagination"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// GetResult temporarily stores the result of a Get call.
 | 
			
		||||
@@ -14,27 +13,21 @@ type GetResult struct {
 | 
			
		||||
 | 
			
		||||
// Extract interprets a GetResult as an Extension.
 | 
			
		||||
func (r GetResult) Extract() (*Extension, error) {
 | 
			
		||||
	if r.Err != nil {
 | 
			
		||||
		return nil, r.Err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var res struct {
 | 
			
		||||
	var s struct {
 | 
			
		||||
		Extension *Extension `json:"extension"`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err := mapstructure.Decode(r.Body, &res)
 | 
			
		||||
 | 
			
		||||
	return res.Extension, err
 | 
			
		||||
	err := r.ExtractInto(&s)
 | 
			
		||||
	return s.Extension, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Extension is a struct that represents an OpenStack extension.
 | 
			
		||||
type Extension struct {
 | 
			
		||||
	Updated     string        `json:"updated" mapstructure:"updated"`
 | 
			
		||||
	Name        string        `json:"name" mapstructure:"name"`
 | 
			
		||||
	Links       []interface{} `json:"links" mapstructure:"links"`
 | 
			
		||||
	Namespace   string        `json:"namespace" mapstructure:"namespace"`
 | 
			
		||||
	Alias       string        `json:"alias" mapstructure:"alias"`
 | 
			
		||||
	Description string        `json:"description" mapstructure:"description"`
 | 
			
		||||
	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.
 | 
			
		||||
@@ -45,21 +38,16 @@ type ExtensionPage struct {
 | 
			
		||||
// IsEmpty checks whether an ExtensionPage struct is empty.
 | 
			
		||||
func (r ExtensionPage) IsEmpty() (bool, error) {
 | 
			
		||||
	is, err := ExtractExtensions(r)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return true, err
 | 
			
		||||
	}
 | 
			
		||||
	return len(is) == 0, nil
 | 
			
		||||
	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(page pagination.Page) ([]Extension, error) {
 | 
			
		||||
	var resp struct {
 | 
			
		||||
		Extensions []Extension `mapstructure:"extensions"`
 | 
			
		||||
func ExtractExtensions(r pagination.Page) ([]Extension, error) {
 | 
			
		||||
	var s struct {
 | 
			
		||||
		Extensions []Extension `json:"extensions"`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err := mapstructure.Decode(page.(ExtensionPage).Body, &resp)
 | 
			
		||||
 | 
			
		||||
	return resp.Extensions, err
 | 
			
		||||
	err := (r.(ExtensionPage)).ExtractInto(&s)
 | 
			
		||||
	return s.Extensions, err
 | 
			
		||||
}
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
package extensions
 | 
			
		||||
 | 
			
		||||
import "github.com/rackspace/gophercloud"
 | 
			
		||||
import "github.com/gophercloud/gophercloud"
 | 
			
		||||
 | 
			
		||||
// ExtensionURL generates the URL for an extension resource by name.
 | 
			
		||||
func ExtensionURL(c *gophercloud.ServiceClient, name string) string {
 | 
			
		||||
							
								
								
									
										3
									
								
								vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/volumeattach/doc.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/volumeattach/doc.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
			
		||||
// Package volumeattach provides the ability to attach and detach volumes
 | 
			
		||||
// to instances
 | 
			
		||||
package volumeattach
 | 
			
		||||
							
								
								
									
										57
									
								
								vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/volumeattach/requests.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/volumeattach/requests.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,57 @@
 | 
			
		||||
package volumeattach
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/gophercloud/gophercloud"
 | 
			
		||||
	"github.com/gophercloud/gophercloud/pagination"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// List returns a Pager that allows you to iterate over a collection of VolumeAttachments.
 | 
			
		||||
func List(client *gophercloud.ServiceClient, serverID string) pagination.Pager {
 | 
			
		||||
	return pagination.NewPager(client, listURL(client, serverID), func(r pagination.PageResult) pagination.Page {
 | 
			
		||||
		return VolumeAttachmentPage{pagination.SinglePageBase(r)}
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CreateOptsBuilder describes struct types that can be accepted by the Create call. Notable, the
 | 
			
		||||
// CreateOpts struct in this package does.
 | 
			
		||||
type CreateOptsBuilder interface {
 | 
			
		||||
	ToVolumeAttachmentCreateMap() (map[string]interface{}, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CreateOpts specifies volume attachment creation or import parameters.
 | 
			
		||||
type CreateOpts struct {
 | 
			
		||||
	// Device is the device that the volume will attach to the instance as. Omit for "auto"
 | 
			
		||||
	Device string `json:"device,omitempty"`
 | 
			
		||||
	// VolumeID is the ID of the volume to attach to the instance
 | 
			
		||||
	VolumeID string `json:"volumeId" required:"true"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ToVolumeAttachmentCreateMap constructs a request body from CreateOpts.
 | 
			
		||||
func (opts CreateOpts) ToVolumeAttachmentCreateMap() (map[string]interface{}, error) {
 | 
			
		||||
	return gophercloud.BuildRequestBody(opts, "volumeAttachment")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Create requests the creation of a new volume attachment on the server
 | 
			
		||||
func Create(client *gophercloud.ServiceClient, serverID string, opts CreateOptsBuilder) (r CreateResult) {
 | 
			
		||||
	b, err := opts.ToVolumeAttachmentCreateMap()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		r.Err = err
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	_, r.Err = client.Post(createURL(client, serverID), b, &r.Body, &gophercloud.RequestOpts{
 | 
			
		||||
		OkCodes: []int{200},
 | 
			
		||||
	})
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Get returns public data about a previously created VolumeAttachment.
 | 
			
		||||
func Get(client *gophercloud.ServiceClient, serverID, attachmentID string) (r GetResult) {
 | 
			
		||||
	_, r.Err = client.Get(getURL(client, serverID, attachmentID), &r.Body, nil)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Delete requests the deletion of a previous stored VolumeAttachment from the server.
 | 
			
		||||
func Delete(client *gophercloud.ServiceClient, serverID, attachmentID string) (r DeleteResult) {
 | 
			
		||||
	_, r.Err = client.Delete(deleteURL(client, serverID, attachmentID), nil)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										76
									
								
								vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/volumeattach/results.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/volumeattach/results.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,76 @@
 | 
			
		||||
package volumeattach
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/gophercloud/gophercloud"
 | 
			
		||||
	"github.com/gophercloud/gophercloud/pagination"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// VolumeAttachment controls the attachment of a volume to an instance.
 | 
			
		||||
type VolumeAttachment struct {
 | 
			
		||||
	// ID is a unique id of the attachment
 | 
			
		||||
	ID string `json:"id"`
 | 
			
		||||
 | 
			
		||||
	// Device is what device the volume is attached as
 | 
			
		||||
	Device string `json:"device"`
 | 
			
		||||
 | 
			
		||||
	// VolumeID is the ID of the attached volume
 | 
			
		||||
	VolumeID string `json:"volumeId"`
 | 
			
		||||
 | 
			
		||||
	// ServerID is the ID of the instance that has the volume attached
 | 
			
		||||
	ServerID string `json:"serverId"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// VolumeAttachmentPage stores a single, only page of VolumeAttachments
 | 
			
		||||
// results from a List call.
 | 
			
		||||
type VolumeAttachmentPage struct {
 | 
			
		||||
	pagination.SinglePageBase
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IsEmpty determines whether or not a VolumeAttachmentsPage is empty.
 | 
			
		||||
func (page VolumeAttachmentPage) IsEmpty() (bool, error) {
 | 
			
		||||
	va, err := ExtractVolumeAttachments(page)
 | 
			
		||||
	return len(va) == 0, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ExtractVolumeAttachments interprets a page of results as a slice of
 | 
			
		||||
// VolumeAttachments.
 | 
			
		||||
func ExtractVolumeAttachments(r pagination.Page) ([]VolumeAttachment, error) {
 | 
			
		||||
	var s struct {
 | 
			
		||||
		VolumeAttachments []VolumeAttachment `json:"volumeAttachments"`
 | 
			
		||||
	}
 | 
			
		||||
	err := (r.(VolumeAttachmentPage)).ExtractInto(&s)
 | 
			
		||||
	return s.VolumeAttachments, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// VolumeAttachmentResult is the result from a volume attachment operation.
 | 
			
		||||
type VolumeAttachmentResult struct {
 | 
			
		||||
	gophercloud.Result
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Extract is a method that attempts to interpret any VolumeAttachment resource
 | 
			
		||||
// response as a VolumeAttachment struct.
 | 
			
		||||
func (r VolumeAttachmentResult) Extract() (*VolumeAttachment, error) {
 | 
			
		||||
	var s struct {
 | 
			
		||||
		VolumeAttachment *VolumeAttachment `json:"volumeAttachment"`
 | 
			
		||||
	}
 | 
			
		||||
	err := r.ExtractInto(&s)
 | 
			
		||||
	return s.VolumeAttachment, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CreateResult is the response from a Create operation. Call its Extract method to interpret it
 | 
			
		||||
// as a VolumeAttachment.
 | 
			
		||||
type CreateResult struct {
 | 
			
		||||
	VolumeAttachmentResult
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetResult is the response from a Get operation. Call its Extract method to interpret it
 | 
			
		||||
// as a VolumeAttachment.
 | 
			
		||||
type GetResult struct {
 | 
			
		||||
	VolumeAttachmentResult
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeleteResult is the response from a Delete operation. Call its Extract method to determine if
 | 
			
		||||
// the call succeeded or failed.
 | 
			
		||||
type DeleteResult struct {
 | 
			
		||||
	gophercloud.ErrResult
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										25
									
								
								vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/volumeattach/urls.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/volumeattach/urls.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,25 @@
 | 
			
		||||
package volumeattach
 | 
			
		||||
 | 
			
		||||
import "github.com/gophercloud/gophercloud"
 | 
			
		||||
 | 
			
		||||
const resourcePath = "os-volume_attachments"
 | 
			
		||||
 | 
			
		||||
func resourceURL(c *gophercloud.ServiceClient, serverID string) string {
 | 
			
		||||
	return c.ServiceURL("servers", serverID, resourcePath)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func listURL(c *gophercloud.ServiceClient, serverID string) string {
 | 
			
		||||
	return resourceURL(c, serverID)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func createURL(c *gophercloud.ServiceClient, serverID string) string {
 | 
			
		||||
	return resourceURL(c, serverID)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func getURL(c *gophercloud.ServiceClient, serverID, aID string) string {
 | 
			
		||||
	return c.ServiceURL("servers", serverID, resourcePath, aID)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func deleteURL(c *gophercloud.ServiceClient, serverID, aID string) string {
 | 
			
		||||
	return getURL(c, serverID, aID)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										7
									
								
								vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/flavors/doc.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/flavors/doc.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,7 @@
 | 
			
		||||
// 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
 | 
			
		||||
							
								
								
									
										100
									
								
								vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/flavors/requests.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										100
									
								
								vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/flavors/requests.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,100 @@
 | 
			
		||||
package flavors
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/gophercloud/gophercloud"
 | 
			
		||||
	"github.com/gophercloud/gophercloud/pagination"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// ListOptsBuilder allows extensions to add additional parameters to the
 | 
			
		||||
// List request.
 | 
			
		||||
type ListOptsBuilder interface {
 | 
			
		||||
	ToFlavorListQuery() (string, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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 {
 | 
			
		||||
 | 
			
		||||
	// 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 int `q:"minDisk"`
 | 
			
		||||
	MinRAM  int `q:"minRam"`
 | 
			
		||||
 | 
			
		||||
	// Marker and Limit control paging.
 | 
			
		||||
	// 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 int `q:"limit"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ToFlavorListQuery formats a ListOpts into a query string.
 | 
			
		||||
func (opts ListOpts) ToFlavorListQuery() (string, error) {
 | 
			
		||||
	q, err := gophercloud.BuildQueryString(opts)
 | 
			
		||||
	return q.String(), err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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.
 | 
			
		||||
func ListDetail(client *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager {
 | 
			
		||||
	url := listURL(client)
 | 
			
		||||
	if opts != nil {
 | 
			
		||||
		query, err := opts.ToFlavorListQuery()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return pagination.Pager{Err: err}
 | 
			
		||||
		}
 | 
			
		||||
		url += query
 | 
			
		||||
	}
 | 
			
		||||
	return pagination.NewPager(client, url, func(r pagination.PageResult) pagination.Page {
 | 
			
		||||
		return FlavorPage{pagination.LinkedPageBase{PageResult: r}}
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Get instructs OpenStack to provide details on a single flavor, identified by its ID.
 | 
			
		||||
// 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.
 | 
			
		||||
func IDFromName(client *gophercloud.ServiceClient, name string) (string, error) {
 | 
			
		||||
	count := 0
 | 
			
		||||
	id := ""
 | 
			
		||||
	allPages, err := ListDetail(client, nil).AllPages()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	all, err := ExtractFlavors(allPages)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, f := range all {
 | 
			
		||||
		if f.Name == name {
 | 
			
		||||
			count++
 | 
			
		||||
			id = f.ID
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	switch count {
 | 
			
		||||
	case 0:
 | 
			
		||||
		err := &gophercloud.ErrResourceNotFound{}
 | 
			
		||||
		err.ResourceType = "flavor"
 | 
			
		||||
		err.Name = name
 | 
			
		||||
		return "", err
 | 
			
		||||
	case 1:
 | 
			
		||||
		return id, nil
 | 
			
		||||
	default:
 | 
			
		||||
		err := &gophercloud.ErrMultipleResourcesFound{}
 | 
			
		||||
		err.ResourceType = "flavor"
 | 
			
		||||
		err.Name = name
 | 
			
		||||
		err.Count = count
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										114
									
								
								vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/flavors/results.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										114
									
								
								vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/flavors/results.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,114 @@
 | 
			
		||||
package flavors
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"strconv"
 | 
			
		||||
 | 
			
		||||
	"github.com/gophercloud/gophercloud"
 | 
			
		||||
	"github.com/gophercloud/gophercloud/pagination"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// GetResult temporarily holds the response from a Get call.
 | 
			
		||||
type GetResult struct {
 | 
			
		||||
	gophercloud.Result
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Extract provides access to the individual Flavor returned by the Get function.
 | 
			
		||||
func (r GetResult) Extract() (*Flavor, error) {
 | 
			
		||||
	var s struct {
 | 
			
		||||
		Flavor *Flavor `json:"flavor"`
 | 
			
		||||
	}
 | 
			
		||||
	err := r.ExtractInto(&s)
 | 
			
		||||
	return s.Flavor, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Flavor records 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 string `json:"id"`
 | 
			
		||||
	// The Disk and RA< fields provide a measure of storage space offered by the flavor, in GB and MB, respectively.
 | 
			
		||||
	Disk int `json:"disk"`
 | 
			
		||||
	RAM  int `json:"ram"`
 | 
			
		||||
	// The Name field provides a human-readable moniker for the flavor.
 | 
			
		||||
	Name       string  `json:"name"`
 | 
			
		||||
	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 int `json:"swap"`
 | 
			
		||||
	// VCPUs indicates how many (virtual) CPUs are available for this flavor.
 | 
			
		||||
	VCPUs int `json:"vcpus"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (f *Flavor) UnmarshalJSON(b []byte) error {
 | 
			
		||||
	var flavor struct {
 | 
			
		||||
		ID         string      `json:"id"`
 | 
			
		||||
		Disk       int         `json:"disk"`
 | 
			
		||||
		RAM        int         `json:"ram"`
 | 
			
		||||
		Name       string      `json:"name"`
 | 
			
		||||
		RxTxFactor float64     `json:"rxtx_factor"`
 | 
			
		||||
		Swap       interface{} `json:"swap"`
 | 
			
		||||
		VCPUs      int         `json:"vcpus"`
 | 
			
		||||
	}
 | 
			
		||||
	err := json.Unmarshal(b, &flavor)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	f.ID = flavor.ID
 | 
			
		||||
	f.Disk = flavor.Disk
 | 
			
		||||
	f.RAM = flavor.RAM
 | 
			
		||||
	f.Name = flavor.Name
 | 
			
		||||
	f.RxTxFactor = flavor.RxTxFactor
 | 
			
		||||
	f.VCPUs = flavor.VCPUs
 | 
			
		||||
 | 
			
		||||
	switch t := flavor.Swap.(type) {
 | 
			
		||||
	case float64:
 | 
			
		||||
		f.Swap = int(t)
 | 
			
		||||
	case string:
 | 
			
		||||
		switch t {
 | 
			
		||||
		case "":
 | 
			
		||||
			f.Swap = 0
 | 
			
		||||
		default:
 | 
			
		||||
			swap, err := strconv.ParseFloat(t, 64)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
			f.Swap = int(swap)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// FlavorPage contains a single page of the response from a List call.
 | 
			
		||||
type FlavorPage struct {
 | 
			
		||||
	pagination.LinkedPageBase
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IsEmpty determines if a page 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.
 | 
			
		||||
func (page FlavorPage) NextPageURL() (string, error) {
 | 
			
		||||
	var s struct {
 | 
			
		||||
		Links []gophercloud.Link `json:"flavors_links"`
 | 
			
		||||
	}
 | 
			
		||||
	err := page.ExtractInto(&s)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
	return gophercloud.ExtractNextURL(s.Links)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ExtractFlavors provides access to the list of flavors in a page acquired from the List operation.
 | 
			
		||||
func ExtractFlavors(r pagination.Page) ([]Flavor, error) {
 | 
			
		||||
	var s struct {
 | 
			
		||||
		Flavors []Flavor `json:"flavors"`
 | 
			
		||||
	}
 | 
			
		||||
	err := (r.(FlavorPage)).ExtractInto(&s)
 | 
			
		||||
	return s.Flavors, err
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										13
									
								
								vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/flavors/urls.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/flavors/urls.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
			
		||||
package flavors
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/gophercloud/gophercloud"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func getURL(client *gophercloud.ServiceClient, id string) string {
 | 
			
		||||
	return client.ServiceURL("flavors", id)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func listURL(client *gophercloud.ServiceClient) string {
 | 
			
		||||
	return client.ServiceURL("flavors", "detail")
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										7
									
								
								vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/images/doc.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/images/doc.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,7 @@
 | 
			
		||||
// 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
 | 
			
		||||
							
								
								
									
										102
									
								
								vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/images/requests.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										102
									
								
								vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/images/requests.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,102 @@
 | 
			
		||||
package images
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/gophercloud/gophercloud"
 | 
			
		||||
	"github.com/gophercloud/gophercloud/pagination"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// ListOptsBuilder allows extensions to add additional parameters to the
 | 
			
		||||
// List request.
 | 
			
		||||
type ListOptsBuilder interface {
 | 
			
		||||
	ToImageListQuery() (string, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ListOpts contain options for limiting the number of Images returned from a call to ListDetail.
 | 
			
		||||
type ListOpts struct {
 | 
			
		||||
	// When the image last changed status (in date-time format).
 | 
			
		||||
	ChangesSince string `q:"changes-since"`
 | 
			
		||||
	// The number of Images to return.
 | 
			
		||||
	Limit int `q:"limit"`
 | 
			
		||||
	// UUID of the Image at which to set a marker.
 | 
			
		||||
	Marker string `q:"marker"`
 | 
			
		||||
	// The name of the Image.
 | 
			
		||||
	Name string `q:"name"`
 | 
			
		||||
	// The name of the Server (in URL format).
 | 
			
		||||
	Server string `q:"server"`
 | 
			
		||||
	// The current status of the Image.
 | 
			
		||||
	Status string `q:"status"`
 | 
			
		||||
	// The value of the type of image (e.g. BASE, SERVER, ALL)
 | 
			
		||||
	Type string `q:"type"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ToImageListQuery formats a ListOpts into a query string.
 | 
			
		||||
func (opts ListOpts) ToImageListQuery() (string, error) {
 | 
			
		||||
	q, err := gophercloud.BuildQueryString(opts)
 | 
			
		||||
	return q.String(), err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ListDetail enumerates the available images.
 | 
			
		||||
func ListDetail(client *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager {
 | 
			
		||||
	url := listDetailURL(client)
 | 
			
		||||
	if opts != nil {
 | 
			
		||||
		query, err := opts.ToImageListQuery()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return pagination.Pager{Err: err}
 | 
			
		||||
		}
 | 
			
		||||
		url += query
 | 
			
		||||
	}
 | 
			
		||||
	return pagination.NewPager(client, url, func(r pagination.PageResult) pagination.Page {
 | 
			
		||||
		return ImagePage{pagination.LinkedPageBase{PageResult: r}}
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Get acquires additional detail about a specific image by ID.
 | 
			
		||||
// Use ExtractImage() to interpret the result as an openstack Image.
 | 
			
		||||
func Get(client *gophercloud.ServiceClient, id string) (r GetResult) {
 | 
			
		||||
	_, r.Err = client.Get(getURL(client, id), &r.Body, nil)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Delete deletes the specified image ID.
 | 
			
		||||
func Delete(client *gophercloud.ServiceClient, id string) (r DeleteResult) {
 | 
			
		||||
	_, r.Err = client.Delete(deleteURL(client, id), nil)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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 := ""
 | 
			
		||||
	allPages, err := ListDetail(client, nil).AllPages()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	all, err := ExtractImages(allPages)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, f := range all {
 | 
			
		||||
		if f.Name == name {
 | 
			
		||||
			count++
 | 
			
		||||
			id = f.ID
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	switch count {
 | 
			
		||||
	case 0:
 | 
			
		||||
		err := &gophercloud.ErrResourceNotFound{}
 | 
			
		||||
		err.ResourceType = "image"
 | 
			
		||||
		err.Name = name
 | 
			
		||||
		return "", err
 | 
			
		||||
	case 1:
 | 
			
		||||
		return id, nil
 | 
			
		||||
	default:
 | 
			
		||||
		err := &gophercloud.ErrMultipleResourcesFound{}
 | 
			
		||||
		err.ResourceType = "image"
 | 
			
		||||
		err.Name = name
 | 
			
		||||
		err.Count = count
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										83
									
								
								vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/images/results.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/images/results.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,83 @@
 | 
			
		||||
package images
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/gophercloud/gophercloud"
 | 
			
		||||
	"github.com/gophercloud/gophercloud/pagination"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// GetResult temporarily stores a Get response.
 | 
			
		||||
type GetResult struct {
 | 
			
		||||
	gophercloud.Result
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeleteResult represents the result of an image.Delete operation.
 | 
			
		||||
type DeleteResult struct {
 | 
			
		||||
	gophercloud.ErrResult
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Extract interprets a GetResult as an Image.
 | 
			
		||||
func (r GetResult) Extract() (*Image, error) {
 | 
			
		||||
	var s struct {
 | 
			
		||||
		Image *Image `json:"image"`
 | 
			
		||||
	}
 | 
			
		||||
	err := r.ExtractInto(&s)
 | 
			
		||||
	return s.Image, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Image is used for JSON (un)marshalling.
 | 
			
		||||
// It provides a description of an OS image.
 | 
			
		||||
type Image struct {
 | 
			
		||||
	// ID contains the image's unique identifier.
 | 
			
		||||
	ID string
 | 
			
		||||
 | 
			
		||||
	Created string
 | 
			
		||||
 | 
			
		||||
	// MinDisk and MinRAM specify the minimum resources a server must provide to be able to install the image.
 | 
			
		||||
	MinDisk int
 | 
			
		||||
	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
 | 
			
		||||
 | 
			
		||||
	Updated string
 | 
			
		||||
	
 | 
			
		||||
	Metadata map[string]string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ImagePage contains a single page of results from a List 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.
 | 
			
		||||
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.
 | 
			
		||||
func (page ImagePage) NextPageURL() (string, error) {
 | 
			
		||||
	var s struct {
 | 
			
		||||
		Links []gophercloud.Link `json:"images_links"`
 | 
			
		||||
	}
 | 
			
		||||
	err := page.ExtractInto(&s)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
	return gophercloud.ExtractNextURL(s.Links)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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"`
 | 
			
		||||
	}
 | 
			
		||||
	err := (r.(ImagePage)).ExtractInto(&s)
 | 
			
		||||
	return s.Images, err
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										15
									
								
								vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/images/urls.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/images/urls.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,15 @@
 | 
			
		||||
package images
 | 
			
		||||
 | 
			
		||||
import "github.com/gophercloud/gophercloud"
 | 
			
		||||
 | 
			
		||||
func listDetailURL(client *gophercloud.ServiceClient) string {
 | 
			
		||||
	return client.ServiceURL("images", "detail")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func getURL(client *gophercloud.ServiceClient, id string) string {
 | 
			
		||||
	return client.ServiceURL("images", id)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func deleteURL(client *gophercloud.ServiceClient, id string) string {
 | 
			
		||||
	return client.ServiceURL("images", id)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										6
									
								
								vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/servers/doc.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/servers/doc.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,6 @@
 | 
			
		||||
// 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
 | 
			
		||||
							
								
								
									
										71
									
								
								vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/servers/errors.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/servers/errors.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,71 @@
 | 
			
		||||
package servers
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
 | 
			
		||||
	"github.com/gophercloud/gophercloud"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// ErrNeitherImageIDNorImageNameProvided is the error when neither the image
 | 
			
		||||
// ID nor the image name is provided for a server operation
 | 
			
		||||
type ErrNeitherImageIDNorImageNameProvided struct{ gophercloud.ErrMissingInput }
 | 
			
		||||
 | 
			
		||||
func (e ErrNeitherImageIDNorImageNameProvided) Error() string {
 | 
			
		||||
	return "One and only one of the image ID and the image name must be provided."
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ErrNeitherFlavorIDNorFlavorNameProvided is the error when neither the flavor
 | 
			
		||||
// ID nor the flavor name is provided for a server operation
 | 
			
		||||
type ErrNeitherFlavorIDNorFlavorNameProvided struct{ gophercloud.ErrMissingInput }
 | 
			
		||||
 | 
			
		||||
func (e ErrNeitherFlavorIDNorFlavorNameProvided) Error() string {
 | 
			
		||||
	return "One and only one of the flavor ID and the flavor name must be provided."
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type ErrNoClientProvidedForIDByName struct{ gophercloud.ErrMissingInput }
 | 
			
		||||
 | 
			
		||||
func (e ErrNoClientProvidedForIDByName) Error() string {
 | 
			
		||||
	return "A service client must be provided to find a resource ID by name."
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ErrInvalidHowParameterProvided is the error when an unknown value is given
 | 
			
		||||
// for the `how` argument
 | 
			
		||||
type ErrInvalidHowParameterProvided struct{ gophercloud.ErrInvalidInput }
 | 
			
		||||
 | 
			
		||||
// ErrNoAdminPassProvided is the error when an administrative password isn't
 | 
			
		||||
// provided for a server operation
 | 
			
		||||
type ErrNoAdminPassProvided struct{ gophercloud.ErrMissingInput }
 | 
			
		||||
 | 
			
		||||
// ErrNoImageIDProvided is the error when an image ID isn't provided for a server
 | 
			
		||||
// operation
 | 
			
		||||
type ErrNoImageIDProvided struct{ gophercloud.ErrMissingInput }
 | 
			
		||||
 | 
			
		||||
// ErrNoIDProvided is the error when a server ID isn't provided for a server
 | 
			
		||||
// operation
 | 
			
		||||
type ErrNoIDProvided struct{ gophercloud.ErrMissingInput }
 | 
			
		||||
 | 
			
		||||
// ErrServer is a generic error type for servers HTTP operations.
 | 
			
		||||
type ErrServer struct {
 | 
			
		||||
	gophercloud.ErrUnexpectedResponseCode
 | 
			
		||||
	ID string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (se ErrServer) Error() string {
 | 
			
		||||
	return fmt.Sprintf("Error while executing HTTP request for server [%s]", se.ID)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Error404 overrides the generic 404 error message.
 | 
			
		||||
func (se ErrServer) Error404(e gophercloud.ErrUnexpectedResponseCode) error {
 | 
			
		||||
	se.ErrUnexpectedResponseCode = e
 | 
			
		||||
	return &ErrServerNotFound{se}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ErrServerNotFound is the error when a 404 is received during server HTTP
 | 
			
		||||
// operations.
 | 
			
		||||
type ErrServerNotFound struct {
 | 
			
		||||
	ErrServer
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e ErrServerNotFound) Error() string {
 | 
			
		||||
	return fmt.Sprintf("I couldn't find server [%s]", e.ID)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										737
									
								
								vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/servers/requests.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										737
									
								
								vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/servers/requests.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,737 @@
 | 
			
		||||
package servers
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/base64"
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
 | 
			
		||||
	"github.com/gophercloud/gophercloud"
 | 
			
		||||
	"github.com/gophercloud/gophercloud/openstack/compute/v2/flavors"
 | 
			
		||||
	"github.com/gophercloud/gophercloud/openstack/compute/v2/images"
 | 
			
		||||
	"github.com/gophercloud/gophercloud/pagination"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// ListOptsBuilder allows extensions to add additional parameters to the
 | 
			
		||||
// List request.
 | 
			
		||||
type ListOptsBuilder interface {
 | 
			
		||||
	ToServerListQuery() (string, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ListOpts allows the filtering and sorting of paginated collections through
 | 
			
		||||
// 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.
 | 
			
		||||
type ListOpts struct {
 | 
			
		||||
	// A time/date stamp for when the server last changed status.
 | 
			
		||||
	ChangesSince string `q:"changes-since"`
 | 
			
		||||
 | 
			
		||||
	// Name of the image in URL format.
 | 
			
		||||
	Image string `q:"image"`
 | 
			
		||||
 | 
			
		||||
	// Name of the flavor in URL format.
 | 
			
		||||
	Flavor string `q:"flavor"`
 | 
			
		||||
 | 
			
		||||
	// 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
 | 
			
		||||
	// 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 string `q:"status"`
 | 
			
		||||
 | 
			
		||||
	// Name of the host as a string.
 | 
			
		||||
	Host string `q:"host"`
 | 
			
		||||
 | 
			
		||||
	// 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 int `q:"limit"`
 | 
			
		||||
 | 
			
		||||
	// Bool to show all tenants
 | 
			
		||||
	AllTenants bool `q:"all_tenants"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ToServerListQuery formats a ListOpts into a query string.
 | 
			
		||||
func (opts ListOpts) ToServerListQuery() (string, error) {
 | 
			
		||||
	q, err := gophercloud.BuildQueryString(opts)
 | 
			
		||||
	return q.String(), err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// List makes a request against the API to list servers accessible to you.
 | 
			
		||||
func List(client *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager {
 | 
			
		||||
	url := listDetailURL(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 ServerPage{pagination.LinkedPageBase{PageResult: r}}
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CreateOptsBuilder describes struct types that can be accepted by the Create call.
 | 
			
		||||
// The CreateOpts struct in this package does.
 | 
			
		||||
type CreateOptsBuilder interface {
 | 
			
		||||
	ToServerCreateMap() (map[string]interface{}, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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.
 | 
			
		||||
	// Required unless Port is provided.
 | 
			
		||||
	UUID string
 | 
			
		||||
 | 
			
		||||
	// Port of a neutron network to attach to the newly provisioned server.
 | 
			
		||||
	// Required unless UUID is provided.
 | 
			
		||||
	Port string
 | 
			
		||||
 | 
			
		||||
	// FixedIP [optional] 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.
 | 
			
		||||
type File struct {
 | 
			
		||||
	// Path of the file
 | 
			
		||||
	Path string
 | 
			
		||||
	// Contents of the file. Maximum content size is 255 bytes.
 | 
			
		||||
	Contents []byte
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// MarshalJSON marshals the escaped file, base64 encoding the contents.
 | 
			
		||||
func (f *File) MarshalJSON() ([]byte, error) {
 | 
			
		||||
	file := struct {
 | 
			
		||||
		Path     string `json:"path"`
 | 
			
		||||
		Contents string `json:"contents"`
 | 
			
		||||
	}{
 | 
			
		||||
		Path:     f.Path,
 | 
			
		||||
		Contents: base64.StdEncoding.EncodeToString(f.Contents),
 | 
			
		||||
	}
 | 
			
		||||
	return json.Marshal(file)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CreateOpts specifies server creation parameters.
 | 
			
		||||
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.
 | 
			
		||||
	// 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.
 | 
			
		||||
	// Also optional if using the boot-from-volume extension.
 | 
			
		||||
	ImageName string `json:"-"`
 | 
			
		||||
 | 
			
		||||
	// FlavorRef [optional; required if FlavorName is not provided] is the ID or
 | 
			
		||||
	// full URL to the flavor that describes the server's specs.
 | 
			
		||||
	FlavorRef string `json:"flavorRef"`
 | 
			
		||||
 | 
			
		||||
	// FlavorName [optional; required if FlavorRef is not provided] is the name of
 | 
			
		||||
	// 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 []string `json:"-"`
 | 
			
		||||
 | 
			
		||||
	// UserData contains configuration information or scripts to use upon launch.
 | 
			
		||||
	// Create will base64-encode it for you.
 | 
			
		||||
	UserData []byte `json:"-"`
 | 
			
		||||
 | 
			
		||||
	// AvailabilityZone in which to launch the server.
 | 
			
		||||
	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.
 | 
			
		||||
	Networks []Network `json:"-"`
 | 
			
		||||
 | 
			
		||||
	// 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.
 | 
			
		||||
	// Create will base64-encode file contents for you.
 | 
			
		||||
	Personality Personality `json:"-"`
 | 
			
		||||
 | 
			
		||||
	// ConfigDrive enables metadata injection through a configuration drive.
 | 
			
		||||
	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.
 | 
			
		||||
	AdminPass string `json:"adminPass,omitempty"`
 | 
			
		||||
 | 
			
		||||
	// AccessIPv4 specifies an IPv4 address for the instance.
 | 
			
		||||
	AccessIPv4 string `json:"accessIPv4,omitempty"`
 | 
			
		||||
 | 
			
		||||
	// AccessIPv6 pecifies an IPv6 address for the instance.
 | 
			
		||||
	AccessIPv6 string `json:"accessIPv6,omitempty"`
 | 
			
		||||
 | 
			
		||||
	// ServiceClient will allow calls to be made to retrieve an image or
 | 
			
		||||
	// flavor ID by name.
 | 
			
		||||
	ServiceClient *gophercloud.ServiceClient `json:"-"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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
 | 
			
		||||
	b, err := gophercloud.BuildRequestBody(opts, "")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if opts.UserData != nil {
 | 
			
		||||
		encoded := base64.StdEncoding.EncodeToString(opts.UserData)
 | 
			
		||||
		b["user_data"] = &encoded
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(opts.SecurityGroups) > 0 {
 | 
			
		||||
		securityGroups := make([]map[string]interface{}, len(opts.SecurityGroups))
 | 
			
		||||
		for i, groupName := range opts.SecurityGroups {
 | 
			
		||||
			securityGroups[i] = map[string]interface{}{"name": groupName}
 | 
			
		||||
		}
 | 
			
		||||
		b["security_groups"] = securityGroups
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(opts.Networks) > 0 {
 | 
			
		||||
		networks := make([]map[string]interface{}, len(opts.Networks))
 | 
			
		||||
		for i, net := range opts.Networks {
 | 
			
		||||
			networks[i] = make(map[string]interface{})
 | 
			
		||||
			if net.UUID != "" {
 | 
			
		||||
				networks[i]["uuid"] = net.UUID
 | 
			
		||||
			}
 | 
			
		||||
			if net.Port != "" {
 | 
			
		||||
				networks[i]["port"] = net.Port
 | 
			
		||||
			}
 | 
			
		||||
			if net.FixedIP != "" {
 | 
			
		||||
				networks[i]["fixed_ip"] = net.FixedIP
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		b["networks"] = networks
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// If ImageRef isn't provided, check if ImageName was provided to ascertain
 | 
			
		||||
	// the image ID.
 | 
			
		||||
	if opts.ImageRef == "" {
 | 
			
		||||
		if opts.ImageName != "" {
 | 
			
		||||
			if sc == nil {
 | 
			
		||||
				err := ErrNoClientProvidedForIDByName{}
 | 
			
		||||
				err.Argument = "ServiceClient"
 | 
			
		||||
				return nil, err
 | 
			
		||||
			}
 | 
			
		||||
			imageID, err := images.IDFromName(sc, opts.ImageName)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return nil, err
 | 
			
		||||
			}
 | 
			
		||||
			b["imageRef"] = imageID
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// If FlavorRef isn't provided, use FlavorName to ascertain the flavor ID.
 | 
			
		||||
	if opts.FlavorRef == "" {
 | 
			
		||||
		if opts.FlavorName == "" {
 | 
			
		||||
			err := ErrNeitherFlavorIDNorFlavorNameProvided{}
 | 
			
		||||
			err.Argument = "FlavorRef/FlavorName"
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		if sc == nil {
 | 
			
		||||
			err := ErrNoClientProvidedForIDByName{}
 | 
			
		||||
			err.Argument = "ServiceClient"
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		flavorID, err := flavors.IDFromName(sc, opts.FlavorName)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		b["flavorRef"] = flavorID
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return map[string]interface{}{"server": b}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Create requests a server to be provisioned to the user in the current tenant.
 | 
			
		||||
func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) (r CreateResult) {
 | 
			
		||||
	reqBody, err := opts.ToServerCreateMap()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		r.Err = err
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	_, r.Err = client.Post(listURL(client), reqBody, &r.Body, nil)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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
 | 
			
		||||
func ForceDelete(client *gophercloud.ServiceClient, id string) (r ActionResult) {
 | 
			
		||||
	_, r.Err = client.Post(actionURL(client, id), map[string]interface{}{"forceDelete": ""}, nil, nil)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Get requests details on a single server, by ID.
 | 
			
		||||
func Get(client *gophercloud.ServiceClient, id string) (r GetResult) {
 | 
			
		||||
	_, r.Err = client.Get(getURL(client, id), &r.Body, &gophercloud.RequestOpts{
 | 
			
		||||
		OkCodes: []int{200, 203},
 | 
			
		||||
	})
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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.
 | 
			
		||||
type UpdateOpts struct {
 | 
			
		||||
	// Name changes the displayed name of the server.
 | 
			
		||||
	// The server host name will *not* change.
 | 
			
		||||
	// Server names are not constrained to be unique, even within the same tenant.
 | 
			
		||||
	Name string `json:"name,omitempty"`
 | 
			
		||||
 | 
			
		||||
	// AccessIPv4 provides a new IPv4 address for the instance.
 | 
			
		||||
	AccessIPv4 string `json:"accessIPv4,omitempty"`
 | 
			
		||||
 | 
			
		||||
	// AccessIPv6 provides a new IPv6 address for the instance.
 | 
			
		||||
	AccessIPv6 string `json:"accessIPv6,omitempty"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ToServerUpdateMap formats an UpdateOpts structure into a request body.
 | 
			
		||||
func (opts UpdateOpts) ToServerUpdateMap() (map[string]interface{}, error) {
 | 
			
		||||
	return gophercloud.BuildRequestBody(opts, "server")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Update requests that various attributes of the indicated server be changed.
 | 
			
		||||
func Update(client *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) (r UpdateResult) {
 | 
			
		||||
	b, err := opts.ToServerUpdateMap()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		r.Err = err
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	_, r.Err = client.Put(updateURL(client, id), b, &r.Body, &gophercloud.RequestOpts{
 | 
			
		||||
		OkCodes: []int{200},
 | 
			
		||||
	})
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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{
 | 
			
		||||
			"adminPass": newPassword,
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	_, r.Err = client.Post(actionURL(client, id), b, nil, nil)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RebootMethod describes the mechanisms by which a server reboot can be requested.
 | 
			
		||||
type RebootMethod string
 | 
			
		||||
 | 
			
		||||
// These constants determine how a server should be rebooted.
 | 
			
		||||
// See the Reboot() function for further details.
 | 
			
		||||
const (
 | 
			
		||||
	SoftReboot RebootMethod = "SOFT"
 | 
			
		||||
	HardReboot RebootMethod = "HARD"
 | 
			
		||||
	OSReboot                = SoftReboot
 | 
			
		||||
	PowerCycle              = HardReboot
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// RebootOptsBuilder is an interface that options must satisfy in order to be
 | 
			
		||||
// used when rebooting a server instance
 | 
			
		||||
type RebootOptsBuilder interface {
 | 
			
		||||
	ToServerRebootMap() (map[string]interface{}, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RebootOpts satisfies the RebootOptsBuilder interface
 | 
			
		||||
type RebootOpts struct {
 | 
			
		||||
	Type RebootMethod `json:"type" required:"true"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ToServerRebootMap allows RebootOpts to satisfiy the RebootOptsBuilder
 | 
			
		||||
// interface
 | 
			
		||||
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.
 | 
			
		||||
func Reboot(client *gophercloud.ServiceClient, id string, opts RebootOptsBuilder) (r ActionResult) {
 | 
			
		||||
	b, err := opts.ToServerRebootMap()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		r.Err = err
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	_, r.Err = client.Post(actionURL(client, id), b, nil, nil)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RebuildOptsBuilder is an interface that allows extensions to override the
 | 
			
		||||
// default behaviour of rebuild options
 | 
			
		||||
type RebuildOptsBuilder interface {
 | 
			
		||||
	ToServerRebuildMap() (map[string]interface{}, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RebuildOpts represents the configuration options used in a server rebuild
 | 
			
		||||
// operation
 | 
			
		||||
type RebuildOpts struct {
 | 
			
		||||
	// The server's admin password
 | 
			
		||||
	AdminPass string `json:"adminPass" required:"true"`
 | 
			
		||||
	// The ID of the image you want your server to be provisioned on
 | 
			
		||||
	ImageID   string `json:"imageRef"`
 | 
			
		||||
	ImageName string `json:"-"`
 | 
			
		||||
	//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 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"`
 | 
			
		||||
	ServiceClient *gophercloud.ServiceClient `json:"-"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ToServerRebuildMap formats a RebuildOpts struct into a map for use in JSON
 | 
			
		||||
func (opts RebuildOpts) ToServerRebuildMap() (map[string]interface{}, error) {
 | 
			
		||||
	b, err := gophercloud.BuildRequestBody(opts, "")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// If ImageRef isn't provided, check if ImageName was provided to ascertain
 | 
			
		||||
	// the image ID.
 | 
			
		||||
	if opts.ImageID == "" {
 | 
			
		||||
		if opts.ImageName != "" {
 | 
			
		||||
			if opts.ServiceClient == nil {
 | 
			
		||||
				err := ErrNoClientProvidedForIDByName{}
 | 
			
		||||
				err.Argument = "ServiceClient"
 | 
			
		||||
				return nil, err
 | 
			
		||||
			}
 | 
			
		||||
			imageID, err := images.IDFromName(opts.ServiceClient, opts.ImageName)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return nil, err
 | 
			
		||||
			}
 | 
			
		||||
			b["imageRef"] = imageID
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return map[string]interface{}{"rebuild": b}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Rebuild will reprovision the server according to the configuration options
 | 
			
		||||
// provided in the RebuildOpts struct.
 | 
			
		||||
func Rebuild(client *gophercloud.ServiceClient, id string, opts RebuildOptsBuilder) (r RebuildResult) {
 | 
			
		||||
	b, err := opts.ToServerRebuildMap()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		r.Err = err
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	_, r.Err = client.Post(actionURL(client, id), b, &r.Body, nil)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ResizeOptsBuilder is an interface that allows extensions to override the default structure of
 | 
			
		||||
// a Resize request.
 | 
			
		||||
type ResizeOptsBuilder interface {
 | 
			
		||||
	ToServerResizeMap() (map[string]interface{}, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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.
 | 
			
		||||
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.
 | 
			
		||||
func Resize(client *gophercloud.ServiceClient, id string, opts ResizeOptsBuilder) (r ActionResult) {
 | 
			
		||||
	b, err := opts.ToServerResizeMap()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		r.Err = err
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	_, r.Err = client.Post(actionURL(client, id), b, nil, nil)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ConfirmResize confirms a previous resize operation on a server.
 | 
			
		||||
// See Resize() for more details.
 | 
			
		||||
func ConfirmResize(client *gophercloud.ServiceClient, id string) (r ActionResult) {
 | 
			
		||||
	_, r.Err = client.Post(actionURL(client, id), map[string]interface{}{"confirmResize": nil}, nil, &gophercloud.RequestOpts{
 | 
			
		||||
		OkCodes: []int{201, 202, 204},
 | 
			
		||||
	})
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RevertResize cancels a previous resize operation on a server.
 | 
			
		||||
// See Resize() for more details.
 | 
			
		||||
func RevertResize(client *gophercloud.ServiceClient, id string) (r ActionResult) {
 | 
			
		||||
	_, r.Err = client.Post(actionURL(client, id), map[string]interface{}{"revertResize": nil}, nil, nil)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RescueOptsBuilder is an interface that allows extensions to override the
 | 
			
		||||
// default structure of a Rescue request.
 | 
			
		||||
type RescueOptsBuilder interface {
 | 
			
		||||
	ToServerRescueMap() (map[string]interface{}, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RescueOpts represents the configuration options used to control a Rescue
 | 
			
		||||
// option.
 | 
			
		||||
type RescueOpts struct {
 | 
			
		||||
	// AdminPass is the desired administrative password for the instance in
 | 
			
		||||
	// RESCUE mode. If it's left blank, the server will generate a password.
 | 
			
		||||
	AdminPass string `json:"adminPass,omitempty"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ToServerRescueMap formats a RescueOpts as a map that can be used as a JSON
 | 
			
		||||
// request body for the Rescue request.
 | 
			
		||||
func (opts RescueOpts) ToServerRescueMap() (map[string]interface{}, error) {
 | 
			
		||||
	return gophercloud.BuildRequestBody(opts, "rescue")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Rescue instructs the provider to place the server into RESCUE mode.
 | 
			
		||||
func Rescue(client *gophercloud.ServiceClient, id string, opts RescueOptsBuilder) (r RescueResult) {
 | 
			
		||||
	b, err := opts.ToServerRescueMap()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		r.Err = err
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	_, r.Err = client.Post(actionURL(client, id), b, &r.Body, &gophercloud.RequestOpts{
 | 
			
		||||
		OkCodes: []int{200},
 | 
			
		||||
	})
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ResetMetadataOptsBuilder allows extensions to add additional parameters to the
 | 
			
		||||
// Reset request.
 | 
			
		||||
type ResetMetadataOptsBuilder interface {
 | 
			
		||||
	ToMetadataResetMap() (map[string]interface{}, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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.
 | 
			
		||||
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.
 | 
			
		||||
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.
 | 
			
		||||
func ResetMetadata(client *gophercloud.ServiceClient, id string, opts ResetMetadataOptsBuilder) (r ResetMetadataResult) {
 | 
			
		||||
	b, err := opts.ToMetadataResetMap()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		r.Err = err
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	_, r.Err = client.Put(metadataURL(client, id), b, &r.Body, &gophercloud.RequestOpts{
 | 
			
		||||
		OkCodes: []int{200},
 | 
			
		||||
	})
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Metadata requests all the metadata for the given server ID.
 | 
			
		||||
func Metadata(client *gophercloud.ServiceClient, id string) (r GetMetadataResult) {
 | 
			
		||||
	_, r.Err = client.Get(metadataURL(client, id), &r.Body, nil)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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.
 | 
			
		||||
func UpdateMetadata(client *gophercloud.ServiceClient, id string, opts UpdateMetadataOptsBuilder) (r UpdateMetadataResult) {
 | 
			
		||||
	b, err := opts.ToMetadataUpdateMap()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		r.Err = err
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	_, r.Err = client.Post(metadataURL(client, id), b, &r.Body, &gophercloud.RequestOpts{
 | 
			
		||||
		OkCodes: []int{200},
 | 
			
		||||
	})
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// MetadatumOptsBuilder allows extensions to add additional parameters to the
 | 
			
		||||
// Create request.
 | 
			
		||||
type MetadatumOptsBuilder interface {
 | 
			
		||||
	ToMetadatumCreateMap() (map[string]interface{}, string, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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.
 | 
			
		||||
func (opts MetadatumOpts) ToMetadatumCreateMap() (map[string]interface{}, string, error) {
 | 
			
		||||
	if len(opts) != 1 {
 | 
			
		||||
		err := gophercloud.ErrInvalidInput{}
 | 
			
		||||
		err.Argument = "servers.MetadatumOpts"
 | 
			
		||||
		err.Info = "Must have 1 and only 1 key-value pair"
 | 
			
		||||
		return nil, "", err
 | 
			
		||||
	}
 | 
			
		||||
	metadatum := map[string]interface{}{"meta": opts}
 | 
			
		||||
	var key string
 | 
			
		||||
	for k := range metadatum["meta"].(MetadatumOpts) {
 | 
			
		||||
		key = k
 | 
			
		||||
	}
 | 
			
		||||
	return metadatum, key, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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 {
 | 
			
		||||
		r.Err = err
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	_, r.Err = client.Put(metadatumURL(client, id, key), b, &r.Body, &gophercloud.RequestOpts{
 | 
			
		||||
		OkCodes: []int{200},
 | 
			
		||||
	})
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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.
 | 
			
		||||
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.
 | 
			
		||||
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.
 | 
			
		||||
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
 | 
			
		||||
type CreateImageOptsBuilder interface {
 | 
			
		||||
	ToServerCreateImageMap() (map[string]interface{}, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CreateImageOpts satisfies the CreateImageOptsBuilder
 | 
			
		||||
type CreateImageOpts struct {
 | 
			
		||||
	// 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 map[string]string `json:"metadata,omitempty"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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
 | 
			
		||||
func CreateImage(client *gophercloud.ServiceClient, id string, opts CreateImageOptsBuilder) (r CreateImageResult) {
 | 
			
		||||
	b, err := opts.ToServerCreateImageMap()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		r.Err = err
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	resp, err := client.Post(actionURL(client, id), b, nil, &gophercloud.RequestOpts{
 | 
			
		||||
		OkCodes: []int{202},
 | 
			
		||||
	})
 | 
			
		||||
	r.Err = err
 | 
			
		||||
	r.Header = resp.Header
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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 := ""
 | 
			
		||||
	allPages, err := List(client, nil).AllPages()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	all, err := ExtractServers(allPages)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, f := range all {
 | 
			
		||||
		if f.Name == name {
 | 
			
		||||
			count++
 | 
			
		||||
			id = f.ID
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	switch count {
 | 
			
		||||
	case 0:
 | 
			
		||||
		return "", gophercloud.ErrResourceNotFound{Name: name, ResourceType: "server"}
 | 
			
		||||
	case 1:
 | 
			
		||||
		return id, nil
 | 
			
		||||
	default:
 | 
			
		||||
		return "", gophercloud.ErrMultipleResourcesFound{Name: name, Count: count, ResourceType: "server"}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										344
									
								
								vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/servers/results.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										344
									
								
								vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/servers/results.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,344 @@
 | 
			
		||||
package servers
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"crypto/rsa"
 | 
			
		||||
	"encoding/base64"
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"net/url"
 | 
			
		||||
	"path"
 | 
			
		||||
 | 
			
		||||
	"github.com/gophercloud/gophercloud"
 | 
			
		||||
	"github.com/gophercloud/gophercloud/pagination"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type serverResult struct {
 | 
			
		||||
	gophercloud.Result
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Extract interprets any serverResult as a Server, if possible.
 | 
			
		||||
func (r serverResult) Extract() (*Server, error) {
 | 
			
		||||
	var s struct {
 | 
			
		||||
		Server *Server `json:"server"`
 | 
			
		||||
	}
 | 
			
		||||
	err := r.ExtractInto(&s)
 | 
			
		||||
	return s.Server, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CreateResult temporarily contains the response from a Create call.
 | 
			
		||||
type CreateResult struct {
 | 
			
		||||
	serverResult
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetResult temporarily contains the response from a Get call.
 | 
			
		||||
type GetResult struct {
 | 
			
		||||
	serverResult
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UpdateResult temporarily contains the response from an Update call.
 | 
			
		||||
type UpdateResult struct {
 | 
			
		||||
	serverResult
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeleteResult temporarily contains the response from a Delete call.
 | 
			
		||||
type DeleteResult struct {
 | 
			
		||||
	gophercloud.ErrResult
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RebuildResult temporarily contains the response from a Rebuild call.
 | 
			
		||||
type RebuildResult struct {
 | 
			
		||||
	serverResult
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ActionResult represents the result of server action operations, like reboot
 | 
			
		||||
type ActionResult struct {
 | 
			
		||||
	gophercloud.ErrResult
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RescueResult represents the result of a server rescue operation
 | 
			
		||||
type RescueResult struct {
 | 
			
		||||
	ActionResult
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CreateImageResult represents the result of an image creation operation
 | 
			
		||||
type CreateImageResult struct {
 | 
			
		||||
	gophercloud.Result
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetPasswordResult represent the result of a get os-server-password operation.
 | 
			
		||||
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:
 | 
			
		||||
//   echo '<pwd>' | base64 -D | openssl rsautl -decrypt -inkey <private_key>
 | 
			
		||||
func (r GetPasswordResult) ExtractPassword(privateKey *rsa.PrivateKey) (string, error) {
 | 
			
		||||
	var s struct {
 | 
			
		||||
		Password string `json:"password"`
 | 
			
		||||
	}
 | 
			
		||||
	err := r.ExtractInto(&s)
 | 
			
		||||
	if err == nil && privateKey != nil && s.Password != "" {
 | 
			
		||||
		return decryptPassword(s.Password, privateKey)
 | 
			
		||||
	}
 | 
			
		||||
	return s.Password, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func decryptPassword(encryptedPassword string, privateKey *rsa.PrivateKey) (string, error) {
 | 
			
		||||
	b64EncryptedPassword := make([]byte, base64.StdEncoding.DecodedLen(len(encryptedPassword)))
 | 
			
		||||
 | 
			
		||||
	n, err := base64.StdEncoding.Decode(b64EncryptedPassword, []byte(encryptedPassword))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", fmt.Errorf("Failed to base64 decode encrypted password: %s", err)
 | 
			
		||||
	}
 | 
			
		||||
	password, err := rsa.DecryptPKCS1v15(nil, privateKey, b64EncryptedPassword[0:n])
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", fmt.Errorf("Failed to decrypt password: %s", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return string(password), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ExtractImageID gets the ID of the newly created server image from the header
 | 
			
		||||
func (res CreateImageResult) ExtractImageID() (string, error) {
 | 
			
		||||
	if res.Err != nil {
 | 
			
		||||
		return "", res.Err
 | 
			
		||||
	}
 | 
			
		||||
	// Get the image id from the header
 | 
			
		||||
	u, err := url.ParseRequestURI(res.Header.Get("Location"))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
	imageID := path.Base(u.Path)
 | 
			
		||||
	if imageID == "." || imageID == "/" {
 | 
			
		||||
		return "", fmt.Errorf("Failed to parse the ID of newly created image: %s", u)
 | 
			
		||||
	}
 | 
			
		||||
	return imageID, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Extract interprets any RescueResult as an AdminPass, if possible.
 | 
			
		||||
func (r RescueResult) Extract() (string, error) {
 | 
			
		||||
	var s struct {
 | 
			
		||||
		AdminPass string `json:"adminPass"`
 | 
			
		||||
	}
 | 
			
		||||
	err := r.ExtractInto(&s)
 | 
			
		||||
	return s.AdminPass, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Server exposes only the standard OpenStack fields corresponding to a given server on the user's account.
 | 
			
		||||
type Server struct {
 | 
			
		||||
	// 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 string
 | 
			
		||||
	Created string
 | 
			
		||||
	HostID  string
 | 
			
		||||
	// Status contains the current operational status of the server, such as IN_PROGRESS or ACTIVE.
 | 
			
		||||
	Status string
 | 
			
		||||
	// Progress ranges from 0..100.
 | 
			
		||||
	// A request made against the server completes only once Progress reaches 100.
 | 
			
		||||
	Progress int
 | 
			
		||||
	// AccessIPv4 and AccessIPv6 contain the IP addresses of the server, suitable for remote access for administration.
 | 
			
		||||
	AccessIPv4, AccessIPv6 string
 | 
			
		||||
	// Image refers to a JSON object, which itself indicates the OS image used to deploy the server.
 | 
			
		||||
	Image map[string]interface{}
 | 
			
		||||
	// Flavor refers to a JSON object, which itself indicates the hardware configuration of the deployed server.
 | 
			
		||||
	Flavor map[string]interface{}
 | 
			
		||||
	// Addresses includes a list of all IP addresses assigned to the server, keyed by pool.
 | 
			
		||||
	Addresses map[string]interface{}
 | 
			
		||||
	// Metadata includes a list of all user-specified key-value pairs attached to the server.
 | 
			
		||||
	Metadata map[string]string
 | 
			
		||||
	// Links includes HTTP references to the itself, useful for passing along to other APIs that might want a server reference.
 | 
			
		||||
	Links []interface{}
 | 
			
		||||
	// 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.
 | 
			
		||||
	// 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 []map[string]interface{} `json:"security_groups"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *Server) UnmarshalJSON(b []byte) error {
 | 
			
		||||
	type tmp Server
 | 
			
		||||
	var server *struct {
 | 
			
		||||
		tmp
 | 
			
		||||
		Image interface{}
 | 
			
		||||
	}
 | 
			
		||||
	err := json.Unmarshal(b, &server)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	*s = Server(server.tmp)
 | 
			
		||||
 | 
			
		||||
	switch t := server.Image.(type) {
 | 
			
		||||
	case map[string]interface{}:
 | 
			
		||||
		s.Image = t
 | 
			
		||||
	case string:
 | 
			
		||||
		switch t {
 | 
			
		||||
		case "":
 | 
			
		||||
			s.Image = nil
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IsEmpty returns true if a page contains no Server results.
 | 
			
		||||
func (page ServerPage) IsEmpty() (bool, error) {
 | 
			
		||||
	servers, err := ExtractServers(page)
 | 
			
		||||
	return len(servers) == 0, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NextPageURL uses the response's embedded link reference to navigate to the next page of results.
 | 
			
		||||
func (page ServerPage) NextPageURL() (string, error) {
 | 
			
		||||
	var s struct {
 | 
			
		||||
		Links []gophercloud.Link `json:"servers_links"`
 | 
			
		||||
	}
 | 
			
		||||
	err := page.ExtractInto(&s)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
	return gophercloud.ExtractNextURL(s.Links)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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 struct {
 | 
			
		||||
		Servers []Server `json:"servers"`
 | 
			
		||||
	}
 | 
			
		||||
	err := (r.(ServerPage)).ExtractInto(&s)
 | 
			
		||||
	return s.Servers, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// MetadataResult contains the result of a call for (potentially) multiple key-value pairs.
 | 
			
		||||
type MetadataResult struct {
 | 
			
		||||
	gophercloud.Result
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetMetadataResult temporarily contains the response from a metadata Get call.
 | 
			
		||||
type GetMetadataResult struct {
 | 
			
		||||
	MetadataResult
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ResetMetadataResult temporarily contains the response from a metadata Reset call.
 | 
			
		||||
type ResetMetadataResult struct {
 | 
			
		||||
	MetadataResult
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UpdateMetadataResult temporarily contains the response from a metadata Update call.
 | 
			
		||||
type UpdateMetadataResult struct {
 | 
			
		||||
	MetadataResult
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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.
 | 
			
		||||
type GetMetadatumResult struct {
 | 
			
		||||
	MetadatumResult
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CreateMetadatumResult temporarily contains the response from a metadatum Create call.
 | 
			
		||||
type CreateMetadatumResult struct {
 | 
			
		||||
	MetadatumResult
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeleteMetadatumResult temporarily contains the response from a metadatum Delete call.
 | 
			
		||||
type DeleteMetadatumResult struct {
 | 
			
		||||
	gophercloud.ErrResult
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Extract interprets any MetadataResult as a Metadata, if possible.
 | 
			
		||||
func (r MetadataResult) Extract() (map[string]string, error) {
 | 
			
		||||
	var s struct {
 | 
			
		||||
		Metadata map[string]string `json:"metadata"`
 | 
			
		||||
	}
 | 
			
		||||
	err := r.ExtractInto(&s)
 | 
			
		||||
	return s.Metadata, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Extract interprets any MetadatumResult as a Metadatum, if possible.
 | 
			
		||||
func (r MetadatumResult) Extract() (map[string]string, error) {
 | 
			
		||||
	var s struct {
 | 
			
		||||
		Metadatum map[string]string `json:"meta"`
 | 
			
		||||
	}
 | 
			
		||||
	err := r.ExtractInto(&s)
 | 
			
		||||
	return s.Metadatum, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Address represents an IP address.
 | 
			
		||||
type Address struct {
 | 
			
		||||
	Version int    `json:"version"`
 | 
			
		||||
	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.
 | 
			
		||||
type AddressPage struct {
 | 
			
		||||
	pagination.SinglePageBase
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IsEmpty returns true if an AddressPage contains no networks.
 | 
			
		||||
func (r AddressPage) IsEmpty() (bool, error) {
 | 
			
		||||
	addresses, err := ExtractAddresses(r)
 | 
			
		||||
	return len(addresses) == 0, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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"`
 | 
			
		||||
	}
 | 
			
		||||
	err := (r.(AddressPage)).ExtractInto(&s)
 | 
			
		||||
	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.
 | 
			
		||||
type NetworkAddressPage struct {
 | 
			
		||||
	pagination.SinglePageBase
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IsEmpty returns true if a NetworkAddressPage contains no addresses.
 | 
			
		||||
func (r NetworkAddressPage) IsEmpty() (bool, error) {
 | 
			
		||||
	addresses, err := ExtractNetworkAddresses(r)
 | 
			
		||||
	return len(addresses) == 0, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var key string
 | 
			
		||||
	for k := range s {
 | 
			
		||||
		key = k
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return s[key], err
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										51
									
								
								vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/servers/urls.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/servers/urls.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,51 @@
 | 
			
		||||
package servers
 | 
			
		||||
 | 
			
		||||
import "github.com/gophercloud/gophercloud"
 | 
			
		||||
 | 
			
		||||
func createURL(client *gophercloud.ServiceClient) string {
 | 
			
		||||
	return client.ServiceURL("servers")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func listURL(client *gophercloud.ServiceClient) string {
 | 
			
		||||
	return createURL(client)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func listDetailURL(client *gophercloud.ServiceClient) string {
 | 
			
		||||
	return client.ServiceURL("servers", "detail")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func deleteURL(client *gophercloud.ServiceClient, id string) string {
 | 
			
		||||
	return client.ServiceURL("servers", id)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func getURL(client *gophercloud.ServiceClient, id string) string {
 | 
			
		||||
	return deleteURL(client, id)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func updateURL(client *gophercloud.ServiceClient, id string) string {
 | 
			
		||||
	return deleteURL(client, id)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func actionURL(client *gophercloud.ServiceClient, id string) string {
 | 
			
		||||
	return client.ServiceURL("servers", id, "action")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func metadatumURL(client *gophercloud.ServiceClient, id, key string) string {
 | 
			
		||||
	return client.ServiceURL("servers", id, "metadata", key)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func metadataURL(client *gophercloud.ServiceClient, id string) string {
 | 
			
		||||
	return client.ServiceURL("servers", id, "metadata")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func listAddressesURL(client *gophercloud.ServiceClient, id string) string {
 | 
			
		||||
	return client.ServiceURL("servers", id, "ips")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func listAddressesByNetworkURL(client *gophercloud.ServiceClient, id, network string) string {
 | 
			
		||||
	return client.ServiceURL("servers", id, "ips", network)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func passwordURL(client *gophercloud.ServiceClient, id string) string {
 | 
			
		||||
	return client.ServiceURL("servers", id, "os-server-password")
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										20
									
								
								vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/servers/util.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/servers/util.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,20 @@
 | 
			
		||||
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.
 | 
			
		||||
func WaitForStatus(c *gophercloud.ServiceClient, id, status string, secs int) error {
 | 
			
		||||
	return gophercloud.WaitFor(secs, func() (bool, error) {
 | 
			
		||||
		current, err := Get(c, id).Extract()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return false, err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if current.Status == status {
 | 
			
		||||
			return true, nil
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return false, nil
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										99
									
								
								vendor/github.com/gophercloud/gophercloud/openstack/endpoint_location.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										99
									
								
								vendor/github.com/gophercloud/gophercloud/openstack/endpoint_location.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,99 @@
 | 
			
		||||
package openstack
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/gophercloud/gophercloud"
 | 
			
		||||
	tokens2 "github.com/gophercloud/gophercloud/openstack/identity/v2/tokens"
 | 
			
		||||
	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.
 | 
			
		||||
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)
 | 
			
		||||
	for _, entry := range catalog.Entries {
 | 
			
		||||
		if (entry.Type == opts.Type) && (opts.Name == "" || entry.Name == opts.Name) {
 | 
			
		||||
			for _, endpoint := range entry.Endpoints {
 | 
			
		||||
				if opts.Region == "" || endpoint.Region == opts.Region {
 | 
			
		||||
					endpoints = append(endpoints, endpoint)
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Report an error if the options were ambiguous.
 | 
			
		||||
	if len(endpoints) > 1 {
 | 
			
		||||
		err := &ErrMultipleMatchingEndpointsV2{}
 | 
			
		||||
		err.Endpoints = endpoints
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Extract the appropriate URL from the matching Endpoint.
 | 
			
		||||
	for _, endpoint := range endpoints {
 | 
			
		||||
		switch opts.Availability {
 | 
			
		||||
		case gophercloud.AvailabilityPublic:
 | 
			
		||||
			return gophercloud.NormalizeURL(endpoint.PublicURL), nil
 | 
			
		||||
		case gophercloud.AvailabilityInternal:
 | 
			
		||||
			return gophercloud.NormalizeURL(endpoint.InternalURL), nil
 | 
			
		||||
		case gophercloud.AvailabilityAdmin:
 | 
			
		||||
			return gophercloud.NormalizeURL(endpoint.AdminURL), nil
 | 
			
		||||
		default:
 | 
			
		||||
			err := &ErrInvalidAvailabilityProvided{}
 | 
			
		||||
			err.Argument = "Availability"
 | 
			
		||||
			err.Value = opts.Availability
 | 
			
		||||
			return "", err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Report an error if there were no matching endpoints.
 | 
			
		||||
	err := &gophercloud.ErrEndpointNotFound{}
 | 
			
		||||
	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.
 | 
			
		||||
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.
 | 
			
		||||
	var endpoints = make([]tokens3.Endpoint, 0, 1)
 | 
			
		||||
	for _, entry := range catalog.Entries {
 | 
			
		||||
		if (entry.Type == opts.Type) && (opts.Name == "" || entry.Name == opts.Name) {
 | 
			
		||||
			for _, endpoint := range entry.Endpoints {
 | 
			
		||||
				if opts.Availability != gophercloud.AvailabilityAdmin &&
 | 
			
		||||
					opts.Availability != gophercloud.AvailabilityPublic &&
 | 
			
		||||
					opts.Availability != gophercloud.AvailabilityInternal {
 | 
			
		||||
					err := &ErrInvalidAvailabilityProvided{}
 | 
			
		||||
					err.Argument = "Availability"
 | 
			
		||||
					err.Value = opts.Availability
 | 
			
		||||
					return "", err
 | 
			
		||||
				}
 | 
			
		||||
				if (opts.Availability == gophercloud.Availability(endpoint.Interface)) &&
 | 
			
		||||
					(opts.Region == "" || endpoint.Region == opts.Region) {
 | 
			
		||||
					endpoints = append(endpoints, endpoint)
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Report an error if the options were ambiguous.
 | 
			
		||||
	if len(endpoints) > 1 {
 | 
			
		||||
		return "", ErrMultipleMatchingEndpointsV3{Endpoints: endpoints}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Extract the URL from the matching Endpoint.
 | 
			
		||||
	for _, endpoint := range endpoints {
 | 
			
		||||
		return gophercloud.NormalizeURL(endpoint.URL), nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Report an error if there were no matching endpoints.
 | 
			
		||||
	err := &gophercloud.ErrEndpointNotFound{}
 | 
			
		||||
	return "", err
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										71
									
								
								vendor/github.com/gophercloud/gophercloud/openstack/errors.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								vendor/github.com/gophercloud/gophercloud/openstack/errors.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,71 @@
 | 
			
		||||
package openstack
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
 | 
			
		||||
	"github.com/gophercloud/gophercloud"
 | 
			
		||||
	tokens2 "github.com/gophercloud/gophercloud/openstack/identity/v2/tokens"
 | 
			
		||||
	tokens3 "github.com/gophercloud/gophercloud/openstack/identity/v3/tokens"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// ErrEndpointNotFound is the error when no suitable endpoint can be found
 | 
			
		||||
// in the user's catalog
 | 
			
		||||
type ErrEndpointNotFound struct{ gophercloud.BaseError }
 | 
			
		||||
 | 
			
		||||
func (e ErrEndpointNotFound) Error() string {
 | 
			
		||||
	return "No suitable endpoint could be found in the service catalog."
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ErrInvalidAvailabilityProvided is the error when an invalid endpoint
 | 
			
		||||
// availability is provided
 | 
			
		||||
type ErrInvalidAvailabilityProvided struct{ gophercloud.ErrInvalidInput }
 | 
			
		||||
 | 
			
		||||
func (e ErrInvalidAvailabilityProvided) Error() string {
 | 
			
		||||
	return fmt.Sprintf("Unexpected availability in endpoint query: %s", e.Value)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ErrMultipleMatchingEndpointsV2 is the error when more than one endpoint
 | 
			
		||||
// for the given options is found in the v2 catalog
 | 
			
		||||
type ErrMultipleMatchingEndpointsV2 struct {
 | 
			
		||||
	gophercloud.BaseError
 | 
			
		||||
	Endpoints []tokens2.Endpoint
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e ErrMultipleMatchingEndpointsV2) Error() string {
 | 
			
		||||
	return fmt.Sprintf("Discovered %d matching endpoints: %#v", len(e.Endpoints), e.Endpoints)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ErrMultipleMatchingEndpointsV3 is the error when more than one endpoint
 | 
			
		||||
// for the given options is found in the v3 catalog
 | 
			
		||||
type ErrMultipleMatchingEndpointsV3 struct {
 | 
			
		||||
	gophercloud.BaseError
 | 
			
		||||
	Endpoints []tokens3.Endpoint
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e ErrMultipleMatchingEndpointsV3) Error() string {
 | 
			
		||||
	return fmt.Sprintf("Discovered %d matching endpoints: %#v", len(e.Endpoints), e.Endpoints)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ErrNoAuthURL is the error when the OS_AUTH_URL environment variable is not
 | 
			
		||||
// found
 | 
			
		||||
type ErrNoAuthURL struct{ gophercloud.ErrInvalidInput }
 | 
			
		||||
 | 
			
		||||
func (e ErrNoAuthURL) Error() string {
 | 
			
		||||
	return "Environment variable OS_AUTH_URL needs to be set."
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ErrNoUsername is the error when the OS_USERNAME environment variable is not
 | 
			
		||||
// found
 | 
			
		||||
type ErrNoUsername struct{ gophercloud.ErrInvalidInput }
 | 
			
		||||
 | 
			
		||||
func (e ErrNoUsername) Error() string {
 | 
			
		||||
	return "Environment variable OS_USERNAME needs to be set."
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ErrNoPassword is the error when the OS_PASSWORD environment variable is not
 | 
			
		||||
// found
 | 
			
		||||
type ErrNoPassword struct{ gophercloud.ErrInvalidInput }
 | 
			
		||||
 | 
			
		||||
func (e ErrNoPassword) Error() string {
 | 
			
		||||
	return "Environment variable OS_PASSWORD needs to be set."
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										7
									
								
								vendor/github.com/gophercloud/gophercloud/openstack/identity/v2/tenants/doc.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								vendor/github.com/gophercloud/gophercloud/openstack/identity/v2/tenants/doc.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,7 @@
 | 
			
		||||
// 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
 | 
			
		||||
							
								
								
									
										29
									
								
								vendor/github.com/gophercloud/gophercloud/openstack/identity/v2/tenants/requests.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								vendor/github.com/gophercloud/gophercloud/openstack/identity/v2/tenants/requests.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,29 @@
 | 
			
		||||
package tenants
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/gophercloud/gophercloud"
 | 
			
		||||
	"github.com/gophercloud/gophercloud/pagination"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// ListOpts filters the Tenants that are returned by the List call.
 | 
			
		||||
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"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// List enumerates the Tenants to which the current token has access.
 | 
			
		||||
func List(client *gophercloud.ServiceClient, opts *ListOpts) pagination.Pager {
 | 
			
		||||
	url := listURL(client)
 | 
			
		||||
	if opts != nil {
 | 
			
		||||
		q, err := gophercloud.BuildQueryString(opts)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return pagination.Pager{Err: err}
 | 
			
		||||
		}
 | 
			
		||||
		url += q.String()
 | 
			
		||||
	}
 | 
			
		||||
	return pagination.NewPager(client, url, func(r pagination.PageResult) pagination.Page {
 | 
			
		||||
		return TenantPage{pagination.LinkedPageBase{PageResult: r}}
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										53
									
								
								vendor/github.com/gophercloud/gophercloud/openstack/identity/v2/tenants/results.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								vendor/github.com/gophercloud/gophercloud/openstack/identity/v2/tenants/results.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,53 @@
 | 
			
		||||
package tenants
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/gophercloud/gophercloud"
 | 
			
		||||
	"github.com/gophercloud/gophercloud/pagination"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Tenant is a grouping of users in the identity service.
 | 
			
		||||
type Tenant struct {
 | 
			
		||||
	// ID is a unique identifier for this tenant.
 | 
			
		||||
	ID string `json:"id"`
 | 
			
		||||
 | 
			
		||||
	// Name is a friendlier user-facing name for this tenant.
 | 
			
		||||
	Name string `json:"name"`
 | 
			
		||||
 | 
			
		||||
	// Description is a human-readable explanation of this Tenant's purpose.
 | 
			
		||||
	Description string `json:"description"`
 | 
			
		||||
 | 
			
		||||
	// Enabled indicates whether or not a tenant is active.
 | 
			
		||||
	Enabled bool `json:"enabled"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// TenantPage is a single page of Tenant results.
 | 
			
		||||
type TenantPage struct {
 | 
			
		||||
	pagination.LinkedPageBase
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IsEmpty determines whether or not a page of Tenants contains any results.
 | 
			
		||||
func (r TenantPage) IsEmpty() (bool, error) {
 | 
			
		||||
	tenants, err := ExtractTenants(r)
 | 
			
		||||
	return len(tenants) == 0, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NextPageURL extracts the "next" link from the tenants_links section of the result.
 | 
			
		||||
func (r TenantPage) NextPageURL() (string, error) {
 | 
			
		||||
	var s struct {
 | 
			
		||||
		Links []gophercloud.Link `json:"tenants_links"`
 | 
			
		||||
	}
 | 
			
		||||
	err := r.ExtractInto(&s)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
	return gophercloud.ExtractNextURL(s.Links)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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"`
 | 
			
		||||
	}
 | 
			
		||||
	err := (r.(TenantPage)).ExtractInto(&s)
 | 
			
		||||
	return s.Tenants, err
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										7
									
								
								vendor/github.com/gophercloud/gophercloud/openstack/identity/v2/tenants/urls.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								vendor/github.com/gophercloud/gophercloud/openstack/identity/v2/tenants/urls.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,7 @@
 | 
			
		||||
package tenants
 | 
			
		||||
 | 
			
		||||
import "github.com/gophercloud/gophercloud"
 | 
			
		||||
 | 
			
		||||
func listURL(client *gophercloud.ServiceClient) string {
 | 
			
		||||
	return client.ServiceURL("tenants")
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										5
									
								
								vendor/github.com/gophercloud/gophercloud/openstack/identity/v2/tokens/doc.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								vendor/github.com/gophercloud/gophercloud/openstack/identity/v2/tokens/doc.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
			
		||||
// 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
 | 
			
		||||
							
								
								
									
										99
									
								
								vendor/github.com/gophercloud/gophercloud/openstack/identity/v2/tokens/requests.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										99
									
								
								vendor/github.com/gophercloud/gophercloud/openstack/identity/v2/tokens/requests.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,99 @@
 | 
			
		||||
package tokens
 | 
			
		||||
 | 
			
		||||
import "github.com/gophercloud/gophercloud"
 | 
			
		||||
 | 
			
		||||
type PasswordCredentialsV2 struct {
 | 
			
		||||
	Username string `json:"username" required:"true"`
 | 
			
		||||
	Password string `json:"password" required:"true"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type TokenCredentialsV2 struct {
 | 
			
		||||
	ID string `json:"id,omitempty" required:"true"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// AuthOptionsV2 wraps a gophercloud AuthOptions in order to adhere to the AuthOptionsBuilder
 | 
			
		||||
// interface.
 | 
			
		||||
type AuthOptionsV2 struct {
 | 
			
		||||
	PasswordCredentials *PasswordCredentialsV2 `json:"passwordCredentials,omitempty" xor:"TokenCredentials"`
 | 
			
		||||
 | 
			
		||||
	// The TenantID and TenantName fields are optional for the Identity V2 API.
 | 
			
		||||
	// Some providers allow you to specify a TenantName instead of the TenantId.
 | 
			
		||||
	// Some require both. Your provider's authentication policies will determine
 | 
			
		||||
	// how these fields influence authentication.
 | 
			
		||||
	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 *TokenCredentialsV2 `json:"token,omitempty" xor:"PasswordCredentials"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// AuthOptionsBuilder describes any argument that may be passed to the Create call.
 | 
			
		||||
type AuthOptionsBuilder interface {
 | 
			
		||||
	// ToTokenCreateMap assembles the Create request body, returning an error if parameters are
 | 
			
		||||
	// missing or inconsistent.
 | 
			
		||||
	ToTokenV2CreateMap() (map[string]interface{}, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// AuthOptions are the valid options for Openstack Identity v2 authentication.
 | 
			
		||||
// For field descriptions, see gophercloud.AuthOptions.
 | 
			
		||||
type AuthOptions struct {
 | 
			
		||||
	IdentityEndpoint string `json:"-"`
 | 
			
		||||
	Username         string `json:"username,omitempty"`
 | 
			
		||||
	Password         string `json:"password,omitempty"`
 | 
			
		||||
	TenantID         string `json:"tenantId,omitempty"`
 | 
			
		||||
	TenantName       string `json:"tenantName,omitempty"`
 | 
			
		||||
	AllowReauth      bool   `json:"-"`
 | 
			
		||||
	TokenID          string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ToTokenV2CreateMap allows AuthOptions to satisfy the AuthOptionsBuilder
 | 
			
		||||
// interface in the v2 tokens package
 | 
			
		||||
func (opts AuthOptions) ToTokenV2CreateMap() (map[string]interface{}, error) {
 | 
			
		||||
	v2Opts := AuthOptionsV2{
 | 
			
		||||
		TenantID:   opts.TenantID,
 | 
			
		||||
		TenantName: opts.TenantName,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if opts.Password != "" {
 | 
			
		||||
		v2Opts.PasswordCredentials = &PasswordCredentialsV2{
 | 
			
		||||
			Username: opts.Username,
 | 
			
		||||
			Password: opts.Password,
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		v2Opts.TokenCredentials = &TokenCredentialsV2{
 | 
			
		||||
			ID: opts.TokenID,
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	b, err := gophercloud.BuildRequestBody(v2Opts, "auth")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return b, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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.
 | 
			
		||||
func Create(client *gophercloud.ServiceClient, auth AuthOptionsBuilder) (r CreateResult) {
 | 
			
		||||
	b, err := auth.ToTokenV2CreateMap()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		r.Err = err
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	_, r.Err = client.Post(CreateURL(client), b, &r.Body, &gophercloud.RequestOpts{
 | 
			
		||||
		OkCodes:     []int{200, 203},
 | 
			
		||||
		MoreHeaders: map[string]string{"X-Auth-Token": ""},
 | 
			
		||||
	})
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Get validates and retrieves information for user's token.
 | 
			
		||||
func Get(client *gophercloud.ServiceClient, token string) (r GetResult) {
 | 
			
		||||
	_, r.Err = client.Get(GetURL(client, token), &r.Body, &gophercloud.RequestOpts{
 | 
			
		||||
		OkCodes: []int{200, 203},
 | 
			
		||||
	})
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										149
									
								
								vendor/github.com/gophercloud/gophercloud/openstack/identity/v2/tokens/results.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										149
									
								
								vendor/github.com/gophercloud/gophercloud/openstack/identity/v2/tokens/results.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,149 @@
 | 
			
		||||
package tokens
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/gophercloud/gophercloud"
 | 
			
		||||
	"github.com/gophercloud/gophercloud/openstack/identity/v2/tenants"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// 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.
 | 
			
		||||
	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.
 | 
			
		||||
	// See the AuthOptions structure for more details.
 | 
			
		||||
	ExpiresAt time.Time
 | 
			
		||||
 | 
			
		||||
	// Tenant provides information about the tenant to which this token grants access.
 | 
			
		||||
	Tenant tenants.Tenant
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Role is a role for a user.
 | 
			
		||||
type Role struct {
 | 
			
		||||
	Name string `json:"name"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// User is an OpenStack user.
 | 
			
		||||
type User struct {
 | 
			
		||||
	ID       string `json:"id"`
 | 
			
		||||
	Name     string `json:"name"`
 | 
			
		||||
	UserName string `json:"username"`
 | 
			
		||||
	Roles    []Role `json:"roles"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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.
 | 
			
		||||
// 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 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"`
 | 
			
		||||
	InternalURL string `json:"internalURL"`
 | 
			
		||||
	AdminURL    string `json:"adminURL"`
 | 
			
		||||
	Region      string `json:"region"`
 | 
			
		||||
	VersionID   string `json:"versionId"`
 | 
			
		||||
	VersionInfo string `json:"versionInfo"`
 | 
			
		||||
	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.
 | 
			
		||||
//
 | 
			
		||||
// 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 string `json:"type"`
 | 
			
		||||
 | 
			
		||||
	// 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.
 | 
			
		||||
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.
 | 
			
		||||
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.
 | 
			
		||||
type GetResult struct {
 | 
			
		||||
	CreateResult
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ExtractToken returns the just-created Token from a CreateResult.
 | 
			
		||||
func (r CreateResult) ExtractToken() (*Token, error) {
 | 
			
		||||
	var s struct {
 | 
			
		||||
		Access struct {
 | 
			
		||||
			Token struct {
 | 
			
		||||
				Expires string         `json:"expires"`
 | 
			
		||||
				ID      string         `json:"id"`
 | 
			
		||||
				Tenant  tenants.Tenant `json:"tenant"`
 | 
			
		||||
			} `json:"token"`
 | 
			
		||||
		} `json:"access"`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err := r.ExtractInto(&s)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	expiresTs, err := time.Parse(gophercloud.RFC3339Milli, s.Access.Token.Expires)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return &Token{
 | 
			
		||||
		ID:        s.Access.Token.ID,
 | 
			
		||||
		ExpiresAt: expiresTs,
 | 
			
		||||
		Tenant:    s.Access.Token.Tenant,
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ExtractServiceCatalog returns the ServiceCatalog that was generated along with the user's Token.
 | 
			
		||||
func (r CreateResult) ExtractServiceCatalog() (*ServiceCatalog, error) {
 | 
			
		||||
	var s struct {
 | 
			
		||||
		Access struct {
 | 
			
		||||
			Entries []CatalogEntry `json:"serviceCatalog"`
 | 
			
		||||
		} `json:"access"`
 | 
			
		||||
	}
 | 
			
		||||
	err := r.ExtractInto(&s)
 | 
			
		||||
	return &ServiceCatalog{Entries: s.Access.Entries}, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// createErr quickly packs an error in a CreateResult.
 | 
			
		||||
func createErr(err error) CreateResult {
 | 
			
		||||
	return CreateResult{gophercloud.Result{Err: err}}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ExtractUser returns the User from a GetResult.
 | 
			
		||||
func (r GetResult) ExtractUser() (*User, error) {
 | 
			
		||||
	var s struct {
 | 
			
		||||
		Access struct {
 | 
			
		||||
			User User `json:"user"`
 | 
			
		||||
		} `json:"access"`
 | 
			
		||||
	}
 | 
			
		||||
	err := r.ExtractInto(&s)
 | 
			
		||||
	return &s.Access.User, err
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										13
									
								
								vendor/github.com/gophercloud/gophercloud/openstack/identity/v2/tokens/urls.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								vendor/github.com/gophercloud/gophercloud/openstack/identity/v2/tokens/urls.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
			
		||||
package tokens
 | 
			
		||||
 | 
			
		||||
import "github.com/gophercloud/gophercloud"
 | 
			
		||||
 | 
			
		||||
// CreateURL generates the URL used to create new Tokens.
 | 
			
		||||
func CreateURL(client *gophercloud.ServiceClient) string {
 | 
			
		||||
	return client.ServiceURL("tokens")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetURL generates the URL used to Validate Tokens.
 | 
			
		||||
func GetURL(client *gophercloud.ServiceClient, token string) string {
 | 
			
		||||
	return client.ServiceURL("tokens", token)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										34
									
								
								vendor/github.com/gophercloud/gophercloud/openstack/identity/v3/extensions/trusts/requests.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								vendor/github.com/gophercloud/gophercloud/openstack/identity/v3/extensions/trusts/requests.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,34 @@
 | 
			
		||||
package trusts
 | 
			
		||||
 | 
			
		||||
import "github.com/gophercloud/gophercloud/openstack/identity/v3/tokens"
 | 
			
		||||
 | 
			
		||||
type AuthOptsExt struct {
 | 
			
		||||
	tokens.AuthOptionsBuilder
 | 
			
		||||
	TrustID string `json:"id"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (opts AuthOptsExt) ToTokenV3CreateMap(scope map[string]interface{}) (map[string]interface{}, error) {
 | 
			
		||||
	return opts.AuthOptionsBuilder.ToTokenV3CreateMap(scope)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (opts AuthOptsExt) ToTokenV3ScopeMap() (map[string]interface{}, error) {
 | 
			
		||||
	b, err := opts.AuthOptionsBuilder.ToTokenV3ScopeMap()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if opts.TrustID != "" {
 | 
			
		||||
		if b == nil {
 | 
			
		||||
			b = make(map[string]interface{})
 | 
			
		||||
		}
 | 
			
		||||
		b["OS-TRUST:trust"] = map[string]interface{}{
 | 
			
		||||
			"id": opts.TrustID,
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return b, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (opts AuthOptsExt) CanReauth() bool {
 | 
			
		||||
	return opts.AuthOptionsBuilder.CanReauth()
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										29
									
								
								vendor/github.com/gophercloud/gophercloud/openstack/identity/v3/extensions/trusts/results.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								vendor/github.com/gophercloud/gophercloud/openstack/identity/v3/extensions/trusts/results.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,29 @@
 | 
			
		||||
package trusts
 | 
			
		||||
 | 
			
		||||
import "github.com/gophercloud/gophercloud/openstack/identity/v3/tokens"
 | 
			
		||||
 | 
			
		||||
type TrusteeUser struct {
 | 
			
		||||
	ID string `json:"id"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type TrustorUser struct {
 | 
			
		||||
	ID string `json:"id"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Trust struct {
 | 
			
		||||
	ID                 string      `json:"id"`
 | 
			
		||||
	Impersonation      bool        `json:"impersonation"`
 | 
			
		||||
	TrusteeUser        TrusteeUser `json:"trustee_user"`
 | 
			
		||||
	TrustorUser        TrustorUser `json:"trustor_user"`
 | 
			
		||||
	RedelegatedTrustID string      `json:"redelegated_trust_id"`
 | 
			
		||||
	RedelegationCount  int         `json:"redelegation_count"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Token struct {
 | 
			
		||||
	tokens.Token
 | 
			
		||||
	Trust Trust `json:"OS-TRUST:trust"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type TokenExt struct {
 | 
			
		||||
	Token Token `json:"token"`
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										6
									
								
								vendor/github.com/gophercloud/gophercloud/openstack/identity/v3/tokens/doc.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								vendor/github.com/gophercloud/gophercloud/openstack/identity/v3/tokens/doc.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,6 @@
 | 
			
		||||
// 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
 | 
			
		||||
							
								
								
									
										200
									
								
								vendor/github.com/gophercloud/gophercloud/openstack/identity/v3/tokens/requests.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										200
									
								
								vendor/github.com/gophercloud/gophercloud/openstack/identity/v3/tokens/requests.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,200 @@
 | 
			
		||||
package tokens
 | 
			
		||||
 | 
			
		||||
import "github.com/gophercloud/gophercloud"
 | 
			
		||||
 | 
			
		||||
// Scope allows a created token to be limited to a specific domain or project.
 | 
			
		||||
type Scope struct {
 | 
			
		||||
	ProjectID   string `json:"scope.project.id,omitempty" not:"ProjectName,DomainID,DomainName"`
 | 
			
		||||
	ProjectName string `json:"scope.project.name,omitempty"`
 | 
			
		||||
	DomainID    string `json:"scope.project.id,omitempty" not:"ProjectName,ProjectID,DomainName"`
 | 
			
		||||
	DomainName  string `json:"scope.project.id,omitempty"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// AuthOptionsBuilder describes any argument that may be passed to the Create call.
 | 
			
		||||
type AuthOptionsBuilder interface {
 | 
			
		||||
	// 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
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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.
 | 
			
		||||
	IdentityEndpoint string `json:"-"`
 | 
			
		||||
 | 
			
		||||
	// Username is required if using Identity V2 API. Consult with your provider's
 | 
			
		||||
	// control panel to discover your account's username. In Identity V3, either
 | 
			
		||||
	// UserID or a combination of Username and DomainID or DomainName are needed.
 | 
			
		||||
	Username string `json:"username,omitempty"`
 | 
			
		||||
	UserID   string `json:"id,omitempty"`
 | 
			
		||||
 | 
			
		||||
	Password string `json:"password,omitempty"`
 | 
			
		||||
 | 
			
		||||
	// At most one of DomainID and DomainName must be provided if using Username
 | 
			
		||||
	// with Identity V3. Otherwise, either are optional.
 | 
			
		||||
	DomainID   string `json:"id,omitempty"`
 | 
			
		||||
	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 bool `json:"-"`
 | 
			
		||||
 | 
			
		||||
	// TokenID allows users to authenticate (possibly as another user) with an
 | 
			
		||||
	// authentication token ID.
 | 
			
		||||
	TokenID string `json:"-"`
 | 
			
		||||
 | 
			
		||||
	Scope Scope `json:"-"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (opts *AuthOptions) ToTokenV3CreateMap(scope map[string]interface{}) (map[string]interface{}, error) {
 | 
			
		||||
	gophercloudAuthOpts := gophercloud.AuthOptions{
 | 
			
		||||
		Username:    opts.Username,
 | 
			
		||||
		UserID:      opts.UserID,
 | 
			
		||||
		Password:    opts.Password,
 | 
			
		||||
		DomainID:    opts.DomainID,
 | 
			
		||||
		DomainName:  opts.DomainName,
 | 
			
		||||
		AllowReauth: opts.AllowReauth,
 | 
			
		||||
		TokenID:     opts.TokenID,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return gophercloudAuthOpts.ToTokenV3CreateMap(scope)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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{}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		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{}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (opts *AuthOptions) CanReauth() bool {
 | 
			
		||||
	return opts.AllowReauth
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func subjectTokenHeaders(c *gophercloud.ServiceClient, subjectToken string) map[string]string {
 | 
			
		||||
	return map[string]string{
 | 
			
		||||
		"X-Subject-Token": subjectToken,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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 {
 | 
			
		||||
		r.Err = err
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	b, err := opts.ToTokenV3CreateMap(scope)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		r.Err = err
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	resp, err := c.Post(tokenURL(c), b, &r.Body, &gophercloud.RequestOpts{
 | 
			
		||||
		MoreHeaders: map[string]string{"X-Auth-Token": ""},
 | 
			
		||||
	})
 | 
			
		||||
	r.Err = err
 | 
			
		||||
	if resp != nil {
 | 
			
		||||
		r.Header = resp.Header
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Get validates and retrieves information about another token.
 | 
			
		||||
func Get(c *gophercloud.ServiceClient, token string) (r GetResult) {
 | 
			
		||||
	resp, err := c.Get(tokenURL(c), &r.Body, &gophercloud.RequestOpts{
 | 
			
		||||
		MoreHeaders: subjectTokenHeaders(c, token),
 | 
			
		||||
		OkCodes:     []int{200, 203},
 | 
			
		||||
	})
 | 
			
		||||
	if resp != nil {
 | 
			
		||||
		r.Err = err
 | 
			
		||||
		r.Header = resp.Header
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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{
 | 
			
		||||
		MoreHeaders: subjectTokenHeaders(c, token),
 | 
			
		||||
		OkCodes:     []int{204, 404},
 | 
			
		||||
	})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return false, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return resp.StatusCode == 204, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Revoke immediately makes specified token invalid.
 | 
			
		||||
func Revoke(c *gophercloud.ServiceClient, token string) (r RevokeResult) {
 | 
			
		||||
	_, r.Err = c.Delete(tokenURL(c), &gophercloud.RequestOpts{
 | 
			
		||||
		MoreHeaders: subjectTokenHeaders(c, token),
 | 
			
		||||
	})
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										114
									
								
								vendor/github.com/gophercloud/gophercloud/openstack/identity/v3/tokens/results.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										114
									
								
								vendor/github.com/gophercloud/gophercloud/openstack/identity/v3/tokens/results.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,114 @@
 | 
			
		||||
package tokens
 | 
			
		||||
 | 
			
		||||
import "errors"
 | 
			
		||||
import "github.com/gophercloud/gophercloud"
 | 
			
		||||
 | 
			
		||||
// Endpoint represents a single API endpoint offered by a service.
 | 
			
		||||
// It matches either a public, internal or admin URL.
 | 
			
		||||
// If supported, it contains a region specifier, again if provided.
 | 
			
		||||
// The significance of the Region field will depend upon your provider.
 | 
			
		||||
type Endpoint struct {
 | 
			
		||||
	ID        string `json:"id"`
 | 
			
		||||
	Region    string `json:"region"`
 | 
			
		||||
	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).
 | 
			
		||||
//
 | 
			
		||||
// 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 string `json:"type"`
 | 
			
		||||
	// 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.
 | 
			
		||||
type ServiceCatalog struct {
 | 
			
		||||
	Entries []CatalogEntry
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// commonResult is the deferred result of a Create or a Get call.
 | 
			
		||||
type commonResult struct {
 | 
			
		||||
	gophercloud.Result
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Extract is a shortcut for ExtractToken.
 | 
			
		||||
// This function is deprecated and still present for backward compatibility.
 | 
			
		||||
func (r commonResult) Extract() (*Token, error) {
 | 
			
		||||
	return r.ExtractToken()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ExtractToken interprets a commonResult as a Token.
 | 
			
		||||
func (r commonResult) ExtractToken() (*Token, error) {
 | 
			
		||||
	var s struct {
 | 
			
		||||
		Token *Token `json:"token"`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err := r.ExtractInto(&s)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if s.Token == nil {
 | 
			
		||||
		return nil, errors.New("'token' missing in JSON response")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Parse the token itself from the stored headers.
 | 
			
		||||
	s.Token.ID = r.Header.Get("X-Subject-Token")
 | 
			
		||||
 | 
			
		||||
	return s.Token, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ExtractServiceCatalog returns the ServiceCatalog that was generated along with the user's Token.
 | 
			
		||||
func (r CreateResult) ExtractServiceCatalog() (*ServiceCatalog, error) {
 | 
			
		||||
	var s struct {
 | 
			
		||||
		Token struct {
 | 
			
		||||
			Entries []CatalogEntry `json:"catalog"`
 | 
			
		||||
		} `json:"token"`
 | 
			
		||||
	}
 | 
			
		||||
	err := r.ExtractInto(&s)
 | 
			
		||||
	return &ServiceCatalog{Entries: s.Token.Entries}, 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.
 | 
			
		||||
type CreateResult struct {
 | 
			
		||||
	commonResult
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// createErr quickly creates a CreateResult that reports an error.
 | 
			
		||||
func createErr(err error) CreateResult {
 | 
			
		||||
	return CreateResult{
 | 
			
		||||
		commonResult: commonResult{Result: gophercloud.Result{Err: err}},
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetResult is the deferred response from a Get call.
 | 
			
		||||
type GetResult struct {
 | 
			
		||||
	commonResult
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RevokeResult is the deferred response from a Revoke call.
 | 
			
		||||
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.
 | 
			
		||||
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 gophercloud.JSONRFC3339Milli `json:"expires_at"`
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										7
									
								
								vendor/github.com/gophercloud/gophercloud/openstack/identity/v3/tokens/urls.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								vendor/github.com/gophercloud/gophercloud/openstack/identity/v3/tokens/urls.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,7 @@
 | 
			
		||||
package tokens
 | 
			
		||||
 | 
			
		||||
import "github.com/gophercloud/gophercloud"
 | 
			
		||||
 | 
			
		||||
func tokenURL(c *gophercloud.ServiceClient) string {
 | 
			
		||||
	return c.ServiceURL("auth", "tokens")
 | 
			
		||||
}
 | 
			
		||||
@@ -1,9 +1,9 @@
 | 
			
		||||
package extensions
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/rackspace/gophercloud"
 | 
			
		||||
	common "github.com/rackspace/gophercloud/openstack/common/extensions"
 | 
			
		||||
	"github.com/rackspace/gophercloud/pagination"
 | 
			
		||||
	"github.com/gophercloud/gophercloud"
 | 
			
		||||
	common "github.com/gophercloud/gophercloud/openstack/common/extensions"
 | 
			
		||||
	"github.com/gophercloud/gophercloud/pagination"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Extension is a single OpenStack extension.
 | 
			
		||||
@@ -1,10 +1,8 @@
 | 
			
		||||
package floatingips
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
 | 
			
		||||
	"github.com/rackspace/gophercloud"
 | 
			
		||||
	"github.com/rackspace/gophercloud/pagination"
 | 
			
		||||
	"github.com/gophercloud/gophercloud"
 | 
			
		||||
	"github.com/gophercloud/gophercloud/pagination"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// ListOpts allows the filtering and sorting of paginated collections through
 | 
			
		||||
@@ -39,20 +37,28 @@ func List(c *gophercloud.ServiceClient, opts ListOpts) pagination.Pager {
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CreateOptsBuilder is the interface type must satisfy to be used as Create
 | 
			
		||||
// options.
 | 
			
		||||
type CreateOptsBuilder interface {
 | 
			
		||||
	ToFloatingIPCreateMap() (map[string]interface{}, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CreateOpts contains all the values needed to create a new floating IP
 | 
			
		||||
// resource. The only required fields are FloatingNetworkID and PortID which
 | 
			
		||||
// refer to the external network and internal port respectively.
 | 
			
		||||
type CreateOpts struct {
 | 
			
		||||
	FloatingNetworkID string
 | 
			
		||||
	FloatingIP        string
 | 
			
		||||
	PortID            string
 | 
			
		||||
	FixedIP           string
 | 
			
		||||
	TenantID          string
 | 
			
		||||
	FloatingNetworkID string `json:"floating_network_id" required:"true"`
 | 
			
		||||
	FloatingIP        string `json:"floating_ip_address,omitempty"`
 | 
			
		||||
	PortID            string `json:"port_id,omitempty"`
 | 
			
		||||
	FixedIP           string `json:"fixed_ip_address,omitempty"`
 | 
			
		||||
	TenantID          string `json:"tenant_id,omitempty"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	errFloatingNetworkIDRequired = fmt.Errorf("A NetworkID is required")
 | 
			
		||||
)
 | 
			
		||||
// ToFloatingIPCreateMap allows CreateOpts to satisfy the CreateOptsBuilder
 | 
			
		||||
// interface
 | 
			
		||||
func (opts CreateOpts) ToFloatingIPCreateMap() (map[string]interface{}, error) {
 | 
			
		||||
	return gophercloud.BuildRequestBody(opts, "floatingip")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Create accepts a CreateOpts struct and uses the values provided to create a
 | 
			
		||||
// new floating IP resource. You can create floating IPs on external networks
 | 
			
		||||
@@ -78,45 +84,26 @@ var (
 | 
			
		||||
// operation will fail and return a 400 error code. If the PortID and FixedIP
 | 
			
		||||
// are already associated with another resource, the operation will fail and
 | 
			
		||||
// returns a 409 error code.
 | 
			
		||||
func Create(c *gophercloud.ServiceClient, opts CreateOpts) CreateResult {
 | 
			
		||||
	var res CreateResult
 | 
			
		||||
 | 
			
		||||
	// Validate
 | 
			
		||||
	if opts.FloatingNetworkID == "" {
 | 
			
		||||
		res.Err = errFloatingNetworkIDRequired
 | 
			
		||||
		return res
 | 
			
		||||
func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) (r CreateResult) {
 | 
			
		||||
	b, err := opts.ToFloatingIPCreateMap()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		r.Err = err
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Define structures
 | 
			
		||||
	type floatingIP struct {
 | 
			
		||||
		FloatingNetworkID string `json:"floating_network_id"`
 | 
			
		||||
		FloatingIP        string `json:"floating_ip_address,omitempty"`
 | 
			
		||||
		PortID            string `json:"port_id,omitempty"`
 | 
			
		||||
		FixedIP           string `json:"fixed_ip_address,omitempty"`
 | 
			
		||||
		TenantID          string `json:"tenant_id,omitempty"`
 | 
			
		||||
	}
 | 
			
		||||
	type request struct {
 | 
			
		||||
		FloatingIP floatingIP `json:"floatingip"`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Populate request body
 | 
			
		||||
	reqBody := request{FloatingIP: floatingIP{
 | 
			
		||||
		FloatingNetworkID: opts.FloatingNetworkID,
 | 
			
		||||
		FloatingIP:        opts.FloatingIP,
 | 
			
		||||
		PortID:            opts.PortID,
 | 
			
		||||
		FixedIP:           opts.FixedIP,
 | 
			
		||||
		TenantID:          opts.TenantID,
 | 
			
		||||
	}}
 | 
			
		||||
 | 
			
		||||
	_, res.Err = c.Post(rootURL(c), reqBody, &res.Body, nil)
 | 
			
		||||
	return res
 | 
			
		||||
	_, r.Err = c.Post(rootURL(c), b, &r.Body, nil)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Get retrieves a particular floating IP resource based on its unique ID.
 | 
			
		||||
func Get(c *gophercloud.ServiceClient, id string) GetResult {
 | 
			
		||||
	var res GetResult
 | 
			
		||||
	_, res.Err = c.Get(resourceURL(c, id), &res.Body, nil)
 | 
			
		||||
	return res
 | 
			
		||||
func Get(c *gophercloud.ServiceClient, id string) (r GetResult) {
 | 
			
		||||
	_, r.Err = c.Get(resourceURL(c, id), &r.Body, nil)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UpdateOptsBuilder is the interface type must satisfy to be used as Update
 | 
			
		||||
// options.
 | 
			
		||||
type UpdateOptsBuilder interface {
 | 
			
		||||
	ToFloatingIPUpdateMap() (map[string]interface{}, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UpdateOpts contains the values used when updating a floating IP resource. The
 | 
			
		||||
@@ -124,45 +111,35 @@ func Get(c *gophercloud.ServiceClient, id string) GetResult {
 | 
			
		||||
// linked to. To associate the floating IP with a new internal port, provide its
 | 
			
		||||
// ID. To disassociate the floating IP from all ports, provide an empty string.
 | 
			
		||||
type UpdateOpts struct {
 | 
			
		||||
	PortID string
 | 
			
		||||
	PortID *string `json:"port_id"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ToFloatingIPUpdateMap allows UpdateOpts to satisfy the UpdateOptsBuilder
 | 
			
		||||
// interface
 | 
			
		||||
func (opts UpdateOpts) ToFloatingIPUpdateMap() (map[string]interface{}, error) {
 | 
			
		||||
	return gophercloud.BuildRequestBody(opts, "floatingip")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Update allows floating IP resources to be updated. Currently, the only way to
 | 
			
		||||
// "update" a floating IP is to associate it with a new internal port, or
 | 
			
		||||
// disassociated it from all ports. See UpdateOpts for instructions of how to
 | 
			
		||||
// do this.
 | 
			
		||||
func Update(c *gophercloud.ServiceClient, id string, opts UpdateOpts) UpdateResult {
 | 
			
		||||
	type floatingIP struct {
 | 
			
		||||
		PortID *string `json:"port_id"`
 | 
			
		||||
func Update(c *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) (r UpdateResult) {
 | 
			
		||||
	b, err := opts.ToFloatingIPUpdateMap()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		r.Err = err
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	type request struct {
 | 
			
		||||
		FloatingIP floatingIP `json:"floatingip"`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var portID *string
 | 
			
		||||
	if opts.PortID == "" {
 | 
			
		||||
		portID = nil
 | 
			
		||||
	} else {
 | 
			
		||||
		portID = &opts.PortID
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	reqBody := request{FloatingIP: floatingIP{PortID: portID}}
 | 
			
		||||
 | 
			
		||||
	// Send request to API
 | 
			
		||||
	var res UpdateResult
 | 
			
		||||
	_, res.Err = c.Put(resourceURL(c, id), reqBody, &res.Body, &gophercloud.RequestOpts{
 | 
			
		||||
	_, r.Err = c.Put(resourceURL(c, id), b, &r.Body, &gophercloud.RequestOpts{
 | 
			
		||||
		OkCodes: []int{200},
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	return res
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Delete will permanently delete a particular floating IP resource. Please
 | 
			
		||||
// ensure this is what you want - you can also disassociate the IP from existing
 | 
			
		||||
// internal ports.
 | 
			
		||||
func Delete(c *gophercloud.ServiceClient, id string) DeleteResult {
 | 
			
		||||
	var res DeleteResult
 | 
			
		||||
	_, res.Err = c.Delete(resourceURL(c, id), nil)
 | 
			
		||||
	return res
 | 
			
		||||
func Delete(c *gophercloud.ServiceClient, id string) (r DeleteResult) {
 | 
			
		||||
	_, r.Err = c.Delete(resourceURL(c, id), nil)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
@@ -1,11 +1,8 @@
 | 
			
		||||
package floatingips
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
 | 
			
		||||
	"github.com/mitchellh/mapstructure"
 | 
			
		||||
	"github.com/rackspace/gophercloud"
 | 
			
		||||
	"github.com/rackspace/gophercloud/pagination"
 | 
			
		||||
	"github.com/gophercloud/gophercloud"
 | 
			
		||||
	"github.com/gophercloud/gophercloud/pagination"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// FloatingIP represents a floating IP resource. A floating IP is an external
 | 
			
		||||
@@ -16,27 +13,27 @@ import (
 | 
			
		||||
// attribute (provided by the external network extension) is set to True.
 | 
			
		||||
type FloatingIP struct {
 | 
			
		||||
	// Unique identifier for the floating IP instance.
 | 
			
		||||
	ID string `json:"id" mapstructure:"id"`
 | 
			
		||||
	ID string `json:"id"`
 | 
			
		||||
 | 
			
		||||
	// UUID of the external network where the floating IP is to be created.
 | 
			
		||||
	FloatingNetworkID string `json:"floating_network_id" mapstructure:"floating_network_id"`
 | 
			
		||||
	FloatingNetworkID string `json:"floating_network_id"`
 | 
			
		||||
 | 
			
		||||
	// Address of the floating IP on the external network.
 | 
			
		||||
	FloatingIP string `json:"floating_ip_address" mapstructure:"floating_ip_address"`
 | 
			
		||||
	FloatingIP string `json:"floating_ip_address"`
 | 
			
		||||
 | 
			
		||||
	// UUID of the port on an internal network that is associated with the floating IP.
 | 
			
		||||
	PortID string `json:"port_id" mapstructure:"port_id"`
 | 
			
		||||
	PortID string `json:"port_id"`
 | 
			
		||||
 | 
			
		||||
	// The specific IP address of the internal port which should be associated
 | 
			
		||||
	// with the floating IP.
 | 
			
		||||
	FixedIP string `json:"fixed_ip_address" mapstructure:"fixed_ip_address"`
 | 
			
		||||
	FixedIP string `json:"fixed_ip_address"`
 | 
			
		||||
 | 
			
		||||
	// Owner of the floating IP. Only admin users can specify a tenant identifier
 | 
			
		||||
	// other than its own.
 | 
			
		||||
	TenantID string `json:"tenant_id" mapstructure:"tenant_id"`
 | 
			
		||||
	TenantID string `json:"tenant_id"`
 | 
			
		||||
 | 
			
		||||
	// The condition of the API resource.
 | 
			
		||||
	Status string `json:"status" mapstructure:"status"`
 | 
			
		||||
	Status string `json:"status"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type commonResult struct {
 | 
			
		||||
@@ -45,20 +42,11 @@ type commonResult struct {
 | 
			
		||||
 | 
			
		||||
// Extract a result and extracts a FloatingIP resource.
 | 
			
		||||
func (r commonResult) Extract() (*FloatingIP, error) {
 | 
			
		||||
	if r.Err != nil {
 | 
			
		||||
		return nil, r.Err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var res struct {
 | 
			
		||||
	var s struct {
 | 
			
		||||
		FloatingIP *FloatingIP `json:"floatingip"`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err := mapstructure.Decode(r.Body, &res)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, fmt.Errorf("Error decoding Neutron floating IP: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return res.FloatingIP, nil
 | 
			
		||||
	err := r.ExtractInto(&s)
 | 
			
		||||
	return s.FloatingIP, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CreateResult represents the result of a create operation.
 | 
			
		||||
@@ -90,38 +78,30 @@ type FloatingIPPage struct {
 | 
			
		||||
// NextPageURL is invoked when a paginated collection of floating IPs has reached
 | 
			
		||||
// the end of a page and the pager seeks to traverse over a new one. In order
 | 
			
		||||
// to do this, it needs to construct the next page's URL.
 | 
			
		||||
func (p FloatingIPPage) NextPageURL() (string, error) {
 | 
			
		||||
	type resp struct {
 | 
			
		||||
		Links []gophercloud.Link `mapstructure:"floatingips_links"`
 | 
			
		||||
func (r FloatingIPPage) NextPageURL() (string, error) {
 | 
			
		||||
	var s struct {
 | 
			
		||||
		Links []gophercloud.Link `json:"floatingips_links"`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var r resp
 | 
			
		||||
	err := mapstructure.Decode(p.Body, &r)
 | 
			
		||||
	err := r.ExtractInto(&s)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return gophercloud.ExtractNextURL(r.Links)
 | 
			
		||||
	return gophercloud.ExtractNextURL(s.Links)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IsEmpty checks whether a NetworkPage struct is empty.
 | 
			
		||||
func (p FloatingIPPage) IsEmpty() (bool, error) {
 | 
			
		||||
	is, err := ExtractFloatingIPs(p)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return true, nil
 | 
			
		||||
	}
 | 
			
		||||
	return len(is) == 0, nil
 | 
			
		||||
func (r FloatingIPPage) IsEmpty() (bool, error) {
 | 
			
		||||
	is, err := ExtractFloatingIPs(r)
 | 
			
		||||
	return len(is) == 0, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ExtractFloatingIPs accepts a Page struct, specifically a FloatingIPPage struct,
 | 
			
		||||
// and extracts the elements into a slice of FloatingIP structs. In other words,
 | 
			
		||||
// a generic collection is mapped into a relevant slice.
 | 
			
		||||
func ExtractFloatingIPs(page pagination.Page) ([]FloatingIP, error) {
 | 
			
		||||
	var resp struct {
 | 
			
		||||
		FloatingIPs []FloatingIP `mapstructure:"floatingips" json:"floatingips"`
 | 
			
		||||
func ExtractFloatingIPs(r pagination.Page) ([]FloatingIP, error) {
 | 
			
		||||
	var s struct {
 | 
			
		||||
		FloatingIPs []FloatingIP `json:"floatingips"`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err := mapstructure.Decode(page.(FloatingIPPage).Body, &resp)
 | 
			
		||||
 | 
			
		||||
	return resp.FloatingIPs, err
 | 
			
		||||
	err := (r.(FloatingIPPage)).ExtractInto(&s)
 | 
			
		||||
	return s.FloatingIPs, err
 | 
			
		||||
}
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
package floatingips
 | 
			
		||||
 | 
			
		||||
import "github.com/rackspace/gophercloud"
 | 
			
		||||
import "github.com/gophercloud/gophercloud"
 | 
			
		||||
 | 
			
		||||
const resourcePath = "floatingips"
 | 
			
		||||
 | 
			
		||||
@@ -1,10 +1,8 @@
 | 
			
		||||
package routers
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
 | 
			
		||||
	"github.com/rackspace/gophercloud"
 | 
			
		||||
	"github.com/rackspace/gophercloud/pagination"
 | 
			
		||||
	"github.com/gophercloud/gophercloud"
 | 
			
		||||
	"github.com/gophercloud/gophercloud/pagination"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// ListOpts allows the filtering and sorting of paginated collections through
 | 
			
		||||
@@ -53,38 +51,15 @@ type CreateOptsBuilder interface {
 | 
			
		||||
// CreateOpts contains all the values needed to create a new router. There are
 | 
			
		||||
// no required values.
 | 
			
		||||
type CreateOpts struct {
 | 
			
		||||
	Name         string
 | 
			
		||||
	AdminStateUp *bool
 | 
			
		||||
	Distributed  *bool
 | 
			
		||||
	TenantID     string
 | 
			
		||||
	GatewayInfo  *GatewayInfo
 | 
			
		||||
	Name         string       `json:"name,omitempty"`
 | 
			
		||||
	AdminStateUp *bool        `json:"admin_state_up,omitempty"`
 | 
			
		||||
	Distributed  *bool        `json:"distributed,omitempty"`
 | 
			
		||||
	TenantID     string       `json:"tenant_id,omitempty"`
 | 
			
		||||
	GatewayInfo  *GatewayInfo `json:"external_gateway_info,omitempty"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ToRouterCreateMap casts a CreateOpts struct to a map.
 | 
			
		||||
func (opts CreateOpts) ToRouterCreateMap() (map[string]interface{}, error) {
 | 
			
		||||
	r := make(map[string]interface{})
 | 
			
		||||
 | 
			
		||||
	if gophercloud.MaybeString(opts.Name) != nil {
 | 
			
		||||
		r["name"] = opts.Name
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if opts.AdminStateUp != nil {
 | 
			
		||||
		r["admin_state_up"] = opts.AdminStateUp
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if opts.Distributed != nil {
 | 
			
		||||
		r["distributed"] = opts.Distributed
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if gophercloud.MaybeString(opts.TenantID) != nil {
 | 
			
		||||
		r["tenant_id"] = opts.TenantID
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if opts.GatewayInfo != nil {
 | 
			
		||||
		r["external_gateway_info"] = opts.GatewayInfo
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return map[string]interface{}{"router": r}, nil
 | 
			
		||||
	return gophercloud.BuildRequestBody(opts, "router")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Create accepts a CreateOpts struct and uses the values to create a new
 | 
			
		||||
@@ -95,33 +70,37 @@ func (opts CreateOpts) ToRouterCreateMap() (map[string]interface{}, error) {
 | 
			
		||||
// GatewayInfo struct. The external gateway for the router must be plugged into
 | 
			
		||||
// an external network (it is external if its `router:external' field is set to
 | 
			
		||||
// true).
 | 
			
		||||
func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult {
 | 
			
		||||
	var res CreateResult
 | 
			
		||||
 | 
			
		||||
	reqBody, err := opts.ToRouterCreateMap()
 | 
			
		||||
func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) (r CreateResult) {
 | 
			
		||||
	b, err := opts.ToRouterCreateMap()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		res.Err = err
 | 
			
		||||
		return res
 | 
			
		||||
		r.Err = err
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	_, res.Err = c.Post(rootURL(c), reqBody, &res.Body, nil)
 | 
			
		||||
	return res
 | 
			
		||||
	_, r.Err = c.Post(rootURL(c), b, &r.Body, nil)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Get retrieves a particular router based on its unique ID.
 | 
			
		||||
func Get(c *gophercloud.ServiceClient, id string) GetResult {
 | 
			
		||||
	var res GetResult
 | 
			
		||||
	_, res.Err = c.Get(resourceURL(c, id), &res.Body, nil)
 | 
			
		||||
	return res
 | 
			
		||||
func Get(c *gophercloud.ServiceClient, id string) (r GetResult) {
 | 
			
		||||
	_, r.Err = c.Get(resourceURL(c, id), &r.Body, nil)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type UpdateOptsBuilder interface {
 | 
			
		||||
	ToRouterUpdateMap() (map[string]interface{}, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UpdateOpts contains the values used when updating a router.
 | 
			
		||||
type UpdateOpts struct {
 | 
			
		||||
	Name         string
 | 
			
		||||
	AdminStateUp *bool
 | 
			
		||||
	Distributed  *bool
 | 
			
		||||
	GatewayInfo  *GatewayInfo
 | 
			
		||||
	Routes       []Route
 | 
			
		||||
	Name         string       `json:"name,omitempty"`
 | 
			
		||||
	AdminStateUp *bool        `json:"admin_state_up,omitempty"`
 | 
			
		||||
	Distributed  *bool        `json:"distributed,omitempty"`
 | 
			
		||||
	GatewayInfo  *GatewayInfo `json:"external_gateway_info,omitempty"`
 | 
			
		||||
	Routes       []Route      `json:"routes"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (opts UpdateOpts) ToRouterUpdateMap() (map[string]interface{}, error) {
 | 
			
		||||
	return gophercloud.BuildRequestBody(opts, "router")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Update allows routers to be updated. You can update the name, administrative
 | 
			
		||||
@@ -129,56 +108,41 @@ type UpdateOpts struct {
 | 
			
		||||
// external gateway for a router, see Create. This operation does not enable
 | 
			
		||||
// the update of router interfaces. To do this, use the AddInterface and
 | 
			
		||||
// RemoveInterface functions.
 | 
			
		||||
func Update(c *gophercloud.ServiceClient, id string, opts UpdateOpts) UpdateResult {
 | 
			
		||||
	type router struct {
 | 
			
		||||
		Name         *string      `json:"name,omitempty"`
 | 
			
		||||
		AdminStateUp *bool        `json:"admin_state_up,omitempty"`
 | 
			
		||||
		Distributed  *bool        `json:"distributed,omitempty"`
 | 
			
		||||
		GatewayInfo  *GatewayInfo `json:"external_gateway_info,omitempty"`
 | 
			
		||||
		Routes       []Route      `json:"routes"`
 | 
			
		||||
func Update(c *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) (r UpdateResult) {
 | 
			
		||||
	b, err := opts.ToRouterUpdateMap()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		r.Err = err
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	type request struct {
 | 
			
		||||
		Router router `json:"router"`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	reqBody := request{Router: router{
 | 
			
		||||
		Name:         gophercloud.MaybeString(opts.Name),
 | 
			
		||||
		AdminStateUp: opts.AdminStateUp,
 | 
			
		||||
		Distributed:  opts.Distributed,
 | 
			
		||||
	}}
 | 
			
		||||
 | 
			
		||||
	if opts.GatewayInfo != nil {
 | 
			
		||||
		reqBody.Router.GatewayInfo = opts.GatewayInfo
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if opts.Routes != nil {
 | 
			
		||||
		reqBody.Router.Routes = opts.Routes
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Send request to API
 | 
			
		||||
	var res UpdateResult
 | 
			
		||||
	_, res.Err = c.Put(resourceURL(c, id), reqBody, &res.Body, &gophercloud.RequestOpts{
 | 
			
		||||
	_, r.Err = c.Put(resourceURL(c, id), b, &r.Body, &gophercloud.RequestOpts{
 | 
			
		||||
		OkCodes: []int{200},
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	return res
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Delete will permanently delete a particular router based on its unique ID.
 | 
			
		||||
func Delete(c *gophercloud.ServiceClient, id string) DeleteResult {
 | 
			
		||||
	var res DeleteResult
 | 
			
		||||
	_, res.Err = c.Delete(resourceURL(c, id), nil)
 | 
			
		||||
	return res
 | 
			
		||||
func Delete(c *gophercloud.ServiceClient, id string) (r DeleteResult) {
 | 
			
		||||
	_, r.Err = c.Delete(resourceURL(c, id), nil)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var errInvalidInterfaceOpts = errors.New("When adding a router interface you must provide either a subnet ID or a port ID")
 | 
			
		||||
// AddInterfaceOptsBuilder is what types must satisfy to be used as AddInterface
 | 
			
		||||
// options.
 | 
			
		||||
type AddInterfaceOptsBuilder interface {
 | 
			
		||||
	ToRouterAddInterfaceMap() (map[string]interface{}, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// InterfaceOpts allow you to work with operations that either add or remote
 | 
			
		||||
// AddInterfaceOpts allow you to work with operations that either add
 | 
			
		||||
// an internal interface from a router.
 | 
			
		||||
type InterfaceOpts struct {
 | 
			
		||||
	SubnetID string
 | 
			
		||||
	PortID   string
 | 
			
		||||
type AddInterfaceOpts struct {
 | 
			
		||||
	SubnetID string `json:"subnet_id,omitempty" xor:"PortID"`
 | 
			
		||||
	PortID   string `json:"port_id,omitempty" xor:"SubnetID"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ToRouterAddInterfaceMap allows InterfaceOpts to satisfy the InterfaceOptsBuilder
 | 
			
		||||
// interface
 | 
			
		||||
func (opts AddInterfaceOpts) ToRouterAddInterfaceMap() (map[string]interface{}, error) {
 | 
			
		||||
	return gophercloud.BuildRequestBody(opts, "")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// AddInterface attaches a subnet to an internal router interface. You must
 | 
			
		||||
@@ -202,27 +166,35 @@ type InterfaceOpts struct {
 | 
			
		||||
// identifier of a new port created by this operation. After the operation
 | 
			
		||||
// completes, the device ID of the port is set to the router ID, and the
 | 
			
		||||
// device owner attribute is set to `network:router_interface'.
 | 
			
		||||
func AddInterface(c *gophercloud.ServiceClient, id string, opts InterfaceOpts) InterfaceResult {
 | 
			
		||||
	var res InterfaceResult
 | 
			
		||||
 | 
			
		||||
	// Validate
 | 
			
		||||
	if (opts.SubnetID == "" && opts.PortID == "") || (opts.SubnetID != "" && opts.PortID != "") {
 | 
			
		||||
		res.Err = errInvalidInterfaceOpts
 | 
			
		||||
		return res
 | 
			
		||||
func AddInterface(c *gophercloud.ServiceClient, id string, opts AddInterfaceOptsBuilder) (r InterfaceResult) {
 | 
			
		||||
	b, err := opts.ToRouterAddInterfaceMap()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		r.Err = err
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	type request struct {
 | 
			
		||||
		SubnetID string `json:"subnet_id,omitempty"`
 | 
			
		||||
		PortID   string `json:"port_id,omitempty"`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	body := request{SubnetID: opts.SubnetID, PortID: opts.PortID}
 | 
			
		||||
 | 
			
		||||
	_, res.Err = c.Put(addInterfaceURL(c, id), body, &res.Body, &gophercloud.RequestOpts{
 | 
			
		||||
	_, r.Err = c.Put(addInterfaceURL(c, id), b, &r.Body, &gophercloud.RequestOpts{
 | 
			
		||||
		OkCodes: []int{200},
 | 
			
		||||
	})
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
	return res
 | 
			
		||||
// RemoveInterfaceOptsBuilder is what types must satisfy to be used as RemoveInterface
 | 
			
		||||
// options.
 | 
			
		||||
type RemoveInterfaceOptsBuilder interface {
 | 
			
		||||
	ToRouterRemoveInterfaceMap() (map[string]interface{}, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RemoveInterfaceOpts allow you to work with operations that either add or remote
 | 
			
		||||
// an internal interface from a router.
 | 
			
		||||
type RemoveInterfaceOpts struct {
 | 
			
		||||
	SubnetID string `json:"subnet_id,omitempty" or:"PortID"`
 | 
			
		||||
	PortID   string `json:"port_id,omitempty" or:"SubnetID"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ToRouterRemoveInterfaceMap allows RemoveInterfaceOpts to satisfy the RemoveInterfaceOptsBuilder
 | 
			
		||||
// interface
 | 
			
		||||
func (opts RemoveInterfaceOpts) ToRouterRemoveInterfaceMap() (map[string]interface{}, error) {
 | 
			
		||||
	return gophercloud.BuildRequestBody(opts, "")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RemoveInterface removes an internal router interface, which detaches a
 | 
			
		||||
@@ -238,19 +210,14 @@ func AddInterface(c *gophercloud.ServiceClient, id string, opts InterfaceOpts) I
 | 
			
		||||
// visible to you, the operation will fail and a 404 Not Found error will be
 | 
			
		||||
// returned. After this operation completes, the port connecting the router
 | 
			
		||||
// with the subnet is removed from the subnet for the network.
 | 
			
		||||
func RemoveInterface(c *gophercloud.ServiceClient, id string, opts InterfaceOpts) InterfaceResult {
 | 
			
		||||
	var res InterfaceResult
 | 
			
		||||
 | 
			
		||||
	type request struct {
 | 
			
		||||
		SubnetID string `json:"subnet_id,omitempty"`
 | 
			
		||||
		PortID   string `json:"port_id,omitempty"`
 | 
			
		||||
func RemoveInterface(c *gophercloud.ServiceClient, id string, opts RemoveInterfaceOptsBuilder) (r InterfaceResult) {
 | 
			
		||||
	b, err := opts.ToRouterRemoveInterfaceMap()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		r.Err = err
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	body := request{SubnetID: opts.SubnetID, PortID: opts.PortID}
 | 
			
		||||
 | 
			
		||||
	_, res.Err = c.Put(removeInterfaceURL(c, id), body, &res.Body, &gophercloud.RequestOpts{
 | 
			
		||||
	_, r.Err = c.Put(removeInterfaceURL(c, id), b, &r.Body, &gophercloud.RequestOpts{
 | 
			
		||||
		OkCodes: []int{200},
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	return res
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
@@ -1,20 +1,20 @@
 | 
			
		||||
package routers
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/mitchellh/mapstructure"
 | 
			
		||||
	"github.com/rackspace/gophercloud"
 | 
			
		||||
	"github.com/rackspace/gophercloud/pagination"
 | 
			
		||||
	"github.com/gophercloud/gophercloud"
 | 
			
		||||
	"github.com/gophercloud/gophercloud/pagination"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// GatewayInfo represents the information of an external gateway for any
 | 
			
		||||
// particular network router.
 | 
			
		||||
type GatewayInfo struct {
 | 
			
		||||
	NetworkID string `json:"network_id" mapstructure:"network_id"`
 | 
			
		||||
	NetworkID string `json:"network_id"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Route is a possible route in a router.
 | 
			
		||||
type Route struct {
 | 
			
		||||
	NextHop         string `mapstructure:"nexthop" json:"nexthop"`
 | 
			
		||||
	DestinationCIDR string `mapstructure:"destination" json:"destination"`
 | 
			
		||||
	NextHop         string `json:"nexthop"`
 | 
			
		||||
	DestinationCIDR string `json:"destination"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Router represents a Neutron router. A router is a logical entity that
 | 
			
		||||
@@ -27,28 +27,28 @@ type Route struct {
 | 
			
		||||
// interface is added to the subnet's network.
 | 
			
		||||
type Router struct {
 | 
			
		||||
	// Indicates whether or not a router is currently operational.
 | 
			
		||||
	Status string `json:"status" mapstructure:"status"`
 | 
			
		||||
	Status string `json:"status"`
 | 
			
		||||
 | 
			
		||||
	// Information on external gateway for the router.
 | 
			
		||||
	GatewayInfo GatewayInfo `json:"external_gateway_info" mapstructure:"external_gateway_info"`
 | 
			
		||||
	GatewayInfo GatewayInfo `json:"external_gateway_info"`
 | 
			
		||||
 | 
			
		||||
	// Administrative state of the router.
 | 
			
		||||
	AdminStateUp bool `json:"admin_state_up" mapstructure:"admin_state_up"`
 | 
			
		||||
	AdminStateUp bool `json:"admin_state_up"`
 | 
			
		||||
 | 
			
		||||
	// Whether router is disitrubted or not..
 | 
			
		||||
	Distributed bool `json:"distributed" mapstructure:"distributed"`
 | 
			
		||||
	Distributed bool `json:"distributed"`
 | 
			
		||||
 | 
			
		||||
	// Human readable name for the router. Does not have to be unique.
 | 
			
		||||
	Name string `json:"name" mapstructure:"name"`
 | 
			
		||||
	Name string `json:"name"`
 | 
			
		||||
 | 
			
		||||
	// Unique identifier for the router.
 | 
			
		||||
	ID string `json:"id" mapstructure:"id"`
 | 
			
		||||
	ID string `json:"id"`
 | 
			
		||||
 | 
			
		||||
	// Owner of the router. Only admin users can specify a tenant identifier
 | 
			
		||||
	// other than its own.
 | 
			
		||||
	TenantID string `json:"tenant_id" mapstructure:"tenant_id"`
 | 
			
		||||
	TenantID string `json:"tenant_id"`
 | 
			
		||||
 | 
			
		||||
	Routes []Route `json:"routes" mapstructure:"routes"`
 | 
			
		||||
	Routes []Route `json:"routes"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RouterPage is the page returned by a pager when traversing over a
 | 
			
		||||
@@ -60,40 +60,32 @@ type RouterPage struct {
 | 
			
		||||
// NextPageURL is invoked when a paginated collection of routers has reached
 | 
			
		||||
// the end of a page and the pager seeks to traverse over a new one. In order
 | 
			
		||||
// to do this, it needs to construct the next page's URL.
 | 
			
		||||
func (p RouterPage) NextPageURL() (string, error) {
 | 
			
		||||
	type resp struct {
 | 
			
		||||
		Links []gophercloud.Link `mapstructure:"routers_links"`
 | 
			
		||||
func (r RouterPage) NextPageURL() (string, error) {
 | 
			
		||||
	var s struct {
 | 
			
		||||
		Links []gophercloud.Link `json:"routers_links"`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var r resp
 | 
			
		||||
	err := mapstructure.Decode(p.Body, &r)
 | 
			
		||||
	err := r.ExtractInto(&s)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return gophercloud.ExtractNextURL(r.Links)
 | 
			
		||||
	return gophercloud.ExtractNextURL(s.Links)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IsEmpty checks whether a RouterPage struct is empty.
 | 
			
		||||
func (p RouterPage) IsEmpty() (bool, error) {
 | 
			
		||||
	is, err := ExtractRouters(p)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return true, nil
 | 
			
		||||
	}
 | 
			
		||||
	return len(is) == 0, nil
 | 
			
		||||
func (r RouterPage) IsEmpty() (bool, error) {
 | 
			
		||||
	is, err := ExtractRouters(r)
 | 
			
		||||
	return len(is) == 0, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ExtractRouters accepts a Page struct, specifically a RouterPage struct,
 | 
			
		||||
// and extracts the elements into a slice of Router structs. In other words,
 | 
			
		||||
// a generic collection is mapped into a relevant slice.
 | 
			
		||||
func ExtractRouters(page pagination.Page) ([]Router, error) {
 | 
			
		||||
	var resp struct {
 | 
			
		||||
		Routers []Router `mapstructure:"routers" json:"routers"`
 | 
			
		||||
func ExtractRouters(r pagination.Page) ([]Router, error) {
 | 
			
		||||
	var s struct {
 | 
			
		||||
		Routers []Router `json:"routers"`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err := mapstructure.Decode(page.(RouterPage).Body, &resp)
 | 
			
		||||
 | 
			
		||||
	return resp.Routers, err
 | 
			
		||||
	err := (r.(RouterPage)).ExtractInto(&s)
 | 
			
		||||
	return s.Routers, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type commonResult struct {
 | 
			
		||||
@@ -102,17 +94,11 @@ type commonResult struct {
 | 
			
		||||
 | 
			
		||||
// Extract is a function that accepts a result and extracts a router.
 | 
			
		||||
func (r commonResult) Extract() (*Router, error) {
 | 
			
		||||
	if r.Err != nil {
 | 
			
		||||
		return nil, r.Err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var res struct {
 | 
			
		||||
	var s struct {
 | 
			
		||||
		Router *Router `json:"router"`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err := mapstructure.Decode(r.Body, &res)
 | 
			
		||||
 | 
			
		||||
	return res.Router, err
 | 
			
		||||
	err := r.ExtractInto(&s)
 | 
			
		||||
	return s.Router, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CreateResult represents the result of a create operation.
 | 
			
		||||
@@ -140,16 +126,16 @@ type DeleteResult struct {
 | 
			
		||||
// interface.
 | 
			
		||||
type InterfaceInfo struct {
 | 
			
		||||
	// The ID of the subnet which this interface is associated with.
 | 
			
		||||
	SubnetID string `json:"subnet_id" mapstructure:"subnet_id"`
 | 
			
		||||
	SubnetID string `json:"subnet_id"`
 | 
			
		||||
 | 
			
		||||
	// The ID of the port that is a part of the subnet.
 | 
			
		||||
	PortID string `json:"port_id" mapstructure:"port_id"`
 | 
			
		||||
	PortID string `json:"port_id"`
 | 
			
		||||
 | 
			
		||||
	// The UUID of the interface.
 | 
			
		||||
	ID string `json:"id" mapstructure:"id"`
 | 
			
		||||
	ID string `json:"id"`
 | 
			
		||||
 | 
			
		||||
	// Owner of the interface.
 | 
			
		||||
	TenantID string `json:"tenant_id" mapstructure:"tenant_id"`
 | 
			
		||||
	TenantID string `json:"tenant_id"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// InterfaceResult represents the result of interface operations, such as
 | 
			
		||||
@@ -160,12 +146,7 @@ type InterfaceResult struct {
 | 
			
		||||
 | 
			
		||||
// Extract is a function that accepts a result and extracts an information struct.
 | 
			
		||||
func (r InterfaceResult) Extract() (*InterfaceInfo, error) {
 | 
			
		||||
	if r.Err != nil {
 | 
			
		||||
		return nil, r.Err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var res *InterfaceInfo
 | 
			
		||||
	err := mapstructure.Decode(r.Body, &res)
 | 
			
		||||
 | 
			
		||||
	return res, err
 | 
			
		||||
	var s InterfaceInfo
 | 
			
		||||
	err := r.ExtractInto(&s)
 | 
			
		||||
	return &s, err
 | 
			
		||||
}
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
package routers
 | 
			
		||||
 | 
			
		||||
import "github.com/rackspace/gophercloud"
 | 
			
		||||
import "github.com/gophercloud/gophercloud"
 | 
			
		||||
 | 
			
		||||
const resourcePath = "routers"
 | 
			
		||||
 | 
			
		||||
@@ -1,8 +1,8 @@
 | 
			
		||||
package members
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/rackspace/gophercloud"
 | 
			
		||||
	"github.com/rackspace/gophercloud/pagination"
 | 
			
		||||
	"github.com/gophercloud/gophercloud"
 | 
			
		||||
	"github.com/gophercloud/gophercloud/pagination"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// ListOpts allows the filtering and sorting of paginated collections through
 | 
			
		||||
@@ -42,82 +42,74 @@ func List(c *gophercloud.ServiceClient, opts ListOpts) pagination.Pager {
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type CreateOptsBuilder interface {
 | 
			
		||||
	ToLBMemberCreateMap() (map[string]interface{}, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CreateOpts contains all the values needed to create a new pool member.
 | 
			
		||||
type CreateOpts struct {
 | 
			
		||||
	// The IP address of the member.
 | 
			
		||||
	Address string `json:"address" required:"true"`
 | 
			
		||||
	// The port on which the application is hosted.
 | 
			
		||||
	ProtocolPort int `json:"protocol_port" required:"true"`
 | 
			
		||||
	// The pool to which this member will belong.
 | 
			
		||||
	PoolID string `json:"pool_id" required:"true"`
 | 
			
		||||
	// Only required if the caller has an admin role and wants to create a pool
 | 
			
		||||
	// for another tenant.
 | 
			
		||||
	TenantID string
 | 
			
		||||
	TenantID string `json:"tenant_id,omitempty"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
	// Required. The IP address of the member.
 | 
			
		||||
	Address string
 | 
			
		||||
 | 
			
		||||
	// Required. The port on which the application is hosted.
 | 
			
		||||
	ProtocolPort int
 | 
			
		||||
 | 
			
		||||
	// Required. The pool to which this member will belong.
 | 
			
		||||
	PoolID string
 | 
			
		||||
func (opts CreateOpts) ToLBMemberCreateMap() (map[string]interface{}, error) {
 | 
			
		||||
	return gophercloud.BuildRequestBody(opts, "member")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Create accepts a CreateOpts struct and uses the values to create a new
 | 
			
		||||
// load balancer pool member.
 | 
			
		||||
func Create(c *gophercloud.ServiceClient, opts CreateOpts) CreateResult {
 | 
			
		||||
	type member struct {
 | 
			
		||||
		TenantID     string `json:"tenant_id,omitempty"`
 | 
			
		||||
		ProtocolPort int    `json:"protocol_port"`
 | 
			
		||||
		Address      string `json:"address"`
 | 
			
		||||
		PoolID       string `json:"pool_id"`
 | 
			
		||||
func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) (r CreateResult) {
 | 
			
		||||
	b, err := opts.ToLBMemberCreateMap()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		r.Err = err
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	type request struct {
 | 
			
		||||
		Member member `json:"member"`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	reqBody := request{Member: member{
 | 
			
		||||
		Address:      opts.Address,
 | 
			
		||||
		TenantID:     opts.TenantID,
 | 
			
		||||
		ProtocolPort: opts.ProtocolPort,
 | 
			
		||||
		PoolID:       opts.PoolID,
 | 
			
		||||
	}}
 | 
			
		||||
 | 
			
		||||
	var res CreateResult
 | 
			
		||||
	_, res.Err = c.Post(rootURL(c), reqBody, &res.Body, nil)
 | 
			
		||||
	return res
 | 
			
		||||
	_, r.Err = c.Post(rootURL(c), b, &r.Body, nil)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Get retrieves a particular pool member based on its unique ID.
 | 
			
		||||
func Get(c *gophercloud.ServiceClient, id string) GetResult {
 | 
			
		||||
	var res GetResult
 | 
			
		||||
	_, res.Err = c.Get(resourceURL(c, id), &res.Body, nil)
 | 
			
		||||
	return res
 | 
			
		||||
func Get(c *gophercloud.ServiceClient, id string) (r GetResult) {
 | 
			
		||||
	_, r.Err = c.Get(resourceURL(c, id), &r.Body, nil)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type UpdateOptsBuilder interface {
 | 
			
		||||
	ToLBMemberUpdateMap() (map[string]interface{}, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UpdateOpts contains the values used when updating a pool member.
 | 
			
		||||
type UpdateOpts struct {
 | 
			
		||||
	// The administrative state of the member, which is up (true) or down (false).
 | 
			
		||||
	AdminStateUp bool
 | 
			
		||||
	AdminStateUp *bool `json:"admin_state_up,omitempty"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (opts UpdateOpts) ToLBMemberUpdateMap() (map[string]interface{}, error) {
 | 
			
		||||
	return gophercloud.BuildRequestBody(opts, "member")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Update allows members to be updated.
 | 
			
		||||
func Update(c *gophercloud.ServiceClient, id string, opts UpdateOpts) UpdateResult {
 | 
			
		||||
	type member struct {
 | 
			
		||||
		AdminStateUp bool `json:"admin_state_up"`
 | 
			
		||||
func Update(c *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) (r UpdateResult) {
 | 
			
		||||
	b, err := opts.ToLBMemberUpdateMap()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		r.Err = err
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	type request struct {
 | 
			
		||||
		Member member `json:"member"`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	reqBody := request{Member: member{AdminStateUp: opts.AdminStateUp}}
 | 
			
		||||
 | 
			
		||||
	// Send request to API
 | 
			
		||||
	var res UpdateResult
 | 
			
		||||
	_, res.Err = c.Put(resourceURL(c, id), reqBody, &res.Body, &gophercloud.RequestOpts{
 | 
			
		||||
	_, r.Err = c.Put(resourceURL(c, id), b, &r.Body, &gophercloud.RequestOpts{
 | 
			
		||||
		OkCodes: []int{200, 201, 202},
 | 
			
		||||
	})
 | 
			
		||||
	return res
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Delete will permanently delete a particular member based on its unique ID.
 | 
			
		||||
func Delete(c *gophercloud.ServiceClient, id string) DeleteResult {
 | 
			
		||||
	var res DeleteResult
 | 
			
		||||
	_, res.Err = c.Delete(resourceURL(c, id), nil)
 | 
			
		||||
	return res
 | 
			
		||||
func Delete(c *gophercloud.ServiceClient, id string) (r DeleteResult) {
 | 
			
		||||
	_, r.Err = c.Delete(resourceURL(c, id), nil)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
@@ -1,9 +1,8 @@
 | 
			
		||||
package members
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/mitchellh/mapstructure"
 | 
			
		||||
	"github.com/rackspace/gophercloud"
 | 
			
		||||
	"github.com/rackspace/gophercloud/pagination"
 | 
			
		||||
	"github.com/gophercloud/gophercloud"
 | 
			
		||||
	"github.com/gophercloud/gophercloud/pagination"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Member represents the application running on a backend server.
 | 
			
		||||
@@ -15,20 +14,20 @@ type Member struct {
 | 
			
		||||
	Weight int
 | 
			
		||||
 | 
			
		||||
	// The administrative state of the member, which is up (true) or down (false).
 | 
			
		||||
	AdminStateUp bool `json:"admin_state_up" mapstructure:"admin_state_up"`
 | 
			
		||||
	AdminStateUp bool `json:"admin_state_up"`
 | 
			
		||||
 | 
			
		||||
	// Owner of the member. Only an administrative user can specify a tenant ID
 | 
			
		||||
	// other than its own.
 | 
			
		||||
	TenantID string `json:"tenant_id" mapstructure:"tenant_id"`
 | 
			
		||||
	TenantID string `json:"tenant_id"`
 | 
			
		||||
 | 
			
		||||
	// The pool to which the member belongs.
 | 
			
		||||
	PoolID string `json:"pool_id" mapstructure:"pool_id"`
 | 
			
		||||
	PoolID string `json:"pool_id"`
 | 
			
		||||
 | 
			
		||||
	// The IP address of the member.
 | 
			
		||||
	Address string
 | 
			
		||||
 | 
			
		||||
	// The port on which the application is hosted.
 | 
			
		||||
	ProtocolPort int `json:"protocol_port" mapstructure:"protocol_port"`
 | 
			
		||||
	ProtocolPort int `json:"protocol_port"`
 | 
			
		||||
 | 
			
		||||
	// The unique ID for the member.
 | 
			
		||||
	ID string
 | 
			
		||||
@@ -43,43 +42,32 @@ type MemberPage struct {
 | 
			
		||||
// NextPageURL is invoked when a paginated collection of members has reached
 | 
			
		||||
// the end of a page and the pager seeks to traverse over a new one. In order
 | 
			
		||||
// to do this, it needs to construct the next page's URL.
 | 
			
		||||
func (p MemberPage) NextPageURL() (string, error) {
 | 
			
		||||
	type resp struct {
 | 
			
		||||
		Links []gophercloud.Link `mapstructure:"members_links"`
 | 
			
		||||
func (r MemberPage) NextPageURL() (string, error) {
 | 
			
		||||
	var s struct {
 | 
			
		||||
		Links []gophercloud.Link `json:"members_links"`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var r resp
 | 
			
		||||
	err := mapstructure.Decode(p.Body, &r)
 | 
			
		||||
	err := r.ExtractInto(&s)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return gophercloud.ExtractNextURL(r.Links)
 | 
			
		||||
	return gophercloud.ExtractNextURL(s.Links)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IsEmpty checks whether a MemberPage struct is empty.
 | 
			
		||||
func (p MemberPage) IsEmpty() (bool, error) {
 | 
			
		||||
	is, err := ExtractMembers(p)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return true, nil
 | 
			
		||||
	}
 | 
			
		||||
	return len(is) == 0, nil
 | 
			
		||||
func (r MemberPage) IsEmpty() (bool, error) {
 | 
			
		||||
	is, err := ExtractMembers(r)
 | 
			
		||||
	return len(is) == 0, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ExtractMembers accepts a Page struct, specifically a MemberPage struct,
 | 
			
		||||
// and extracts the elements into a slice of Member structs. In other words,
 | 
			
		||||
// a generic collection is mapped into a relevant slice.
 | 
			
		||||
func ExtractMembers(page pagination.Page) ([]Member, error) {
 | 
			
		||||
	var resp struct {
 | 
			
		||||
		Members []Member `mapstructure:"members" json:"members"`
 | 
			
		||||
func ExtractMembers(r pagination.Page) ([]Member, error) {
 | 
			
		||||
	var s struct {
 | 
			
		||||
		Members []Member `json:"members"`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err := mapstructure.Decode(page.(MemberPage).Body, &resp)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return resp.Members, nil
 | 
			
		||||
	err := (r.(MemberPage)).ExtractInto(&s)
 | 
			
		||||
	return s.Members, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type commonResult struct {
 | 
			
		||||
@@ -88,17 +76,11 @@ type commonResult struct {
 | 
			
		||||
 | 
			
		||||
// Extract is a function that accepts a result and extracts a router.
 | 
			
		||||
func (r commonResult) Extract() (*Member, error) {
 | 
			
		||||
	if r.Err != nil {
 | 
			
		||||
		return nil, r.Err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var res struct {
 | 
			
		||||
	var s struct {
 | 
			
		||||
		Member *Member `json:"member"`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err := mapstructure.Decode(r.Body, &res)
 | 
			
		||||
 | 
			
		||||
	return res.Member, err
 | 
			
		||||
	err := r.ExtractInto(&s)
 | 
			
		||||
	return s.Member, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CreateResult represents the result of a create operation.
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
package members
 | 
			
		||||
 | 
			
		||||
import "github.com/rackspace/gophercloud"
 | 
			
		||||
import "github.com/gophercloud/gophercloud"
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	rootPath     = "lb"
 | 
			
		||||
@@ -3,8 +3,8 @@ package monitors
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
 | 
			
		||||
	"github.com/rackspace/gophercloud"
 | 
			
		||||
	"github.com/rackspace/gophercloud/pagination"
 | 
			
		||||
	"github.com/gophercloud/gophercloud"
 | 
			
		||||
	"github.com/gophercloud/gophercloud/pagination"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// ListOpts allows the filtering and sorting of paginated collections through
 | 
			
		||||
@@ -42,64 +42,78 @@ func List(c *gophercloud.ServiceClient, opts ListOpts) pagination.Pager {
 | 
			
		||||
		return pagination.Pager{Err: err}
 | 
			
		||||
	}
 | 
			
		||||
	u := rootURL(c) + q.String()
 | 
			
		||||
 | 
			
		||||
	return pagination.NewPager(c, u, func(r pagination.PageResult) pagination.Page {
 | 
			
		||||
		return MonitorPage{pagination.LinkedPageBase{PageResult: r}}
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// MonitorType is the type for all the types of LB monitors
 | 
			
		||||
type MonitorType string
 | 
			
		||||
 | 
			
		||||
// Constants that represent approved monitoring types.
 | 
			
		||||
const (
 | 
			
		||||
	TypePING  = "PING"
 | 
			
		||||
	TypeTCP   = "TCP"
 | 
			
		||||
	TypeHTTP  = "HTTP"
 | 
			
		||||
	TypeHTTPS = "HTTPS"
 | 
			
		||||
	TypePING  MonitorType = "PING"
 | 
			
		||||
	TypeTCP   MonitorType = "TCP"
 | 
			
		||||
	TypeHTTP  MonitorType = "HTTP"
 | 
			
		||||
	TypeHTTPS MonitorType = "HTTPS"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	errValidTypeRequired     = fmt.Errorf("A valid Type is required. Supported values are PING, TCP, HTTP and HTTPS")
 | 
			
		||||
	errDelayRequired         = fmt.Errorf("Delay is required")
 | 
			
		||||
	errTimeoutRequired       = fmt.Errorf("Timeout is required")
 | 
			
		||||
	errMaxRetriesRequired    = fmt.Errorf("MaxRetries is required")
 | 
			
		||||
	errURLPathRequired       = fmt.Errorf("URL path is required")
 | 
			
		||||
	errExpectedCodesRequired = fmt.Errorf("ExpectedCodes is required")
 | 
			
		||||
	errDelayMustGETimeout    = fmt.Errorf("Delay must be greater than or equal to timeout")
 | 
			
		||||
)
 | 
			
		||||
// CreateOptsBuilder is what types must satisfy to be used as Create
 | 
			
		||||
// options.
 | 
			
		||||
type CreateOptsBuilder interface {
 | 
			
		||||
	ToLBMonitorCreateMap() (map[string]interface{}, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CreateOpts contains all the values needed to create a new health monitor.
 | 
			
		||||
type CreateOpts struct {
 | 
			
		||||
	// Required for admins. Indicates the owner of the VIP.
 | 
			
		||||
	TenantID string
 | 
			
		||||
 | 
			
		||||
	// Required. The type of probe, which is PING, TCP, HTTP, or HTTPS, that is
 | 
			
		||||
	// sent by the load balancer to verify the member state.
 | 
			
		||||
	Type string
 | 
			
		||||
 | 
			
		||||
	Type MonitorType `json:"type" required:"true"`
 | 
			
		||||
	// Required. The time, in seconds, between sending probes to members.
 | 
			
		||||
	Delay int
 | 
			
		||||
 | 
			
		||||
	Delay int `json:"delay" required:"true"`
 | 
			
		||||
	// Required. Maximum number of seconds for a monitor to wait for a ping reply
 | 
			
		||||
	// before it times out. The value must be less than the delay value.
 | 
			
		||||
	Timeout int
 | 
			
		||||
 | 
			
		||||
	Timeout int `json:"timeout" required:"true"`
 | 
			
		||||
	// Required. Number of permissible ping failures before changing the member's
 | 
			
		||||
	// status to INACTIVE. Must be a number between 1 and 10.
 | 
			
		||||
	MaxRetries int
 | 
			
		||||
 | 
			
		||||
	MaxRetries int `json:"max_retries" required:"true"`
 | 
			
		||||
	// Required for HTTP(S) types. URI path that will be accessed if monitor type
 | 
			
		||||
	// is HTTP or HTTPS.
 | 
			
		||||
	URLPath string
 | 
			
		||||
 | 
			
		||||
	URLPath string `json:"url_path,omitempty"`
 | 
			
		||||
	// Required for HTTP(S) types. The HTTP method used for requests by the
 | 
			
		||||
	// monitor. If this attribute is not specified, it defaults to "GET".
 | 
			
		||||
	HTTPMethod string
 | 
			
		||||
 | 
			
		||||
	HTTPMethod string `json:"http_method,omitempty"`
 | 
			
		||||
	// Required for HTTP(S) types. Expected HTTP codes for a passing HTTP(S)
 | 
			
		||||
	// monitor. You can either specify a single status like "200", or a range
 | 
			
		||||
	// like "200-202".
 | 
			
		||||
	ExpectedCodes string
 | 
			
		||||
	ExpectedCodes string `json:"expected_codes,omitempty"`
 | 
			
		||||
	// Required for admins. Indicates the owner of the VIP.
 | 
			
		||||
	TenantID     string `json:"tenant_id,omitempty"`
 | 
			
		||||
	AdminStateUp *bool  `json:"admin_state_up,omitempty"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
	AdminStateUp *bool
 | 
			
		||||
// ToLBMonitorCreateMap allows CreateOpts to satisfy the CreateOptsBuilder
 | 
			
		||||
// interface
 | 
			
		||||
func (opts CreateOpts) ToLBMonitorCreateMap() (map[string]interface{}, error) {
 | 
			
		||||
	if opts.Type == TypeHTTP || opts.Type == TypeHTTPS {
 | 
			
		||||
		if opts.URLPath == "" {
 | 
			
		||||
			err := gophercloud.ErrMissingInput{}
 | 
			
		||||
			err.Argument = "monitors.CreateOpts.URLPath"
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		if opts.ExpectedCodes == "" {
 | 
			
		||||
			err := gophercloud.ErrMissingInput{}
 | 
			
		||||
			err.Argument = "monitors.CreateOpts.ExpectedCodes"
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if opts.Delay < opts.Timeout {
 | 
			
		||||
		err := gophercloud.ErrInvalidInput{}
 | 
			
		||||
		err.Argument = "monitors.CreateOpts.Delay/monitors.CreateOpts.Timeout"
 | 
			
		||||
		err.Info = "Delay must be greater than or equal to timeout"
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return gophercloud.BuildRequestBody(opts, "health_monitor")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Create is an operation which provisions a new health monitor. There are
 | 
			
		||||
@@ -116,150 +130,81 @@ type CreateOpts struct {
 | 
			
		||||
// CreateOpts{Type: TypeHTTP, Delay: 20, Timeout: 10, MaxRetries: 3,
 | 
			
		||||
//  HttpMethod: "HEAD", ExpectedCodes: "200"}
 | 
			
		||||
//
 | 
			
		||||
func Create(c *gophercloud.ServiceClient, opts CreateOpts) CreateResult {
 | 
			
		||||
	var res CreateResult
 | 
			
		||||
 | 
			
		||||
	// Validate inputs
 | 
			
		||||
	allowed := map[string]bool{TypeHTTP: true, TypeHTTPS: true, TypeTCP: true, TypePING: true}
 | 
			
		||||
	if opts.Type == "" || allowed[opts.Type] == false {
 | 
			
		||||
		res.Err = errValidTypeRequired
 | 
			
		||||
func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) (r CreateResult) {
 | 
			
		||||
	b, err := opts.ToLBMonitorCreateMap()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		r.Err = err
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	if opts.Delay == 0 {
 | 
			
		||||
		res.Err = errDelayRequired
 | 
			
		||||
	}
 | 
			
		||||
	if opts.Timeout == 0 {
 | 
			
		||||
		res.Err = errTimeoutRequired
 | 
			
		||||
	}
 | 
			
		||||
	if opts.MaxRetries == 0 {
 | 
			
		||||
		res.Err = errMaxRetriesRequired
 | 
			
		||||
	}
 | 
			
		||||
	if opts.Type == TypeHTTP || opts.Type == TypeHTTPS {
 | 
			
		||||
		if opts.URLPath == "" {
 | 
			
		||||
			res.Err = errURLPathRequired
 | 
			
		||||
		}
 | 
			
		||||
		if opts.ExpectedCodes == "" {
 | 
			
		||||
			res.Err = errExpectedCodesRequired
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if opts.Delay < opts.Timeout {
 | 
			
		||||
		res.Err = errDelayMustGETimeout
 | 
			
		||||
	}
 | 
			
		||||
	if res.Err != nil {
 | 
			
		||||
		return res
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	type monitor struct {
 | 
			
		||||
		Type          string  `json:"type"`
 | 
			
		||||
		Delay         int     `json:"delay"`
 | 
			
		||||
		Timeout       int     `json:"timeout"`
 | 
			
		||||
		MaxRetries    int     `json:"max_retries"`
 | 
			
		||||
		TenantID      *string `json:"tenant_id,omitempty"`
 | 
			
		||||
		URLPath       *string `json:"url_path,omitempty"`
 | 
			
		||||
		ExpectedCodes *string `json:"expected_codes,omitempty"`
 | 
			
		||||
		HTTPMethod    *string `json:"http_method,omitempty"`
 | 
			
		||||
		AdminStateUp  *bool   `json:"admin_state_up,omitempty"`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	type request struct {
 | 
			
		||||
		Monitor monitor `json:"health_monitor"`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	reqBody := request{Monitor: monitor{
 | 
			
		||||
		Type:          opts.Type,
 | 
			
		||||
		Delay:         opts.Delay,
 | 
			
		||||
		Timeout:       opts.Timeout,
 | 
			
		||||
		MaxRetries:    opts.MaxRetries,
 | 
			
		||||
		TenantID:      gophercloud.MaybeString(opts.TenantID),
 | 
			
		||||
		URLPath:       gophercloud.MaybeString(opts.URLPath),
 | 
			
		||||
		ExpectedCodes: gophercloud.MaybeString(opts.ExpectedCodes),
 | 
			
		||||
		HTTPMethod:    gophercloud.MaybeString(opts.HTTPMethod),
 | 
			
		||||
		AdminStateUp:  opts.AdminStateUp,
 | 
			
		||||
	}}
 | 
			
		||||
 | 
			
		||||
	_, res.Err = c.Post(rootURL(c), reqBody, &res.Body, nil)
 | 
			
		||||
	return res
 | 
			
		||||
	_, r.Err = c.Post(rootURL(c), b, &r.Body, nil)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Get retrieves a particular health monitor based on its unique ID.
 | 
			
		||||
func Get(c *gophercloud.ServiceClient, id string) GetResult {
 | 
			
		||||
	var res GetResult
 | 
			
		||||
	_, res.Err = c.Get(resourceURL(c, id), &res.Body, nil)
 | 
			
		||||
	return res
 | 
			
		||||
func Get(c *gophercloud.ServiceClient, id string) (r GetResult) {
 | 
			
		||||
	_, r.Err = c.Get(resourceURL(c, id), &r.Body, nil)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UpdateOptsBuilder is what types must satisfy to be used as Update
 | 
			
		||||
// options.
 | 
			
		||||
type UpdateOptsBuilder interface {
 | 
			
		||||
	ToLBMonitorUpdateMap() (map[string]interface{}, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UpdateOpts contains all the values needed to update an existing virtual IP.
 | 
			
		||||
// Attributes not listed here but appear in CreateOpts are immutable and cannot
 | 
			
		||||
// be updated.
 | 
			
		||||
type UpdateOpts struct {
 | 
			
		||||
	// Required. The time, in seconds, between sending probes to members.
 | 
			
		||||
	Delay int
 | 
			
		||||
 | 
			
		||||
	// Required. Maximum number of seconds for a monitor to wait for a ping reply
 | 
			
		||||
	// The time, in seconds, between sending probes to members.
 | 
			
		||||
	Delay int `json:"delay,omitempty"`
 | 
			
		||||
	// Maximum number of seconds for a monitor to wait for a ping reply
 | 
			
		||||
	// before it times out. The value must be less than the delay value.
 | 
			
		||||
	Timeout int
 | 
			
		||||
 | 
			
		||||
	// Required. Number of permissible ping failures before changing the member's
 | 
			
		||||
	Timeout int `json:"timeout,omitempty"`
 | 
			
		||||
	// Number of permissible ping failures before changing the member's
 | 
			
		||||
	// status to INACTIVE. Must be a number between 1 and 10.
 | 
			
		||||
	MaxRetries int
 | 
			
		||||
 | 
			
		||||
	// Required for HTTP(S) types. URI path that will be accessed if monitor type
 | 
			
		||||
	MaxRetries int `json:"max_retries,omitempty"`
 | 
			
		||||
	// URI path that will be accessed if monitor type
 | 
			
		||||
	// is HTTP or HTTPS.
 | 
			
		||||
	URLPath string
 | 
			
		||||
 | 
			
		||||
	// Required for HTTP(S) types. The HTTP method used for requests by the
 | 
			
		||||
	URLPath string `json:"url_path,omitempty"`
 | 
			
		||||
	// The HTTP method used for requests by the
 | 
			
		||||
	// monitor. If this attribute is not specified, it defaults to "GET".
 | 
			
		||||
	HTTPMethod string
 | 
			
		||||
 | 
			
		||||
	// Required for HTTP(S) types. Expected HTTP codes for a passing HTTP(S)
 | 
			
		||||
	HTTPMethod string `json:"http_method,omitempty"`
 | 
			
		||||
	// Expected HTTP codes for a passing HTTP(S)
 | 
			
		||||
	// monitor. You can either specify a single status like "200", or a range
 | 
			
		||||
	// like "200-202".
 | 
			
		||||
	ExpectedCodes string
 | 
			
		||||
 | 
			
		||||
	AdminStateUp *bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Update is an operation which modifies the attributes of the specified monitor.
 | 
			
		||||
func Update(c *gophercloud.ServiceClient, id string, opts UpdateOpts) UpdateResult {
 | 
			
		||||
	var res UpdateResult
 | 
			
		||||
 | 
			
		||||
	if opts.Delay > 0 && opts.Timeout > 0 && opts.Delay < opts.Timeout {
 | 
			
		||||
		res.Err = errDelayMustGETimeout
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	type monitor struct {
 | 
			
		||||
		Delay         int     `json:"delay"`
 | 
			
		||||
		Timeout       int     `json:"timeout"`
 | 
			
		||||
		MaxRetries    int     `json:"max_retries"`
 | 
			
		||||
		URLPath       *string `json:"url_path,omitempty"`
 | 
			
		||||
		ExpectedCodes *string `json:"expected_codes,omitempty"`
 | 
			
		||||
		HTTPMethod    *string `json:"http_method,omitempty"`
 | 
			
		||||
	ExpectedCodes string `json:"expected_codes,omitempty"`
 | 
			
		||||
	AdminStateUp  *bool  `json:"admin_state_up,omitempty"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
	type request struct {
 | 
			
		||||
		Monitor monitor `json:"health_monitor"`
 | 
			
		||||
// ToLBMonitorUpdateMap allows UpdateOpts to satisfy the UpdateOptsBuilder
 | 
			
		||||
// interface
 | 
			
		||||
func (opts UpdateOpts) ToLBMonitorUpdateMap() (map[string]interface{}, error) {
 | 
			
		||||
	if opts.Delay > 0 && opts.Timeout > 0 && opts.Delay < opts.Timeout {
 | 
			
		||||
		err := gophercloud.ErrInvalidInput{}
 | 
			
		||||
		err.Argument = "monitors.CreateOpts.Delay/monitors.CreateOpts.Timeout"
 | 
			
		||||
		err.Value = fmt.Sprintf("%d/%d", opts.Delay, opts.Timeout)
 | 
			
		||||
		err.Info = "Delay must be greater than or equal to timeout"
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return gophercloud.BuildRequestBody(opts, "health_monitor")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
	reqBody := request{Monitor: monitor{
 | 
			
		||||
		Delay:         opts.Delay,
 | 
			
		||||
		Timeout:       opts.Timeout,
 | 
			
		||||
		MaxRetries:    opts.MaxRetries,
 | 
			
		||||
		URLPath:       gophercloud.MaybeString(opts.URLPath),
 | 
			
		||||
		ExpectedCodes: gophercloud.MaybeString(opts.ExpectedCodes),
 | 
			
		||||
		HTTPMethod:    gophercloud.MaybeString(opts.HTTPMethod),
 | 
			
		||||
		AdminStateUp:  opts.AdminStateUp,
 | 
			
		||||
	}}
 | 
			
		||||
 | 
			
		||||
	_, res.Err = c.Put(resourceURL(c, id), reqBody, &res.Body, &gophercloud.RequestOpts{
 | 
			
		||||
// Update is an operation which modifies the attributes of the specified monitor.
 | 
			
		||||
func Update(c *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) (r UpdateResult) {
 | 
			
		||||
	b, err := opts.ToLBMonitorUpdateMap()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		r.Err = err
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	_, r.Err = c.Put(resourceURL(c, id), b, &r.Body, &gophercloud.RequestOpts{
 | 
			
		||||
		OkCodes: []int{200, 202},
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	return res
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Delete will permanently delete a particular monitor based on its unique ID.
 | 
			
		||||
func Delete(c *gophercloud.ServiceClient, id string) DeleteResult {
 | 
			
		||||
	var res DeleteResult
 | 
			
		||||
	_, res.Err = c.Delete(resourceURL(c, id), nil)
 | 
			
		||||
	return res
 | 
			
		||||
func Delete(c *gophercloud.ServiceClient, id string) (r DeleteResult) {
 | 
			
		||||
	_, r.Err = c.Delete(resourceURL(c, id), nil)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
@@ -1,9 +1,8 @@
 | 
			
		||||
package monitors
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/mitchellh/mapstructure"
 | 
			
		||||
	"github.com/rackspace/gophercloud"
 | 
			
		||||
	"github.com/rackspace/gophercloud/pagination"
 | 
			
		||||
	"github.com/gophercloud/gophercloud"
 | 
			
		||||
	"github.com/gophercloud/gophercloud/pagination"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Monitor represents a load balancer health monitor. A health monitor is used
 | 
			
		||||
@@ -30,7 +29,7 @@ type Monitor struct {
 | 
			
		||||
 | 
			
		||||
	// Owner of the VIP. Only an administrative user can specify a tenant ID
 | 
			
		||||
	// other than its own.
 | 
			
		||||
	TenantID string `json:"tenant_id" mapstructure:"tenant_id"`
 | 
			
		||||
	TenantID string `json:"tenant_id"`
 | 
			
		||||
 | 
			
		||||
	// The type of probe sent by the load balancer to verify the member state,
 | 
			
		||||
	// which is PING, TCP, HTTP, or HTTPS.
 | 
			
		||||
@@ -45,20 +44,20 @@ type Monitor struct {
 | 
			
		||||
 | 
			
		||||
	// Number of allowed connection failures before changing the status of the
 | 
			
		||||
	// member to INACTIVE. A valid value is from 1 to 10.
 | 
			
		||||
	MaxRetries int `json:"max_retries" mapstructure:"max_retries"`
 | 
			
		||||
	MaxRetries int `json:"max_retries"`
 | 
			
		||||
 | 
			
		||||
	// The HTTP method that the monitor uses for requests.
 | 
			
		||||
	HTTPMethod string `json:"http_method" mapstructure:"http_method"`
 | 
			
		||||
	HTTPMethod string `json:"http_method"`
 | 
			
		||||
 | 
			
		||||
	// The HTTP path of the request sent by the monitor to test the health of a
 | 
			
		||||
	// member. Must be a string beginning with a forward slash (/).
 | 
			
		||||
	URLPath string `json:"url_path" mapstructure:"url_path"`
 | 
			
		||||
	URLPath string `json:"url_path"`
 | 
			
		||||
 | 
			
		||||
	// Expected HTTP codes for a passing HTTP(S) monitor.
 | 
			
		||||
	ExpectedCodes string `json:"expected_codes" mapstructure:"expected_codes"`
 | 
			
		||||
	ExpectedCodes string `json:"expected_codes"`
 | 
			
		||||
 | 
			
		||||
	// The administrative state of the health monitor, which is up (true) or down (false).
 | 
			
		||||
	AdminStateUp bool `json:"admin_state_up" mapstructure:"admin_state_up"`
 | 
			
		||||
	AdminStateUp bool `json:"admin_state_up"`
 | 
			
		||||
 | 
			
		||||
	// The status of the health monitor. Indicates whether the health monitor is
 | 
			
		||||
	// operational.
 | 
			
		||||
@@ -74,40 +73,33 @@ type MonitorPage struct {
 | 
			
		||||
// NextPageURL is invoked when a paginated collection of monitors has reached
 | 
			
		||||
// the end of a page and the pager seeks to traverse over a new one. In order
 | 
			
		||||
// to do this, it needs to construct the next page's URL.
 | 
			
		||||
func (p MonitorPage) NextPageURL() (string, error) {
 | 
			
		||||
	type resp struct {
 | 
			
		||||
		Links []gophercloud.Link `mapstructure:"health_monitors_links"`
 | 
			
		||||
func (r MonitorPage) NextPageURL() (string, error) {
 | 
			
		||||
	var s struct {
 | 
			
		||||
		Links []gophercloud.Link `json:"health_monitors_links"`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var r resp
 | 
			
		||||
	err := mapstructure.Decode(p.Body, &r)
 | 
			
		||||
	err := r.ExtractInto(&s)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return gophercloud.ExtractNextURL(r.Links)
 | 
			
		||||
	return gophercloud.ExtractNextURL(s.Links)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IsEmpty checks whether a PoolPage struct is empty.
 | 
			
		||||
func (p MonitorPage) IsEmpty() (bool, error) {
 | 
			
		||||
	is, err := ExtractMonitors(p)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return true, nil
 | 
			
		||||
	}
 | 
			
		||||
	return len(is) == 0, nil
 | 
			
		||||
func (r MonitorPage) IsEmpty() (bool, error) {
 | 
			
		||||
	is, err := ExtractMonitors(r)
 | 
			
		||||
	return len(is) == 0, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ExtractMonitors accepts a Page struct, specifically a MonitorPage struct,
 | 
			
		||||
// and extracts the elements into a slice of Monitor structs. In other words,
 | 
			
		||||
// a generic collection is mapped into a relevant slice.
 | 
			
		||||
func ExtractMonitors(page pagination.Page) ([]Monitor, error) {
 | 
			
		||||
	var resp struct {
 | 
			
		||||
		Monitors []Monitor `mapstructure:"health_monitors" json:"health_monitors"`
 | 
			
		||||
func ExtractMonitors(r pagination.Page) ([]Monitor, error) {
 | 
			
		||||
	var s struct {
 | 
			
		||||
		Monitors []Monitor `json:"health_monitors"`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err := mapstructure.Decode(page.(MonitorPage).Body, &resp)
 | 
			
		||||
 | 
			
		||||
	return resp.Monitors, err
 | 
			
		||||
	err := (r.(MonitorPage)).ExtractInto(&s)
 | 
			
		||||
	return s.Monitors, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type commonResult struct {
 | 
			
		||||
@@ -116,17 +108,11 @@ type commonResult struct {
 | 
			
		||||
 | 
			
		||||
// Extract is a function that accepts a result and extracts a monitor.
 | 
			
		||||
func (r commonResult) Extract() (*Monitor, error) {
 | 
			
		||||
	if r.Err != nil {
 | 
			
		||||
		return nil, r.Err
 | 
			
		||||
	var s struct {
 | 
			
		||||
		Monitor *Monitor `json:"health_monitor"`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var res struct {
 | 
			
		||||
		Monitor *Monitor `json:"health_monitor" mapstructure:"health_monitor"`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err := mapstructure.Decode(r.Body, &res)
 | 
			
		||||
 | 
			
		||||
	return res.Monitor, err
 | 
			
		||||
	err := r.ExtractInto(&s)
 | 
			
		||||
	return s.Monitor, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CreateResult represents the result of a create operation.
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
package monitors
 | 
			
		||||
 | 
			
		||||
import "github.com/rackspace/gophercloud"
 | 
			
		||||
import "github.com/gophercloud/gophercloud"
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	rootPath     = "lb"
 | 
			
		||||
@@ -1,8 +1,8 @@
 | 
			
		||||
package pools
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/rackspace/gophercloud"
 | 
			
		||||
	"github.com/rackspace/gophercloud/pagination"
 | 
			
		||||
	"github.com/gophercloud/gophercloud"
 | 
			
		||||
	"github.com/gophercloud/gophercloud/pagination"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// ListOpts allows the filtering and sorting of paginated collections through
 | 
			
		||||
@@ -43,117 +43,111 @@ func List(c *gophercloud.ServiceClient, opts ListOpts) pagination.Pager {
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// LBMethod is a type used for possible load balancing methods
 | 
			
		||||
type LBMethod string
 | 
			
		||||
 | 
			
		||||
// LBProtocol is a type used for possible load balancing protocols
 | 
			
		||||
type LBProtocol string
 | 
			
		||||
 | 
			
		||||
// Supported attributes for create/update operations.
 | 
			
		||||
const (
 | 
			
		||||
	LBMethodRoundRobin       = "ROUND_ROBIN"
 | 
			
		||||
	LBMethodLeastConnections = "LEAST_CONNECTIONS"
 | 
			
		||||
	LBMethodRoundRobin       LBMethod = "ROUND_ROBIN"
 | 
			
		||||
	LBMethodLeastConnections LBMethod = "LEAST_CONNECTIONS"
 | 
			
		||||
 | 
			
		||||
	ProtocolTCP   = "TCP"
 | 
			
		||||
	ProtocolHTTP  = "HTTP"
 | 
			
		||||
	ProtocolHTTPS = "HTTPS"
 | 
			
		||||
	ProtocolTCP   LBProtocol = "TCP"
 | 
			
		||||
	ProtocolHTTP  LBProtocol = "HTTP"
 | 
			
		||||
	ProtocolHTTPS LBProtocol = "HTTPS"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// CreateOptsBuilder is the interface types must satisfy to be used as options
 | 
			
		||||
// for the Create function
 | 
			
		||||
type CreateOptsBuilder interface {
 | 
			
		||||
	ToLBPoolCreateMap() (map[string]interface{}, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CreateOpts contains all the values needed to create a new pool.
 | 
			
		||||
type CreateOpts struct {
 | 
			
		||||
	// Name of the pool.
 | 
			
		||||
	Name string `json:"name" required:"true"`
 | 
			
		||||
	// The protocol used by the pool members, you can use either
 | 
			
		||||
	// ProtocolTCP, ProtocolHTTP, or ProtocolHTTPS.
 | 
			
		||||
	Protocol LBProtocol `json:"protocol" required:"true"`
 | 
			
		||||
	// Only required if the caller has an admin role and wants to create a pool
 | 
			
		||||
	// for another tenant.
 | 
			
		||||
	TenantID string
 | 
			
		||||
 | 
			
		||||
	// Required. Name of the pool.
 | 
			
		||||
	Name string
 | 
			
		||||
 | 
			
		||||
	// Required. The protocol used by the pool members, you can use either
 | 
			
		||||
	// ProtocolTCP, ProtocolHTTP, or ProtocolHTTPS.
 | 
			
		||||
	Protocol string
 | 
			
		||||
 | 
			
		||||
	TenantID string `json:"tenant_id,omitempty"`
 | 
			
		||||
	// The network on which the members of the pool will be located. Only members
 | 
			
		||||
	// that are on this network can be added to the pool.
 | 
			
		||||
	SubnetID string
 | 
			
		||||
 | 
			
		||||
	SubnetID string `json:"subnet_id,omitempty"`
 | 
			
		||||
	// The algorithm used to distribute load between the members of the pool. The
 | 
			
		||||
	// current specification supports LBMethodRoundRobin and
 | 
			
		||||
	// LBMethodLeastConnections as valid values for this attribute.
 | 
			
		||||
	LBMethod string
 | 
			
		||||
	LBMethod LBMethod `json:"lb_method" required:"true"`
 | 
			
		||||
 | 
			
		||||
	// The provider of the pool
 | 
			
		||||
	Provider string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Create accepts a CreateOpts struct and uses the values to create a new
 | 
			
		||||
// load balancer pool.
 | 
			
		||||
func Create(c *gophercloud.ServiceClient, opts CreateOpts) CreateResult {
 | 
			
		||||
	type pool struct {
 | 
			
		||||
		Name     string `json:"name"`
 | 
			
		||||
		TenantID string `json:"tenant_id,omitempty"`
 | 
			
		||||
		Protocol string `json:"protocol"`
 | 
			
		||||
		SubnetID string `json:"subnet_id"`
 | 
			
		||||
		LBMethod string `json:"lb_method"`
 | 
			
		||||
	Provider string `json:"provider,omitempty"`
 | 
			
		||||
}
 | 
			
		||||
	type request struct {
 | 
			
		||||
		Pool pool `json:"pool"`
 | 
			
		||||
 | 
			
		||||
// ToLBPoolCreateMap allows CreateOpts to satisfy the CreateOptsBuilder interface
 | 
			
		||||
func (opts CreateOpts) ToLBPoolCreateMap() (map[string]interface{}, error) {
 | 
			
		||||
	return gophercloud.BuildRequestBody(opts, "pool")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
	reqBody := request{Pool: pool{
 | 
			
		||||
		Name:     opts.Name,
 | 
			
		||||
		TenantID: opts.TenantID,
 | 
			
		||||
		Protocol: opts.Protocol,
 | 
			
		||||
		SubnetID: opts.SubnetID,
 | 
			
		||||
		LBMethod: opts.LBMethod,
 | 
			
		||||
		Provider: opts.Provider,
 | 
			
		||||
	}}
 | 
			
		||||
 | 
			
		||||
	var res CreateResult
 | 
			
		||||
	_, res.Err = c.Post(rootURL(c), reqBody, &res.Body, nil)
 | 
			
		||||
	return res
 | 
			
		||||
// Create accepts a CreateOptsBuilder and uses the values to create a new
 | 
			
		||||
// load balancer pool.
 | 
			
		||||
func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) (r CreateResult) {
 | 
			
		||||
	b, err := opts.ToLBPoolCreateMap()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		r.Err = err
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	_, r.Err = c.Post(rootURL(c), b, &r.Body, nil)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Get retrieves a particular pool based on its unique ID.
 | 
			
		||||
func Get(c *gophercloud.ServiceClient, id string) GetResult {
 | 
			
		||||
	var res GetResult
 | 
			
		||||
	_, res.Err = c.Get(resourceURL(c, id), &res.Body, nil)
 | 
			
		||||
	return res
 | 
			
		||||
func Get(c *gophercloud.ServiceClient, id string) (r GetResult) {
 | 
			
		||||
	_, r.Err = c.Get(resourceURL(c, id), &r.Body, nil)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UpdateOptsBuilder is the interface types must satisfy to be used as options
 | 
			
		||||
// for the Update function
 | 
			
		||||
type UpdateOptsBuilder interface {
 | 
			
		||||
	ToLBPoolUpdateMap() (map[string]interface{}, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UpdateOpts contains the values used when updating a pool.
 | 
			
		||||
type UpdateOpts struct {
 | 
			
		||||
	// Required. Name of the pool.
 | 
			
		||||
	Name string
 | 
			
		||||
 | 
			
		||||
	// Name of the pool.
 | 
			
		||||
	Name string `json:"name,omitempty"`
 | 
			
		||||
	// The algorithm used to distribute load between the members of the pool. The
 | 
			
		||||
	// current specification supports LBMethodRoundRobin and
 | 
			
		||||
	// LBMethodLeastConnections as valid values for this attribute.
 | 
			
		||||
	LBMethod string
 | 
			
		||||
	LBMethod LBMethod `json:"lb_method,omitempty"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ToLBPoolUpdateMap allows UpdateOpts to satisfy the UpdateOptsBuilder interface
 | 
			
		||||
func (opts UpdateOpts) ToLBPoolUpdateMap() (map[string]interface{}, error) {
 | 
			
		||||
	return gophercloud.BuildRequestBody(opts, "pool")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Update allows pools to be updated.
 | 
			
		||||
func Update(c *gophercloud.ServiceClient, id string, opts UpdateOpts) UpdateResult {
 | 
			
		||||
	type pool struct {
 | 
			
		||||
		Name     string `json:"name,"`
 | 
			
		||||
		LBMethod string `json:"lb_method"`
 | 
			
		||||
func Update(c *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) (r UpdateResult) {
 | 
			
		||||
	b, err := opts.ToLBPoolUpdateMap()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		r.Err = err
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	type request struct {
 | 
			
		||||
		Pool pool `json:"pool"`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	reqBody := request{Pool: pool{
 | 
			
		||||
		Name:     opts.Name,
 | 
			
		||||
		LBMethod: opts.LBMethod,
 | 
			
		||||
	}}
 | 
			
		||||
 | 
			
		||||
	// Send request to API
 | 
			
		||||
	var res UpdateResult
 | 
			
		||||
	_, res.Err = c.Put(resourceURL(c, id), reqBody, &res.Body, &gophercloud.RequestOpts{
 | 
			
		||||
	_, r.Err = c.Put(resourceURL(c, id), b, &r.Body, &gophercloud.RequestOpts{
 | 
			
		||||
		OkCodes: []int{200},
 | 
			
		||||
	})
 | 
			
		||||
	return res
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Delete will permanently delete a particular pool based on its unique ID.
 | 
			
		||||
func Delete(c *gophercloud.ServiceClient, id string) DeleteResult {
 | 
			
		||||
	var res DeleteResult
 | 
			
		||||
	_, res.Err = c.Delete(resourceURL(c, id), nil)
 | 
			
		||||
	return res
 | 
			
		||||
func Delete(c *gophercloud.ServiceClient, id string) (r DeleteResult) {
 | 
			
		||||
	_, r.Err = c.Delete(resourceURL(c, id), nil)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// AssociateMonitor will associate a health monitor with a particular pool.
 | 
			
		||||
@@ -161,26 +155,16 @@ func Delete(c *gophercloud.ServiceClient, id string) DeleteResult {
 | 
			
		||||
// pool and will deactivate these members if they are deemed unhealthy. A
 | 
			
		||||
// member can be deactivated (status set to INACTIVE) if any of health monitors
 | 
			
		||||
// finds it unhealthy.
 | 
			
		||||
func AssociateMonitor(c *gophercloud.ServiceClient, poolID, monitorID string) AssociateResult {
 | 
			
		||||
	type hm struct {
 | 
			
		||||
		ID string `json:"id"`
 | 
			
		||||
	}
 | 
			
		||||
	type request struct {
 | 
			
		||||
		Monitor hm `json:"health_monitor"`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	reqBody := request{hm{ID: monitorID}}
 | 
			
		||||
 | 
			
		||||
	var res AssociateResult
 | 
			
		||||
	_, res.Err = c.Post(associateURL(c, poolID), reqBody, &res.Body, nil)
 | 
			
		||||
	return res
 | 
			
		||||
func AssociateMonitor(c *gophercloud.ServiceClient, poolID, monitorID string) (r AssociateResult) {
 | 
			
		||||
	b := map[string]interface{}{"health_monitor": map[string]string{"id": monitorID}}
 | 
			
		||||
	_, r.Err = c.Post(associateURL(c, poolID), b, &r.Body, nil)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DisassociateMonitor will disassociate a health monitor with a particular
 | 
			
		||||
// pool. When dissociation is successful, the health monitor will no longer
 | 
			
		||||
// check for the health of the members of the pool.
 | 
			
		||||
func DisassociateMonitor(c *gophercloud.ServiceClient, poolID, monitorID string) AssociateResult {
 | 
			
		||||
	var res AssociateResult
 | 
			
		||||
	_, res.Err = c.Delete(disassociateURL(c, poolID, monitorID), nil)
 | 
			
		||||
	return res
 | 
			
		||||
func DisassociateMonitor(c *gophercloud.ServiceClient, poolID, monitorID string) (r AssociateResult) {
 | 
			
		||||
	_, r.Err = c.Delete(disassociateURL(c, poolID, monitorID), nil)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
@@ -1,9 +1,8 @@
 | 
			
		||||
package pools
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/mitchellh/mapstructure"
 | 
			
		||||
	"github.com/rackspace/gophercloud"
 | 
			
		||||
	"github.com/rackspace/gophercloud/pagination"
 | 
			
		||||
	"github.com/gophercloud/gophercloud"
 | 
			
		||||
	"github.com/gophercloud/gophercloud/pagination"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Pool represents a logical set of devices, such as web servers, that you
 | 
			
		||||
@@ -18,7 +17,7 @@ type Pool struct {
 | 
			
		||||
	// The load-balancer algorithm, which is round-robin, least-connections, and
 | 
			
		||||
	// so on. This value, which must be supported, is dependent on the provider.
 | 
			
		||||
	// Round-robin must be supported.
 | 
			
		||||
	LBMethod string `json:"lb_method" mapstructure:"lb_method"`
 | 
			
		||||
	LBMethod string `json:"lb_method"`
 | 
			
		||||
 | 
			
		||||
	// The protocol of the pool, which is TCP, HTTP, or HTTPS.
 | 
			
		||||
	Protocol string
 | 
			
		||||
@@ -27,30 +26,30 @@ type Pool struct {
 | 
			
		||||
	Description string
 | 
			
		||||
 | 
			
		||||
	// The IDs of associated monitors which check the health of the pool members.
 | 
			
		||||
	MonitorIDs []string `json:"health_monitors" mapstructure:"health_monitors"`
 | 
			
		||||
	MonitorIDs []string `json:"health_monitors"`
 | 
			
		||||
 | 
			
		||||
	// The network on which the members of the pool will be located. Only members
 | 
			
		||||
	// that are on this network can be added to the pool.
 | 
			
		||||
	SubnetID string `json:"subnet_id" mapstructure:"subnet_id"`
 | 
			
		||||
	SubnetID string `json:"subnet_id"`
 | 
			
		||||
 | 
			
		||||
	// Owner of the pool. Only an administrative user can specify a tenant ID
 | 
			
		||||
	// other than its own.
 | 
			
		||||
	TenantID string `json:"tenant_id" mapstructure:"tenant_id"`
 | 
			
		||||
	TenantID string `json:"tenant_id"`
 | 
			
		||||
 | 
			
		||||
	// The administrative state of the pool, which is up (true) or down (false).
 | 
			
		||||
	AdminStateUp bool `json:"admin_state_up" mapstructure:"admin_state_up"`
 | 
			
		||||
	AdminStateUp bool `json:"admin_state_up"`
 | 
			
		||||
 | 
			
		||||
	// Pool name. Does not have to be unique.
 | 
			
		||||
	Name string
 | 
			
		||||
 | 
			
		||||
	// List of member IDs that belong to the pool.
 | 
			
		||||
	MemberIDs []string `json:"members" mapstructure:"members"`
 | 
			
		||||
	MemberIDs []string `json:"members"`
 | 
			
		||||
 | 
			
		||||
	// The unique ID for the pool.
 | 
			
		||||
	ID string
 | 
			
		||||
 | 
			
		||||
	// The ID of the virtual IP associated with this pool
 | 
			
		||||
	VIPID string `json:"vip_id" mapstructure:"vip_id"`
 | 
			
		||||
	VIPID string `json:"vip_id"`
 | 
			
		||||
 | 
			
		||||
	// The provider
 | 
			
		||||
	Provider string
 | 
			
		||||
@@ -65,40 +64,32 @@ type PoolPage struct {
 | 
			
		||||
// NextPageURL is invoked when a paginated collection of pools has reached
 | 
			
		||||
// the end of a page and the pager seeks to traverse over a new one. In order
 | 
			
		||||
// to do this, it needs to construct the next page's URL.
 | 
			
		||||
func (p PoolPage) NextPageURL() (string, error) {
 | 
			
		||||
	type resp struct {
 | 
			
		||||
		Links []gophercloud.Link `mapstructure:"pools_links"`
 | 
			
		||||
func (r PoolPage) NextPageURL() (string, error) {
 | 
			
		||||
	var s struct {
 | 
			
		||||
		Links []gophercloud.Link `json:"pools_links"`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var r resp
 | 
			
		||||
	err := mapstructure.Decode(p.Body, &r)
 | 
			
		||||
	err := r.ExtractInto(&s)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return gophercloud.ExtractNextURL(r.Links)
 | 
			
		||||
	return gophercloud.ExtractNextURL(s.Links)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IsEmpty checks whether a PoolPage struct is empty.
 | 
			
		||||
func (p PoolPage) IsEmpty() (bool, error) {
 | 
			
		||||
	is, err := ExtractPools(p)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return true, nil
 | 
			
		||||
	}
 | 
			
		||||
	return len(is) == 0, nil
 | 
			
		||||
func (r PoolPage) IsEmpty() (bool, error) {
 | 
			
		||||
	is, err := ExtractPools(r)
 | 
			
		||||
	return len(is) == 0, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ExtractPools accepts a Page struct, specifically a RouterPage struct,
 | 
			
		||||
// and extracts the elements into a slice of Router structs. In other words,
 | 
			
		||||
// a generic collection is mapped into a relevant slice.
 | 
			
		||||
func ExtractPools(page pagination.Page) ([]Pool, error) {
 | 
			
		||||
	var resp struct {
 | 
			
		||||
		Pools []Pool `mapstructure:"pools" json:"pools"`
 | 
			
		||||
func ExtractPools(r pagination.Page) ([]Pool, error) {
 | 
			
		||||
	var s struct {
 | 
			
		||||
		Pools []Pool `json:"pools"`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err := mapstructure.Decode(page.(PoolPage).Body, &resp)
 | 
			
		||||
 | 
			
		||||
	return resp.Pools, err
 | 
			
		||||
	err := (r.(PoolPage)).ExtractInto(&s)
 | 
			
		||||
	return s.Pools, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type commonResult struct {
 | 
			
		||||
@@ -107,17 +98,11 @@ type commonResult struct {
 | 
			
		||||
 | 
			
		||||
// Extract is a function that accepts a result and extracts a router.
 | 
			
		||||
func (r commonResult) Extract() (*Pool, error) {
 | 
			
		||||
	if r.Err != nil {
 | 
			
		||||
		return nil, r.Err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var res struct {
 | 
			
		||||
	var s struct {
 | 
			
		||||
		Pool *Pool `json:"pool"`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err := mapstructure.Decode(r.Body, &res)
 | 
			
		||||
 | 
			
		||||
	return res.Pool, err
 | 
			
		||||
	err := r.ExtractInto(&s)
 | 
			
		||||
	return s.Pool, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CreateResult represents the result of a create operation.
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
package pools
 | 
			
		||||
 | 
			
		||||
import "github.com/rackspace/gophercloud"
 | 
			
		||||
import "github.com/gophercloud/gophercloud"
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	rootPath     = "lb"
 | 
			
		||||
							
								
								
									
										163
									
								
								vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas/vips/requests.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										163
									
								
								vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas/vips/requests.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,163 @@
 | 
			
		||||
package vips
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/gophercloud/gophercloud"
 | 
			
		||||
	"github.com/gophercloud/gophercloud/pagination"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// ListOpts allows the filtering and sorting of paginated collections through
 | 
			
		||||
// the API. Filtering is achieved by passing in struct field values that map to
 | 
			
		||||
// the floating IP attributes you want to see returned. SortKey allows you to
 | 
			
		||||
// sort by a particular network attribute. SortDir sets the direction, and is
 | 
			
		||||
// either `asc' or `desc'. Marker and Limit are used for pagination.
 | 
			
		||||
type ListOpts struct {
 | 
			
		||||
	ID              string `q:"id"`
 | 
			
		||||
	Name            string `q:"name"`
 | 
			
		||||
	AdminStateUp    *bool  `q:"admin_state_up"`
 | 
			
		||||
	Status          string `q:"status"`
 | 
			
		||||
	TenantID        string `q:"tenant_id"`
 | 
			
		||||
	SubnetID        string `q:"subnet_id"`
 | 
			
		||||
	Address         string `q:"address"`
 | 
			
		||||
	PortID          string `q:"port_id"`
 | 
			
		||||
	Protocol        string `q:"protocol"`
 | 
			
		||||
	ProtocolPort    int    `q:"protocol_port"`
 | 
			
		||||
	ConnectionLimit int    `q:"connection_limit"`
 | 
			
		||||
	Limit           int    `q:"limit"`
 | 
			
		||||
	Marker          string `q:"marker"`
 | 
			
		||||
	SortKey         string `q:"sort_key"`
 | 
			
		||||
	SortDir         string `q:"sort_dir"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// List returns a Pager which allows you to iterate over a collection of
 | 
			
		||||
// routers. It accepts a ListOpts struct, which allows you to filter and sort
 | 
			
		||||
// the returned collection for greater efficiency.
 | 
			
		||||
//
 | 
			
		||||
// Default policy settings return only those routers that are owned by the
 | 
			
		||||
// tenant who submits the request, unless an admin user submits the request.
 | 
			
		||||
func List(c *gophercloud.ServiceClient, opts ListOpts) pagination.Pager {
 | 
			
		||||
	q, err := gophercloud.BuildQueryString(&opts)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return pagination.Pager{Err: err}
 | 
			
		||||
	}
 | 
			
		||||
	u := rootURL(c) + q.String()
 | 
			
		||||
	return pagination.NewPager(c, u, func(r pagination.PageResult) pagination.Page {
 | 
			
		||||
		return VIPPage{pagination.LinkedPageBase{PageResult: r}}
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CreateOptsBuilder is what types must satisfy to be used as Create
 | 
			
		||||
// options.
 | 
			
		||||
type CreateOptsBuilder interface {
 | 
			
		||||
	ToVIPCreateMap() (map[string]interface{}, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CreateOpts contains all the values needed to create a new virtual IP.
 | 
			
		||||
type CreateOpts struct {
 | 
			
		||||
	// Human-readable name for the VIP. Does not have to be unique.
 | 
			
		||||
	Name string `json:"name" required:"true"`
 | 
			
		||||
	// The network on which to allocate the VIP's address. A tenant can
 | 
			
		||||
	// only create VIPs on networks authorized by policy (e.g. networks that
 | 
			
		||||
	// belong to them or networks that are shared).
 | 
			
		||||
	SubnetID string `json:"subnet_id" required:"true"`
 | 
			
		||||
	// The protocol - can either be TCP, HTTP or HTTPS.
 | 
			
		||||
	Protocol string `json:"protocol" required:"true"`
 | 
			
		||||
	// The port on which to listen for client traffic.
 | 
			
		||||
	ProtocolPort int `json:"protocol_port" required:"true"`
 | 
			
		||||
	// The ID of the pool with which the VIP is associated.
 | 
			
		||||
	PoolID string `json:"pool_id" required:"true"`
 | 
			
		||||
	// Required for admins. Indicates the owner of the VIP.
 | 
			
		||||
	TenantID string `json:"tenant_id,omitempty"`
 | 
			
		||||
	// The IP address of the VIP.
 | 
			
		||||
	Address string `json:"address,omitempty"`
 | 
			
		||||
	// Human-readable description for the VIP.
 | 
			
		||||
	Description string `json:"description,omitempty"`
 | 
			
		||||
	// Omit this field to prevent session persistence.
 | 
			
		||||
	Persistence *SessionPersistence `json:"session_persistence,omitempty"`
 | 
			
		||||
	// The maximum number of connections allowed for the VIP.
 | 
			
		||||
	ConnLimit *int `json:"connection_limit,omitempty"`
 | 
			
		||||
	// The administrative state of the VIP. A valid value is true (UP)
 | 
			
		||||
	// or false (DOWN).
 | 
			
		||||
	AdminStateUp *bool `json:"admin_state_up,omitempty"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ToVIPCreateMap allows CreateOpts to satisfy the CreateOptsBuilder
 | 
			
		||||
// interface
 | 
			
		||||
func (opts CreateOpts) ToVIPCreateMap() (map[string]interface{}, error) {
 | 
			
		||||
	return gophercloud.BuildRequestBody(opts, "vip")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Create is an operation which provisions a new virtual IP based on the
 | 
			
		||||
// configuration defined in the CreateOpts struct. Once the request is
 | 
			
		||||
// validated and progress has started on the provisioning process, a
 | 
			
		||||
// CreateResult will be returned.
 | 
			
		||||
//
 | 
			
		||||
// Please note that the PoolID should refer to a pool that is not already
 | 
			
		||||
// associated with another vip. If the pool is already used by another vip,
 | 
			
		||||
// then the operation will fail with a 409 Conflict error will be returned.
 | 
			
		||||
//
 | 
			
		||||
// Users with an admin role can create VIPs on behalf of other tenants by
 | 
			
		||||
// specifying a TenantID attribute different than their own.
 | 
			
		||||
func Create(c *gophercloud.ServiceClient, opts CreateOpts) (r CreateResult) {
 | 
			
		||||
	b, err := opts.ToVIPCreateMap()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		r.Err = err
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	_, r.Err = c.Post(rootURL(c), b, &r.Body, nil)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Get retrieves a particular virtual IP based on its unique ID.
 | 
			
		||||
func Get(c *gophercloud.ServiceClient, id string) (r GetResult) {
 | 
			
		||||
	_, r.Err = c.Get(resourceURL(c, id), &r.Body, nil)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UpdateOptsBuilder is what types must satisfy to be used as Update
 | 
			
		||||
// options.
 | 
			
		||||
type UpdateOptsBuilder interface {
 | 
			
		||||
	ToVIPUpdateMap() (map[string]interface{}, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UpdateOpts contains all the values needed to update an existing virtual IP.
 | 
			
		||||
// Attributes not listed here but appear in CreateOpts are immutable and cannot
 | 
			
		||||
// be updated.
 | 
			
		||||
type UpdateOpts struct {
 | 
			
		||||
	// Human-readable name for the VIP. Does not have to be unique.
 | 
			
		||||
	Name *string `json:"name,omitempty"`
 | 
			
		||||
	// The ID of the pool with which the VIP is associated.
 | 
			
		||||
	PoolID *string `json:"pool_id,omitempty"`
 | 
			
		||||
	// Human-readable description for the VIP.
 | 
			
		||||
	Description *string `json:"description,omitempty"`
 | 
			
		||||
	// Omit this field to prevent session persistence.
 | 
			
		||||
	Persistence *SessionPersistence `json:"session_persistence,omitempty"`
 | 
			
		||||
	// The maximum number of connections allowed for the VIP.
 | 
			
		||||
	ConnLimit *int `json:"connection_limit,omitempty"`
 | 
			
		||||
	// The administrative state of the VIP. A valid value is true (UP)
 | 
			
		||||
	// or false (DOWN).
 | 
			
		||||
	AdminStateUp *bool `json:"admin_state_up,omitempty"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ToVIPUpdateMap allows UpdateOpts to satisfy the UpdateOptsBuilder interface
 | 
			
		||||
func (opts UpdateOpts) ToVIPUpdateMap() (map[string]interface{}, error) {
 | 
			
		||||
	return gophercloud.BuildRequestBody(opts, "vip")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Update is an operation which modifies the attributes of the specified VIP.
 | 
			
		||||
func Update(c *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) (r UpdateResult) {
 | 
			
		||||
	b, err := opts.ToVIPUpdateMap()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		r.Err = err
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	_, r.Err = c.Put(resourceURL(c, id), b, &r.Body, &gophercloud.RequestOpts{
 | 
			
		||||
		OkCodes: []int{200, 202},
 | 
			
		||||
	})
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Delete will permanently delete a particular virtual IP based on its unique ID.
 | 
			
		||||
func Delete(c *gophercloud.ServiceClient, id string) (r DeleteResult) {
 | 
			
		||||
	_, r.Err = c.Delete(resourceURL(c, id), nil)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
@@ -1,9 +1,8 @@
 | 
			
		||||
package vips
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/mitchellh/mapstructure"
 | 
			
		||||
	"github.com/rackspace/gophercloud"
 | 
			
		||||
	"github.com/rackspace/gophercloud/pagination"
 | 
			
		||||
	"github.com/gophercloud/gophercloud"
 | 
			
		||||
	"github.com/gophercloud/gophercloud/pagination"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// SessionPersistence represents the session persistence feature of the load
 | 
			
		||||
@@ -23,10 +22,10 @@ import (
 | 
			
		||||
//              same member of the pool.
 | 
			
		||||
type SessionPersistence struct {
 | 
			
		||||
	// The type of persistence mode
 | 
			
		||||
	Type string `mapstructure:"type" json:"type"`
 | 
			
		||||
	Type string `json:"type"`
 | 
			
		||||
 | 
			
		||||
	// Name of cookie if persistence mode is set appropriately
 | 
			
		||||
	CookieName string `mapstructure:"cookie_name" json:"cookie_name,omitempty"`
 | 
			
		||||
	CookieName string `json:"cookie_name,omitempty"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// VirtualIP is the primary load balancing configuration object that specifies
 | 
			
		||||
@@ -36,49 +35,49 @@ type SessionPersistence struct {
 | 
			
		||||
// server", a "vserver" or a "listener".
 | 
			
		||||
type VirtualIP struct {
 | 
			
		||||
	// The unique ID for the VIP.
 | 
			
		||||
	ID string `mapstructure:"id" json:"id"`
 | 
			
		||||
	ID string `json:"id"`
 | 
			
		||||
 | 
			
		||||
	// Owner of the VIP. Only an admin user can specify a tenant ID other than its own.
 | 
			
		||||
	TenantID string `mapstructure:"tenant_id" json:"tenant_id"`
 | 
			
		||||
	TenantID string `json:"tenant_id"`
 | 
			
		||||
 | 
			
		||||
	// Human-readable name for the VIP. Does not have to be unique.
 | 
			
		||||
	Name string `mapstructure:"name" json:"name"`
 | 
			
		||||
	Name string `json:"name"`
 | 
			
		||||
 | 
			
		||||
	// Human-readable description for the VIP.
 | 
			
		||||
	Description string `mapstructure:"description" json:"description"`
 | 
			
		||||
	Description string `json:"description"`
 | 
			
		||||
 | 
			
		||||
	// The ID of the subnet on which to allocate the VIP address.
 | 
			
		||||
	SubnetID string `mapstructure:"subnet_id" json:"subnet_id"`
 | 
			
		||||
	SubnetID string `json:"subnet_id"`
 | 
			
		||||
 | 
			
		||||
	// The IP address of the VIP.
 | 
			
		||||
	Address string `mapstructure:"address" json:"address"`
 | 
			
		||||
	Address string `json:"address"`
 | 
			
		||||
 | 
			
		||||
	// The protocol of the VIP address. A valid value is TCP, HTTP, or HTTPS.
 | 
			
		||||
	Protocol string `mapstructure:"protocol" json:"protocol"`
 | 
			
		||||
	Protocol string `json:"protocol"`
 | 
			
		||||
 | 
			
		||||
	// The port on which to listen to client traffic that is associated with the
 | 
			
		||||
	// VIP address. A valid value is from 0 to 65535.
 | 
			
		||||
	ProtocolPort int `mapstructure:"protocol_port" json:"protocol_port"`
 | 
			
		||||
	ProtocolPort int `json:"protocol_port"`
 | 
			
		||||
 | 
			
		||||
	// The ID of the pool with which the VIP is associated.
 | 
			
		||||
	PoolID string `mapstructure:"pool_id" json:"pool_id"`
 | 
			
		||||
	PoolID string `json:"pool_id"`
 | 
			
		||||
 | 
			
		||||
	// The ID of the port which belongs to the load balancer
 | 
			
		||||
	PortID string `mapstructure:"port_id" json:"port_id"`
 | 
			
		||||
	PortID string `json:"port_id"`
 | 
			
		||||
 | 
			
		||||
	// Indicates whether connections in the same session will be processed by the
 | 
			
		||||
	// same pool member or not.
 | 
			
		||||
	Persistence SessionPersistence `mapstructure:"session_persistence" json:"session_persistence"`
 | 
			
		||||
	Persistence SessionPersistence `json:"session_persistence"`
 | 
			
		||||
 | 
			
		||||
	// The maximum number of connections allowed for the VIP. Default is -1,
 | 
			
		||||
	// meaning no limit.
 | 
			
		||||
	ConnLimit int `mapstructure:"connection_limit" json:"connection_limit"`
 | 
			
		||||
	ConnLimit int `json:"connection_limit"`
 | 
			
		||||
 | 
			
		||||
	// The administrative state of the VIP. A valid value is true (UP) or false (DOWN).
 | 
			
		||||
	AdminStateUp bool `mapstructure:"admin_state_up" json:"admin_state_up"`
 | 
			
		||||
	AdminStateUp bool `json:"admin_state_up"`
 | 
			
		||||
 | 
			
		||||
	// The status of the VIP. Indicates whether the VIP is operational.
 | 
			
		||||
	Status string `mapstructure:"status" json:"status"`
 | 
			
		||||
	Status string `json:"status"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// VIPPage is the page returned by a pager when traversing over a
 | 
			
		||||
@@ -90,40 +89,32 @@ type VIPPage struct {
 | 
			
		||||
// NextPageURL is invoked when a paginated collection of routers has reached
 | 
			
		||||
// the end of a page and the pager seeks to traverse over a new one. In order
 | 
			
		||||
// to do this, it needs to construct the next page's URL.
 | 
			
		||||
func (p VIPPage) NextPageURL() (string, error) {
 | 
			
		||||
	type resp struct {
 | 
			
		||||
		Links []gophercloud.Link `mapstructure:"vips_links"`
 | 
			
		||||
func (r VIPPage) NextPageURL() (string, error) {
 | 
			
		||||
	var s struct {
 | 
			
		||||
		Links []gophercloud.Link `json:"vips_links"`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var r resp
 | 
			
		||||
	err := mapstructure.Decode(p.Body, &r)
 | 
			
		||||
	err := r.ExtractInto(&s)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return gophercloud.ExtractNextURL(r.Links)
 | 
			
		||||
	return gophercloud.ExtractNextURL(s.Links)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IsEmpty checks whether a RouterPage struct is empty.
 | 
			
		||||
func (p VIPPage) IsEmpty() (bool, error) {
 | 
			
		||||
	is, err := ExtractVIPs(p)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return true, nil
 | 
			
		||||
	}
 | 
			
		||||
	return len(is) == 0, nil
 | 
			
		||||
// IsEmpty checks whether a VIPPage struct is empty.
 | 
			
		||||
func (r VIPPage) IsEmpty() (bool, error) {
 | 
			
		||||
	is, err := ExtractVIPs(r)
 | 
			
		||||
	return len(is) == 0, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ExtractVIPs accepts a Page struct, specifically a VIPPage struct,
 | 
			
		||||
// and extracts the elements into a slice of VirtualIP structs. In other words,
 | 
			
		||||
// a generic collection is mapped into a relevant slice.
 | 
			
		||||
func ExtractVIPs(page pagination.Page) ([]VirtualIP, error) {
 | 
			
		||||
	var resp struct {
 | 
			
		||||
		VIPs []VirtualIP `mapstructure:"vips" json:"vips"`
 | 
			
		||||
func ExtractVIPs(r pagination.Page) ([]VirtualIP, error) {
 | 
			
		||||
	var s struct {
 | 
			
		||||
		VIPs []VirtualIP `json:"vips"`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err := mapstructure.Decode(page.(VIPPage).Body, &resp)
 | 
			
		||||
 | 
			
		||||
	return resp.VIPs, err
 | 
			
		||||
	err := (r.(VIPPage)).ExtractInto(&s)
 | 
			
		||||
	return s.VIPs, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type commonResult struct {
 | 
			
		||||
@@ -132,17 +123,11 @@ type commonResult struct {
 | 
			
		||||
 | 
			
		||||
// Extract is a function that accepts a result and extracts a router.
 | 
			
		||||
func (r commonResult) Extract() (*VirtualIP, error) {
 | 
			
		||||
	if r.Err != nil {
 | 
			
		||||
		return nil, r.Err
 | 
			
		||||
	var s struct {
 | 
			
		||||
		VirtualIP *VirtualIP `json:"vip" json:"vip"`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var res struct {
 | 
			
		||||
		VirtualIP *VirtualIP `mapstructure:"vip" json:"vip"`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err := mapstructure.Decode(r.Body, &res)
 | 
			
		||||
 | 
			
		||||
	return res.VirtualIP, err
 | 
			
		||||
	err := r.ExtractInto(&s)
 | 
			
		||||
	return s.VirtualIP, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CreateResult represents the result of a create operation.
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
package vips
 | 
			
		||||
 | 
			
		||||
import "github.com/rackspace/gophercloud"
 | 
			
		||||
import "github.com/gophercloud/gophercloud"
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	rootPath     = "lb"
 | 
			
		||||
@@ -1,59 +1,17 @@
 | 
			
		||||
package listeners
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
 | 
			
		||||
	"github.com/rackspace/gophercloud"
 | 
			
		||||
	"github.com/rackspace/gophercloud/pagination"
 | 
			
		||||
	"github.com/gophercloud/gophercloud"
 | 
			
		||||
	"github.com/gophercloud/gophercloud/pagination"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// AdminState gives users a solid type to work with for create and update
 | 
			
		||||
// operations. It is recommended that users use the `Up` and `Down` enums.
 | 
			
		||||
type AdminState *bool
 | 
			
		||||
type Protocol string
 | 
			
		||||
 | 
			
		||||
type listenerOpts struct {
 | 
			
		||||
	// Required. The protocol - can either be TCP, HTTP or HTTPS.
 | 
			
		||||
	Protocol Protocol
 | 
			
		||||
 | 
			
		||||
	// Required. The port on which to listen for client traffic.
 | 
			
		||||
	ProtocolPort int
 | 
			
		||||
 | 
			
		||||
	// Required for admins. Indicates the owner of the Listener.
 | 
			
		||||
	TenantID string
 | 
			
		||||
 | 
			
		||||
	// Required. The load balancer on which to provision this listener.
 | 
			
		||||
	LoadbalancerID string
 | 
			
		||||
 | 
			
		||||
	// Human-readable name for the Listener. Does not have to be unique.
 | 
			
		||||
	Name string
 | 
			
		||||
 | 
			
		||||
	// Optional. The ID of the default pool with which the Listener is associated.
 | 
			
		||||
	DefaultPoolID string
 | 
			
		||||
 | 
			
		||||
	// Optional. Human-readable description for the Listener.
 | 
			
		||||
	Description string
 | 
			
		||||
 | 
			
		||||
	// Optional. The maximum number of connections allowed for the Listener.
 | 
			
		||||
	ConnLimit *int
 | 
			
		||||
 | 
			
		||||
	// Optional. A reference to a container of TLS secrets.
 | 
			
		||||
	DefaultTlsContainerRef string
 | 
			
		||||
 | 
			
		||||
	// Optional. A list of references to TLS secrets.
 | 
			
		||||
	SniContainerRefs []string
 | 
			
		||||
 | 
			
		||||
	// Optional. The administrative state of the Listener. A valid value is true (UP)
 | 
			
		||||
	// or false (DOWN).
 | 
			
		||||
	AdminStateUp *bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Convenience vars for AdminStateUp values.
 | 
			
		||||
var (
 | 
			
		||||
	iTrue  = true
 | 
			
		||||
	iFalse = false
 | 
			
		||||
 | 
			
		||||
	Up   AdminState = &iTrue
 | 
			
		||||
	Down AdminState = &iFalse
 | 
			
		||||
// Supported attributes for create/update operations.
 | 
			
		||||
const (
 | 
			
		||||
	ProtocolTCP   Protocol = "TCP"
 | 
			
		||||
	ProtocolHTTP  Protocol = "HTTP"
 | 
			
		||||
	ProtocolHTTPS Protocol = "HTTPS"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// ListOptsBuilder allows extensions to add additional parameters to the
 | 
			
		||||
@@ -86,10 +44,7 @@ type ListOpts struct {
 | 
			
		||||
// ToListenerListQuery formats a ListOpts into a query string.
 | 
			
		||||
func (opts ListOpts) ToListenerListQuery() (string, error) {
 | 
			
		||||
	q, err := gophercloud.BuildQueryString(opts)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
	return q.String(), nil
 | 
			
		||||
	return q.String(), err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// List returns a Pager which allows you to iterate over a collection of
 | 
			
		||||
@@ -107,27 +62,11 @@ func List(c *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager {
 | 
			
		||||
		}
 | 
			
		||||
		url += query
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return pagination.NewPager(c, url, func(r pagination.PageResult) pagination.Page {
 | 
			
		||||
		return ListenerPage{pagination.LinkedPageBase{PageResult: r}}
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Protocol string
 | 
			
		||||
 | 
			
		||||
// Supported attributes for create/update operations.
 | 
			
		||||
const (
 | 
			
		||||
	ProtocolTCP   Protocol = "TCP"
 | 
			
		||||
	ProtocolHTTP  Protocol = "HTTP"
 | 
			
		||||
	ProtocolHTTPS Protocol = "HTTPS"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	errLoadbalancerIdRequired = fmt.Errorf("LoadbalancerID is required")
 | 
			
		||||
	errProtocolRequired       = fmt.Errorf("Protocol is required")
 | 
			
		||||
	errProtocolPortRequired   = fmt.Errorf("ProtocolPort  is required")
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// CreateOptsBuilder is the interface options structs have to satisfy in order
 | 
			
		||||
// to be used in the main Create operation in this package. Since many
 | 
			
		||||
// extensions decorate or modify the common logic, it is useful for them to
 | 
			
		||||
@@ -138,53 +77,35 @@ type CreateOptsBuilder interface {
 | 
			
		||||
 | 
			
		||||
// CreateOpts is the common options struct used in this package's Create
 | 
			
		||||
// operation.
 | 
			
		||||
type CreateOpts listenerOpts
 | 
			
		||||
type CreateOpts struct {
 | 
			
		||||
	// The load balancer on which to provision this listener.
 | 
			
		||||
	LoadbalancerID string `json:"loadbalancer_id" required:"true"`
 | 
			
		||||
	// The protocol - can either be TCP, HTTP or HTTPS.
 | 
			
		||||
	Protocol Protocol `json:"protocol" required:"true"`
 | 
			
		||||
	// The port on which to listen for client traffic.
 | 
			
		||||
	ProtocolPort int `json:"protocol_port" required:"true"`
 | 
			
		||||
	// Indicates the owner of the Listener. Required for admins.
 | 
			
		||||
	TenantID string `json:"tenant_id,omitempty"`
 | 
			
		||||
	// Human-readable name for the Listener. Does not have to be unique.
 | 
			
		||||
	Name string `json:"name,omitempty"`
 | 
			
		||||
	// The ID of the default pool with which the Listener is associated.
 | 
			
		||||
	DefaultPoolID string `json:"default_pool_id,omitempty"`
 | 
			
		||||
	// Human-readable description for the Listener.
 | 
			
		||||
	Description string `json:"description,omitempty"`
 | 
			
		||||
	// The maximum number of connections allowed for the Listener.
 | 
			
		||||
	ConnLimit *int `json:"connection_limit,omitempty"`
 | 
			
		||||
	// A reference to a container of TLS secrets.
 | 
			
		||||
	DefaultTlsContainerRef string `json:"default_tls_container_ref,omitempty"`
 | 
			
		||||
	// A list of references to TLS secrets.
 | 
			
		||||
	SniContainerRefs []string `json:"sni_container_refs,omitempty"`
 | 
			
		||||
	// The administrative state of the Listener. A valid value is true (UP)
 | 
			
		||||
	// or false (DOWN).
 | 
			
		||||
	AdminStateUp *bool `json:"admin_state_up,omitempty"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ToListenerCreateMap casts a CreateOpts struct to a map.
 | 
			
		||||
func (opts CreateOpts) ToListenerCreateMap() (map[string]interface{}, error) {
 | 
			
		||||
	l := make(map[string]interface{})
 | 
			
		||||
 | 
			
		||||
	if opts.LoadbalancerID != "" {
 | 
			
		||||
		l["loadbalancer_id"] = opts.LoadbalancerID
 | 
			
		||||
	} else {
 | 
			
		||||
		return nil, errLoadbalancerIdRequired
 | 
			
		||||
	}
 | 
			
		||||
	if opts.Protocol != "" {
 | 
			
		||||
		l["protocol"] = opts.Protocol
 | 
			
		||||
	} else {
 | 
			
		||||
		return nil, errProtocolRequired
 | 
			
		||||
	}
 | 
			
		||||
	if opts.ProtocolPort != 0 {
 | 
			
		||||
		l["protocol_port"] = opts.ProtocolPort
 | 
			
		||||
	} else {
 | 
			
		||||
		return nil, errProtocolPortRequired
 | 
			
		||||
	}
 | 
			
		||||
	if opts.AdminStateUp != nil {
 | 
			
		||||
		l["admin_state_up"] = &opts.AdminStateUp
 | 
			
		||||
	}
 | 
			
		||||
	if opts.Name != "" {
 | 
			
		||||
		l["name"] = opts.Name
 | 
			
		||||
	}
 | 
			
		||||
	if opts.TenantID != "" {
 | 
			
		||||
		l["tenant_id"] = opts.TenantID
 | 
			
		||||
	}
 | 
			
		||||
	if opts.DefaultPoolID != "" {
 | 
			
		||||
		l["default_pool_id"] = opts.DefaultPoolID
 | 
			
		||||
	}
 | 
			
		||||
	if opts.Description != "" {
 | 
			
		||||
		l["description"] = opts.Description
 | 
			
		||||
	}
 | 
			
		||||
	if opts.ConnLimit != nil {
 | 
			
		||||
		l["connection_limit"] = &opts.ConnLimit
 | 
			
		||||
	}
 | 
			
		||||
	if opts.DefaultTlsContainerRef != "" {
 | 
			
		||||
		l["default_tls_container_ref"] = opts.DefaultTlsContainerRef
 | 
			
		||||
	}
 | 
			
		||||
	if opts.SniContainerRefs != nil {
 | 
			
		||||
		l["sni_container_refs"] = opts.SniContainerRefs
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return map[string]interface{}{"listener": l}, nil
 | 
			
		||||
	return gophercloud.BuildRequestBody(opts, "listener")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Create is an operation which provisions a new Listeners based on the
 | 
			
		||||
@@ -194,25 +115,20 @@ func (opts CreateOpts) ToListenerCreateMap() (map[string]interface{}, error) {
 | 
			
		||||
//
 | 
			
		||||
// Users with an admin role can create Listeners on behalf of other tenants by
 | 
			
		||||
// specifying a TenantID attribute different than their own.
 | 
			
		||||
func Create(c *gophercloud.ServiceClient, opts CreateOpts) CreateResult {
 | 
			
		||||
	var res CreateResult
 | 
			
		||||
 | 
			
		||||
	reqBody, err := opts.ToListenerCreateMap()
 | 
			
		||||
func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) (r CreateResult) {
 | 
			
		||||
	b, err := opts.ToListenerCreateMap()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		res.Err = err
 | 
			
		||||
		return res
 | 
			
		||||
		r.Err = err
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Send request to API
 | 
			
		||||
	_, res.Err = c.Post(rootURL(c), reqBody, &res.Body, nil)
 | 
			
		||||
	return res
 | 
			
		||||
	_, r.Err = c.Post(rootURL(c), b, &r.Body, nil)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Get retrieves a particular Listeners based on its unique ID.
 | 
			
		||||
func Get(c *gophercloud.ServiceClient, id string) GetResult {
 | 
			
		||||
	var res GetResult
 | 
			
		||||
	_, res.Err = c.Get(resourceURL(c, id), &res.Body, nil)
 | 
			
		||||
	return res
 | 
			
		||||
func Get(c *gophercloud.ServiceClient, id string) (r GetResult) {
 | 
			
		||||
	_, r.Err = c.Get(resourceURL(c, id), &r.Body, nil)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UpdateOptsBuilder is the interface options structs have to satisfy in order
 | 
			
		||||
@@ -225,55 +141,42 @@ type UpdateOptsBuilder interface {
 | 
			
		||||
 | 
			
		||||
// UpdateOpts is the common options struct used in this package's Update
 | 
			
		||||
// operation.
 | 
			
		||||
type UpdateOpts listenerOpts
 | 
			
		||||
type UpdateOpts struct {
 | 
			
		||||
	// Human-readable name for the Listener. Does not have to be unique.
 | 
			
		||||
	Name string `json:"name,omitempty"`
 | 
			
		||||
	// Human-readable description for the Listener.
 | 
			
		||||
	Description string `json:"description,omitempty"`
 | 
			
		||||
	// The maximum number of connections allowed for the Listener.
 | 
			
		||||
	ConnLimit *int `json:"connection_limit,omitempty"`
 | 
			
		||||
	// A reference to a container of TLS secrets.
 | 
			
		||||
	DefaultTlsContainerRef string `json:"default_tls_container_ref,omitempty"`
 | 
			
		||||
	//  A list of references to TLS secrets.
 | 
			
		||||
	SniContainerRefs []string `json:"sni_container_refs,omitempty"`
 | 
			
		||||
	// The administrative state of the Listener. A valid value is true (UP)
 | 
			
		||||
	// or false (DOWN).
 | 
			
		||||
	AdminStateUp *bool `json:"admin_state_up,omitempty"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ToListenerUpdateMap casts a UpdateOpts struct to a map.
 | 
			
		||||
func (opts UpdateOpts) ToListenerUpdateMap() (map[string]interface{}, error) {
 | 
			
		||||
	l := make(map[string]interface{})
 | 
			
		||||
 | 
			
		||||
	if opts.Name != "" {
 | 
			
		||||
		l["name"] = opts.Name
 | 
			
		||||
	}
 | 
			
		||||
	if opts.Description != "" {
 | 
			
		||||
		l["description"] = opts.Description
 | 
			
		||||
	}
 | 
			
		||||
	if opts.ConnLimit != nil {
 | 
			
		||||
		l["connection_limit"] = &opts.ConnLimit
 | 
			
		||||
	}
 | 
			
		||||
	if opts.DefaultTlsContainerRef != "" {
 | 
			
		||||
		l["default_tls_container_ref"] = opts.DefaultTlsContainerRef
 | 
			
		||||
	}
 | 
			
		||||
	if opts.SniContainerRefs != nil {
 | 
			
		||||
		l["sni_container_refs"] = opts.SniContainerRefs
 | 
			
		||||
	}
 | 
			
		||||
	if opts.AdminStateUp != nil {
 | 
			
		||||
		l["admin_state_up"] = &opts.AdminStateUp
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return map[string]interface{}{"listener": l}, nil
 | 
			
		||||
	return gophercloud.BuildRequestBody(opts, "listener")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Update is an operation which modifies the attributes of the specified Listener.
 | 
			
		||||
func Update(c *gophercloud.ServiceClient, id string, opts UpdateOpts) UpdateResult {
 | 
			
		||||
	var res UpdateResult
 | 
			
		||||
 | 
			
		||||
	reqBody, err := opts.ToListenerUpdateMap()
 | 
			
		||||
func Update(c *gophercloud.ServiceClient, id string, opts UpdateOpts) (r UpdateResult) {
 | 
			
		||||
	b, err := opts.ToListenerUpdateMap()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		res.Err = err
 | 
			
		||||
		return res
 | 
			
		||||
		r.Err = err
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Send request to API
 | 
			
		||||
	_, res.Err = c.Put(resourceURL(c, id), reqBody, &res.Body, &gophercloud.RequestOpts{
 | 
			
		||||
	_, r.Err = c.Put(resourceURL(c, id), b, &r.Body, &gophercloud.RequestOpts{
 | 
			
		||||
		OkCodes: []int{200, 202},
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	return res
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Delete will permanently delete a particular Listeners based on its unique ID.
 | 
			
		||||
func Delete(c *gophercloud.ServiceClient, id string) DeleteResult {
 | 
			
		||||
	var res DeleteResult
 | 
			
		||||
	_, res.Err = c.Delete(resourceURL(c, id), nil)
 | 
			
		||||
	return res
 | 
			
		||||
func Delete(c *gophercloud.ServiceClient, id string) (r DeleteResult) {
 | 
			
		||||
	_, r.Err = c.Delete(resourceURL(c, id), nil)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
@@ -1,14 +1,13 @@
 | 
			
		||||
package listeners
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/mitchellh/mapstructure"
 | 
			
		||||
	"github.com/rackspace/gophercloud"
 | 
			
		||||
	"github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas_v2/pools"
 | 
			
		||||
	"github.com/rackspace/gophercloud/pagination"
 | 
			
		||||
	"github.com/gophercloud/gophercloud"
 | 
			
		||||
	"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/pools"
 | 
			
		||||
	"github.com/gophercloud/gophercloud/pagination"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type LoadBalancerID struct {
 | 
			
		||||
	ID string `mapstructure:"id" json:"id"`
 | 
			
		||||
	ID string `json:"id"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Listener is the primary load balancing configuration object that specifies
 | 
			
		||||
@@ -16,44 +15,32 @@ type LoadBalancerID struct {
 | 
			
		||||
// as other details such as the load balancing method to be use, protocol, etc.
 | 
			
		||||
type Listener struct {
 | 
			
		||||
	// The unique ID for the Listener.
 | 
			
		||||
	ID string `mapstructure:"id" json:"id"`
 | 
			
		||||
 | 
			
		||||
	ID string `json:"id"`
 | 
			
		||||
	// Owner of the Listener. Only an admin user can specify a tenant ID other than its own.
 | 
			
		||||
	TenantID string `mapstructure:"tenant_id" json:"tenant_id"`
 | 
			
		||||
 | 
			
		||||
	TenantID string `json:"tenant_id"`
 | 
			
		||||
	// Human-readable name for the Listener. Does not have to be unique.
 | 
			
		||||
	Name string `mapstructure:"name" json:"name"`
 | 
			
		||||
 | 
			
		||||
	Name string `json:"name"`
 | 
			
		||||
	// Human-readable description for the Listener.
 | 
			
		||||
	Description string `mapstructure:"description" json:"description"`
 | 
			
		||||
 | 
			
		||||
	Description string `json:"description"`
 | 
			
		||||
	// The protocol to loadbalance. A valid value is TCP, HTTP, or HTTPS.
 | 
			
		||||
	Protocol string `mapstructure:"protocol" json:"protocol"`
 | 
			
		||||
 | 
			
		||||
	Protocol string `json:"protocol"`
 | 
			
		||||
	// The port on which to listen to client traffic that is associated with the
 | 
			
		||||
	// Loadbalancer. A valid value is from 0 to 65535.
 | 
			
		||||
	ProtocolPort int `mapstructure:"protocol_port" json:"protocol_port"`
 | 
			
		||||
 | 
			
		||||
	ProtocolPort int `json:"protocol_port"`
 | 
			
		||||
	// The UUID of default pool. Must have compatible protocol with listener.
 | 
			
		||||
	DefaultPoolID string `mapstructure:"default_pool_id" json:"default_pool_id"`
 | 
			
		||||
 | 
			
		||||
	DefaultPoolID string `json:"default_pool_id"`
 | 
			
		||||
	// A list of load balancer IDs.
 | 
			
		||||
	Loadbalancers []LoadBalancerID `mapstructure:"loadbalancers" json:"loadbalancers"`
 | 
			
		||||
 | 
			
		||||
	Loadbalancers []LoadBalancerID `json:"loadbalancers"`
 | 
			
		||||
	// The maximum number of connections allowed for the Loadbalancer. Default is -1,
 | 
			
		||||
	// meaning no limit.
 | 
			
		||||
	ConnLimit int `mapstructure:"connection_limit" json:"connection_limit"`
 | 
			
		||||
 | 
			
		||||
	ConnLimit int `json:"connection_limit"`
 | 
			
		||||
	// The list of references to TLS secrets.
 | 
			
		||||
	SniContainerRefs []string `mapstructure:"sni_container_refs" json:"sni_container_refs"`
 | 
			
		||||
 | 
			
		||||
	SniContainerRefs []string `json:"sni_container_refs"`
 | 
			
		||||
	// Optional. A reference to a container of TLS secrets.
 | 
			
		||||
	DefaultTlsContainerRef string `mapstructure:"default_tls_container_ref" json:"default_tls_container_ref"`
 | 
			
		||||
 | 
			
		||||
	DefaultTlsContainerRef string `json:"default_tls_container_ref"`
 | 
			
		||||
	// The administrative state of the Listener. A valid value is true (UP) or false (DOWN).
 | 
			
		||||
	AdminStateUp bool `mapstructure:"admin_state_up" json:"admin_state_up"`
 | 
			
		||||
 | 
			
		||||
	Pools []pools.Pool `mapstructure:"pools" json:"pools"`
 | 
			
		||||
	AdminStateUp bool         `json:"admin_state_up"`
 | 
			
		||||
	Pools        []pools.Pool `json:"pools"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ListenerPage is the page returned by a pager when traversing over a
 | 
			
		||||
@@ -65,38 +52,32 @@ type ListenerPage struct {
 | 
			
		||||
// NextPageURL is invoked when a paginated collection of routers has reached
 | 
			
		||||
// the end of a page and the pager seeks to traverse over a new one. In order
 | 
			
		||||
// to do this, it needs to construct the next page's URL.
 | 
			
		||||
func (p ListenerPage) NextPageURL() (string, error) {
 | 
			
		||||
	type resp struct {
 | 
			
		||||
		Links []gophercloud.Link `mapstructure:"listeners_links"`
 | 
			
		||||
func (r ListenerPage) NextPageURL() (string, error) {
 | 
			
		||||
	var s struct {
 | 
			
		||||
		Links []gophercloud.Link `json:"listeners_links"`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var r resp
 | 
			
		||||
	err := mapstructure.Decode(p.Body, &r)
 | 
			
		||||
	err := r.ExtractInto(&s)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return gophercloud.ExtractNextURL(r.Links)
 | 
			
		||||
	return gophercloud.ExtractNextURL(s.Links)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IsEmpty checks whether a RouterPage struct is empty.
 | 
			
		||||
func (p ListenerPage) IsEmpty() (bool, error) {
 | 
			
		||||
	is, err := ExtractListeners(p)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return true, nil
 | 
			
		||||
	}
 | 
			
		||||
	return len(is) == 0, nil
 | 
			
		||||
func (r ListenerPage) IsEmpty() (bool, error) {
 | 
			
		||||
	is, err := ExtractListeners(r)
 | 
			
		||||
	return len(is) == 0, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ExtractListeners accepts a Page struct, specifically a ListenerPage struct,
 | 
			
		||||
// and extracts the elements into a slice of Listener structs. In other words,
 | 
			
		||||
// a generic collection is mapped into a relevant slice.
 | 
			
		||||
func ExtractListeners(page pagination.Page) ([]Listener, error) {
 | 
			
		||||
	var resp struct {
 | 
			
		||||
		Listeners []Listener `mapstructure:"listeners" json:"listeners"`
 | 
			
		||||
func ExtractListeners(r pagination.Page) ([]Listener, error) {
 | 
			
		||||
	var s struct {
 | 
			
		||||
		Listeners []Listener `json:"listeners"`
 | 
			
		||||
	}
 | 
			
		||||
	err := mapstructure.Decode(page.(ListenerPage).Body, &resp)
 | 
			
		||||
	return resp.Listeners, err
 | 
			
		||||
	err := (r.(ListenerPage)).ExtractInto(&s)
 | 
			
		||||
	return s.Listeners, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type commonResult struct {
 | 
			
		||||
@@ -105,17 +86,11 @@ type commonResult struct {
 | 
			
		||||
 | 
			
		||||
// Extract is a function that accepts a result and extracts a router.
 | 
			
		||||
func (r commonResult) Extract() (*Listener, error) {
 | 
			
		||||
	if r.Err != nil {
 | 
			
		||||
		return nil, r.Err
 | 
			
		||||
	var s struct {
 | 
			
		||||
		Listener *Listener `json:"listener"`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var res struct {
 | 
			
		||||
		Listener *Listener `mapstructure:"listener" json:"listener"`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err := mapstructure.Decode(r.Body, &res)
 | 
			
		||||
 | 
			
		||||
	return res.Listener, err
 | 
			
		||||
	err := r.ExtractInto(&s)
 | 
			
		||||
	return s.Listener, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CreateResult represents the result of a create operation.
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
package listeners
 | 
			
		||||
 | 
			
		||||
import "github.com/rackspace/gophercloud"
 | 
			
		||||
import "github.com/gophercloud/gophercloud"
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	rootPath     = "lbaas"
 | 
			
		||||
@@ -1,59 +1,14 @@
 | 
			
		||||
package loadbalancers
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
 | 
			
		||||
	"github.com/rackspace/gophercloud"
 | 
			
		||||
	"github.com/rackspace/gophercloud/pagination"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// AdminState gives users a solid type to work with for create and update
 | 
			
		||||
// operations. It is recommended that users use the `Up` and `Down` enums.
 | 
			
		||||
type AdminState *bool
 | 
			
		||||
 | 
			
		||||
type loadbalancerOpts struct {
 | 
			
		||||
	// Optional. Human-readable name for the Loadbalancer. Does not have to be unique.
 | 
			
		||||
	Name string
 | 
			
		||||
 | 
			
		||||
	// Optional. Human-readable description for the Loadbalancer.
 | 
			
		||||
	Description string
 | 
			
		||||
 | 
			
		||||
	// Required. The network on which to allocate the Loadbalancer's address. A tenant can
 | 
			
		||||
	// only create Loadbalancers on networks authorized by policy (e.g. networks that
 | 
			
		||||
	// belong to them or networks that are shared).
 | 
			
		||||
	VipSubnetID string
 | 
			
		||||
 | 
			
		||||
	// Required for admins. The UUID of the tenant who owns the Loadbalancer.
 | 
			
		||||
	// Only administrative users can specify a tenant UUID other than their own.
 | 
			
		||||
	TenantID string
 | 
			
		||||
 | 
			
		||||
	// Optional. The IP address of the Loadbalancer.
 | 
			
		||||
	VipAddress string
 | 
			
		||||
 | 
			
		||||
	// Optional. The administrative state of the Loadbalancer. A valid value is true (UP)
 | 
			
		||||
	// or false (DOWN).
 | 
			
		||||
	AdminStateUp *bool
 | 
			
		||||
 | 
			
		||||
	// Optional. The UUID of a flavor.
 | 
			
		||||
	Flavor string
 | 
			
		||||
 | 
			
		||||
	// Optional. The name of the provider.
 | 
			
		||||
	Provider string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Convenience vars for AdminStateUp values.
 | 
			
		||||
var (
 | 
			
		||||
	iTrue  = true
 | 
			
		||||
	iFalse = false
 | 
			
		||||
 | 
			
		||||
	Up   AdminState = &iTrue
 | 
			
		||||
	Down AdminState = &iFalse
 | 
			
		||||
	"github.com/gophercloud/gophercloud"
 | 
			
		||||
	"github.com/gophercloud/gophercloud/pagination"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// ListOptsBuilder allows extensions to add additional parameters to the
 | 
			
		||||
// List request.
 | 
			
		||||
type ListOptsBuilder interface {
 | 
			
		||||
	ToLoadbalancerListQuery() (string, error)
 | 
			
		||||
	ToLoadBalancerListQuery() (string, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ListOpts allows the filtering and sorting of paginated collections through
 | 
			
		||||
@@ -67,6 +22,7 @@ type ListOpts struct {
 | 
			
		||||
	TenantID           string `q:"tenant_id"`
 | 
			
		||||
	ProvisioningStatus string `q:"provisioning_status"`
 | 
			
		||||
	VipAddress         string `q:"vip_address"`
 | 
			
		||||
	VipPortID          string `q:"vip_port_id"`
 | 
			
		||||
	VipSubnetID        string `q:"vip_subnet_id"`
 | 
			
		||||
	ID                 string `q:"id"`
 | 
			
		||||
	OperatingStatus    string `q:"operating_status"`
 | 
			
		||||
@@ -80,12 +36,9 @@ type ListOpts struct {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ToLoadbalancerListQuery formats a ListOpts into a query string.
 | 
			
		||||
func (opts ListOpts) ToLoadbalancerListQuery() (string, error) {
 | 
			
		||||
func (opts ListOpts) ToLoadBalancerListQuery() (string, error) {
 | 
			
		||||
	q, err := gophercloud.BuildQueryString(opts)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
	return q.String(), nil
 | 
			
		||||
	return q.String(), err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// List returns a Pager which allows you to iterate over a collection of
 | 
			
		||||
@@ -97,66 +50,53 @@ func (opts ListOpts) ToLoadbalancerListQuery() (string, error) {
 | 
			
		||||
func List(c *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager {
 | 
			
		||||
	url := rootURL(c)
 | 
			
		||||
	if opts != nil {
 | 
			
		||||
		query, err := opts.ToLoadbalancerListQuery()
 | 
			
		||||
		query, err := opts.ToLoadBalancerListQuery()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return pagination.Pager{Err: err}
 | 
			
		||||
		}
 | 
			
		||||
		url += query
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return pagination.NewPager(c, url, func(r pagination.PageResult) pagination.Page {
 | 
			
		||||
		return LoadbalancerPage{pagination.LinkedPageBase{PageResult: r}}
 | 
			
		||||
		return LoadBalancerPage{pagination.LinkedPageBase{PageResult: r}}
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	errVipSubnetIDRequried = fmt.Errorf("VipSubnetID is required")
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// CreateOptsBuilder is the interface options structs have to satisfy in order
 | 
			
		||||
// to be used in the main Create operation in this package. Since many
 | 
			
		||||
// extensions decorate or modify the common logic, it is useful for them to
 | 
			
		||||
// satisfy a basic interface in order for them to be used.
 | 
			
		||||
type CreateOptsBuilder interface {
 | 
			
		||||
	ToLoadbalancerCreateMap() (map[string]interface{}, error)
 | 
			
		||||
	ToLoadBalancerCreateMap() (map[string]interface{}, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CreateOpts is the common options struct used in this package's Create
 | 
			
		||||
// operation.
 | 
			
		||||
type CreateOpts loadbalancerOpts
 | 
			
		||||
 | 
			
		||||
// ToLoadbalancerCreateMap casts a CreateOpts struct to a map.
 | 
			
		||||
func (opts CreateOpts) ToLoadbalancerCreateMap() (map[string]interface{}, error) {
 | 
			
		||||
	l := make(map[string]interface{})
 | 
			
		||||
 | 
			
		||||
	if opts.VipSubnetID != "" {
 | 
			
		||||
		l["vip_subnet_id"] = opts.VipSubnetID
 | 
			
		||||
	} else {
 | 
			
		||||
		return nil, errVipSubnetIDRequried
 | 
			
		||||
	}
 | 
			
		||||
	if opts.AdminStateUp != nil {
 | 
			
		||||
		l["admin_state_up"] = &opts.AdminStateUp
 | 
			
		||||
	}
 | 
			
		||||
	if opts.Name != "" {
 | 
			
		||||
		l["name"] = opts.Name
 | 
			
		||||
	}
 | 
			
		||||
	if opts.TenantID != "" {
 | 
			
		||||
		l["tenant_id"] = opts.TenantID
 | 
			
		||||
	}
 | 
			
		||||
	if opts.Description != "" {
 | 
			
		||||
		l["description"] = opts.Description
 | 
			
		||||
	}
 | 
			
		||||
	if opts.VipAddress != "" {
 | 
			
		||||
		l["vip_address"] = opts.VipAddress
 | 
			
		||||
	}
 | 
			
		||||
	if opts.Flavor != "" {
 | 
			
		||||
		l["flavor"] = opts.Flavor
 | 
			
		||||
	}
 | 
			
		||||
	if opts.Provider != "" {
 | 
			
		||||
		l["provider"] = opts.Provider
 | 
			
		||||
type CreateOpts struct {
 | 
			
		||||
	// Optional. Human-readable name for the Loadbalancer. Does not have to be unique.
 | 
			
		||||
	Name string `json:"name,omitempty"`
 | 
			
		||||
	// Optional. Human-readable description for the Loadbalancer.
 | 
			
		||||
	Description string `json:"description,omitempty"`
 | 
			
		||||
	// Required. The network on which to allocate the Loadbalancer's address. A tenant can
 | 
			
		||||
	// only create Loadbalancers on networks authorized by policy (e.g. networks that
 | 
			
		||||
	// belong to them or networks that are shared).
 | 
			
		||||
	VipSubnetID string `json:"vip_subnet_id" required:"true"`
 | 
			
		||||
	// Required for admins. The UUID of the tenant who owns the Loadbalancer.
 | 
			
		||||
	// Only administrative users can specify a tenant UUID other than their own.
 | 
			
		||||
	TenantID string `json:"tenant_id,omitempty"`
 | 
			
		||||
	// Optional. The IP address of the Loadbalancer.
 | 
			
		||||
	VipAddress string `json:"vip_address,omitempty"`
 | 
			
		||||
	// Optional. The administrative state of the Loadbalancer. A valid value is true (UP)
 | 
			
		||||
	// or false (DOWN).
 | 
			
		||||
	AdminStateUp *bool `json:"admin_state_up,omitempty"`
 | 
			
		||||
	// Optional. The UUID of a flavor.
 | 
			
		||||
	Flavor string `json:"flavor,omitempty"`
 | 
			
		||||
	// Optional. The name of the provider.
 | 
			
		||||
	Provider string `json:"provider,omitempty"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
	return map[string]interface{}{"loadbalancer": l}, nil
 | 
			
		||||
// ToLoadBalancerCreateMap casts a CreateOpts struct to a map.
 | 
			
		||||
func (opts CreateOpts) ToLoadBalancerCreateMap() (map[string]interface{}, error) {
 | 
			
		||||
	return gophercloud.BuildRequestBody(opts, "loadbalancer")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Create is an operation which provisions a new loadbalancer based on the
 | 
			
		||||
@@ -166,25 +106,20 @@ func (opts CreateOpts) ToLoadbalancerCreateMap() (map[string]interface{}, error)
 | 
			
		||||
//
 | 
			
		||||
// Users with an admin role can create loadbalancers on behalf of other tenants by
 | 
			
		||||
// specifying a TenantID attribute different than their own.
 | 
			
		||||
func Create(c *gophercloud.ServiceClient, opts CreateOpts) CreateResult {
 | 
			
		||||
	var res CreateResult
 | 
			
		||||
 | 
			
		||||
	reqBody, err := opts.ToLoadbalancerCreateMap()
 | 
			
		||||
func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) (r CreateResult) {
 | 
			
		||||
	b, err := opts.ToLoadBalancerCreateMap()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		res.Err = err
 | 
			
		||||
		return res
 | 
			
		||||
		r.Err = err
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Send request to API
 | 
			
		||||
	_, res.Err = c.Post(rootURL(c), reqBody, &res.Body, nil)
 | 
			
		||||
	return res
 | 
			
		||||
	_, r.Err = c.Post(rootURL(c), b, &r.Body, nil)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Get retrieves a particular Loadbalancer based on its unique ID.
 | 
			
		||||
func Get(c *gophercloud.ServiceClient, id string) GetResult {
 | 
			
		||||
	var res GetResult
 | 
			
		||||
	_, res.Err = c.Get(resourceURL(c, id), &res.Body, nil)
 | 
			
		||||
	return res
 | 
			
		||||
func Get(c *gophercloud.ServiceClient, id string) (r GetResult) {
 | 
			
		||||
	_, r.Err = c.Get(resourceURL(c, id), &r.Body, nil)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UpdateOptsBuilder is the interface options structs have to satisfy in order
 | 
			
		||||
@@ -192,57 +127,46 @@ func Get(c *gophercloud.ServiceClient, id string) GetResult {
 | 
			
		||||
// extensions decorate or modify the common logic, it is useful for them to
 | 
			
		||||
// satisfy a basic interface in order for them to be used.
 | 
			
		||||
type UpdateOptsBuilder interface {
 | 
			
		||||
	ToLoadbalancerUpdateMap() (map[string]interface{}, error)
 | 
			
		||||
	ToLoadBalancerUpdateMap() (map[string]interface{}, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UpdateOpts is the common options struct used in this package's Update
 | 
			
		||||
// operation.
 | 
			
		||||
type UpdateOpts loadbalancerOpts
 | 
			
		||||
 | 
			
		||||
// ToLoadbalancerUpdateMap casts a UpdateOpts struct to a map.
 | 
			
		||||
func (opts UpdateOpts) ToLoadbalancerUpdateMap() (map[string]interface{}, error) {
 | 
			
		||||
	l := make(map[string]interface{})
 | 
			
		||||
 | 
			
		||||
	if opts.Name != "" {
 | 
			
		||||
		l["name"] = opts.Name
 | 
			
		||||
	}
 | 
			
		||||
	if opts.Description != "" {
 | 
			
		||||
		l["description"] = opts.Description
 | 
			
		||||
	}
 | 
			
		||||
	if opts.AdminStateUp != nil {
 | 
			
		||||
		l["admin_state_up"] = &opts.AdminStateUp
 | 
			
		||||
type UpdateOpts struct {
 | 
			
		||||
	// Optional. Human-readable name for the Loadbalancer. Does not have to be unique.
 | 
			
		||||
	Name string `json:"name,omitempty"`
 | 
			
		||||
	// Optional. Human-readable description for the Loadbalancer.
 | 
			
		||||
	Description string `json:"description,omitempty"`
 | 
			
		||||
	// Optional. The administrative state of the Loadbalancer. A valid value is true (UP)
 | 
			
		||||
	// or false (DOWN).
 | 
			
		||||
	AdminStateUp *bool `json:"admin_state_up,omitempty"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
	return map[string]interface{}{"loadbalancer": l}, nil
 | 
			
		||||
// ToLoadBalancerUpdateMap casts a UpdateOpts struct to a map.
 | 
			
		||||
func (opts UpdateOpts) ToLoadBalancerUpdateMap() (map[string]interface{}, error) {
 | 
			
		||||
	return gophercloud.BuildRequestBody(opts, "loadbalancer")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Update is an operation which modifies the attributes of the specified Loadbalancer.
 | 
			
		||||
func Update(c *gophercloud.ServiceClient, id string, opts UpdateOpts) UpdateResult {
 | 
			
		||||
	var res UpdateResult
 | 
			
		||||
 | 
			
		||||
	reqBody, err := opts.ToLoadbalancerUpdateMap()
 | 
			
		||||
// Update is an operation which modifies the attributes of the specified LoadBalancer.
 | 
			
		||||
func Update(c *gophercloud.ServiceClient, id string, opts UpdateOpts) (r UpdateResult) {
 | 
			
		||||
	b, err := opts.ToLoadBalancerUpdateMap()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		res.Err = err
 | 
			
		||||
		return res
 | 
			
		||||
		r.Err = err
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Send request to API
 | 
			
		||||
	_, res.Err = c.Put(resourceURL(c, id), reqBody, &res.Body, &gophercloud.RequestOpts{
 | 
			
		||||
	_, r.Err = c.Put(resourceURL(c, id), b, &r.Body, &gophercloud.RequestOpts{
 | 
			
		||||
		OkCodes: []int{200, 202},
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	return res
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Delete will permanently delete a particular Loadbalancer based on its unique ID.
 | 
			
		||||
func Delete(c *gophercloud.ServiceClient, id string) DeleteResult {
 | 
			
		||||
	var res DeleteResult
 | 
			
		||||
	_, res.Err = c.Delete(resourceURL(c, id), nil)
 | 
			
		||||
	return res
 | 
			
		||||
// Delete will permanently delete a particular LoadBalancer based on its unique ID.
 | 
			
		||||
func Delete(c *gophercloud.ServiceClient, id string) (r DeleteResult) {
 | 
			
		||||
	_, r.Err = c.Delete(resourceURL(c, id), nil)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func GetStatuses(c *gophercloud.ServiceClient, id string) GetResult {
 | 
			
		||||
	var res GetResult
 | 
			
		||||
	_, res.Err = c.Get(statusRootURL(c, id), &res.Body, nil)
 | 
			
		||||
	return res
 | 
			
		||||
func GetStatuses(c *gophercloud.ServiceClient, id string) (r GetStatusesResult) {
 | 
			
		||||
	_, r.Err = c.Get(statusRootURL(c, id), &r.Body, nil)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										125
									
								
								vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/loadbalancers/results.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										125
									
								
								vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/loadbalancers/results.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,125 @@
 | 
			
		||||
package loadbalancers
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/gophercloud/gophercloud"
 | 
			
		||||
	"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/listeners"
 | 
			
		||||
	"github.com/gophercloud/gophercloud/pagination"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// LoadBalancer is the primary load balancing configuration object that specifies
 | 
			
		||||
// the virtual IP address on which client traffic is received, as well
 | 
			
		||||
// as other details such as the load balancing method to be use, protocol, etc.
 | 
			
		||||
type LoadBalancer struct {
 | 
			
		||||
	// Human-readable description for the Loadbalancer.
 | 
			
		||||
	Description string `json:"description"`
 | 
			
		||||
	// The administrative state of the Loadbalancer. A valid value is true (UP) or false (DOWN).
 | 
			
		||||
	AdminStateUp bool `json:"admin_state_up"`
 | 
			
		||||
	// Owner of the LoadBalancer. Only an admin user can specify a tenant ID other than its own.
 | 
			
		||||
	TenantID string `json:"tenant_id"`
 | 
			
		||||
	// The provisioning status of the LoadBalancer. This value is ACTIVE, PENDING_CREATE or ERROR.
 | 
			
		||||
	ProvisioningStatus string `json:"provisioning_status"`
 | 
			
		||||
	// The IP address of the Loadbalancer.
 | 
			
		||||
	VipAddress string `json:"vip_address"`
 | 
			
		||||
	// The UUID of the port associated with the IP address.
 | 
			
		||||
	VipPortID string `json:"vip_port_id"`
 | 
			
		||||
	// The UUID of the subnet on which to allocate the virtual IP for the Loadbalancer address.
 | 
			
		||||
	VipSubnetID string `json:"vip_subnet_id"`
 | 
			
		||||
	// The unique ID for the LoadBalancer.
 | 
			
		||||
	ID string `json:"id"`
 | 
			
		||||
	// The operating status of the LoadBalancer. This value is ONLINE or OFFLINE.
 | 
			
		||||
	OperatingStatus string `json:"operating_status"`
 | 
			
		||||
	// Human-readable name for the LoadBalancer. Does not have to be unique.
 | 
			
		||||
	Name string `json:"name"`
 | 
			
		||||
	// The UUID of a flavor if set.
 | 
			
		||||
	Flavor string `json:"flavor"`
 | 
			
		||||
	// The name of the provider.
 | 
			
		||||
	Provider  string               `json:"provider"`
 | 
			
		||||
	Listeners []listeners.Listener `json:"listeners"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type StatusTree struct {
 | 
			
		||||
	Loadbalancer *LoadBalancer `json:"loadbalancer"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// LoadBalancerPage is the page returned by a pager when traversing over a
 | 
			
		||||
// collection of routers.
 | 
			
		||||
type LoadBalancerPage struct {
 | 
			
		||||
	pagination.LinkedPageBase
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NextPageURL is invoked when a paginated collection of routers has reached
 | 
			
		||||
// the end of a page and the pager seeks to traverse over a new one. In order
 | 
			
		||||
// to do this, it needs to construct the next page's URL.
 | 
			
		||||
func (r LoadBalancerPage) NextPageURL() (string, error) {
 | 
			
		||||
	var s struct {
 | 
			
		||||
		Links []gophercloud.Link `json:"loadbalancers_links"`
 | 
			
		||||
	}
 | 
			
		||||
	err := r.ExtractInto(&s)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
	return gophercloud.ExtractNextURL(s.Links)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IsEmpty checks whether a LoadBalancerPage struct is empty.
 | 
			
		||||
func (p LoadBalancerPage) IsEmpty() (bool, error) {
 | 
			
		||||
	is, err := ExtractLoadBalancers(p)
 | 
			
		||||
	return len(is) == 0, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ExtractLoadBalancers accepts a Page struct, specifically a LoadbalancerPage struct,
 | 
			
		||||
// and extracts the elements into a slice of LoadBalancer structs. In other words,
 | 
			
		||||
// a generic collection is mapped into a relevant slice.
 | 
			
		||||
func ExtractLoadBalancers(r pagination.Page) ([]LoadBalancer, error) {
 | 
			
		||||
	var s struct {
 | 
			
		||||
		LoadBalancers []LoadBalancer `json:"loadbalancers"`
 | 
			
		||||
	}
 | 
			
		||||
	err := (r.(LoadBalancerPage)).ExtractInto(&s)
 | 
			
		||||
	return s.LoadBalancers, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type commonResult struct {
 | 
			
		||||
	gophercloud.Result
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Extract is a function that accepts a result and extracts a router.
 | 
			
		||||
func (r commonResult) Extract() (*LoadBalancer, error) {
 | 
			
		||||
	var s struct {
 | 
			
		||||
		LoadBalancer *LoadBalancer `json:"loadbalancer"`
 | 
			
		||||
	}
 | 
			
		||||
	err := r.ExtractInto(&s)
 | 
			
		||||
	return s.LoadBalancer, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type GetStatusesResult struct {
 | 
			
		||||
	gophercloud.Result
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Extract is a function that accepts a result and extracts a Loadbalancer.
 | 
			
		||||
func (r GetStatusesResult) Extract() (*StatusTree, error) {
 | 
			
		||||
	var s struct {
 | 
			
		||||
		Statuses *StatusTree `json:"statuses"`
 | 
			
		||||
	}
 | 
			
		||||
	err := r.ExtractInto(&s)
 | 
			
		||||
	return s.Statuses, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CreateResult represents the result of a create operation.
 | 
			
		||||
type CreateResult struct {
 | 
			
		||||
	commonResult
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetResult represents the result of a get operation.
 | 
			
		||||
type GetResult struct {
 | 
			
		||||
	commonResult
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UpdateResult represents the result of an update operation.
 | 
			
		||||
type UpdateResult struct {
 | 
			
		||||
	commonResult
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeleteResult represents the result of a delete operation.
 | 
			
		||||
type DeleteResult struct {
 | 
			
		||||
	gophercloud.ErrResult
 | 
			
		||||
}
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
package loadbalancers
 | 
			
		||||
 | 
			
		||||
import "github.com/rackspace/gophercloud"
 | 
			
		||||
import "github.com/gophercloud/gophercloud"
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	rootPath     = "lbaas"
 | 
			
		||||
@@ -2,51 +2,11 @@ package monitors
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"github.com/rackspace/gophercloud"
 | 
			
		||||
	"github.com/rackspace/gophercloud/pagination"
 | 
			
		||||
 | 
			
		||||
	"github.com/gophercloud/gophercloud"
 | 
			
		||||
	"github.com/gophercloud/gophercloud/pagination"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type monitorOpts struct {
 | 
			
		||||
	// Required. The Pool to Monitor.
 | 
			
		||||
	PoolID string
 | 
			
		||||
 | 
			
		||||
	// Optional. The Name of the Monitor.
 | 
			
		||||
	Name string
 | 
			
		||||
 | 
			
		||||
	// Required for admins. Indicates the owner of the Loadbalancer.
 | 
			
		||||
	TenantID string
 | 
			
		||||
 | 
			
		||||
	// Required. The type of probe, which is PING, TCP, HTTP, or HTTPS, that is
 | 
			
		||||
	// sent by the load balancer to verify the member state.
 | 
			
		||||
	Type string
 | 
			
		||||
 | 
			
		||||
	// Required. The time, in seconds, between sending probes to members.
 | 
			
		||||
	Delay int
 | 
			
		||||
 | 
			
		||||
	// Required. Maximum number of seconds for a Monitor to wait for a ping reply
 | 
			
		||||
	// before it times out. The value must be less than the delay value.
 | 
			
		||||
	Timeout int
 | 
			
		||||
 | 
			
		||||
	// Required. Number of permissible ping failures before changing the member's
 | 
			
		||||
	// status to INACTIVE. Must be a number between 1 and 10.
 | 
			
		||||
	MaxRetries int
 | 
			
		||||
 | 
			
		||||
	// Required for HTTP(S) types. URI path that will be accessed if Monitor type
 | 
			
		||||
	// is HTTP or HTTPS.
 | 
			
		||||
	URLPath string
 | 
			
		||||
 | 
			
		||||
	// Required for HTTP(S) types. The HTTP method used for requests by the
 | 
			
		||||
	// Monitor. If this attribute is not specified, it defaults to "GET".
 | 
			
		||||
	HTTPMethod string
 | 
			
		||||
 | 
			
		||||
	// Required for HTTP(S) types. Expected HTTP codes for a passing HTTP(S)
 | 
			
		||||
	// Monitor. You can either specify a single status like "200", or a range
 | 
			
		||||
	// like "200-202".
 | 
			
		||||
	ExpectedCodes string
 | 
			
		||||
 | 
			
		||||
	AdminStateUp *bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ListOptsBuilder allows extensions to add additional parameters to the
 | 
			
		||||
// List request.
 | 
			
		||||
type ListOptsBuilder interface {
 | 
			
		||||
@@ -102,7 +62,6 @@ func List(c *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager {
 | 
			
		||||
		}
 | 
			
		||||
		url += query
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return pagination.NewPager(c, url, func(r pagination.PageResult) pagination.Page {
 | 
			
		||||
		return MonitorPage{pagination.LinkedPageBase{PageResult: r}}
 | 
			
		||||
	})
 | 
			
		||||
@@ -117,13 +76,6 @@ const (
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	errPoolIDRequired        = fmt.Errorf("PoolID to monitor is required")
 | 
			
		||||
	errValidTypeRequired     = fmt.Errorf("A valid Type is required. Supported values are PING, TCP, HTTP and HTTPS")
 | 
			
		||||
	errDelayRequired         = fmt.Errorf("Delay is required")
 | 
			
		||||
	errTimeoutRequired       = fmt.Errorf("Timeout is required")
 | 
			
		||||
	errMaxRetriesRequired    = fmt.Errorf("MaxRetries is required")
 | 
			
		||||
	errURLPathRequired       = fmt.Errorf("URL path is required")
 | 
			
		||||
	errExpectedCodesRequired = fmt.Errorf("ExpectedCodes is required")
 | 
			
		||||
	errDelayMustGETimeout = fmt.Errorf("Delay must be greater than or equal to timeout")
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
@@ -137,64 +89,57 @@ type CreateOptsBuilder interface {
 | 
			
		||||
 | 
			
		||||
// CreateOpts is the common options struct used in this package's Create
 | 
			
		||||
// operation.
 | 
			
		||||
type CreateOpts monitorOpts
 | 
			
		||||
type CreateOpts struct {
 | 
			
		||||
	// Required. The Pool to Monitor.
 | 
			
		||||
	PoolID string `json:"pool_id" required:"true"`
 | 
			
		||||
	// Required. The type of probe, which is PING, TCP, HTTP, or HTTPS, that is
 | 
			
		||||
	// sent by the load balancer to verify the member state.
 | 
			
		||||
	Type string `json:"type" required:"true"`
 | 
			
		||||
	// Required. The time, in seconds, between sending probes to members.
 | 
			
		||||
	Delay int `json:"delay" required:"true"`
 | 
			
		||||
	// Required. Maximum number of seconds for a Monitor to wait for a ping reply
 | 
			
		||||
	// before it times out. The value must be less than the delay value.
 | 
			
		||||
	Timeout int `json:"timeout" required:"true"`
 | 
			
		||||
	// Required. Number of permissible ping failures before changing the member's
 | 
			
		||||
	// status to INACTIVE. Must be a number between 1 and 10.
 | 
			
		||||
	MaxRetries int `json:"max_retries" required:"true"`
 | 
			
		||||
	// Required for HTTP(S) types. URI path that will be accessed if Monitor type
 | 
			
		||||
	// is HTTP or HTTPS.
 | 
			
		||||
	URLPath string `json:"url_path,omitempty"`
 | 
			
		||||
	// Required for HTTP(S) types. The HTTP method used for requests by the
 | 
			
		||||
	// Monitor. If this attribute is not specified, it defaults to "GET".
 | 
			
		||||
	HTTPMethod string `json:"http_method,omitempty"`
 | 
			
		||||
	// Required for HTTP(S) types. Expected HTTP codes for a passing HTTP(S)
 | 
			
		||||
	// Monitor. You can either specify a single status like "200", or a range
 | 
			
		||||
	// like "200-202".
 | 
			
		||||
	ExpectedCodes string `json:"expected_codes,omitempty"`
 | 
			
		||||
	// Indicates the owner of the Loadbalancer. Required for admins.
 | 
			
		||||
	TenantID string `json:"tenant_id,omitempty"`
 | 
			
		||||
	// Optional. The Name of the Monitor.
 | 
			
		||||
	Name         string `json:"name,omitempty"`
 | 
			
		||||
	AdminStateUp *bool  `json:"admin_state_up,omitempty"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ToMonitorCreateMap casts a CreateOpts struct to a map.
 | 
			
		||||
func (opts CreateOpts) ToMonitorCreateMap() (map[string]interface{}, error) {
 | 
			
		||||
	l := make(map[string]interface{})
 | 
			
		||||
	allowed := map[string]bool{TypeHTTP: true, TypeHTTPS: true, TypeTCP: true, TypePING: true}
 | 
			
		||||
 | 
			
		||||
	if allowed[opts.Type] {
 | 
			
		||||
		l["type"] = opts.Type
 | 
			
		||||
	} else {
 | 
			
		||||
		return nil, errValidTypeRequired
 | 
			
		||||
	}
 | 
			
		||||
	if opts.Type == TypeHTTP || opts.Type == TypeHTTPS {
 | 
			
		||||
		if opts.URLPath != "" {
 | 
			
		||||
			l["url_path"] = opts.URLPath
 | 
			
		||||
		} else {
 | 
			
		||||
			return nil, errURLPathRequired
 | 
			
		||||
		}
 | 
			
		||||
		if opts.ExpectedCodes != "" {
 | 
			
		||||
			l["expected_codes"] = opts.ExpectedCodes
 | 
			
		||||
		} else {
 | 
			
		||||
			return nil, errExpectedCodesRequired
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if opts.PoolID != "" {
 | 
			
		||||
		l["pool_id"] = opts.PoolID
 | 
			
		||||
	} else {
 | 
			
		||||
		return nil, errPoolIDRequired
 | 
			
		||||
	}
 | 
			
		||||
	if opts.Delay != 0 {
 | 
			
		||||
		l["delay"] = opts.Delay
 | 
			
		||||
	} else {
 | 
			
		||||
		return nil, errDelayRequired
 | 
			
		||||
	}
 | 
			
		||||
	if opts.Timeout != 0 {
 | 
			
		||||
		l["timeout"] = opts.Timeout
 | 
			
		||||
	} else {
 | 
			
		||||
		return nil, errMaxRetriesRequired
 | 
			
		||||
	}
 | 
			
		||||
	if opts.MaxRetries != 0 {
 | 
			
		||||
		l["max_retries"] = opts.MaxRetries
 | 
			
		||||
	} else {
 | 
			
		||||
		return nil, errMaxRetriesRequired
 | 
			
		||||
	}
 | 
			
		||||
	if opts.AdminStateUp != nil {
 | 
			
		||||
		l["admin_state_up"] = &opts.AdminStateUp
 | 
			
		||||
	}
 | 
			
		||||
	if opts.Name != "" {
 | 
			
		||||
		l["name"] = opts.Name
 | 
			
		||||
	}
 | 
			
		||||
	if opts.TenantID != "" {
 | 
			
		||||
		l["tenant_id"] = opts.TenantID
 | 
			
		||||
	}
 | 
			
		||||
	if opts.HTTPMethod != "" {
 | 
			
		||||
		l["http_method"] = opts.HTTPMethod
 | 
			
		||||
	b, err := gophercloud.BuildRequestBody(opts, "healthmonitor")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return map[string]interface{}{"healthmonitor": l}, nil
 | 
			
		||||
	switch opts.Type {
 | 
			
		||||
	case TypeHTTP, TypeHTTPS:
 | 
			
		||||
		switch opts.URLPath {
 | 
			
		||||
		case "":
 | 
			
		||||
			return nil, fmt.Errorf("URLPath must be provided for HTTP and HTTPS")
 | 
			
		||||
		}
 | 
			
		||||
		switch opts.ExpectedCodes {
 | 
			
		||||
		case "":
 | 
			
		||||
			return nil, fmt.Errorf("ExpectedCodes must be provided for HTTP and HTTPS")
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return b, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
@@ -212,26 +157,20 @@ func (opts CreateOpts) ToMonitorCreateMap() (map[string]interface{}, error) {
 | 
			
		||||
 CreateOpts{Type: TypeHTTP, Delay: 20, Timeout: 10, MaxRetries: 3,
 | 
			
		||||
 HttpMethod: "HEAD", ExpectedCodes: "200", PoolID: "2c946bfc-1804-43ab-a2ff-58f6a762b505"}
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult {
 | 
			
		||||
	var res CreateResult
 | 
			
		||||
 | 
			
		||||
	reqBody, err := opts.ToMonitorCreateMap()
 | 
			
		||||
func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) (r CreateResult) {
 | 
			
		||||
	b, err := opts.ToMonitorCreateMap()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		res.Err = err
 | 
			
		||||
		return res
 | 
			
		||||
		r.Err = err
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Send request to API
 | 
			
		||||
	_, res.Err = c.Post(rootURL(c), reqBody, &res.Body, nil)
 | 
			
		||||
	return res
 | 
			
		||||
	_, r.Err = c.Post(rootURL(c), b, &r.Body, nil)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Get retrieves a particular Health Monitor based on its unique ID.
 | 
			
		||||
func Get(c *gophercloud.ServiceClient, id string) GetResult {
 | 
			
		||||
	var res GetResult
 | 
			
		||||
	_, res.Err = c.Get(resourceURL(c, id), &res.Body, nil)
 | 
			
		||||
	return res
 | 
			
		||||
func Get(c *gophercloud.ServiceClient, id string) (r GetResult) {
 | 
			
		||||
	_, r.Err = c.Get(resourceURL(c, id), &r.Body, nil)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UpdateOptsBuilder is the interface options structs have to satisfy in order
 | 
			
		||||
@@ -244,61 +183,51 @@ type UpdateOptsBuilder interface {
 | 
			
		||||
 | 
			
		||||
// UpdateOpts is the common options struct used in this package's Update
 | 
			
		||||
// operation.
 | 
			
		||||
type UpdateOpts monitorOpts
 | 
			
		||||
type UpdateOpts struct {
 | 
			
		||||
	// Required. The time, in seconds, between sending probes to members.
 | 
			
		||||
	Delay int `json:"delay,omitempty"`
 | 
			
		||||
	// Required. Maximum number of seconds for a Monitor to wait for a ping reply
 | 
			
		||||
	// before it times out. The value must be less than the delay value.
 | 
			
		||||
	Timeout int `json:"timeout,omitempty"`
 | 
			
		||||
	// Required. Number of permissible ping failures before changing the member's
 | 
			
		||||
	// status to INACTIVE. Must be a number between 1 and 10.
 | 
			
		||||
	MaxRetries int `json:"max_retries,omitempty"`
 | 
			
		||||
	// Required for HTTP(S) types. URI path that will be accessed if Monitor type
 | 
			
		||||
	// is HTTP or HTTPS.
 | 
			
		||||
	URLPath string `json:"url_path,omitempty"`
 | 
			
		||||
	// Required for HTTP(S) types. The HTTP method used for requests by the
 | 
			
		||||
	// Monitor. If this attribute is not specified, it defaults to "GET".
 | 
			
		||||
	HTTPMethod string `json:"http_method,omitempty"`
 | 
			
		||||
	// Required for HTTP(S) types. Expected HTTP codes for a passing HTTP(S)
 | 
			
		||||
	// Monitor. You can either specify a single status like "200", or a range
 | 
			
		||||
	// like "200-202".
 | 
			
		||||
	ExpectedCodes string `json:"expected_codes,omitempty"`
 | 
			
		||||
	// Optional. The Name of the Monitor.
 | 
			
		||||
	Name         string `json:"name,omitempty"`
 | 
			
		||||
	AdminStateUp *bool  `json:"admin_state_up,omitempty"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ToMonitorUpdateMap casts a UpdateOpts struct to a map.
 | 
			
		||||
func (opts UpdateOpts) ToMonitorUpdateMap() (map[string]interface{}, error) {
 | 
			
		||||
	l := make(map[string]interface{})
 | 
			
		||||
 | 
			
		||||
	if opts.URLPath != "" {
 | 
			
		||||
		l["url_path"] = opts.URLPath
 | 
			
		||||
	}
 | 
			
		||||
	if opts.ExpectedCodes != "" {
 | 
			
		||||
		l["expected_codes"] = opts.ExpectedCodes
 | 
			
		||||
	}
 | 
			
		||||
	if opts.Delay != 0 {
 | 
			
		||||
		l["delay"] = opts.Delay
 | 
			
		||||
	}
 | 
			
		||||
	if opts.Timeout != 0 {
 | 
			
		||||
		l["timeout"] = opts.Timeout
 | 
			
		||||
	}
 | 
			
		||||
	if opts.MaxRetries != 0 {
 | 
			
		||||
		l["max_retries"] = opts.MaxRetries
 | 
			
		||||
	}
 | 
			
		||||
	if opts.AdminStateUp != nil {
 | 
			
		||||
		l["admin_state_up"] = &opts.AdminStateUp
 | 
			
		||||
	}
 | 
			
		||||
	if opts.Name != "" {
 | 
			
		||||
		l["name"] = opts.Name
 | 
			
		||||
	}
 | 
			
		||||
	if opts.HTTPMethod != "" {
 | 
			
		||||
		l["http_method"] = opts.HTTPMethod
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return map[string]interface{}{"healthmonitor": l}, nil
 | 
			
		||||
	return gophercloud.BuildRequestBody(opts, "healthmonitor")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Update is an operation which modifies the attributes of the specified Monitor.
 | 
			
		||||
func Update(c *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) UpdateResult {
 | 
			
		||||
	var res UpdateResult
 | 
			
		||||
 | 
			
		||||
	reqBody, err := opts.ToMonitorUpdateMap()
 | 
			
		||||
func Update(c *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) (r UpdateResult) {
 | 
			
		||||
	b, err := opts.ToMonitorUpdateMap()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		res.Err = err
 | 
			
		||||
		return res
 | 
			
		||||
		r.Err = err
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Send request to API
 | 
			
		||||
	_, res.Err = c.Put(resourceURL(c, id), reqBody, &res.Body, &gophercloud.RequestOpts{
 | 
			
		||||
	_, r.Err = c.Put(resourceURL(c, id), b, &r.Body, &gophercloud.RequestOpts{
 | 
			
		||||
		OkCodes: []int{200, 202},
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	return res
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Delete will permanently delete a particular Monitor based on its unique ID.
 | 
			
		||||
func Delete(c *gophercloud.ServiceClient, id string) DeleteResult {
 | 
			
		||||
	var res DeleteResult
 | 
			
		||||
	_, res.Err = c.Delete(resourceURL(c, id), nil)
 | 
			
		||||
	return res
 | 
			
		||||
func Delete(c *gophercloud.ServiceClient, id string) (r DeleteResult) {
 | 
			
		||||
	_, r.Err = c.Delete(resourceURL(c, id), nil)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
@@ -1,13 +1,12 @@
 | 
			
		||||
package monitors
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/mitchellh/mapstructure"
 | 
			
		||||
	"github.com/rackspace/gophercloud"
 | 
			
		||||
	"github.com/rackspace/gophercloud/pagination"
 | 
			
		||||
	"github.com/gophercloud/gophercloud"
 | 
			
		||||
	"github.com/gophercloud/gophercloud/pagination"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type PoolID struct {
 | 
			
		||||
	ID string `mapstructure:"id" json:"id"`
 | 
			
		||||
	ID string `json:"id"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Monitor represents a load balancer health monitor. A health monitor is used
 | 
			
		||||
@@ -27,52 +26,49 @@ type PoolID struct {
 | 
			
		||||
// must declare the member to be healthy for it to stay ACTIVE.
 | 
			
		||||
type Monitor struct {
 | 
			
		||||
	// The unique ID for the Monitor.
 | 
			
		||||
	ID string
 | 
			
		||||
	ID string `json:"id"`
 | 
			
		||||
 | 
			
		||||
	// The Name of the Monitor.
 | 
			
		||||
	Name string
 | 
			
		||||
	Name string `json:"name"`
 | 
			
		||||
 | 
			
		||||
	// Only an administrative user can specify a tenant ID
 | 
			
		||||
	// other than its own.
 | 
			
		||||
	TenantID string `json:"tenant_id" mapstructure:"tenant_id"`
 | 
			
		||||
	TenantID string `json:"tenant_id"`
 | 
			
		||||
 | 
			
		||||
	// The type of probe sent by the load balancer to verify the member state,
 | 
			
		||||
	// which is PING, TCP, HTTP, or HTTPS.
 | 
			
		||||
	Type string
 | 
			
		||||
	Type string `json:"type"`
 | 
			
		||||
 | 
			
		||||
	// The time, in seconds, between sending probes to members.
 | 
			
		||||
	Delay int
 | 
			
		||||
	Delay int `json:"delay"`
 | 
			
		||||
 | 
			
		||||
	// The maximum number of seconds for a monitor to wait for a connection to be
 | 
			
		||||
	// established before it times out. This value must be less than the delay value.
 | 
			
		||||
	Timeout int
 | 
			
		||||
	Timeout int `json:"timeout"`
 | 
			
		||||
 | 
			
		||||
	// Number of allowed connection failures before changing the status of the
 | 
			
		||||
	// member to INACTIVE. A valid value is from 1 to 10.
 | 
			
		||||
	MaxRetries int `json:"max_retries" mapstructure:"max_retries"`
 | 
			
		||||
	MaxRetries int `json:"max_retries"`
 | 
			
		||||
 | 
			
		||||
	// The HTTP method that the monitor uses for requests.
 | 
			
		||||
	HTTPMethod string `json:"http_method" mapstructure:"http_method"`
 | 
			
		||||
	HTTPMethod string `json:"http_method"`
 | 
			
		||||
 | 
			
		||||
	// The HTTP path of the request sent by the monitor to test the health of a
 | 
			
		||||
	// member. Must be a string beginning with a forward slash (/).
 | 
			
		||||
	URLPath string `json:"url_path" mapstructure:"url_path"`
 | 
			
		||||
	URLPath string `json:"url_path" `
 | 
			
		||||
 | 
			
		||||
	// Expected HTTP codes for a passing HTTP(S) monitor.
 | 
			
		||||
	ExpectedCodes string `json:"expected_codes" mapstructure:"expected_codes"`
 | 
			
		||||
	ExpectedCodes string `json:"expected_codes"`
 | 
			
		||||
 | 
			
		||||
	// The administrative state of the health monitor, which is up (true) or down (false).
 | 
			
		||||
	AdminStateUp bool `json:"admin_state_up" mapstructure:"admin_state_up"`
 | 
			
		||||
	AdminStateUp bool `json:"admin_state_up"`
 | 
			
		||||
 | 
			
		||||
	// The status of the health monitor. Indicates whether the health monitor is
 | 
			
		||||
	// operational.
 | 
			
		||||
	Status string
 | 
			
		||||
	Status string `json:"status"`
 | 
			
		||||
 | 
			
		||||
	// List of pools that are associated with the health monitor.
 | 
			
		||||
	Pools []PoolID `mapstructure:"pools" json:"pools"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Pool struct {
 | 
			
		||||
	Pools []PoolID `json:"pools"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// MonitorPage is the page returned by a pager when traversing over a
 | 
			
		||||
@@ -84,40 +80,34 @@ type MonitorPage struct {
 | 
			
		||||
// NextPageURL is invoked when a paginated collection of monitors has reached
 | 
			
		||||
// the end of a page and the pager seeks to traverse over a new one. In order
 | 
			
		||||
// to do this, it needs to construct the next page's URL.
 | 
			
		||||
func (p MonitorPage) NextPageURL() (string, error) {
 | 
			
		||||
	type resp struct {
 | 
			
		||||
		Links []gophercloud.Link `mapstructure:"healthmonitors_links"`
 | 
			
		||||
func (r MonitorPage) NextPageURL() (string, error) {
 | 
			
		||||
	var s struct {
 | 
			
		||||
		Links []gophercloud.Link `json:"healthmonitors_links"`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var r resp
 | 
			
		||||
	err := mapstructure.Decode(p.Body, &r)
 | 
			
		||||
	err := r.ExtractInto(&s)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return gophercloud.ExtractNextURL(r.Links)
 | 
			
		||||
	return gophercloud.ExtractNextURL(s.Links)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IsEmpty checks whether a PoolPage struct is empty.
 | 
			
		||||
func (p MonitorPage) IsEmpty() (bool, error) {
 | 
			
		||||
	is, err := ExtractMonitors(p)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return true, nil
 | 
			
		||||
	}
 | 
			
		||||
	return len(is) == 0, nil
 | 
			
		||||
// IsEmpty checks whether a MonitorPage struct is empty.
 | 
			
		||||
func (r MonitorPage) IsEmpty() (bool, error) {
 | 
			
		||||
	is, err := ExtractMonitors(r)
 | 
			
		||||
	return len(is) == 0, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ExtractMonitors accepts a Page struct, specifically a MonitorPage struct,
 | 
			
		||||
// and extracts the elements into a slice of Monitor structs. In other words,
 | 
			
		||||
// a generic collection is mapped into a relevant slice.
 | 
			
		||||
func ExtractMonitors(page pagination.Page) ([]Monitor, error) {
 | 
			
		||||
	var resp struct {
 | 
			
		||||
		Monitors []Monitor `mapstructure:"healthmonitors" json:"healthmonitors"`
 | 
			
		||||
func ExtractMonitors(r pagination.Page) ([]Monitor, error) {
 | 
			
		||||
	var s struct {
 | 
			
		||||
		Monitors []Monitor `json:"healthmonitors"`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err := mapstructure.Decode(page.(MonitorPage).Body, &resp)
 | 
			
		||||
 | 
			
		||||
	return resp.Monitors, err
 | 
			
		||||
	err := (r.(MonitorPage)).ExtractInto(&s)
 | 
			
		||||
	return s.Monitors, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type commonResult struct {
 | 
			
		||||
@@ -126,17 +116,11 @@ type commonResult struct {
 | 
			
		||||
 | 
			
		||||
// Extract is a function that accepts a result and extracts a monitor.
 | 
			
		||||
func (r commonResult) Extract() (*Monitor, error) {
 | 
			
		||||
	if r.Err != nil {
 | 
			
		||||
		return nil, r.Err
 | 
			
		||||
	var s struct {
 | 
			
		||||
		Monitor *Monitor `json:"healthmonitor"`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var res struct {
 | 
			
		||||
		Monitor *Monitor `json:"healthmonitor" mapstructure:"healthmonitor"`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err := mapstructure.Decode(r.Body, &res)
 | 
			
		||||
 | 
			
		||||
	return res.Monitor, err
 | 
			
		||||
	err := r.ExtractInto(&s)
 | 
			
		||||
	return s.Monitor, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CreateResult represents the result of a create operation.
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
package monitors
 | 
			
		||||
 | 
			
		||||
import "github.com/rackspace/gophercloud"
 | 
			
		||||
import "github.com/gophercloud/gophercloud"
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	rootPath     = "lbaas"
 | 
			
		||||
@@ -1,58 +1,8 @@
 | 
			
		||||
package pools
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"github.com/rackspace/gophercloud"
 | 
			
		||||
	"github.com/rackspace/gophercloud/pagination"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// AdminState gives users a solid type to work with for create and update
 | 
			
		||||
// operations. It is recommended that users use the `Up` and `Down` enums.
 | 
			
		||||
type AdminState *bool
 | 
			
		||||
 | 
			
		||||
type poolOpts struct {
 | 
			
		||||
	// Only required if the caller has an admin role and wants to create a pool
 | 
			
		||||
	// for another tenant.
 | 
			
		||||
	TenantID string
 | 
			
		||||
 | 
			
		||||
	// Optional. Name of the pool.
 | 
			
		||||
	Name string
 | 
			
		||||
 | 
			
		||||
	// Optional. Human-readable description for the pool.
 | 
			
		||||
	Description string
 | 
			
		||||
 | 
			
		||||
	// Required. The protocol used by the pool members, you can use either
 | 
			
		||||
	// ProtocolTCP, ProtocolHTTP, or ProtocolHTTPS.
 | 
			
		||||
	Protocol Protocol
 | 
			
		||||
 | 
			
		||||
	// The Loadbalancer on which the members of the pool will be associated with.
 | 
			
		||||
	// Note:  one of LoadbalancerID or ListenerID must be provided.
 | 
			
		||||
	LoadbalancerID string
 | 
			
		||||
 | 
			
		||||
	// The Listener on which the members of the pool will be associated with.
 | 
			
		||||
	// Note:  one of LoadbalancerID or ListenerID must be provided.
 | 
			
		||||
	ListenerID string
 | 
			
		||||
 | 
			
		||||
	// Required. The algorithm used to distribute load between the members of the pool. The
 | 
			
		||||
	// current specification supports LBMethodRoundRobin, LBMethodLeastConnections
 | 
			
		||||
	// and LBMethodSourceIp as valid values for this attribute.
 | 
			
		||||
	LBMethod LBMethod
 | 
			
		||||
 | 
			
		||||
	// Optional. Omit this field to prevent session persistence.
 | 
			
		||||
	Persistence *SessionPersistence
 | 
			
		||||
 | 
			
		||||
	// Optional. The administrative state of the Pool. A valid value is true (UP)
 | 
			
		||||
	// or false (DOWN).
 | 
			
		||||
	AdminStateUp *bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Convenience vars for AdminStateUp values.
 | 
			
		||||
var (
 | 
			
		||||
	iTrue  = true
 | 
			
		||||
	iFalse = false
 | 
			
		||||
 | 
			
		||||
	Up   AdminState = &iTrue
 | 
			
		||||
	Down AdminState = &iFalse
 | 
			
		||||
	"github.com/gophercloud/gophercloud"
 | 
			
		||||
	"github.com/gophercloud/gophercloud/pagination"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// ListOptsBuilder allows extensions to add additional parameters to the
 | 
			
		||||
@@ -84,10 +34,7 @@ type ListOpts struct {
 | 
			
		||||
// ToPoolListQuery formats a ListOpts into a query string.
 | 
			
		||||
func (opts ListOpts) ToPoolListQuery() (string, error) {
 | 
			
		||||
	q, err := gophercloud.BuildQueryString(opts)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
	return q.String(), nil
 | 
			
		||||
	return q.String(), err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// List returns a Pager which allows you to iterate over a collection of
 | 
			
		||||
@@ -105,7 +52,6 @@ func List(c *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager {
 | 
			
		||||
		}
 | 
			
		||||
		url += query
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return pagination.NewPager(c, url, func(r pagination.PageResult) pagination.Page {
 | 
			
		||||
		return PoolPage{pagination.LinkedPageBase{PageResult: r}}
 | 
			
		||||
	})
 | 
			
		||||
@@ -125,12 +71,6 @@ const (
 | 
			
		||||
	ProtocolHTTPS Protocol = "HTTPS"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	errLoadbalancerOrListenerRequired = fmt.Errorf("A ListenerID or LoadbalancerID is required")
 | 
			
		||||
	errValidLBMethodRequired          = fmt.Errorf("A valid LBMethod is required. Supported values are ROUND_ROBIN, LEAST_CONNECTIONS, SOURCE_IP")
 | 
			
		||||
	errValidProtocolRequired          = fmt.Errorf("A valid Protocol is required. Supported values are TCP, HTTP, HTTPS")
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// CreateOptsBuilder is the interface options structs have to satisfy in order
 | 
			
		||||
// to be used in the main Create operation in this package. Since many
 | 
			
		||||
// extensions decorate or modify the common logic, it is useful for them to
 | 
			
		||||
@@ -141,71 +81,55 @@ type CreateOptsBuilder interface {
 | 
			
		||||
 | 
			
		||||
// CreateOpts is the common options struct used in this package's Create
 | 
			
		||||
// operation.
 | 
			
		||||
type CreateOpts poolOpts
 | 
			
		||||
type CreateOpts struct {
 | 
			
		||||
	// The algorithm used to distribute load between the members of the pool. The
 | 
			
		||||
	// current specification supports LBMethodRoundRobin, LBMethodLeastConnections
 | 
			
		||||
	// and LBMethodSourceIp as valid values for this attribute.
 | 
			
		||||
	LBMethod LBMethod `json:"lb_algorithm" required:"true"`
 | 
			
		||||
	// The protocol used by the pool members, you can use either
 | 
			
		||||
	// ProtocolTCP, ProtocolHTTP, or ProtocolHTTPS.
 | 
			
		||||
	Protocol Protocol `json:"protocol" required:"true"`
 | 
			
		||||
	// 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"`
 | 
			
		||||
	// 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"`
 | 
			
		||||
	// Only required if the caller has an admin role and wants to create a pool
 | 
			
		||||
	// for another tenant.
 | 
			
		||||
	TenantID string `json:"tenant_id,omitempty"`
 | 
			
		||||
	// Name of the pool.
 | 
			
		||||
	Name string `json:"name,omitempty"`
 | 
			
		||||
	// Human-readable description for the pool.
 | 
			
		||||
	Description string `json:"description,omitempty"`
 | 
			
		||||
	// Omit this field to prevent session persistence.
 | 
			
		||||
	Persistence *SessionPersistence `json:"session_persistence,omitempty"`
 | 
			
		||||
	// The administrative state of the Pool. A valid value is true (UP)
 | 
			
		||||
	// or false (DOWN).
 | 
			
		||||
	AdminStateUp *bool `json:"admin_state_up,omitempty"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ToPoolCreateMap casts a CreateOpts struct to a map.
 | 
			
		||||
func (opts CreateOpts) ToPoolCreateMap() (map[string]interface{}, error) {
 | 
			
		||||
	l := make(map[string]interface{})
 | 
			
		||||
	allowedLBMethod := map[LBMethod]bool{LBMethodRoundRobin: true, LBMethodLeastConnections: true, LBMethodSourceIp: true}
 | 
			
		||||
	allowedProtocol := map[Protocol]bool{ProtocolTCP: true, ProtocolHTTP: true, ProtocolHTTPS: true}
 | 
			
		||||
 | 
			
		||||
	if allowedLBMethod[opts.LBMethod] {
 | 
			
		||||
		l["lb_algorithm"] = opts.LBMethod
 | 
			
		||||
	} else {
 | 
			
		||||
		return nil, errValidLBMethodRequired
 | 
			
		||||
	}
 | 
			
		||||
	if allowedProtocol[opts.Protocol] {
 | 
			
		||||
		l["protocol"] = opts.Protocol
 | 
			
		||||
	} else {
 | 
			
		||||
		return nil, errValidProtocolRequired
 | 
			
		||||
	}
 | 
			
		||||
	if opts.LoadbalancerID == "" && opts.ListenerID == "" {
 | 
			
		||||
		return nil, errLoadbalancerOrListenerRequired
 | 
			
		||||
	} else {
 | 
			
		||||
		if opts.LoadbalancerID != "" {
 | 
			
		||||
			l["loadbalancer_id"] = opts.LoadbalancerID
 | 
			
		||||
		}
 | 
			
		||||
		if opts.ListenerID != "" {
 | 
			
		||||
			l["listener_id"] = opts.ListenerID
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if opts.AdminStateUp != nil {
 | 
			
		||||
		l["admin_state_up"] = &opts.AdminStateUp
 | 
			
		||||
	}
 | 
			
		||||
	if opts.Name != "" {
 | 
			
		||||
		l["name"] = opts.Name
 | 
			
		||||
	}
 | 
			
		||||
	if opts.TenantID != "" {
 | 
			
		||||
		l["tenant_id"] = opts.TenantID
 | 
			
		||||
	}
 | 
			
		||||
	if opts.Persistence != nil {
 | 
			
		||||
		l["session_persistence"] = &opts.Persistence
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return map[string]interface{}{"pool": l}, nil
 | 
			
		||||
	return gophercloud.BuildRequestBody(opts, "pool")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Create accepts a CreateOpts struct and uses the values to create a new
 | 
			
		||||
// load balancer pool.
 | 
			
		||||
func Create(c *gophercloud.ServiceClient, opts CreateOpts) CreateResult {
 | 
			
		||||
	var res CreateResult
 | 
			
		||||
 | 
			
		||||
	reqBody, err := opts.ToPoolCreateMap()
 | 
			
		||||
func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) (r CreateResult) {
 | 
			
		||||
	b, err := opts.ToPoolCreateMap()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		res.Err = err
 | 
			
		||||
		return res
 | 
			
		||||
		r.Err = err
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Send request to API
 | 
			
		||||
	_, res.Err = c.Post(rootURL(c), reqBody, &res.Body, nil)
 | 
			
		||||
	return res
 | 
			
		||||
	_, r.Err = c.Post(rootURL(c), b, &r.Body, nil)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Get retrieves a particular pool based on its unique ID.
 | 
			
		||||
func Get(c *gophercloud.ServiceClient, id string) GetResult {
 | 
			
		||||
	var res GetResult
 | 
			
		||||
	_, res.Err = c.Get(resourceURL(c, id), &res.Body, nil)
 | 
			
		||||
	return res
 | 
			
		||||
func Get(c *gophercloud.ServiceClient, id string) (r GetResult) {
 | 
			
		||||
	_, r.Err = c.Get(resourceURL(c, id), &r.Body, nil)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UpdateOptsBuilder is the interface options structs have to satisfy in order
 | 
			
		||||
@@ -218,99 +142,56 @@ type UpdateOptsBuilder interface {
 | 
			
		||||
 | 
			
		||||
// UpdateOpts is the common options struct used in this package's Update
 | 
			
		||||
// operation.
 | 
			
		||||
type UpdateOpts poolOpts
 | 
			
		||||
type UpdateOpts struct {
 | 
			
		||||
	// Name of the pool.
 | 
			
		||||
	Name string `json:"name,omitempty"`
 | 
			
		||||
	// Human-readable description for the pool.
 | 
			
		||||
	Description string `json:"description,omitempty"`
 | 
			
		||||
	// The algorithm used to distribute load between the members of the pool. The
 | 
			
		||||
	// current specification supports LBMethodRoundRobin, LBMethodLeastConnections
 | 
			
		||||
	// and LBMethodSourceIp as valid values for this attribute.
 | 
			
		||||
	LBMethod LBMethod `json:"lb_algorithm,omitempty"`
 | 
			
		||||
	// The administrative state of the Pool. A valid value is true (UP)
 | 
			
		||||
	// or false (DOWN).
 | 
			
		||||
	AdminStateUp *bool `json:"admin_state_up,omitempty"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ToPoolUpdateMap casts a UpdateOpts struct to a map.
 | 
			
		||||
func (opts UpdateOpts) ToPoolUpdateMap() (map[string]interface{}, error) {
 | 
			
		||||
	l := make(map[string]interface{})
 | 
			
		||||
	allowedLBMethod := map[LBMethod]bool{LBMethodRoundRobin: true, LBMethodLeastConnections: true, LBMethodSourceIp: true}
 | 
			
		||||
 | 
			
		||||
	if opts.LBMethod != "" {
 | 
			
		||||
		if allowedLBMethod[opts.LBMethod] {
 | 
			
		||||
			l["lb_algorithm"] = opts.LBMethod
 | 
			
		||||
		} else {
 | 
			
		||||
			return nil, errValidLBMethodRequired
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if opts.Name != "" {
 | 
			
		||||
		l["name"] = opts.Name
 | 
			
		||||
	}
 | 
			
		||||
	if opts.Description != "" {
 | 
			
		||||
		l["description"] = opts.Description
 | 
			
		||||
	}
 | 
			
		||||
	if opts.AdminStateUp != nil {
 | 
			
		||||
		l["admin_state_up"] = &opts.AdminStateUp
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return map[string]interface{}{"pool": l}, nil
 | 
			
		||||
	return gophercloud.BuildRequestBody(opts, "pool")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Update allows pools to be updated.
 | 
			
		||||
func Update(c *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) UpdateResult {
 | 
			
		||||
	var res UpdateResult
 | 
			
		||||
 | 
			
		||||
	reqBody, err := opts.ToPoolUpdateMap()
 | 
			
		||||
func Update(c *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) (r UpdateResult) {
 | 
			
		||||
	b, err := opts.ToPoolUpdateMap()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		res.Err = err
 | 
			
		||||
		return res
 | 
			
		||||
		r.Err = err
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Send request to API
 | 
			
		||||
	_, res.Err = c.Put(resourceURL(c, id), reqBody, &res.Body, &gophercloud.RequestOpts{
 | 
			
		||||
	_, r.Err = c.Put(resourceURL(c, id), b, &r.Body, &gophercloud.RequestOpts{
 | 
			
		||||
		OkCodes: []int{200},
 | 
			
		||||
	})
 | 
			
		||||
	return res
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Delete will permanently delete a particular pool based on its unique ID.
 | 
			
		||||
func Delete(c *gophercloud.ServiceClient, id string) DeleteResult {
 | 
			
		||||
	var res DeleteResult
 | 
			
		||||
	_, res.Err = c.Delete(resourceURL(c, id), nil)
 | 
			
		||||
	return res
 | 
			
		||||
func Delete(c *gophercloud.ServiceClient, id string) (r DeleteResult) {
 | 
			
		||||
	_, r.Err = c.Delete(resourceURL(c, id), nil)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CreateOpts contains all the values needed to create a new Member for a Pool.
 | 
			
		||||
type memberOpts struct {
 | 
			
		||||
	// Optional. Name of the Member.
 | 
			
		||||
	Name string
 | 
			
		||||
 | 
			
		||||
	// Only required if the caller has an admin role and wants to create a Member
 | 
			
		||||
	// for another tenant.
 | 
			
		||||
	TenantID string
 | 
			
		||||
 | 
			
		||||
	// Required. The IP address of the member to receive traffic from the load balancer.
 | 
			
		||||
	Address string
 | 
			
		||||
 | 
			
		||||
	// Required. The port on which to listen for client traffic.
 | 
			
		||||
	ProtocolPort int
 | 
			
		||||
 | 
			
		||||
	// Optional. A positive integer value that indicates the relative portion of
 | 
			
		||||
	// traffic that this member should receive from the pool. For example, a
 | 
			
		||||
	// member with a weight of 10 receives five times as much traffic as a member
 | 
			
		||||
	// with a weight of 2.
 | 
			
		||||
	Weight int
 | 
			
		||||
 | 
			
		||||
	// Optional.  If you omit this parameter, LBaaS uses the vip_subnet_id
 | 
			
		||||
	// parameter value for the subnet UUID.
 | 
			
		||||
	SubnetID string
 | 
			
		||||
 | 
			
		||||
	// Optional. The administrative state of the Pool. A valid value is true (UP)
 | 
			
		||||
	// or false (DOWN).
 | 
			
		||||
	AdminStateUp *bool
 | 
			
		||||
// ListMemberOptsBuilder allows extensions to add additional parameters to the
 | 
			
		||||
// ListMembers request.
 | 
			
		||||
type ListMembersOptsBuilder interface {
 | 
			
		||||
	ToMembersListQuery() (string, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// MemberListOptsBuilder allows extensions to add additional parameters to the
 | 
			
		||||
// Member List request.
 | 
			
		||||
type MemberListOptsBuilder interface {
 | 
			
		||||
	ToMemberListQuery() (string, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// MemberListOpts allows the filtering and sorting of paginated collections through
 | 
			
		||||
// ListMembersOpts allows the filtering and sorting of paginated collections through
 | 
			
		||||
// the API. Filtering is achieved by passing in struct field values that map to
 | 
			
		||||
// the Member attributes you want to see returned. SortKey allows you to
 | 
			
		||||
// sort by a particular Member attribute. SortDir sets the direction, and is
 | 
			
		||||
// either `asc' or `desc'. Marker and Limit are used for pagination.
 | 
			
		||||
type MemberListOpts struct {
 | 
			
		||||
type ListMembersOpts struct {
 | 
			
		||||
	Name         string `q:"name"`
 | 
			
		||||
	Weight       int    `q:"weight"`
 | 
			
		||||
	AdminStateUp *bool  `q:"admin_state_up"`
 | 
			
		||||
@@ -325,161 +206,129 @@ type MemberListOpts struct {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ToMemberListQuery formats a ListOpts into a query string.
 | 
			
		||||
func (opts MemberListOpts) ToMemberListQuery() (string, error) {
 | 
			
		||||
func (opts ListMembersOpts) ToMembersListQuery() (string, error) {
 | 
			
		||||
	q, err := gophercloud.BuildQueryString(opts)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
	return q.String(), nil
 | 
			
		||||
	return q.String(), err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// List returns a Pager which allows you to iterate over a collection of
 | 
			
		||||
// members. It accepts a ListOpts struct, which allows you to filter and sort
 | 
			
		||||
// ListMembers returns a Pager which allows you to iterate over a collection of
 | 
			
		||||
// members. It accepts a ListMembersOptsBuilder, which allows you to filter and sort
 | 
			
		||||
// the returned collection for greater efficiency.
 | 
			
		||||
//
 | 
			
		||||
// Default policy settings return only those members that are owned by the
 | 
			
		||||
// tenant who submits the request, unless an admin user submits the request.
 | 
			
		||||
func ListAssociateMembers(c *gophercloud.ServiceClient, poolID string, opts MemberListOptsBuilder) pagination.Pager {
 | 
			
		||||
func ListMembers(c *gophercloud.ServiceClient, poolID string, opts ListMembersOptsBuilder) pagination.Pager {
 | 
			
		||||
	url := memberRootURL(c, poolID)
 | 
			
		||||
	if opts != nil {
 | 
			
		||||
		query, err := opts.ToMemberListQuery()
 | 
			
		||||
		query, err := opts.ToMembersListQuery()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return pagination.Pager{Err: err}
 | 
			
		||||
		}
 | 
			
		||||
		url += query
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return pagination.NewPager(c, url, func(r pagination.PageResult) pagination.Page {
 | 
			
		||||
		return MemberPage{pagination.LinkedPageBase{PageResult: r}}
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	errPoolIdRequired       = fmt.Errorf("PoolID is required")
 | 
			
		||||
	errAddressRequired      = fmt.Errorf("Address is required")
 | 
			
		||||
	errProtocolPortRequired = fmt.Errorf("ProtocolPort is required")
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// MemberCreateOptsBuilder is the interface options structs have to satisfy in order
 | 
			
		||||
// to be used in the main Create operation in this package. Since many
 | 
			
		||||
// CreateMemberOptsBuilder is the interface options structs have to satisfy in order
 | 
			
		||||
// to be used in the CreateMember operation in this package. Since many
 | 
			
		||||
// extensions decorate or modify the common logic, it is useful for them to
 | 
			
		||||
// satisfy a basic interface in order for them to be used.
 | 
			
		||||
type MemberCreateOptsBuilder interface {
 | 
			
		||||
type CreateMemberOptsBuilder interface {
 | 
			
		||||
	ToMemberCreateMap() (map[string]interface{}, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// MemberCreateOpts is the common options struct used in this package's Create
 | 
			
		||||
// CreateMemberOpts is the common options struct used in this package's CreateMember
 | 
			
		||||
// operation.
 | 
			
		||||
type MemberCreateOpts memberOpts
 | 
			
		||||
type CreateMemberOpts struct {
 | 
			
		||||
	// Required. The IP address of the member to receive traffic from the load balancer.
 | 
			
		||||
	Address string `json:"address" required:"true"`
 | 
			
		||||
	// Required. The port on which to listen for client traffic.
 | 
			
		||||
	ProtocolPort int `json:"protocol_port" required:"true"`
 | 
			
		||||
	// Optional. Name of the Member.
 | 
			
		||||
	Name string `json:"name,omitempty"`
 | 
			
		||||
	// Only required if the caller has an admin role and wants to create a Member
 | 
			
		||||
	// for another tenant.
 | 
			
		||||
	TenantID string `json:"tenant_id,omitempty"`
 | 
			
		||||
	// Optional. A positive integer value that indicates the relative portion of
 | 
			
		||||
	// traffic that this member should receive from the pool. For example, a
 | 
			
		||||
	// member with a weight of 10 receives five times as much traffic as a member
 | 
			
		||||
	// with a weight of 2.
 | 
			
		||||
	Weight int `json:"weight,omitempty"`
 | 
			
		||||
	// Optional.  If you omit this parameter, LBaaS uses the vip_subnet_id
 | 
			
		||||
	// parameter value for the subnet UUID.
 | 
			
		||||
	SubnetID string `json:"subnet_id,omitempty"`
 | 
			
		||||
	// Optional. The administrative state of the Pool. A valid value is true (UP)
 | 
			
		||||
	// or false (DOWN).
 | 
			
		||||
	AdminStateUp *bool `json:"admin_state_up,omitempty"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ToMemberCreateMap casts a CreateOpts struct to a map.
 | 
			
		||||
func (opts MemberCreateOpts) ToMemberCreateMap() (map[string]interface{}, error) {
 | 
			
		||||
	l := make(map[string]interface{})
 | 
			
		||||
 | 
			
		||||
	if opts.Address != "" {
 | 
			
		||||
		l["address"] = opts.Address
 | 
			
		||||
	} else {
 | 
			
		||||
		return nil, errAddressRequired
 | 
			
		||||
	}
 | 
			
		||||
	if opts.ProtocolPort != 0 {
 | 
			
		||||
		l["protocol_port"] = opts.ProtocolPort
 | 
			
		||||
	} else {
 | 
			
		||||
		return nil, errProtocolPortRequired
 | 
			
		||||
	}
 | 
			
		||||
	if opts.AdminStateUp != nil {
 | 
			
		||||
		l["admin_state_up"] = &opts.AdminStateUp
 | 
			
		||||
	}
 | 
			
		||||
	if opts.Name != "" {
 | 
			
		||||
		l["name"] = opts.Name
 | 
			
		||||
	}
 | 
			
		||||
	if opts.TenantID != "" {
 | 
			
		||||
		l["tenant_id"] = opts.TenantID
 | 
			
		||||
	}
 | 
			
		||||
	if opts.SubnetID != "" {
 | 
			
		||||
		l["subnet_id"] = opts.SubnetID
 | 
			
		||||
	}
 | 
			
		||||
	if opts.Weight != 0 {
 | 
			
		||||
		l["weight"] = opts.Weight
 | 
			
		||||
func (opts CreateMemberOpts) ToMemberCreateMap() (map[string]interface{}, error) {
 | 
			
		||||
	return gophercloud.BuildRequestBody(opts, "member")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
	return map[string]interface{}{"member": l}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CreateAssociateMember will create and associate a Member with a particular Pool.
 | 
			
		||||
func CreateAssociateMember(c *gophercloud.ServiceClient, poolID string, opts MemberCreateOpts) AssociateResult {
 | 
			
		||||
	var res AssociateResult
 | 
			
		||||
 | 
			
		||||
	if poolID == "" {
 | 
			
		||||
		res.Err = errPoolIdRequired
 | 
			
		||||
		return res
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	reqBody, err := opts.ToMemberCreateMap()
 | 
			
		||||
// CreateMember will create and associate a Member with a particular Pool.
 | 
			
		||||
func CreateMember(c *gophercloud.ServiceClient, poolID string, opts CreateMemberOpts) (r CreateMemberResult) {
 | 
			
		||||
	b, err := opts.ToMemberCreateMap()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		res.Err = err
 | 
			
		||||
		return res
 | 
			
		||||
		r.Err = err
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	_, r.Err = c.Post(memberRootURL(c, poolID), b, &r.Body, nil)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
	_, res.Err = c.Post(memberRootURL(c, poolID), reqBody, &res.Body, nil)
 | 
			
		||||
	return res
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Get retrieves a particular Pool Member based on its unique ID.
 | 
			
		||||
func GetAssociateMember(c *gophercloud.ServiceClient, poolID string, memberID string) GetResult {
 | 
			
		||||
	var res GetResult
 | 
			
		||||
	_, res.Err = c.Get(memberResourceURL(c, poolID, memberID), &res.Body, nil)
 | 
			
		||||
	return res
 | 
			
		||||
// GetMember retrieves a particular Pool Member based on its unique ID.
 | 
			
		||||
func GetMember(c *gophercloud.ServiceClient, poolID string, memberID string) (r GetMemberResult) {
 | 
			
		||||
	_, r.Err = c.Get(memberResourceURL(c, poolID, memberID), &r.Body, nil)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// MemberUpdateOptsBuilder is the interface options structs have to satisfy in order
 | 
			
		||||
// to be used in the main Update operation in this package. Since many
 | 
			
		||||
// extensions decorate or modify the common logic, it is useful for them to
 | 
			
		||||
// satisfy a basic interface in order for them to be used.
 | 
			
		||||
type MemberUpdateOptsBuilder interface {
 | 
			
		||||
type UpdateMemberOptsBuilder interface {
 | 
			
		||||
	ToMemberUpdateMap() (map[string]interface{}, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UpdateOpts is the common options struct used in this package's Update
 | 
			
		||||
// UpdateMemberOpts is the common options struct used in this package's Update
 | 
			
		||||
// operation.
 | 
			
		||||
type MemberUpdateOpts memberOpts
 | 
			
		||||
type UpdateMemberOpts struct {
 | 
			
		||||
	// Optional. Name of the Member.
 | 
			
		||||
	Name string `json:"name,omitempty"`
 | 
			
		||||
	// Optional. A positive integer value that indicates the relative portion of
 | 
			
		||||
	// traffic that this member should receive from the pool. For example, a
 | 
			
		||||
	// member with a weight of 10 receives five times as much traffic as a member
 | 
			
		||||
	// with a weight of 2.
 | 
			
		||||
	Weight int `json:"weight,omitempty"`
 | 
			
		||||
	// Optional. The administrative state of the Pool. A valid value is true (UP)
 | 
			
		||||
	// or false (DOWN).
 | 
			
		||||
	AdminStateUp *bool `json:"admin_state_up,omitempty"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ToMemberUpdateMap casts a UpdateOpts struct to a map.
 | 
			
		||||
func (opts MemberUpdateOpts) ToMemberUpdateMap() (map[string]interface{}, error) {
 | 
			
		||||
	l := make(map[string]interface{})
 | 
			
		||||
 | 
			
		||||
	if opts.AdminStateUp != nil {
 | 
			
		||||
		l["admin_state_up"] = &opts.AdminStateUp
 | 
			
		||||
	}
 | 
			
		||||
	if opts.Name != "" {
 | 
			
		||||
		l["name"] = opts.Name
 | 
			
		||||
	}
 | 
			
		||||
	if opts.Weight != 0 {
 | 
			
		||||
		l["weight"] = opts.Weight
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return map[string]interface{}{"member": l}, nil
 | 
			
		||||
func (opts UpdateMemberOpts) ToMemberUpdateMap() (map[string]interface{}, error) {
 | 
			
		||||
	return gophercloud.BuildRequestBody(opts, "member")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Update allows Member to be updated.
 | 
			
		||||
func UpdateAssociateMember(c *gophercloud.ServiceClient, poolID string, memberID string, opts MemberUpdateOpts) UpdateResult {
 | 
			
		||||
	var res UpdateResult
 | 
			
		||||
 | 
			
		||||
	reqBody, err := opts.ToMemberUpdateMap()
 | 
			
		||||
func UpdateMember(c *gophercloud.ServiceClient, poolID string, memberID string, opts UpdateMemberOptsBuilder) (r UpdateMemberResult) {
 | 
			
		||||
	b, err := opts.ToMemberUpdateMap()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		res.Err = err
 | 
			
		||||
		return res
 | 
			
		||||
		r.Err = err
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Send request to API
 | 
			
		||||
	_, res.Err = c.Put(memberResourceURL(c, poolID, memberID), reqBody, &res.Body, &gophercloud.RequestOpts{
 | 
			
		||||
	_, r.Err = c.Put(memberResourceURL(c, poolID, memberID), b, &r.Body, &gophercloud.RequestOpts{
 | 
			
		||||
		OkCodes: []int{200, 201, 202},
 | 
			
		||||
	})
 | 
			
		||||
	return res
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DisassociateMember will remove and disassociate a Member from a particular Pool.
 | 
			
		||||
func DeleteMember(c *gophercloud.ServiceClient, poolID string, memberID string) DeleteResult {
 | 
			
		||||
	var res DeleteResult
 | 
			
		||||
	_, res.Err = c.Delete(memberResourceURL(c, poolID, memberID), nil)
 | 
			
		||||
	return res
 | 
			
		||||
func DeleteMember(c *gophercloud.ServiceClient, poolID string, memberID string) (r DeleteMemberResult) {
 | 
			
		||||
	_, r.Err = c.Delete(memberResourceURL(c, poolID, memberID), nil)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
@@ -1,10 +1,9 @@
 | 
			
		||||
package pools
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/mitchellh/mapstructure"
 | 
			
		||||
	"github.com/rackspace/gophercloud"
 | 
			
		||||
	"github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas_v2/monitors"
 | 
			
		||||
	"github.com/rackspace/gophercloud/pagination"
 | 
			
		||||
	"github.com/gophercloud/gophercloud"
 | 
			
		||||
	"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/monitors"
 | 
			
		||||
	"github.com/gophercloud/gophercloud/pagination"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// SessionPersistence represents the session persistence feature of the load
 | 
			
		||||
@@ -24,18 +23,18 @@ import (
 | 
			
		||||
//              same Member of the Pool.
 | 
			
		||||
type SessionPersistence struct {
 | 
			
		||||
	// The type of persistence mode
 | 
			
		||||
	Type string `mapstructure:"type" json:"type"`
 | 
			
		||||
	Type string `json:"type"`
 | 
			
		||||
 | 
			
		||||
	// Name of cookie if persistence mode is set appropriately
 | 
			
		||||
	CookieName string `mapstructure:"cookie_name" json:"cookie_name,omitempty"`
 | 
			
		||||
	CookieName string `json:"cookie_name,omitempty"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type LoadBalancerID struct {
 | 
			
		||||
	ID string `mapstructure:"id" json:"id"`
 | 
			
		||||
	ID string `json:"id"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type ListenerID struct {
 | 
			
		||||
	ID string `mapstructure:"id" json:"id"`
 | 
			
		||||
	ID string `json:"id"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Pool represents a logical set of devices, such as web servers, that you
 | 
			
		||||
@@ -46,51 +45,37 @@ type Pool struct {
 | 
			
		||||
	// The load-balancer algorithm, which is round-robin, least-connections, and
 | 
			
		||||
	// so on. This value, which must be supported, is dependent on the provider.
 | 
			
		||||
	// Round-robin must be supported.
 | 
			
		||||
	LBMethod string `json:"lb_algorithm" mapstructure:"lb_algorithm"`
 | 
			
		||||
 | 
			
		||||
	LBMethod string `json:"lb_algorithm"`
 | 
			
		||||
	// The protocol of the Pool, which is TCP, HTTP, or HTTPS.
 | 
			
		||||
	Protocol string
 | 
			
		||||
 | 
			
		||||
	Protocol string `json:"protocol"`
 | 
			
		||||
	// Description for the Pool.
 | 
			
		||||
	Description string
 | 
			
		||||
 | 
			
		||||
	Description string `json:"description"`
 | 
			
		||||
	// A list of listeners objects IDs.
 | 
			
		||||
	Listeners []ListenerID `mapstructure:"listeners" json:"listeners"` //[]map[string]interface{}
 | 
			
		||||
 | 
			
		||||
	Listeners []ListenerID `json:"listeners"` //[]map[string]interface{}
 | 
			
		||||
	// A list of member objects IDs.
 | 
			
		||||
	Members []Member `mapstructure:"members" json:"members"`
 | 
			
		||||
 | 
			
		||||
	Members []Member `json:"members"`
 | 
			
		||||
	// The ID of associated health monitor.
 | 
			
		||||
	MonitorID string `json:"healthmonitor_id" mapstructure:"healthmonitor_id"`
 | 
			
		||||
 | 
			
		||||
	MonitorID string `json:"healthmonitor_id"`
 | 
			
		||||
	// The network on which the members of the Pool will be located. Only members
 | 
			
		||||
	// that are on this network can be added to the Pool.
 | 
			
		||||
	SubnetID string `json:"subnet_id" mapstructure:"subnet_id"`
 | 
			
		||||
 | 
			
		||||
	SubnetID string `json:"subnet_id"`
 | 
			
		||||
	// Owner of the Pool. Only an administrative user can specify a tenant ID
 | 
			
		||||
	// other than its own.
 | 
			
		||||
	TenantID string `json:"tenant_id" mapstructure:"tenant_id"`
 | 
			
		||||
 | 
			
		||||
	TenantID string `json:"tenant_id"`
 | 
			
		||||
	// The administrative state of the Pool, which is up (true) or down (false).
 | 
			
		||||
	AdminStateUp bool `json:"admin_state_up" mapstructure:"admin_state_up"`
 | 
			
		||||
 | 
			
		||||
	AdminStateUp bool `json:"admin_state_up"`
 | 
			
		||||
	// Pool name. Does not have to be unique.
 | 
			
		||||
	Name string
 | 
			
		||||
 | 
			
		||||
	Name string `json:"name"`
 | 
			
		||||
	// The unique ID for the Pool.
 | 
			
		||||
	ID string
 | 
			
		||||
 | 
			
		||||
	ID string `json:"id"`
 | 
			
		||||
	// A list of load balancer objects IDs.
 | 
			
		||||
	Loadbalancers []LoadBalancerID `mapstructure:"loadbalancers" json:"loadbalancers"`
 | 
			
		||||
 | 
			
		||||
	Loadbalancers []LoadBalancerID `json:"loadbalancers"`
 | 
			
		||||
	// Indicates whether connections in the same session will be processed by the
 | 
			
		||||
	// same Pool member or not.
 | 
			
		||||
	Persistence SessionPersistence `mapstructure:"session_persistence" json:"session_persistence"`
 | 
			
		||||
 | 
			
		||||
	Persistence SessionPersistence `json:"session_persistence"`
 | 
			
		||||
	// The provider
 | 
			
		||||
	Provider string
 | 
			
		||||
 | 
			
		||||
	Monitor monitors.Monitor `mapstructure:"healthmonitor" json:"healthmonitor"`
 | 
			
		||||
	Provider string           `json:"provider"`
 | 
			
		||||
	Monitor  monitors.Monitor `json:"healthmonitor"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// PoolPage is the page returned by a pager when traversing over a
 | 
			
		||||
@@ -102,40 +87,32 @@ type PoolPage struct {
 | 
			
		||||
// NextPageURL is invoked when a paginated collection of pools has reached
 | 
			
		||||
// the end of a page and the pager seeks to traverse over a new one. In order
 | 
			
		||||
// to do this, it needs to construct the next page's URL.
 | 
			
		||||
func (p PoolPage) NextPageURL() (string, error) {
 | 
			
		||||
	type resp struct {
 | 
			
		||||
		Links []gophercloud.Link `mapstructure:"pools_links"`
 | 
			
		||||
func (r PoolPage) NextPageURL() (string, error) {
 | 
			
		||||
	var s struct {
 | 
			
		||||
		Links []gophercloud.Link `json:"pools_links"`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var r resp
 | 
			
		||||
	err := mapstructure.Decode(p.Body, &r)
 | 
			
		||||
	err := r.ExtractInto(&s)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return gophercloud.ExtractNextURL(r.Links)
 | 
			
		||||
	return gophercloud.ExtractNextURL(s.Links)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IsEmpty checks whether a PoolPage struct is empty.
 | 
			
		||||
func (p PoolPage) IsEmpty() (bool, error) {
 | 
			
		||||
	is, err := ExtractPools(p)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return true, nil
 | 
			
		||||
	}
 | 
			
		||||
	return len(is) == 0, nil
 | 
			
		||||
func (r PoolPage) IsEmpty() (bool, error) {
 | 
			
		||||
	is, err := ExtractPools(r)
 | 
			
		||||
	return len(is) == 0, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ExtractPools accepts a Page struct, specifically a RouterPage struct,
 | 
			
		||||
// ExtractPools accepts a Page struct, specifically a PoolPage struct,
 | 
			
		||||
// and extracts the elements into a slice of Router structs. In other words,
 | 
			
		||||
// a generic collection is mapped into a relevant slice.
 | 
			
		||||
func ExtractPools(page pagination.Page) ([]Pool, error) {
 | 
			
		||||
	var resp struct {
 | 
			
		||||
		Pools []Pool `mapstructure:"pools" json:"pools"`
 | 
			
		||||
func ExtractPools(r pagination.Page) ([]Pool, error) {
 | 
			
		||||
	var s struct {
 | 
			
		||||
		Pools []Pool `json:"pools"`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err := mapstructure.Decode(page.(PoolPage).Body, &resp)
 | 
			
		||||
 | 
			
		||||
	return resp.Pools, err
 | 
			
		||||
	err := (r.(PoolPage)).ExtractInto(&s)
 | 
			
		||||
	return s.Pools, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type commonResult struct {
 | 
			
		||||
@@ -144,48 +121,54 @@ type commonResult struct {
 | 
			
		||||
 | 
			
		||||
// Extract is a function that accepts a result and extracts a router.
 | 
			
		||||
func (r commonResult) Extract() (*Pool, error) {
 | 
			
		||||
	if r.Err != nil {
 | 
			
		||||
		return nil, r.Err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var res struct {
 | 
			
		||||
	var s struct {
 | 
			
		||||
		Pool *Pool `json:"pool"`
 | 
			
		||||
	}
 | 
			
		||||
	err := r.ExtractInto(&s)
 | 
			
		||||
	return s.Pool, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
	err := mapstructure.Decode(r.Body, &res)
 | 
			
		||||
// CreateResult represents the result of a Create operation.
 | 
			
		||||
type CreateResult struct {
 | 
			
		||||
	commonResult
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
	return res.Pool, err
 | 
			
		||||
// GetResult represents the result of a Get operation.
 | 
			
		||||
type GetResult struct {
 | 
			
		||||
	commonResult
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UpdateResult represents the result of an Update operation.
 | 
			
		||||
type UpdateResult struct {
 | 
			
		||||
	commonResult
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeleteResult represents the result of a Delete operation.
 | 
			
		||||
type DeleteResult struct {
 | 
			
		||||
	gophercloud.ErrResult
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Member represents the application running on a backend server.
 | 
			
		||||
type Member struct {
 | 
			
		||||
	// Name of the Member.
 | 
			
		||||
	Name string `json:"name" mapstructure:"name"`
 | 
			
		||||
 | 
			
		||||
	Name string `json:"name"`
 | 
			
		||||
	// Weight of Member.
 | 
			
		||||
	Weight int `json:"weight" mapstructure:"weight"`
 | 
			
		||||
 | 
			
		||||
	Weight int `json:"weight"`
 | 
			
		||||
	// The administrative state of the member, which is up (true) or down (false).
 | 
			
		||||
	AdminStateUp bool `json:"admin_state_up" mapstructure:"admin_state_up"`
 | 
			
		||||
 | 
			
		||||
	AdminStateUp bool `json:"admin_state_up"`
 | 
			
		||||
	// Owner of the Member. Only an administrative user can specify a tenant ID
 | 
			
		||||
	// other than its own.
 | 
			
		||||
	TenantID string `json:"tenant_id" mapstructure:"tenant_id"`
 | 
			
		||||
 | 
			
		||||
	TenantID string `json:"tenant_id"`
 | 
			
		||||
	// parameter value for the subnet UUID.
 | 
			
		||||
	SubnetID string `json:"subnet_id" mapstructure:"subnet_id"`
 | 
			
		||||
 | 
			
		||||
	SubnetID string `json:"subnet_id"`
 | 
			
		||||
	// The Pool to which the Member belongs.
 | 
			
		||||
	PoolID string `json:"pool_id" mapstructure:"pool_id"`
 | 
			
		||||
 | 
			
		||||
	PoolID string `json:"pool_id"`
 | 
			
		||||
	// The IP address of the Member.
 | 
			
		||||
	Address string `json:"address" mapstructure:"address"`
 | 
			
		||||
 | 
			
		||||
	Address string `json:"address"`
 | 
			
		||||
	// The port on which the application is hosted.
 | 
			
		||||
	ProtocolPort int `json:"protocol_port" mapstructure:"protocol_port"`
 | 
			
		||||
 | 
			
		||||
	ProtocolPort int `json:"protocol_port"`
 | 
			
		||||
	// The unique ID for the Member.
 | 
			
		||||
	ID string
 | 
			
		||||
	ID string `json:"id"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// MemberPage is the page returned by a pager when traversing over a
 | 
			
		||||
@@ -197,78 +180,63 @@ type MemberPage struct {
 | 
			
		||||
// NextPageURL is invoked when a paginated collection of members has reached
 | 
			
		||||
// the end of a page and the pager seeks to traverse over a new one. In order
 | 
			
		||||
// to do this, it needs to construct the next page's URL.
 | 
			
		||||
func (p MemberPage) NextPageURL() (string, error) {
 | 
			
		||||
	type resp struct {
 | 
			
		||||
		Links []gophercloud.Link `mapstructure:"members_links"`
 | 
			
		||||
func (r MemberPage) NextPageURL() (string, error) {
 | 
			
		||||
	var s struct {
 | 
			
		||||
		Links []gophercloud.Link `json:"members_links"`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var r resp
 | 
			
		||||
	err := mapstructure.Decode(p.Body, &r)
 | 
			
		||||
	err := r.ExtractInto(&s)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return gophercloud.ExtractNextURL(r.Links)
 | 
			
		||||
	return gophercloud.ExtractNextURL(s.Links)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IsEmpty checks whether a MemberPage struct is empty.
 | 
			
		||||
func (p MemberPage) IsEmpty() (bool, error) {
 | 
			
		||||
	is, err := ExtractMembers(p)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return true, nil
 | 
			
		||||
	}
 | 
			
		||||
	return len(is) == 0, nil
 | 
			
		||||
func (r MemberPage) IsEmpty() (bool, error) {
 | 
			
		||||
	is, err := ExtractMembers(r)
 | 
			
		||||
	return len(is) == 0, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ExtractMembers accepts a Page struct, specifically a RouterPage struct,
 | 
			
		||||
// and extracts the elements into a slice of Router structs. In other words,
 | 
			
		||||
// a generic collection is mapped into a relevant slice.
 | 
			
		||||
func ExtractMembers(page pagination.Page) ([]Member, error) {
 | 
			
		||||
	var resp struct {
 | 
			
		||||
		Member []Member `mapstructure:"members" json:"members"`
 | 
			
		||||
func ExtractMembers(r pagination.Page) ([]Member, error) {
 | 
			
		||||
	var s struct {
 | 
			
		||||
		Members []Member `json:"members"`
 | 
			
		||||
	}
 | 
			
		||||
	err := (r.(MemberPage)).ExtractInto(&s)
 | 
			
		||||
	return s.Members, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
	err := mapstructure.Decode(page.(MemberPage).Body, &resp)
 | 
			
		||||
 | 
			
		||||
	return resp.Member, err
 | 
			
		||||
type commonMemberResult struct {
 | 
			
		||||
	gophercloud.Result
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ExtractMember is a function that accepts a result and extracts a router.
 | 
			
		||||
func (r commonResult) ExtractMember() (*Member, error) {
 | 
			
		||||
	if r.Err != nil {
 | 
			
		||||
		return nil, r.Err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var res struct {
 | 
			
		||||
func (r commonMemberResult) Extract() (*Member, error) {
 | 
			
		||||
	var s struct {
 | 
			
		||||
		Member *Member `json:"member"`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err := mapstructure.Decode(r.Body, &res)
 | 
			
		||||
 | 
			
		||||
	return res.Member, err
 | 
			
		||||
	err := r.ExtractInto(&s)
 | 
			
		||||
	return s.Member, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CreateResult represents the result of a create operation.
 | 
			
		||||
type CreateResult struct {
 | 
			
		||||
	commonResult
 | 
			
		||||
// CreateMemberResult represents the result of a CreateMember operation.
 | 
			
		||||
type CreateMemberResult struct {
 | 
			
		||||
	commonMemberResult
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetResult represents the result of a get operation.
 | 
			
		||||
type GetResult struct {
 | 
			
		||||
	commonResult
 | 
			
		||||
// GetMemberResult represents the result of a GetMember operation.
 | 
			
		||||
type GetMemberResult struct {
 | 
			
		||||
	commonMemberResult
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UpdateResult represents the result of an update operation.
 | 
			
		||||
type UpdateResult struct {
 | 
			
		||||
	commonResult
 | 
			
		||||
// UpdateMemberResult represents the result of an UpdateMember operation.
 | 
			
		||||
type UpdateMemberResult struct {
 | 
			
		||||
	commonMemberResult
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeleteResult represents the result of a delete operation.
 | 
			
		||||
type DeleteResult struct {
 | 
			
		||||
// DeleteMemberResult represents the result of a DeleteMember operation.
 | 
			
		||||
type DeleteMemberResult struct {
 | 
			
		||||
	gophercloud.ErrResult
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// AssociateResult represents the result of an association operation.
 | 
			
		||||
type AssociateResult struct {
 | 
			
		||||
	commonResult
 | 
			
		||||
}
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
package pools
 | 
			
		||||
 | 
			
		||||
import "github.com/rackspace/gophercloud"
 | 
			
		||||
import "github.com/gophercloud/gophercloud"
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	rootPath     = "lbaas"
 | 
			
		||||
@@ -1,10 +1,8 @@
 | 
			
		||||
package groups
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
 | 
			
		||||
	"github.com/rackspace/gophercloud"
 | 
			
		||||
	"github.com/rackspace/gophercloud/pagination"
 | 
			
		||||
	"github.com/gophercloud/gophercloud"
 | 
			
		||||
	"github.com/gophercloud/gophercloud/pagination"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// ListOpts allows the filtering and sorting of paginated collections through
 | 
			
		||||
@@ -36,96 +34,75 @@ func List(c *gophercloud.ServiceClient, opts ListOpts) pagination.Pager {
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	errNameRequired = fmt.Errorf("Name is required")
 | 
			
		||||
)
 | 
			
		||||
type CreateOptsBuilder interface {
 | 
			
		||||
	ToSecGroupCreateMap() (map[string]interface{}, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CreateOpts contains all the values needed to create a new security group.
 | 
			
		||||
type CreateOpts struct {
 | 
			
		||||
	// Required. Human-readable name for the VIP. Does not have to be unique.
 | 
			
		||||
	Name string
 | 
			
		||||
 | 
			
		||||
	Name string `json:"name" required:"true"`
 | 
			
		||||
	// Required for admins. Indicates the owner of the VIP.
 | 
			
		||||
	TenantID string
 | 
			
		||||
 | 
			
		||||
	TenantID string `json:"tenant_id,omitempty"`
 | 
			
		||||
	// Optional. Describes the security group.
 | 
			
		||||
	Description string
 | 
			
		||||
	Description string `json:"description,omitempty"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (opts CreateOpts) ToSecGroupCreateMap() (map[string]interface{}, error) {
 | 
			
		||||
	return gophercloud.BuildRequestBody(opts, "security_group")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Create is an operation which provisions a new security group with default
 | 
			
		||||
// security group rules for the IPv4 and IPv6 ether types.
 | 
			
		||||
func Create(c *gophercloud.ServiceClient, opts CreateOpts) CreateResult {
 | 
			
		||||
	var res CreateResult
 | 
			
		||||
 | 
			
		||||
	// Validate required opts
 | 
			
		||||
	if opts.Name == "" {
 | 
			
		||||
		res.Err = errNameRequired
 | 
			
		||||
		return res
 | 
			
		||||
func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) (r CreateResult) {
 | 
			
		||||
	b, err := opts.ToSecGroupCreateMap()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		r.Err = err
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	type secgroup struct {
 | 
			
		||||
		Name        string `json:"name"`
 | 
			
		||||
		TenantID    string `json:"tenant_id,omitempty"`
 | 
			
		||||
		Description string `json:"description,omitempty"`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	type request struct {
 | 
			
		||||
		SecGroup secgroup `json:"security_group"`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	reqBody := request{SecGroup: secgroup{
 | 
			
		||||
		Name:        opts.Name,
 | 
			
		||||
		TenantID:    opts.TenantID,
 | 
			
		||||
		Description: opts.Description,
 | 
			
		||||
	}}
 | 
			
		||||
 | 
			
		||||
	_, res.Err = c.Post(rootURL(c), reqBody, &res.Body, nil)
 | 
			
		||||
	return res
 | 
			
		||||
	_, r.Err = c.Post(rootURL(c), b, &r.Body, nil)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Get retrieves a particular security group based on its unique ID.
 | 
			
		||||
func Get(c *gophercloud.ServiceClient, id string) GetResult {
 | 
			
		||||
	var res GetResult
 | 
			
		||||
	_, res.Err = c.Get(resourceURL(c, id), &res.Body, nil)
 | 
			
		||||
	return res
 | 
			
		||||
func Get(c *gophercloud.ServiceClient, id string) (r GetResult) {
 | 
			
		||||
	_, r.Err = c.Get(resourceURL(c, id), &r.Body, nil)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Delete will permanently delete a particular security group based on its unique ID.
 | 
			
		||||
func Delete(c *gophercloud.ServiceClient, id string) DeleteResult {
 | 
			
		||||
	var res DeleteResult
 | 
			
		||||
	_, res.Err = c.Delete(resourceURL(c, id), nil)
 | 
			
		||||
	return res
 | 
			
		||||
func Delete(c *gophercloud.ServiceClient, id string) (r DeleteResult) {
 | 
			
		||||
	_, r.Err = c.Delete(resourceURL(c, id), nil)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IDFromName is a convenience function that returns a security group's ID given its name.
 | 
			
		||||
func IDFromName(client *gophercloud.ServiceClient, name string) (string, error) {
 | 
			
		||||
	securityGroupCount := 0
 | 
			
		||||
	securityGroupID := ""
 | 
			
		||||
	if name == "" {
 | 
			
		||||
		return "", fmt.Errorf("A security group name must be provided.")
 | 
			
		||||
	}
 | 
			
		||||
	pager := List(client, ListOpts{})
 | 
			
		||||
	pager.EachPage(func(page pagination.Page) (bool, error) {
 | 
			
		||||
		securityGroupList, err := ExtractGroups(page)
 | 
			
		||||
	count := 0
 | 
			
		||||
	id := ""
 | 
			
		||||
	pages, err := List(client, ListOpts{}).AllPages()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
			return false, err
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
		for _, s := range securityGroupList {
 | 
			
		||||
	all, err := ExtractGroups(pages)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, s := range all {
 | 
			
		||||
		if s.Name == name {
 | 
			
		||||
				securityGroupCount++
 | 
			
		||||
				securityGroupID = s.ID
 | 
			
		||||
			count++
 | 
			
		||||
			id = s.ID
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
		return true, nil
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	switch securityGroupCount {
 | 
			
		||||
	switch count {
 | 
			
		||||
	case 0:
 | 
			
		||||
		return "", fmt.Errorf("Unable to find security group: %s", name)
 | 
			
		||||
		return "", gophercloud.ErrResourceNotFound{Name: name, ResourceType: "security group"}
 | 
			
		||||
	case 1:
 | 
			
		||||
		return securityGroupID, nil
 | 
			
		||||
		return id, nil
 | 
			
		||||
	default:
 | 
			
		||||
		return "", fmt.Errorf("Found %d security groups matching %s", securityGroupCount, name)
 | 
			
		||||
		return "", gophercloud.ErrMultipleResourcesFound{Name: name, Count: count, ResourceType: "security group"}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user