4
4
package commands
5
5
6
6
import (
7
+ "encoding/base64"
8
+ "encoding/json"
7
9
"fmt"
8
10
"io/ioutil"
11
+ "log"
9
12
"os"
13
+ "path/filepath"
10
14
"strings"
11
15
12
16
"gopkg.in/yaml.v2"
13
17
18
+ "github.com/docker/docker-credential-helpers/client"
19
+ homedir "github.com/mitchellh/go-homedir"
14
20
"github.com/openfaas/faas-cli/proxy"
15
21
"github.com/openfaas/faas-cli/stack"
16
22
"github.com/spf13/cobra"
@@ -72,7 +78,7 @@ var deployCmd = &cobra.Command{
72
78
[--constraint PLACEMENT_CONSTRAINT ...]
73
79
[--regex "REGEX"]
74
80
[--filter "WILDCARD"]
75
- [--secret "SECRET_NAME"]` ,
81
+ [--secret "SECRET_NAME"]` ,
76
82
77
83
Short : "Deploy OpenFaaS functions" ,
78
84
Long : `Deploys OpenFaaS function containers either via the supplied YAML config using
@@ -112,6 +118,12 @@ func runDeployCommand(args []string, image string, fprocess string, functionName
112
118
return fmt .Errorf ("cannot specify --update and --replace at the same time" )
113
119
}
114
120
121
+ dockerConfig := configFile {}
122
+ err := readDockerConfig (& dockerConfig )
123
+ if err != nil {
124
+ log .Println ("Unable to read the docker config - %v" , err .Error ())
125
+ }
126
+
115
127
var services stack.Services
116
128
if len (yamlFile ) > 0 {
117
129
parsedServices , err := stack .ParseYAMLFile (yamlFile , regex , filter )
@@ -153,6 +165,8 @@ func runDeployCommand(args []string, image string, fprocess string, functionName
153
165
deployFlags .secrets = mergeSlice (function .Secrets , deployFlags .secrets )
154
166
}
155
167
168
+ function .RegistryAuth = getRegistryAuth (& dockerConfig , function .Image )
169
+
156
170
fileEnvironment , err := readFiles (function .EnvironmentFile )
157
171
if err != nil {
158
172
return err
@@ -191,16 +205,17 @@ Error: %s`, fprocessErr.Error())
191
205
Requests : function .Requests ,
192
206
}
193
207
194
- proxy .DeployFunction (function .FProcess , services .Provider .GatewayURL , function .Name , function .Image , function .Language , deployFlags .replace , allEnvironment , services .Provider .Network , functionConstraints , deployFlags .update , deployFlags .secrets , allLabels , functionResourceRequest1 )
208
+ proxy .DeployFunction (function .FProcess , services .Provider .GatewayURL , function .Name , function .Image , function .RegistryAuth , function . Language , deployFlags .replace , allEnvironment , services .Provider .Network , functionConstraints , deployFlags .update , deployFlags .secrets , allLabels , functionResourceRequest1 )
195
209
}
196
210
} else {
197
211
if len (image ) == 0 || len (functionName ) == 0 {
198
212
return fmt .Errorf ("To deploy a function give --yaml/-f or a --image flag" )
199
213
}
200
214
201
215
gateway = getGatewayURL (gateway , defaultGateway , gateway , os .Getenv (openFaaSURLEnvironment ))
216
+ registryAuth := getRegistryAuth (& dockerConfig , image )
202
217
203
- if err := deployImage (image , fprocess , functionName , deployFlags ); err != nil {
218
+ if err := deployImage (image , fprocess , functionName , registryAuth , deployFlags ); err != nil {
204
219
return err
205
220
}
206
221
}
@@ -213,6 +228,7 @@ func deployImage(
213
228
image string ,
214
229
fprocess string ,
215
230
functionName string ,
231
+ registryAuth string ,
216
232
deployFlags DeployFlags ,
217
233
) error {
218
234
envvars , err := parseMap (deployFlags .envvarOpts , "env" )
@@ -226,7 +242,7 @@ func deployImage(
226
242
}
227
243
228
244
functionResourceRequest1 := proxy.FunctionResourceRequest {}
229
- proxy .DeployFunction (fprocess , gateway , functionName , image , language , deployFlags .replace , envvars , network , deployFlags .constraints , deployFlags .update , deployFlags .secrets , labelMap , functionResourceRequest1 )
245
+ proxy .DeployFunction (fprocess , gateway , functionName , registryAuth , image , language , deployFlags .replace , envvars , network , deployFlags .constraints , deployFlags .update , deployFlags .secrets , labelMap , functionResourceRequest1 )
230
246
231
247
return nil
232
248
}
@@ -340,3 +356,91 @@ func deriveFprocess(function stack.Function) (string, error) {
340
356
func languageExistsNotDockerfile (language string ) bool {
341
357
return len (language ) > 0 && strings .ToLower (language ) != "dockerfile"
342
358
}
359
+
360
+ type authConfig struct {
361
+ Auth string `json:"auth,omitempty"`
362
+ }
363
+
364
+ type configFile struct {
365
+ AuthConfigs map [string ]authConfig `json:"auths"`
366
+ CredentialsStore string `json:"credsStore,omitempty"`
367
+ }
368
+
369
+ const (
370
+ // docker default settings
371
+ configFileName = "config.json"
372
+ configFileDir = ".docker"
373
+ defaultDockerRegistry = "https://index.docker.io/v1/"
374
+ )
375
+
376
+ var (
377
+ configDir = os .Getenv ("DOCKER_CONFIG" )
378
+ )
379
+
380
+ func readDockerConfig (config * configFile ) error {
381
+
382
+ if configDir == "" {
383
+ home , err := homedir .Dir ()
384
+ if err != nil {
385
+ return err
386
+ }
387
+ configDir = filepath .Join (home , configFileDir )
388
+ }
389
+ filename := filepath .Join (configDir , configFileName )
390
+
391
+ file , err := os .Open (filename )
392
+ if err != nil {
393
+ return err
394
+ }
395
+ defer file .Close ()
396
+ content , err := ioutil .ReadAll (file )
397
+ if err != nil {
398
+ return err
399
+ }
400
+
401
+ err = json .Unmarshal (content , config )
402
+ if err != nil {
403
+ return err
404
+ }
405
+
406
+ if config .CredentialsStore != "" {
407
+ p := client .NewShellProgramFunc ("docker-credential-" + config .CredentialsStore )
408
+
409
+ for k := range config .AuthConfigs {
410
+ creds , err := client .Get (p , k )
411
+ if err != nil {
412
+ return err
413
+ }
414
+
415
+ if config .AuthConfigs [k ].Auth == "" {
416
+ // apend base64 encoded "auth": "dGVzdDpQdXFxR3E2THZDYzhGQUwyUWtLcA==" (user:pass)
417
+ registryAuth := creds .Username + ":" + creds .Secret
418
+ registryAuth = base64 .StdEncoding .EncodeToString ([]byte (registryAuth ))
419
+
420
+ var tmp = config .AuthConfigs [k ]
421
+ tmp .Auth = registryAuth
422
+ config .AuthConfigs [k ] = tmp
423
+ }
424
+ }
425
+ }
426
+ return nil
427
+ }
428
+
429
+ func getRegistryAuth (config * configFile , image string ) string {
430
+
431
+ if len (config .AuthConfigs ) == 0 {
432
+ return ""
433
+ }
434
+
435
+ // image format is: <docker registry>/<user>/<image>
436
+ // so we trim <user>/<image>
437
+ regS := strings .Split (image , "/" )
438
+ registry := strings .Join (regS [:len (regS )- 2 ], ", " )
439
+
440
+ if registry != "" {
441
+ return config .AuthConfigs [registry ].Auth
442
+ } else if (registry == "" ) && (config .AuthConfigs [defaultDockerRegistry ].Auth != "" ) {
443
+ return config .AuthConfigs [defaultDockerRegistry ].Auth
444
+ }
445
+ return ""
446
+ }
0 commit comments