File: client.go

package info (click to toggle)
golang-github-vmware-photon-controller-go-sdk 0.0~PROMOTED-339-1.1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bullseye, forky, sid, trixie
  • size: 7,080 kB
  • sloc: sh: 33; makefile: 4
file content (169 lines) | stat: -rw-r--r-- 5,087 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
// Copyright (c) 2016 VMware, Inc. All Rights Reserved.
//
// This product is licensed to you under the Apache License, Version 2.0 (the "License").
// You may not use this product except in compliance with the License.
//
// This product may include a number of subcomponents with separate copyright notices and
// license terms. Your use of these subcomponents is subject to the terms and conditions
// of the subcomponent's license, as noted in the LICENSE file.

package photon

import (
	"crypto/tls"
	"crypto/x509"
	"io/ioutil"
	"log"
	"net/http"
	"strings"
	"time"
)

// Represents stateless context needed to call photon APIs.
type Client struct {
	options           ClientOptions
	restClient        *restClient
	logger            *log.Logger
	Endpoint          string
	Status            *StatusAPI
	Tenants           *TenantsAPI
	Tasks             *TasksAPI
	Projects          *ProjectsAPI
	Flavors           *FlavorsAPI
	Images            *ImagesAPI
	Disks             *DisksAPI
	VMs               *VmAPI
	Hosts             *HostsAPI
	Deployments       *DeploymentsAPI
	ResourceTickets   *ResourceTicketsAPI
	Subnets           *SubnetsAPI
	VirtualSubnets    *VirtualSubnetsAPI
	Clusters          *ClustersAPI
	Auth              *AuthAPI
	AvailabilityZones *AvailabilityZonesAPI
	Info              *InfoAPI
}

// Represents Tokens
type TokenOptions struct {
	AccessToken  string `json:"access_token"`
	ExpiresIn    int    `json:"expires_in"`
	RefreshToken string `json:"refresh_token,omitempty"`
	IdToken      string `json:"id_token"`
	TokenType    string `json:"token_type"`
}

// Options for Client
type ClientOptions struct {
	// When using the Tasks.Wait APIs, defines the duration of how long
	// the SDK should continue to poll the server. Default is 30 minutes.
	// TasksAPI.WaitTimeout() can be used to specify timeout on
	// individual calls.
	TaskPollTimeout time.Duration

	// Whether or not to ignore any TLS errors when talking to photon,
	// false by default.
	IgnoreCertificate bool

	// List of root CA's to use for server validation
	// nil by default.
	RootCAs *x509.CertPool

	// For tasks APIs, defines the delay between each polling attempt.
	// Default is 100 milliseconds.
	TaskPollDelay time.Duration

	// For tasks APIs, defines the number of retries to make in the event
	// of an error. Default is 3.
	TaskRetryCount int

	// Tokens for user authentication. Default is empty.
	TokenOptions *TokenOptions
}

// Creates a new photon client with specified options. If options
// is nil, default options will be used.
func NewClient(endpoint string, options *ClientOptions, logger *log.Logger) (c *Client) {
	defaultOptions := &ClientOptions{
		TaskPollTimeout:   30 * time.Minute,
		TaskPollDelay:     100 * time.Millisecond,
		TaskRetryCount:    3,
		TokenOptions:      &TokenOptions{},
		IgnoreCertificate: false,
		RootCAs:           nil,
	}

	if options != nil {
		if options.TaskPollTimeout != 0 {
			defaultOptions.TaskPollTimeout = options.TaskPollTimeout
		}
		if options.TaskPollDelay != 0 {
			defaultOptions.TaskPollDelay = options.TaskPollDelay
		}
		if options.TaskRetryCount != 0 {
			defaultOptions.TaskRetryCount = options.TaskRetryCount
		}
		if options.TokenOptions != nil {
			defaultOptions.TokenOptions = options.TokenOptions
		}
		if options.RootCAs != nil {
			defaultOptions.RootCAs = options.RootCAs
		}
		defaultOptions.IgnoreCertificate = options.IgnoreCertificate
	}

	if logger == nil {
		logger = createPassThroughLogger()
	}

	tr := &http.Transport{
		TLSClientConfig: &tls.Config{
			InsecureSkipVerify: defaultOptions.IgnoreCertificate,
			RootCAs:            defaultOptions.RootCAs},
	}

	endpoint = strings.TrimRight(endpoint, "/")

	restClient := &restClient{
		httpClient: &http.Client{Transport: tr},
		logger:     logger,
	}

	c = &Client{Endpoint: endpoint, restClient: restClient, logger: logger}

	// Ensure a copy of options is made, rather than using a pointer
	// which may change out from underneath if misused by the caller.
	c.options = *defaultOptions
	c.Status = &StatusAPI{c}
	c.Tenants = &TenantsAPI{c}
	c.Tasks = &TasksAPI{c}
	c.Projects = &ProjectsAPI{c}
	c.Flavors = &FlavorsAPI{c}
	c.Images = &ImagesAPI{c}
	c.Disks = &DisksAPI{c}
	c.VMs = &VmAPI{c}
	c.Hosts = &HostsAPI{c}
	c.Deployments = &DeploymentsAPI{c}
	c.ResourceTickets = &ResourceTicketsAPI{c}
	c.Subnets = &SubnetsAPI{c}
	c.VirtualSubnets = &VirtualSubnetsAPI{c}
	c.Clusters = &ClustersAPI{c}
	c.Auth = &AuthAPI{c}
	c.AvailabilityZones = &AvailabilityZonesAPI{c}
	c.Info = &InfoAPI{c}
	return
}

// Creates a new photon client with specified options and http.Client.
// Useful for functional testing where http calls must be mocked out.
// If options is nil, default options will be used.
func NewTestClient(endpoint string, options *ClientOptions, httpClient *http.Client) (c *Client) {
	c = NewClient(endpoint, options, nil)
	c.restClient.httpClient = httpClient
	return
}

func createPassThroughLogger() (l *log.Logger) {
	// ioutil.Discard makes all logging operation be a no-op.
	return log.New(ioutil.Discard, "", log.LstdFlags)
}