@@ -26,13 +26,14 @@ func main() {
26
26
log .SetOutput (os .Stderr )
27
27
28
28
// Common command-line arguments.
29
- host := flag .String ("host" , "" , "Duplo API base URL" )
30
- token := flag .String ("token" , "" , "Duplo API token" )
29
+ host := flag .String ("host" , "" , "DuploCloud base URL" )
30
+ token := flag .String ("token" , "" , "DuploCloud API token" )
31
31
debug := flag .Bool ("debug" , false , "Turn on verbose (debugging) output" )
32
32
noCache := flag .Bool ("no-cache" , false , "Disable caching (not recommended)" )
33
33
interactive := flag .Bool ("interactive" , false , "Allow getting Duplo credentials via an interactive browser session" )
34
34
port := flag .Int ("port" , 0 , "Port to use for the local web server" )
35
35
showVersion := flag .Bool ("version" , false , "Output version information and exit" )
36
+ apiHost := flag .String ("api-host" , "" , "Specify an alternate DuploCloud API base URL if it differs from the UI host (defaults to the value of --host if omitted)" )
36
37
admin = new (bool )
37
38
duploOps = new (bool )
38
39
@@ -76,13 +77,35 @@ func main() {
76
77
os .Exit (1 )
77
78
}
78
79
79
- // Refuse to call APIs over anything but https://
80
- // Trim a trailing slash.
81
- if host == nil || ! strings .HasPrefix (* host , "https://" ) {
82
- log .Fatalf ("%s: %s" , os .Args [0 ], "--host must be present and start with https://" )
80
+ // Validate the host.
81
+ const fatalFmt = "%s: %s"
82
+ if * host == "" {
83
+ log .Fatalf (fatalFmt , os .Args [0 ], "--host must be present" )
84
+ } else if strings .HasPrefix (* host , "http://localhost" ) {
85
+ fmt .Fprintf (os .Stderr , "Using developer host %s\n " , * host )
86
+ } else if ! strings .HasPrefix (* host , "https://" ) {
87
+ // Refuse to call APIs over anything but https://
88
+ log .Fatalf (fatalFmt , os .Args [0 ], "--host must start with https://" )
83
89
}
90
+
91
+ // Trim a trailing slash.
84
92
* host = strings .TrimSuffix (* host , "/" )
85
93
94
+ // Validate the api-host if provided.
95
+ if * apiHost != "" {
96
+ if strings .HasPrefix (* apiHost , "http://localhost" ) {
97
+ fmt .Printf ("Using developer api-host %s\n " , * apiHost )
98
+ } else if ! strings .HasPrefix (* apiHost , "https://" ) {
99
+ // Refuse to call APIs over anything but https://
100
+ log .Fatalf (fatalFmt , os .Args [0 ], "--api-host must start with https://" )
101
+ }
102
+ // Trim a trailing slash.
103
+ * apiHost = strings .TrimSuffix (* apiHost , "/" )
104
+ } else {
105
+ // By default, the api host is the same as the UI host.
106
+ apiHost = host
107
+ }
108
+
86
109
// Possibly enable debugging
87
110
if * debug {
88
111
duplocloud .LogLevel = duplocloud .TRACE
@@ -92,21 +115,22 @@ func main() {
92
115
internal .MustInitCache ("duplo-jit" , * noCache )
93
116
94
117
// Get AWS credentials and output them
118
+ cacheKey := internal .GetHostCacheKey (* host )
119
+
95
120
switch cmd {
96
121
case "aws" :
97
122
var creds * internal.AwsConfigOutput
98
- var cacheKey string
99
123
if * admin {
100
124
101
125
// Build the cache key
102
- cacheKey = strings .Join ([]string {strings . TrimPrefix ( * host , "https://" ) , "admin" }, "," )
126
+ cacheKey = strings .Join ([]string {cacheKey , "admin" }, "," )
103
127
104
128
// Try to find credentials from the cache.
105
129
creds = internal .CacheGetAwsConfigOutput (cacheKey )
106
130
107
131
// Otherwise, get the credentials from Duplo.
108
132
if creds == nil {
109
- client , _ := internal .MustDuploClient (* host , * token , * interactive , true , * port )
133
+ client , _ := internal .MustDuploClient (* host , * apiHost , * token , * interactive , true , * port )
110
134
result , err := client .AdminGetJitAwsCredentials ()
111
135
internal .DieIf (err , "failed to get credentials" )
112
136
creds = internal .ConvertAwsCreds (result )
@@ -115,14 +139,14 @@ func main() {
115
139
} else if * duploOps {
116
140
117
141
// Build the cache key
118
- cacheKey = strings .Join ([]string {strings . TrimPrefix ( * host , "https://" ) , "duplo-ops" }, "," )
142
+ cacheKey = strings .Join ([]string {cacheKey , "duplo-ops" }, "," )
119
143
120
144
// Try to find credentials from the cache.
121
145
creds = internal .CacheGetAwsConfigOutput (cacheKey )
122
146
123
147
// Otherwise, get the credentials from Duplo.
124
148
if creds == nil {
125
- client , _ := internal .MustDuploClient (* host , * token , * interactive , true , * port )
149
+ client , _ := internal .MustDuploClient (* host , * apiHost , * token , * interactive , true , * port )
126
150
result , err := client .AdminAwsGetJitAccess ("duplo-ops" )
127
151
internal .DieIf (err , "failed to get credentials" )
128
152
creds = internal .ConvertAwsCreds (result )
@@ -137,11 +161,11 @@ func main() {
137
161
138
162
// Identify the tenant name to use for the cache key.
139
163
var tenantName string
140
- client , _ := internal .MustDuploClient (* host , * token , * interactive , false , * port )
164
+ client , _ := internal .MustDuploClient (* host , * apiHost , * token , * interactive , false , * port )
141
165
* tenantID , tenantName = getTenantIDAndName (* tenantID , client )
142
166
143
167
// Build the cache key.
144
- cacheKey = strings .Join ([]string {strings . TrimPrefix ( * host , "https://" ) , "tenant" , tenantName }, "," )
168
+ cacheKey = strings .Join ([]string {cacheKey , "tenant" , tenantName }, "," )
145
169
146
170
// Try to find credentials from the cache.
147
171
creds = internal .CacheGetAwsConfigOutput (cacheKey )
@@ -159,23 +183,22 @@ func main() {
159
183
internal .OutputAwsCreds (creds , cacheKey )
160
184
161
185
case "duplo" :
162
- _ , creds := internal .MustDuploClient (* host , * token , * interactive , true , * port )
186
+ _ , creds := internal .MustDuploClient (* host , * apiHost , * token , * interactive , true , * port )
163
187
internal .OutputDuploCreds (creds )
164
188
165
189
case "k8s" :
166
190
var creds * clientauthv1beta1.ExecCredential
167
- var cacheKey string
168
191
if planID != nil && * planID != "" {
169
192
170
193
// Build the cache key
171
- cacheKey = strings .Join ([]string {strings . TrimPrefix ( * host , "https://" ) , "plan" , * planID }, "," )
194
+ cacheKey = strings .Join ([]string {cacheKey , "plan" , * planID }, "," )
172
195
173
196
// Try to find credentials from the cache.
174
197
creds = internal .CacheGetK8sConfigOutput (cacheKey , "" )
175
198
176
199
// Otherwise, get the credentials from Duplo.
177
200
if creds == nil {
178
- client , _ := internal .MustDuploClient (* host , * token , * interactive , true , * port )
201
+ client , _ := internal .MustDuploClient (* host , * apiHost , * token , * interactive , true , * port )
179
202
result , err := client .AdminGetK8sJitAccess (* planID )
180
203
internal .DieIf (err , "failed to get credentials" )
181
204
creds = internal .ConvertK8sCreds (result )
@@ -190,11 +213,11 @@ func main() {
190
213
191
214
// Identify the tenant name to use for the cache key.
192
215
var tenantName string
193
- client , _ := internal .MustDuploClient (* host , * token , * interactive , false , * port )
216
+ client , _ := internal .MustDuploClient (* host , * apiHost , * token , * interactive , false , * port )
194
217
* tenantID , tenantName = getTenantIDAndName (* tenantID , client )
195
218
196
219
// Build the cache key.
197
- cacheKey = strings .Join ([]string {strings . TrimPrefix ( * host , "https://" ) , "tenant" , tenantName }, "," )
220
+ cacheKey = strings .Join ([]string {cacheKey , "tenant" , tenantName }, "," )
198
221
199
222
// Try to find credentials from the cache.
200
223
creds = internal .CacheGetK8sConfigOutput (cacheKey , tenantName )
0 commit comments