Browse code

make GetAll use client.List as the source of truth

Signed-off-by: Jake Sanders <jsand@google.com>

Jake Sanders authored on 2016/09/07 06:10:04
Showing 7 changed files
... ...
@@ -58,17 +58,29 @@ func (c *nativeStore) Get(serverAddress string) (types.AuthConfig, error) {
58 58
 
59 59
 // GetAll retrieves all the credentials from the native store.
60 60
 func (c *nativeStore) GetAll() (map[string]types.AuthConfig, error) {
61
-	auths, _ := c.fileStore.GetAll()
61
+	auths, err := c.listCredentialsInStore()
62
+	if err != nil {
63
+		return nil, err
64
+	}
65
+
66
+	// Emails are only stored in the file store.
67
+	// This call can be safely eliminated when emails are removed.
68
+	fileConfigs, _ := c.fileStore.GetAll()
62 69
 
63
-	for s, ac := range auths {
64
-		creds, _ := c.getCredentialsFromStore(s)
70
+	authConfigs := make(map[string]types.AuthConfig)
71
+	for registry := range auths {
72
+		creds, err := c.getCredentialsFromStore(registry)
73
+		if err != nil {
74
+			return nil, err
75
+		}
76
+		ac, _ := fileConfigs[registry] // might contain Email
65 77
 		ac.Username = creds.Username
66 78
 		ac.Password = creds.Password
67 79
 		ac.IdentityToken = creds.IdentityToken
68
-		auths[s] = ac
80
+		authConfigs[registry] = ac
69 81
 	}
70 82
 
71
-	return auths, nil
83
+	return authConfigs, nil
72 84
 }
73 85
 
74 86
 // Store saves the given credentials in the file store.
... ...
@@ -124,3 +136,9 @@ func (c *nativeStore) getCredentialsFromStore(serverAddress string) (types.AuthC
124 124
 	ret.ServerAddress = serverAddress
125 125
 	return ret, nil
126 126
 }
127
+
128
+// listCredentialsInStore returns a listing of stored credentials as a map of
129
+// URL -> username.
130
+func (c *nativeStore) listCredentialsInStore() (map[string]string, error) {
131
+	return client.List(c.programFunc)
132
+}
... ...
@@ -70,6 +70,8 @@ func (m *mockCommand) Output() ([]byte, error) {
70 70
 		default:
71 71
 			return []byte("program failed"), errCommandExited
72 72
 		}
73
+	case "list":
74
+		return []byte(fmt.Sprintf(`{"%s": "%s", "%s": "%s"}`, validServerAddress, "foo", validServerAddress2, "<token>")), nil
73 75
 	}
74 76
 
75 77
 	return []byte(fmt.Sprintf("unknown argument %q with %q", m.arg, inS)), errCommandExited
... ...
@@ -225,9 +227,6 @@ func TestNativeStoreGetAll(t *testing.T) {
225 225
 		validServerAddress: {
226 226
 			Email: "foo@example.com",
227 227
 		},
228
-		validServerAddress2: {
229
-			Email: "foo@example2.com",
230
-		},
231 228
 	})
232 229
 	f.CredentialsStore = "mock"
233 230
 
... ...
@@ -265,8 +264,8 @@ func TestNativeStoreGetAll(t *testing.T) {
265 265
 	if as[validServerAddress2].IdentityToken != "abcd1234" {
266 266
 		t.Fatalf("expected identity token `abcd1324` for %s, got %s", validServerAddress2, as[validServerAddress2].IdentityToken)
267 267
 	}
268
-	if as[validServerAddress2].Email != "foo@example2.com" {
269
-		t.Fatalf("expected email `foo@example2.com` for %s, got %s", validServerAddress2, as[validServerAddress2].Email)
268
+	if as[validServerAddress2].Email != "" {
269
+		t.Fatalf("expected no email for %s, got %s", validServerAddress2, as[validServerAddress2].Email)
270 270
 	}
271 271
 }
272 272
 
... ...
@@ -137,7 +137,7 @@ clone git google.golang.org/api dc6d2353af16e2a2b0ff6986af051d473a4ed468 https:/
137 137
 clone git google.golang.org/cloud dae7e3d993bc3812a2185af60552bb6b847e52a0 https://code.googlesource.com/gocloud
138 138
 
139 139
 # native credentials
140
-clone git github.com/docker/docker-credential-helpers v0.3.0
140
+clone git github.com/docker/docker-credential-helpers f72c04f1d8e71959a6d103f808c50ccbad79b9fd
141 141
 
142 142
 # containerd
143 143
 clone git github.com/docker/containerd 2545227b0357eb55e369fa0072baef9ad91cdb69
... ...
@@ -2,29 +2,51 @@
2 2
 
3 3
 set -e
4 4
 
5
+listFile=shell_test_list.json
6
+
5 7
 case $1 in
6 8
 	"store")
7 9
 		in=$(</dev/stdin)
8
-		server=$(echo "$in" | jq --raw-output ".ServerURL" | sha1sum - | awk '{print $1}')
10
+		server=$(echo "$in" | jq --raw-output ".ServerURL")
11
+		serverHash=$(echo "$server" | sha1sum - | awk '{print $1}')
9 12
 
10 13
 		username=$(echo "$in" | jq --raw-output ".Username")
11 14
 		password=$(echo "$in" | jq --raw-output ".Secret")
