1// Package clients contains functions for creating OpenStack service clients
2// for use in acceptance tests. It also manages the required environment
3// variables to run the tests.
4package clients
5
6import (
7	"fmt"
8	"net/http"
9	"os"
10	"strings"
11
12	"github.com/gophercloud/gophercloud"
13	"github.com/gophercloud/gophercloud/openstack"
14	baremetalHTTPBasic "github.com/gophercloud/gophercloud/openstack/baremetal/httpbasic"
15	baremetalNoAuth "github.com/gophercloud/gophercloud/openstack/baremetal/noauth"
16	blockstorageNoAuth "github.com/gophercloud/gophercloud/openstack/blockstorage/noauth"
17)
18
19// AcceptanceTestChoices contains image and flavor selections for use by the acceptance tests.
20type AcceptanceTestChoices struct {
21	// ImageID contains the ID of a valid image.
22	ImageID string
23
24	// FlavorID contains the ID of a valid flavor.
25	FlavorID string
26
27	// FlavorIDResize contains the ID of a different flavor available on the same OpenStack installation, that is distinct
28	// from FlavorID.
29	FlavorIDResize string
30
31	// FloatingIPPool contains the name of the pool from where to obtain floating IPs.
32	FloatingIPPoolName string
33
34	// MagnumKeypair contains the ID of a valid key pair.
35	MagnumKeypair string
36
37	// MagnumImageID contains the ID of a valid magnum image.
38	MagnumImageID string
39
40	// NetworkName is the name of a network to launch the instance on.
41	NetworkName string
42
43	// NetworkID is the ID of a network to launch the instance on.
44	NetworkID string
45
46	// SubnetID is the ID of a subnet to launch the instance on.
47	SubnetID string
48
49	// ExternalNetworkID is the network ID of the external network.
50	ExternalNetworkID string
51
52	// DBDatastoreType is the datastore type for DB tests.
53	DBDatastoreType string
54
55	// DBDatastoreTypeID is the datastore type version for DB tests.
56	DBDatastoreVersion string
57}
58
59// AcceptanceTestChoicesFromEnv populates a ComputeChoices struct from environment variables.
60// If any required state is missing, an `error` will be returned that enumerates the missing properties.
61func AcceptanceTestChoicesFromEnv() (*AcceptanceTestChoices, error) {
62	imageID := os.Getenv("OS_IMAGE_ID")
63	flavorID := os.Getenv("OS_FLAVOR_ID")
64	flavorIDResize := os.Getenv("OS_FLAVOR_ID_RESIZE")
65	magnumImageID := os.Getenv("OS_MAGNUM_IMAGE_ID")
66	magnumKeypair := os.Getenv("OS_MAGNUM_KEYPAIR")
67	networkName := os.Getenv("OS_NETWORK_NAME")
68	networkID := os.Getenv("OS_NETWORK_ID")
69	subnetID := os.Getenv("OS_SUBNET_ID")
70	floatingIPPoolName := os.Getenv("OS_POOL_NAME")
71	externalNetworkID := os.Getenv("OS_EXTGW_ID")
72	dbDatastoreType := os.Getenv("OS_DB_DATASTORE_TYPE")
73	dbDatastoreVersion := os.Getenv("OS_DB_DATASTORE_VERSION")
74
75	missing := make([]string, 0, 3)
76	if imageID == "" {
77		missing = append(missing, "OS_IMAGE_ID")
78	}
79	if flavorID == "" {
80		missing = append(missing, "OS_FLAVOR_ID")
81	}
82	if flavorIDResize == "" {
83		missing = append(missing, "OS_FLAVOR_ID_RESIZE")
84	}
85	if floatingIPPoolName == "" {
86		missing = append(missing, "OS_POOL_NAME")
87	}
88	if externalNetworkID == "" {
89		missing = append(missing, "OS_EXTGW_ID")
90	}
91
92	/* // Temporarily disabled, see https://github.com/gophercloud/gophercloud/issues/1345
93	if networkID == "" {
94		missing = append(missing, "OS_NETWORK_ID")
95	}
96	if subnetID == "" {
97		missing = append(missing, "OS_SUBNET_ID")
98	}
99	*/
100
101	if networkName == "" {
102		networkName = "private"
103	}
104	notDistinct := ""
105	if flavorID == flavorIDResize {
106		notDistinct = "OS_FLAVOR_ID and OS_FLAVOR_ID_RESIZE must be distinct."
107	}
108
109	if len(missing) > 0 || notDistinct != "" {
110		text := "You're missing some important setup:\n"
111		if len(missing) > 0 {
112			text += " * These environment variables must be provided: " + strings.Join(missing, ", ") + "\n"
113		}
114		if notDistinct != "" {
115			text += " * " + notDistinct + "\n"
116		}
117
118		return nil, fmt.Errorf(text)
119	}
120
121	return &AcceptanceTestChoices{
122		ImageID:            imageID,
123		FlavorID:           flavorID,
124		FlavorIDResize:     flavorIDResize,
125		FloatingIPPoolName: floatingIPPoolName,
126		MagnumImageID:      magnumImageID,
127		MagnumKeypair:      magnumKeypair,
128		NetworkName:        networkName,
129		NetworkID:          networkID,
130		SubnetID:           subnetID,
131		ExternalNetworkID:  externalNetworkID,
132		DBDatastoreType:    dbDatastoreType,
133		DBDatastoreVersion: dbDatastoreVersion,
134	}, nil
135}
136
137// NewBlockStorageV1Client returns a *ServiceClient for making calls
138// to the OpenStack Block Storage v1 API. An error will be returned
139// if authentication or client creation was not possible.
140func NewBlockStorageV1Client() (*gophercloud.ServiceClient, error) {
141	ao, err := openstack.AuthOptionsFromEnv()
142	if err != nil {
143		return nil, err
144	}
145
146	client, err := openstack.AuthenticatedClient(ao)
147	if err != nil {
148		return nil, err
149	}
150
151	client = configureDebug(client)
152
153	return openstack.NewBlockStorageV1(client, gophercloud.EndpointOpts{
154		Region: os.Getenv("OS_REGION_NAME"),
155	})
156}
157
158// NewBlockStorageV2Client returns a *ServiceClient for making calls
159// to the OpenStack Block Storage v2 API. An error will be returned
160// if authentication or client creation was not possible.
161func NewBlockStorageV2Client() (*gophercloud.ServiceClient, error) {
162	ao, err := openstack.AuthOptionsFromEnv()
163	if err != nil {
164		return nil, err
165	}
166
167	client, err := openstack.AuthenticatedClient(ao)
168	if err != nil {
169		return nil, err
170	}
171
172	client = configureDebug(client)
173
174	return openstack.NewBlockStorageV2(client, gophercloud.EndpointOpts{
175		Region: os.Getenv("OS_REGION_NAME"),
176	})
177}
178
179// NewBlockStorageV3Client returns a *ServiceClient for making calls
180// to the OpenStack Block Storage v3 API. An error will be returned
181// if authentication or client creation was not possible.
182func NewBlockStorageV3Client() (*gophercloud.ServiceClient, error) {
183	ao, err := openstack.AuthOptionsFromEnv()
184	if err != nil {
185		return nil, err
186	}
187
188	client, err := openstack.AuthenticatedClient(ao)
189	if err != nil {
190		return nil, err
191	}
192
193	client = configureDebug(client)
194
195	return openstack.NewBlockStorageV3(client, gophercloud.EndpointOpts{
196		Region: os.Getenv("OS_REGION_NAME"),
197	})
198}
199
200// NewBlockStorageV2NoAuthClient returns a noauth *ServiceClient for
201// making calls to the OpenStack Block Storage v2 API. An error will be
202// returned if client creation was not possible.
203func NewBlockStorageV2NoAuthClient() (*gophercloud.ServiceClient, error) {
204	client, err := blockstorageNoAuth.NewClient(gophercloud.AuthOptions{
205		Username:   os.Getenv("OS_USERNAME"),
206		TenantName: os.Getenv("OS_TENANT_NAME"),
207	})
208	if err != nil {
209		return nil, err
210	}
211
212	client = configureDebug(client)
213
214	return blockstorageNoAuth.NewBlockStorageNoAuth(client, blockstorageNoAuth.EndpointOpts{
215		CinderEndpoint: os.Getenv("CINDER_ENDPOINT"),
216	})
217}
218
219// NewBlockStorageV3NoAuthClient returns a noauth *ServiceClient for
220// making calls to the OpenStack Block Storage v2 API. An error will be
221// returned if client creation was not possible.
222func NewBlockStorageV3NoAuthClient() (*gophercloud.ServiceClient, error) {
223	client, err := blockstorageNoAuth.NewClient(gophercloud.AuthOptions{
224		Username:   os.Getenv("OS_USERNAME"),
225		TenantName: os.Getenv("OS_TENANT_NAME"),
226	})
227	if err != nil {
228		return nil, err
229	}
230
231	client = configureDebug(client)
232
233	return blockstorageNoAuth.NewBlockStorageNoAuth(client, blockstorageNoAuth.EndpointOpts{
234		CinderEndpoint: os.Getenv("CINDER_ENDPOINT"),
235	})
236}
237
238// NewComputeV2Client returns a *ServiceClient for making calls
239// to the OpenStack Compute v2 API. An error will be returned
240// if authentication or client creation was not possible.
241func NewComputeV2Client() (*gophercloud.ServiceClient, error) {
242	ao, err := openstack.AuthOptionsFromEnv()
243	if err != nil {
244		return nil, err
245	}
246
247	client, err := openstack.AuthenticatedClient(ao)
248	if err != nil {
249		return nil, err
250	}
251
252	client = configureDebug(client)
253
254	return openstack.NewComputeV2(client, gophercloud.EndpointOpts{
255		Region: os.Getenv("OS_REGION_NAME"),
256	})
257}
258
259// NewBareMetalV1Client returns a *ServiceClient for making calls
260// to the OpenStack Bare Metal v1 API. An error will be returned
261// if authentication or client creation was not possible.
262func NewBareMetalV1Client() (*gophercloud.ServiceClient, error) {
263	ao, err := openstack.AuthOptionsFromEnv()
264	if err != nil {
265		return nil, err
266	}
267
268	client, err := openstack.AuthenticatedClient(ao)
269	if err != nil {
270		return nil, err
271	}
272
273	client = configureDebug(client)
274
275	return openstack.NewBareMetalV1(client, gophercloud.EndpointOpts{
276		Region: os.Getenv("OS_REGION_NAME"),
277	})
278}
279
280// NewBareMetalV1NoAuthClient returns a *ServiceClient for making calls
281// to the OpenStack Bare Metal v1 API. An error will be returned
282// if authentication or client creation was not possible.
283func NewBareMetalV1NoAuthClient() (*gophercloud.ServiceClient, error) {
284	return baremetalNoAuth.NewBareMetalNoAuth(baremetalNoAuth.EndpointOpts{
285		IronicEndpoint: os.Getenv("IRONIC_ENDPOINT"),
286	})
287}
288
289// NewBareMetalV1HTTPBasic returns a *ServiceClient for making calls
290// to the OpenStack Bare Metal v1 API. An error will be returned
291// if authentication or client creation was not possible.
292func NewBareMetalV1HTTPBasic() (*gophercloud.ServiceClient, error) {
293	return baremetalHTTPBasic.NewBareMetalHTTPBasic(baremetalHTTPBasic.EndpointOpts{
294		IronicEndpoint:     os.Getenv("IRONIC_ENDPOINT"),
295		IronicUser:         os.Getenv("OS_USERNAME"),
296		IronicUserPassword: os.Getenv("OS_PASSWORD"),
297	})
298}
299
300// NewBareMetalIntrospectionV1Client returns a *ServiceClient for making calls
301// to the OpenStack Bare Metal Introspection v1 API. An error will be returned
302// if authentication or client creation was not possible.
303func NewBareMetalIntrospectionV1Client() (*gophercloud.ServiceClient, error) {
304	ao, err := openstack.AuthOptionsFromEnv()
305	if err != nil {
306		return nil, err
307	}
308
309	client, err := openstack.AuthenticatedClient(ao)
310	if err != nil {
311		return nil, err
312	}
313
314	client = configureDebug(client)
315
316	return openstack.NewBareMetalIntrospectionV1(client, gophercloud.EndpointOpts{
317		Region: os.Getenv("OS_REGION_NAME"),
318	})
319}
320
321// NewDBV1Client returns a *ServiceClient for making calls
322// to the OpenStack Database v1 API. An error will be returned
323// if authentication or client creation was not possible.
324func NewDBV1Client() (*gophercloud.ServiceClient, error) {
325	ao, err := openstack.AuthOptionsFromEnv()
326	if err != nil {
327		return nil, err
328	}
329
330	client, err := openstack.AuthenticatedClient(ao)
331	if err != nil {
332		return nil, err
333	}
334
335	client = configureDebug(client)
336
337	return openstack.NewDBV1(client, gophercloud.EndpointOpts{
338		Region: os.Getenv("OS_REGION_NAME"),
339	})
340}
341
342// NewDNSV2Client returns a *ServiceClient for making calls
343// to the OpenStack Compute v2 API. An error will be returned
344// if authentication or client creation was not possible.
345func NewDNSV2Client() (*gophercloud.ServiceClient, error) {
346	ao, err := openstack.AuthOptionsFromEnv()
347	if err != nil {
348		return nil, err
349	}
350
351	client, err := openstack.AuthenticatedClient(ao)
352	if err != nil {
353		return nil, err
354	}
355
356	client = configureDebug(client)
357
358	return openstack.NewDNSV2(client, gophercloud.EndpointOpts{
359		Region: os.Getenv("OS_REGION_NAME"),
360	})
361}
362
363// NewIdentityV2Client returns a *ServiceClient for making calls
364// to the OpenStack Identity v2 API. An error will be returned
365// if authentication or client creation was not possible.
366func NewIdentityV2Client() (*gophercloud.ServiceClient, error) {
367	ao, err := openstack.AuthOptionsFromEnv()
368	if err != nil {
369		return nil, err
370	}
371
372	client, err := openstack.AuthenticatedClient(ao)
373	if err != nil {
374		return nil, err
375	}
376
377	client = configureDebug(client)
378
379	return openstack.NewIdentityV2(client, gophercloud.EndpointOpts{
380		Region: os.Getenv("OS_REGION_NAME"),
381	})
382}
383
384// NewIdentityV2AdminClient returns a *ServiceClient for making calls
385// to the Admin Endpoint of the OpenStack Identity v2 API. An error
386// will be returned if authentication or client creation was not possible.
387func NewIdentityV2AdminClient() (*gophercloud.ServiceClient, error) {
388	ao, err := openstack.AuthOptionsFromEnv()
389	if err != nil {
390		return nil, err
391	}
392
393	client, err := openstack.AuthenticatedClient(ao)
394	if err != nil {
395		return nil, err
396	}
397
398	client = configureDebug(client)
399
400	return openstack.NewIdentityV2(client, gophercloud.EndpointOpts{
401		Region:       os.Getenv("OS_REGION_NAME"),
402		Availability: gophercloud.AvailabilityAdmin,
403	})
404}
405
406// NewIdentityV2UnauthenticatedClient returns an unauthenticated *ServiceClient
407// for the OpenStack Identity v2 API. An error  will be returned if
408// authentication or client creation was not possible.
409func NewIdentityV2UnauthenticatedClient() (*gophercloud.ServiceClient, error) {
410	ao, err := openstack.AuthOptionsFromEnv()
411	if err != nil {
412		return nil, err
413	}
414
415	client, err := openstack.NewClient(ao.IdentityEndpoint)
416	if err != nil {
417		return nil, err
418	}
419
420	client = configureDebug(client)
421
422	return openstack.NewIdentityV2(client, gophercloud.EndpointOpts{})
423}
424
425// NewIdentityV3Client returns a *ServiceClient for making calls
426// to the OpenStack Identity v3 API. An error will be returned
427// if authentication or client creation was not possible.
428func NewIdentityV3Client() (*gophercloud.ServiceClient, error) {
429	ao, err := openstack.AuthOptionsFromEnv()
430	if err != nil {
431		return nil, err
432	}
433
434	client, err := openstack.AuthenticatedClient(ao)
435	if err != nil {
436		return nil, err
437	}
438
439	client = configureDebug(client)
440
441	return openstack.NewIdentityV3(client, gophercloud.EndpointOpts{
442		Region: os.Getenv("OS_REGION_NAME"),
443	})
444}
445
446// NewIdentityV3UnauthenticatedClient returns an unauthenticated *ServiceClient
447// for the OpenStack Identity v3 API. An error  will be returned if
448// authentication or client creation was not possible.
449func NewIdentityV3UnauthenticatedClient() (*gophercloud.ServiceClient, error) {
450	ao, err := openstack.AuthOptionsFromEnv()
451	if err != nil {
452		return nil, err
453	}
454
455	client, err := openstack.NewClient(ao.IdentityEndpoint)
456	if err != nil {
457		return nil, err
458	}
459
460	client = configureDebug(client)
461
462	return openstack.NewIdentityV3(client, gophercloud.EndpointOpts{})
463}
464
465// NewImageServiceV2Client returns a *ServiceClient for making calls to the
466// OpenStack Image v2 API. An error will be returned if authentication or
467// client creation was not possible.
468func NewImageServiceV2Client() (*gophercloud.ServiceClient, error) {
469	ao, err := openstack.AuthOptionsFromEnv()
470	if err != nil {
471		return nil, err
472	}
473
474	client, err := openstack.AuthenticatedClient(ao)
475	if err != nil {
476		return nil, err
477	}
478
479	client = configureDebug(client)
480
481	return openstack.NewImageServiceV2(client, gophercloud.EndpointOpts{
482		Region: os.Getenv("OS_REGION_NAME"),
483	})
484}
485
486// NewNetworkV2Client returns a *ServiceClient for making calls to the
487// OpenStack Networking v2 API. An error will be returned if authentication
488// or client creation was not possible.
489func NewNetworkV2Client() (*gophercloud.ServiceClient, error) {
490	ao, err := openstack.AuthOptionsFromEnv()
491	if err != nil {
492		return nil, err
493	}
494
495	client, err := openstack.AuthenticatedClient(ao)
496	if err != nil {
497		return nil, err
498	}
499
500	client = configureDebug(client)
501
502	return openstack.NewNetworkV2(client, gophercloud.EndpointOpts{
503		Region: os.Getenv("OS_REGION_NAME"),
504	})
505}
506
507// NewObjectStorageV1Client returns a *ServiceClient for making calls to the
508// OpenStack Object Storage v1 API. An error will be returned if authentication
509// or client creation was not possible.
510func NewObjectStorageV1Client() (*gophercloud.ServiceClient, error) {
511	ao, err := openstack.AuthOptionsFromEnv()
512	if err != nil {
513		return nil, err
514	}
515
516	client, err := openstack.AuthenticatedClient(ao)
517	if err != nil {
518		return nil, err
519	}
520
521	client = configureDebug(client)
522
523	return openstack.NewObjectStorageV1(client, gophercloud.EndpointOpts{
524		Region: os.Getenv("OS_REGION_NAME"),
525	})
526}
527
528// NewSharedFileSystemV2Client returns a *ServiceClient for making calls
529// to the OpenStack Shared File System v2 API. An error will be returned
530// if authentication or client creation was not possible.
531func NewSharedFileSystemV2Client() (*gophercloud.ServiceClient, error) {
532	ao, err := openstack.AuthOptionsFromEnv()
533	if err != nil {
534		return nil, err
535	}
536
537	client, err := openstack.AuthenticatedClient(ao)
538	if err != nil {
539		return nil, err
540	}
541
542	client = configureDebug(client)
543
544	return openstack.NewSharedFileSystemV2(client, gophercloud.EndpointOpts{
545		Region: os.Getenv("OS_REGION_NAME"),
546	})
547}
548
549// NewLoadBalancerV2Client returns a *ServiceClient for making calls to the
550// OpenStack Octavia v2 API. An error will be returned if authentication
551// or client creation was not possible.
552func NewLoadBalancerV2Client() (*gophercloud.ServiceClient, error) {
553	ao, err := openstack.AuthOptionsFromEnv()
554	if err != nil {
555		return nil, err
556	}
557
558	client, err := openstack.AuthenticatedClient(ao)
559	if err != nil {
560		return nil, err
561	}
562
563	client = configureDebug(client)
564
565	return openstack.NewLoadBalancerV2(client, gophercloud.EndpointOpts{
566		Region: os.Getenv("OS_REGION_NAME"),
567	})
568}
569
570// NewClusteringV1Client returns a *ServiceClient for making calls
571// to the OpenStack Clustering v1 API. An error will be returned
572// if authentication or client creation was not possible.
573func NewClusteringV1Client() (*gophercloud.ServiceClient, error) {
574	ao, err := openstack.AuthOptionsFromEnv()
575	if err != nil {
576		return nil, err
577	}
578
579	client, err := openstack.AuthenticatedClient(ao)
580	if err != nil {
581		return nil, err
582	}
583
584	client = configureDebug(client)
585
586	return openstack.NewClusteringV1(client, gophercloud.EndpointOpts{
587		Region: os.Getenv("OS_REGION_NAME"),
588	})
589}
590
591// NewMessagingV2Client returns a *ServiceClient for making calls
592// to the OpenStack Messaging (Zaqar) v2 API. An error will be returned
593// if authentication or client creation was not possible.
594func NewMessagingV2Client(clientID string) (*gophercloud.ServiceClient, error) {
595	ao, err := openstack.AuthOptionsFromEnv()
596	if err != nil {
597		return nil, err
598	}
599
600	client, err := openstack.AuthenticatedClient(ao)
601	if err != nil {
602		return nil, err
603	}
604
605	client = configureDebug(client)
606
607	return openstack.NewMessagingV2(client, clientID, gophercloud.EndpointOpts{
608		Region: os.Getenv("OS_REGION_NAME"),
609	})
610}
611
612// NewContainerV1Client returns a *ServiceClient for making calls
613// to the OpenStack Container V1 API. An error will be returned
614// if authentication or client creation was not possible.
615func NewContainerV1Client() (*gophercloud.ServiceClient, error) {
616	ao, err := openstack.AuthOptionsFromEnv()
617	if err != nil {
618		return nil, err
619	}
620
621	client, err := openstack.AuthenticatedClient(ao)
622	if err != nil {
623		return nil, err
624	}
625
626	client = configureDebug(client)
627
628	return openstack.NewContainerV1(client, gophercloud.EndpointOpts{
629		Region: os.Getenv("OS_REGION_NAME"),
630	})
631}
632
633// NewKeyManagerV1Client returns a *ServiceClient for making calls
634// to the OpenStack Key Manager (Barbican) v1 API. An error will be
635// returned if authentication or client creation was not possible.
636func NewKeyManagerV1Client() (*gophercloud.ServiceClient, error) {
637	ao, err := openstack.AuthOptionsFromEnv()
638	if err != nil {
639		return nil, err
640	}
641
642	client, err := openstack.AuthenticatedClient(ao)
643	if err != nil {
644		return nil, err
645	}
646
647	client = configureDebug(client)
648
649	return openstack.NewKeyManagerV1(client, gophercloud.EndpointOpts{
650		Region: os.Getenv("OS_REGION_NAME"),
651	})
652}
653
654// configureDebug will configure the provider client to print the API
655// requests and responses if OS_DEBUG is enabled.
656func configureDebug(client *gophercloud.ProviderClient) *gophercloud.ProviderClient {
657	if os.Getenv("OS_DEBUG") != "" {
658		client.HTTPClient = http.Client{
659			Transport: &LogRoundTripper{
660				Rt: &http.Transport{},
661			},
662		}
663	}
664
665	return client
666}
667
668// NewContainerInfraV1Client returns a *ServiceClient for making calls
669// to the OpenStack Container Infra Management v1 API. An error will be returned
670// if authentication or client creation was not possible.
671func NewContainerInfraV1Client() (*gophercloud.ServiceClient, error) {
672	ao, err := openstack.AuthOptionsFromEnv()
673	if err != nil {
674		return nil, err
675	}
676
677	client, err := openstack.AuthenticatedClient(ao)
678	if err != nil {
679		return nil, err
680	}
681
682	client = configureDebug(client)
683
684	return openstack.NewContainerInfraV1(client, gophercloud.EndpointOpts{
685		Region: os.Getenv("OS_REGION_NAME"),
686	})
687}
688
689// NewWorkflowV2Client returns a *ServiceClient for making calls
690// to the OpenStack Workflow v2 API (Mistral). An error will be returned if
691// authentication or client creation failed.
692func NewWorkflowV2Client() (*gophercloud.ServiceClient, error) {
693	ao, err := openstack.AuthOptionsFromEnv()
694	if err != nil {
695		return nil, err
696	}
697
698	client, err := openstack.AuthenticatedClient(ao)
699	if err != nil {
700		return nil, err
701	}
702
703	client = configureDebug(client)
704
705	return openstack.NewWorkflowV2(client, gophercloud.EndpointOpts{
706		Region: os.Getenv("OS_REGION_NAME"),
707	})
708}
709
710// NewOrchestrationV1Client returns a *ServiceClient for making calls
711// to the OpenStack Orchestration v1 API. An error will be returned
712// if authentication or client creation was not possible.
713func NewOrchestrationV1Client() (*gophercloud.ServiceClient, error) {
714	ao, err := openstack.AuthOptionsFromEnv()
715	if err != nil {
716		return nil, err
717	}
718
719	client, err := openstack.AuthenticatedClient(ao)
720	if err != nil {
721		return nil, err
722	}
723
724	client = configureDebug(client)
725
726	return openstack.NewOrchestrationV1(client, gophercloud.EndpointOpts{
727		Region: os.Getenv("OS_REGION_NAME"),
728	})
729}
730
731// NewPlacementV1Client returns a *ServiceClient for making calls
732// to the OpenStack Placement API. An error will be returned
733// if authentication or client creation was not possible.
734func NewPlacementV1Client() (*gophercloud.ServiceClient, error) {
735	ao, err := openstack.AuthOptionsFromEnv()
736	if err != nil {
737		return nil, err
738	}
739
740	client, err := openstack.AuthenticatedClient(ao)
741	if err != nil {
742		return nil, err
743	}
744
745	client = configureDebug(client)
746
747	return openstack.NewPlacementV1(client, gophercloud.EndpointOpts{
748		Region: os.Getenv("OS_REGION_NAME"),
749	})
750}
751