@@ -4,12 +4,18 @@ import (
4
4
"os"
5
5
"testing"
6
6
7
+ "crypto/x509"
8
+
7
9
"github.com/docker/cli/cli/config/configfile"
8
10
"github.com/docker/cli/cli/flags"
11
+ "github.com/docker/cli/internal/test/testutil"
9
12
"github.com/docker/docker/api"
13
+ "github.com/docker/docker/api/types"
10
14
"github.com/docker/docker/client"
15
+ "github.com/pkg/errors"
11
16
"github.com/stretchr/testify/assert"
12
17
"github.com/stretchr/testify/require"
18
+ "golang.org/x/net/context"
13
19
)
14
20
15
21
func TestNewAPIClientFromFlags (t * testing.T ) {
@@ -43,7 +49,7 @@ func TestNewAPIClientFromFlagsWithAPIVersionFromEnv(t *testing.T) {
43
49
assert .Equal (t , customVersion , apiclient .ClientVersion ())
44
50
}
45
51
46
- // TODO: move to gotestyourself
52
+ // TODO: use gotestyourself/env.Patch
47
53
func patchEnvVariable (t * testing.T , key , value string ) func () {
48
54
oldValue , ok := os .LookupEnv (key )
49
55
require .NoError (t , os .Setenv (key , value ))
@@ -55,3 +61,138 @@ func patchEnvVariable(t *testing.T, key, value string) func() {
55
61
require .NoError (t , os .Setenv (key , oldValue ))
56
62
}
57
63
}
64
+
65
+ type fakeClient struct {
66
+ client.Client
67
+ pingFunc func () (types.Ping , error )
68
+ version string
69
+ negotiated bool
70
+ }
71
+
72
+ func (c * fakeClient ) Ping (_ context.Context ) (types.Ping , error ) {
73
+ return c .pingFunc ()
74
+ }
75
+
76
+ func (c * fakeClient ) ClientVersion () string {
77
+ return c .version
78
+ }
79
+
80
+ func (c * fakeClient ) NegotiateAPIVersionPing (types.Ping ) {
81
+ c .negotiated = true
82
+ }
83
+
84
+ func TestInitializeFromClient (t * testing.T ) {
85
+ defaultVersion := "v1.55"
86
+
87
+ var testcases = []struct {
88
+ doc string
89
+ pingFunc func () (types.Ping , error )
90
+ expectedServer ServerInfo
91
+ negotiated bool
92
+ }{
93
+ {
94
+ doc : "successful ping" ,
95
+ pingFunc : func () (types.Ping , error ) {
96
+ return types.Ping {Experimental : true , OSType : "linux" , APIVersion : "v1.30" }, nil
97
+ },
98
+ expectedServer : ServerInfo {HasExperimental : true , OSType : "linux" },
99
+ negotiated : true ,
100
+ },
101
+ {
102
+ doc : "failed ping, no API version" ,
103
+ pingFunc : func () (types.Ping , error ) {
104
+ return types.Ping {}, errors .New ("failed" )
105
+ },
106
+ expectedServer : ServerInfo {HasExperimental : true },
107
+ },
108
+ {
109
+ doc : "failed ping, with API version" ,
110
+ pingFunc : func () (types.Ping , error ) {
111
+ return types.Ping {APIVersion : "v1.33" }, errors .New ("failed" )
112
+ },
113
+ expectedServer : ServerInfo {HasExperimental : true },
114
+ negotiated : true ,
115
+ },
116
+ }
117
+
118
+ for _ , testcase := range testcases {
119
+ t .Run (testcase .doc , func (t * testing.T ) {
120
+ apiclient := & fakeClient {
121
+ pingFunc : testcase .pingFunc ,
122
+ version : defaultVersion ,
123
+ }
124
+
125
+ cli := & DockerCli {client : apiclient }
126
+ cli .initializeFromClient ()
127
+ assert .Equal (t , defaultVersion , cli .defaultVersion )
128
+ assert .Equal (t , testcase .expectedServer , cli .server )
129
+ assert .Equal (t , testcase .negotiated , apiclient .negotiated )
130
+ })
131
+ }
132
+ }
133
+
134
+ func TestGetClientWithPassword (t * testing.T ) {
135
+ expected := "password"
136
+
137
+ var testcases = []struct {
138
+ doc string
139
+ password string
140
+ retrieverErr error
141
+ retrieverGiveup bool
142
+ newClientErr error
143
+ expectedErr string
144
+ }{
145
+ {
146
+ doc : "successful connect" ,
147
+ password : expected ,
148
+ },
149
+ {
150
+ doc : "password retriever exhausted" ,
151
+ retrieverGiveup : true ,
152
+ retrieverErr : errors .New ("failed" ),
153
+ expectedErr : "private key is encrypted, but could not get passphrase" ,
154
+ },
155
+ {
156
+ doc : "password retriever error" ,
157
+ retrieverErr : errors .New ("failed" ),
158
+ expectedErr : "failed" ,
159
+ },
160
+ {
161
+ doc : "newClient error" ,
162
+ newClientErr : errors .New ("failed to connect" ),
163
+ expectedErr : "failed to connect" ,
164
+ },
165
+ }
166
+
167
+ for _ , testcase := range testcases {
168
+ t .Run (testcase .doc , func (t * testing.T ) {
169
+ passRetriever := func (_ , _ string , _ bool , attempts int ) (passphrase string , giveup bool , err error ) {
170
+ // Always return an invalid pass first to test iteration
171
+ switch attempts {
172
+ case 0 :
173
+ return "something else" , false , nil
174
+ default :
175
+ return testcase .password , testcase .retrieverGiveup , testcase .retrieverErr
176
+ }
177
+ }
178
+
179
+ newClient := func (currentPassword string ) (client.APIClient , error ) {
180
+ if testcase .newClientErr != nil {
181
+ return nil , testcase .newClientErr
182
+ }
183
+ if currentPassword == expected {
184
+ return & client.Client {}, nil
185
+ }
186
+ return & client.Client {}, x509 .IncorrectPasswordError
187
+ }
188
+
189
+ _ , err := getClientWithPassword (passRetriever , newClient )
190
+ if testcase .expectedErr != "" {
191
+ testutil .ErrorContains (t , err , testcase .expectedErr )
192
+ return
193
+ }
194
+
195
+ assert .NoError (t , err )
196
+ })
197
+ }
198
+ }
0 commit comments