12
-		echo "{ \"Username\": \"${username}\", \"Secret\": \"${password}\" }" > $TEMP/$server
15
+		echo "{ \"Username\": \"${username}\", \"Secret\": \"${password}\" }" > $TEMP/$serverHash
16
+		# add the server to the list file
17
+		if [[ ! -f $TEMP/$listFile ]]; then
18
+			echo "{ \"${server}\": \"${username}\" }" > $TEMP/$listFile
19
+		else
20
+			list=$(<$TEMP/$listFile)
21
+			echo "$list" | jq ". + {\"${server}\": \"${username}\"}" > $TEMP/$listFile
22
+		fi
13 23
 		;;
14 24
 	"get")
15 25
 		in=$(</dev/stdin)
16
-		server=$(echo "$in" | sha1sum - | awk '{print $1}')
17
-		if [[ ! -f $TEMP/$server ]]; then
26
+		serverHash=$(echo "$in" | sha1sum - | awk '{print $1}')
27
+		if [[ ! -f $TEMP/$serverHash ]]; then
18 28
 			echo "credentials not found in native keychain"
19 29
 			exit 1
20 30
 		fi
21
-		payload=$(<$TEMP/$server)
31
+		payload=$(<$TEMP/$serverHash)
22 32
 		echo "$payload"
23 33
 		;;
24 34
 	"erase")
25 35
 		in=$(</dev/stdin)
26
-		server=$(echo "$in" | sha1sum - | awk '{print $1}')
27
-		rm -f $TEMP/$server
36
+		serverHash=$(echo "$in" | sha1sum - | awk '{print $1}')
37
+		rm -f $TEMP/$serverHash
38
+
39
+		# Remove the server from the list
40
+		list=$(<$TEMP/$listFile)
41
+		echo "$list" | jq "del(.\"${in}\")" > $TEMP/$listFile
42
+		;;
43
+	"list")
44
+		if [[ ! -f $TEMP/$listFile ]]; then
45
+			echo "{}"
46
+		else
47
+			payload=$(<$TEMP/$listFile)
48
+			echo "$payload"
49
+		fi
28 50
 		;;
29 51
 	*)
30 52
 		echo "unknown credential option"
... ...
@@ -55,11 +55,10 @@ func Get(program ProgramFunc, serverURL string) (*credentials.Credentials, error
55 55
 	return resp, nil
56 56
 }
57 57
 
58
-// Erase executes a program to remove the server credentails from the native store.
58
+// Erase executes a program to remove the server credentials from the native store.
59 59
 func Erase(program ProgramFunc, serverURL string) error {
60 60
 	cmd := program("erase")
61 61
 	cmd.Input(strings.NewReader(serverURL))
62
-
63 62
 	out, err := cmd.Output()
64 63
 	if err != nil {
65 64
 		t := strings.TrimSpace(string(out))
... ...
@@ -68,3 +67,21 @@ func Erase(program ProgramFunc, serverURL string) error {
68 68
 
69 69
 	return nil
70 70
 }
71
+
72
+// List executes a program to list server credentials in the native store.
73
+func List(program ProgramFunc) (map[string]string, error) {
74
+	cmd := program("list")
75
+	cmd.Input(strings.NewReader("unused"))
76
+	out, err := cmd.Output()
77
+	if err != nil {
78
+		t := strings.TrimSpace(string(out))
79
+		return nil, fmt.Errorf("error listing credentials - err: %v, out: `%s`", err, t)
80
+	}
81
+
82
+	var resp map[string]string
83
+	if err = json.NewDecoder(bytes.NewReader(out)).Decode(&resp); err != nil {
84
+		return nil, err
85
+	}
86
+
87
+	return resp, nil
88
+}
... ...
@@ -25,7 +25,7 @@ type Credentials struct {
25 25
 func Serve(helper Helper) {
26 26
 	var err error
27 27
 	if len(os.Args) != 2 {
28
-		err = fmt.Errorf("Usage: %s <store|get|erase>", os.Args[0])
28
+		err = fmt.Errorf("Usage: %s <store|get|erase|list>", os.Args[0])
29 29
 	}
30 30
 
31 31
 	if err == nil {
... ...
@@ -47,6 +47,8 @@ func HandleCommand(helper Helper, key string, in io.Reader, out io.Writer) error
47 47
 		return Get(helper, in, out)
48 48
 	case "erase":
49 49
 		return Erase(helper, in)
50
+	case "list":
51
+		return List(helper, out)
50 52
 	}
51 53
 	return fmt.Errorf("Unknown credential action `%s`", key)
52 54
 }
... ...
@@ -127,3 +129,13 @@ func Erase(helper Helper, reader io.Reader) error {
127 127
 
128 128
 	return helper.Delete(serverURL)
129 129
 }
130
+
131
+//List returns all the serverURLs of keys in
132
+//the OS store as a list of strings
133
+func List(helper Helper, writer io.Writer) error {
134
+	accts, err := helper.List()
135
+	if err != nil {
136
+		return err
137
+	}
138
+	return json.NewEncoder(writer).Encode(accts)
139
+}
... ...
@@ -9,4 +9,6 @@ type Helper interface {
9 9
 	// Get retrieves credentials from the store.
10 10
 	// It returns username and secret as strings.
11 11
 	Get(serverURL string) (string, string, error)
12
+	// List returns the stored serverURLs and their associated usernames.
13
+	List() (map[string]string, error)
12 14
 }