github.com/mook-as/cf-cli@v7.0.0-beta.28.0.20200120190804-b91c115fae48+incompatible/cf/configuration/coreconfig/config_repository_test.go (about) 1 package coreconfig_test 2 3 import ( 4 "io/ioutil" 5 "os" 6 "path/filepath" 7 8 "code.cloudfoundry.org/cli/cf/configuration" 9 "code.cloudfoundry.org/cli/cf/configuration/configurationfakes" 10 "code.cloudfoundry.org/cli/cf/configuration/coreconfig" 11 "code.cloudfoundry.org/cli/cf/models" 12 "code.cloudfoundry.org/cli/version" 13 "github.com/blang/semver" 14 15 . "github.com/onsi/ginkgo" 16 . "github.com/onsi/gomega" 17 ) 18 19 var _ = Describe("Configuration Repository", func() { 20 21 const ( 22 AccessTokenForClientUsers = "bearer eyJhbGciOiJSUzI1NiIsImtpZCI6ImtleS0xIiwidHlwIjoiSldUIn0.eyJqdGkiOiI5MTExMzczOTRjYTg0NzQzOGUxZjQyOWY4OTQ2ZGZmMyIsInN1YiI6InBvdGF0by1mYWNlIiwiYXV0aG9yaXRpZXMiOlsicm91dGluZy5yb3V0ZXJfZ3JvdXBzLnJlYWQiLCJjbG91ZF9jb250cm9sbGVyLnJlYWQiLCJwYXNzd29yZC53cml0ZSIsImNsb3VkX2NvbnRyb2xsZXIud3JpdGUiLCJvcGVuaWQiLCJuZXR3b3JrLmFkbWluIiwicm91dGluZy5yb3V0ZXJfZ3JvdXBzLndyaXRlIiwiZG9wcGxlci5maXJlaG9zZSIsInNjaW0ud3JpdGUiLCJzY2ltLnJlYWQiLCJjbG91ZF9jb250cm9sbGVyLmFkbWluIiwidWFhLnVzZXIiXSwic2NvcGUiOlsicm91dGluZy5yb3V0ZXJfZ3JvdXBzLnJlYWQiLCJjbG91ZF9jb250cm9sbGVyLnJlYWQiLCJwYXNzd29yZC53cml0ZSIsImNsb3VkX2NvbnRyb2xsZXIud3JpdGUiLCJvcGVuaWQiLCJuZXR3b3JrLmFkbWluIiwicm91dGluZy5yb3V0ZXJfZ3JvdXBzLndyaXRlIiwiZG9wcGxlci5maXJlaG9zZSIsInNjaW0ud3JpdGUiLCJzY2ltLnJlYWQiLCJjbG91ZF9jb250cm9sbGVyLmFkbWluIiwidWFhLnVzZXIiXSwiY2xpZW50X2lkIjoicG90YXRvLWZhY2UiLCJjaWQiOiJwb3RhdG8tZmFjZSIsImF6cCI6InBvdGF0by1mYWNlIiwiZ3JhbnRfdHlwZSI6ImNsaWVudF9jcmVkZW50aWFscyIsInJldl9zaWciOiJkMjU1NjdjYiIsImlhdCI6MTUxNjg0MTY4MCwiZXhwIjoxNTE2ODQxNzQwLCJpc3MiOiJodHRwczovL3VhYS5ib3NoLWxpdGUuY29tL29hdXRoL3Rva2VuIiwiemlkIjoidWFhIiwiYXVkIjpbImNsb3VkX2NvbnRyb2xsZXIiLCJzY2ltIiwicG90YXRvLWZhY2UiLCJwYXNzd29yZCIsInVhYSIsIm9wZW5pZCIsImRvcHBsZXIiLCJyb3V0aW5nLnJvdXRlcl9ncm91cHMiLCJuZXR3b3JrIl19.I2flQSfAhWiCdhyd0414dZ0qmv0W-dPTGvj0pIXnaFPNae7gXSz79MPipTelSxCvdtigX8SoW8O7dWU5zt0O7VRkQX_YYElTHnQeWBfljoFvHhYPRMUv24I3lO6beeujKlYbUxVP5BXoyEdyfiDwzJjoX9lzxriBKdY_BO81oRUjItl7oI1VFhj1A_UwUcDwK2t-c7zDxSmh4P48r77QdqDoAjuweZPUU4PdzRlp99XYdmke52KeG7Xums6hrEJJBSDLbczd_308FAitaQKHgAQH1swLQXqcuD29-eoB4_nTSBwok2H5hoHicHWohSBkMOyFqD4HPb8ta8d_FOi8HA" 23 AccessTokenForHumanUsers = "bearer eyJhbGciOiJSUzI1NiIsImtpZCI6ImxlZ2FjeS10b2tlbi1rZXkiLCJ0eXAiOiJKV1QifQ.eyJqdGkiOiI3YzZkMDA2MjA2OTI0NmViYWI0ZjBmZjY3NGQ3Zjk4OSIsInN1YiI6Ijk1MTliZTNlLTQ0ZDktNDBkMC1hYjlhLWY0YWNlMTFkZjE1OSIsInNjb3BlIjpbIm9wZW5pZCIsInJvdXRpbmcucm91dGVyX2dyb3Vwcy53cml0ZSIsInNjaW0ucmVhZCIsImNsb3VkX2NvbnRyb2xsZXIuYWRtaW4iLCJ1YWEudXNlciIsInJvdXRpbmcucm91dGVyX2dyb3Vwcy5yZWFkIiwiY2xvdWRfY29udHJvbGxlci5yZWFkIiwicGFzc3dvcmQud3JpdGUiLCJjbG91ZF9jb250cm9sbGVyLndyaXRlIiwiZG9wcGxlci5maXJlaG9zZSIsInNjaW0ud3JpdGUiXSwiY2xpZW50X2lkIjoiY2YiLCJjaWQiOiJjZiIsImF6cCI6ImNmIiwiZ3JhbnRfdHlwZSI6InBhc3N3b3JkIiwidXNlcl9pZCI6Ijk1MTliZTNlLTQ0ZDktNDBkMC1hYjlhLWY0YWNlMTFkZjE1OSIsIm9yaWdpbiI6InVhYSIsInVzZXJfbmFtZSI6ImFkbWluIiwiZW1haWwiOiJhZG1pbiIsImF1dGhfdGltZSI6MTQ3MzI4NDU3NywicmV2X3NpZyI6IjZiMjdkYTZjIiwiaWF0IjoxNDczMjg0NTc3LCJleHAiOjE0NzMyODUxNzcsImlzcyI6Imh0dHBzOi8vdWFhLmJvc2gtbGl0ZS5jb20vb2F1dGgvdG9rZW4iLCJ6aWQiOiJ1YWEiLCJhdWQiOlsiY2YiLCJvcGVuaWQiLCJyb3V0aW5nLnJvdXRlcl9ncm91cHMiLCJzY2ltIiwiY2xvdWRfY29udHJvbGxlciIsInVhYSIsInBhc3N3b3JkIiwiZG9wcGxlciJdfQ.OcH_w9yIKJkEcTZMThIs-qJAHk3G0JwNjG-aomVH9hKye4ciFO6IMQMLKmCBrrAQVc7ST1SZZwq7gv12Dq__6Jp-hai0a2_ADJK-Vc9YXyNZKgYTWIeVNGM1JGdHgFSrBR2Lz7IIrH9HqeN8plrKV5HzU8uI9LL4lyOCjbXJ9cM" 24 InvalidAccessToken = "bearer eyJhbGciOiJSUzI1NiJ9" 25 ) 26 27 var ( 28 config coreconfig.Repository 29 persistor *configurationfakes.FakePersistor 30 ) 31 32 BeforeEach(func() { 33 persistor = new(configurationfakes.FakePersistor) 34 persistor.ExistsReturns(true) 35 config = coreconfig.NewRepositoryFromPersistor(persistor, func(err error) { panic(err) }) 36 }) 37 38 It("is threadsafe", func() { 39 performSaveCh := make(chan struct{}) 40 beginSaveCh := make(chan struct{}) 41 finishSaveCh := make(chan struct{}) 42 finishReadCh := make(chan struct{}) 43 44 persistor.SaveStub = func(configuration.DataInterface) error { 45 close(beginSaveCh) 46 <-performSaveCh 47 close(finishSaveCh) 48 49 return nil 50 } 51 52 go func() { 53 config.SetAPIEndpoint("foo") 54 }() 55 56 <-beginSaveCh 57 58 go func() { 59 config.APIEndpoint() 60 close(finishReadCh) 61 }() 62 63 Consistently(finishSaveCh).ShouldNot(BeClosed()) 64 Consistently(finishReadCh).ShouldNot(BeClosed()) 65 66 performSaveCh <- struct{}{} 67 68 Eventually(finishReadCh).Should(BeClosed()) 69 }) 70 71 It("has acccessor methods for all config fields", func() { 72 config.SetAPIEndpoint("http://api.the-endpoint") 73 Expect(config.APIEndpoint()).To(Equal("http://api.the-endpoint")) 74 75 config.SetAPIVersion("3") 76 Expect(config.APIVersion()).To(Equal("3")) 77 78 config.SetAuthenticationEndpoint("http://auth.the-endpoint") 79 Expect(config.AuthenticationEndpoint()).To(Equal("http://auth.the-endpoint")) 80 81 config.SetUaaEndpoint("http://uaa.the-endpoint") 82 Expect(config.UaaEndpoint()).To(Equal("http://uaa.the-endpoint")) 83 84 config.SetAccessToken("the-token") 85 Expect(config.AccessToken()).To(Equal("the-token")) 86 87 config.SetUAAOAuthClient("cf-oauth-client-id") 88 Expect(config.UAAOAuthClient()).To(Equal("cf-oauth-client-id")) 89 90 config.SetUAAOAuthClientSecret("cf-oauth-client-secret") 91 Expect(config.UAAOAuthClientSecret()).To(Equal("cf-oauth-client-secret")) 92 93 config.SetSSHOAuthClient("oauth-client-id") 94 Expect(config.SSHOAuthClient()).To(Equal("oauth-client-id")) 95 96 config.SetDopplerEndpoint("doppler.the-endpoint") 97 Expect(config.DopplerEndpoint()).To(Equal("doppler.the-endpoint")) 98 99 config.SetRefreshToken("the-token") 100 Expect(config.RefreshToken()).To(Equal("the-token")) 101 102 organization := models.OrganizationFields{Name: "the-org"} 103 config.SetOrganizationFields(organization) 104 Expect(config.OrganizationFields()).To(Equal(organization)) 105 106 space := models.SpaceFields{Name: "the-space"} 107 config.SetSpaceFields(space) 108 Expect(config.SpaceFields()).To(Equal(space)) 109 110 config.SetSSLDisabled(false) 111 Expect(config.IsSSLDisabled()).To(BeFalse()) 112 113 config.SetLocale("en_US") 114 Expect(config.Locale()).To(Equal("en_US")) 115 116 config.SetPluginRepo(models.PluginRepo{Name: "repo", URL: "nowhere.com"}) 117 Expect(config.PluginRepos()[0].Name).To(Equal("repo")) 118 Expect(config.PluginRepos()[0].URL).To(Equal("nowhere.com")) 119 120 s, _ := semver.Make("3.1") 121 Expect(config.IsMinAPIVersion(s)).To(Equal(false)) 122 123 config.SetMinCLIVersion("6.5.0") 124 Expect(config.MinCLIVersion()).To(Equal("6.5.0")) 125 126 config.SetMinRecommendedCLIVersion("6.9.0") 127 Expect(config.MinRecommendedCLIVersion()).To(Equal("6.9.0")) 128 }) 129 130 Describe("APIEndpoint", func() { 131 It("sanitizes the target URL", func() { 132 config.SetAPIEndpoint("http://api.the-endpoint/") 133 Expect(config.APIEndpoint()).To(Equal("http://api.the-endpoint")) 134 }) 135 }) 136 137 Describe("HasAPIEndpoint", func() { 138 Context("when both endpoint and version are set", func() { 139 BeforeEach(func() { 140 config.SetAPIEndpoint("http://example.org") 141 config.SetAPIVersion("42.1.2.3") 142 }) 143 144 It("returns true", func() { 145 Expect(config.HasAPIEndpoint()).To(BeTrue()) 146 }) 147 }) 148 149 Context("when endpoint is not set", func() { 150 BeforeEach(func() { 151 config.SetAPIVersion("42.1.2.3") 152 }) 153 154 It("returns false", func() { 155 Expect(config.HasAPIEndpoint()).To(BeFalse()) 156 }) 157 }) 158 159 Context("when version is not set", func() { 160 BeforeEach(func() { 161 config.SetAPIEndpoint("http://example.org") 162 }) 163 164 It("returns false", func() { 165 Expect(config.HasAPIEndpoint()).To(BeFalse()) 166 }) 167 }) 168 }) 169 170 Describe("UserGUID", func() { 171 Context("with a valid user access token", func() { 172 BeforeEach(func() { 173 config.SetAccessToken(AccessTokenForHumanUsers) 174 }) 175 176 It("returns the guid", func() { 177 Expect(config.UserGUID()).To(Equal("9519be3e-44d9-40d0-ab9a-f4ace11df159")) 178 }) 179 }) 180 181 Context("with a valid client access token", func() { 182 BeforeEach(func() { 183 config.SetAccessToken(AccessTokenForClientUsers) 184 }) 185 186 It("returns an empty string", func() { 187 Expect(config.UserGUID()).To(BeEmpty()) 188 }) 189 }) 190 191 Context("with an invalid access token", func() { 192 BeforeEach(func() { 193 config.SetAccessToken(InvalidAccessToken) 194 }) 195 196 It("returns an empty string", func() { 197 Expect(config.UserGUID()).To(BeEmpty()) 198 }) 199 }) 200 201 Context("with an empty access token", func() { 202 BeforeEach(func() { 203 config.SetAccessToken("") 204 }) 205 206 It("returns an empty string", func() { 207 Expect(config.UserGUID()).To(BeEmpty()) 208 }) 209 }) 210 211 }) 212 213 Describe("Username", func() { 214 Context("with a valid user access token", func() { 215 BeforeEach(func() { 216 config.SetAccessToken(AccessTokenForHumanUsers) 217 }) 218 219 It("returns the username", func() { 220 Expect(config.Username()).To(Equal("admin")) 221 }) 222 }) 223 224 Context("with a valid client access token", func() { 225 BeforeEach(func() { 226 config.SetAccessToken(AccessTokenForClientUsers) 227 }) 228 229 It("returns the client id", func() { 230 Expect(config.Username()).To(Equal("potato-face")) 231 }) 232 }) 233 234 Context("with an invalid access token", func() { 235 BeforeEach(func() { 236 config.SetAccessToken(InvalidAccessToken) 237 }) 238 239 It("returns an empty string", func() { 240 Expect(config.Username()).To(BeEmpty()) 241 }) 242 }) 243 244 Context("with an empty access token", func() { 245 BeforeEach(func() { 246 config.SetAccessToken("") 247 }) 248 249 It("returns an empty string", func() { 250 Expect(config.Username()).To(BeEmpty()) 251 }) 252 }) 253 }) 254 255 Describe("UserEmail", func() { 256 Context("with a valid user access token", func() { 257 BeforeEach(func() { 258 config.SetAccessToken(AccessTokenForHumanUsers) 259 }) 260 261 It("returns the email", func() { 262 Expect(config.UserEmail()).To(Equal("admin")) 263 }) 264 }) 265 266 Context("with a valid client access token", func() { 267 BeforeEach(func() { 268 config.SetAccessToken(AccessTokenForClientUsers) 269 }) 270 271 It("returns an empty string", func() { 272 Expect(config.UserEmail()).To(BeEmpty()) 273 }) 274 }) 275 276 Context("with an invalid access token", func() { 277 BeforeEach(func() { 278 config.SetAccessToken(InvalidAccessToken) 279 }) 280 281 It("returns an empty string", func() { 282 Expect(config.UserEmail()).To(BeEmpty()) 283 }) 284 }) 285 286 Context("with an empty access token", func() { 287 BeforeEach(func() { 288 config.SetAccessToken("") 289 }) 290 291 It("returns an empty string", func() { 292 Expect(config.UserEmail()).To(BeEmpty()) 293 }) 294 }) 295 }) 296 297 Describe("NewRepositoryFromFilepath", func() { 298 var configPath string 299 300 It("returns nil repository if no error handler provided", func() { 301 config = coreconfig.NewRepositoryFromFilepath(configPath, nil) 302 Expect(config).To(BeNil()) 303 }) 304 305 Context("when the configuration file doesn't exist", func() { 306 var tmpDir string 307 308 BeforeEach(func() { 309 var err error 310 tmpDir, err = ioutil.TempDir("", "test-config") 311 if err != nil { 312 Fail("Couldn't create tmp file") 313 } 314 315 configPath = filepath.Join(tmpDir, ".cf", "config.json") 316 }) 317 318 AfterEach(func() { 319 Expect(os.RemoveAll(tmpDir)).ToNot(HaveOccurred()) 320 }) 321 322 It("has sane defaults when there is no config to read", func() { 323 config = coreconfig.NewRepositoryFromFilepath(configPath, func(err error) { 324 panic(err) 325 }) 326 327 Expect(config.APIEndpoint()).To(Equal("")) 328 Expect(config.APIVersion()).To(Equal("")) 329 Expect(config.AuthenticationEndpoint()).To(Equal("")) 330 Expect(config.AccessToken()).To(Equal("")) 331 }) 332 }) 333 334 Context("when the configuration version is older than the current version", func() { 335 BeforeEach(func() { 336 cwd, err := os.Getwd() 337 Expect(err).NotTo(HaveOccurred()) 338 configPath = filepath.Join(cwd, "..", "..", "..", "fixtures", "config", "outdated-config", ".cf", "config.json") 339 }) 340 341 It("returns a new empty config", func() { 342 config = coreconfig.NewRepositoryFromFilepath(configPath, func(err error) { 343 panic(err) 344 }) 345 346 Expect(config.APIEndpoint()).To(Equal("")) 347 }) 348 }) 349 }) 350 351 Describe("IsMinCLIVersion", func() { 352 It("returns true when the actual version is the default version string", func() { 353 Expect(config.IsMinCLIVersion(version.DefaultVersion)).To(BeTrue()) 354 }) 355 356 It("returns true when the MinCLIVersion is empty", func() { 357 config.SetMinCLIVersion("") 358 Expect(config.IsMinCLIVersion("1.2.3")).To(BeTrue()) 359 }) 360 361 It("returns false when the actual version is less than the MinCLIVersion", func() { 362 actualVersion := "1.2.3+abc123" 363 minCLIVersion := "1.2.4" 364 config.SetMinCLIVersion(minCLIVersion) 365 Expect(config.IsMinCLIVersion(actualVersion)).To(BeFalse()) 366 }) 367 368 It("returns true when the actual version is equal to the MinCLIVersion", func() { 369 actualVersion := "1.2.3+abc123" 370 minCLIVersion := "1.2.3" 371 config.SetMinCLIVersion(minCLIVersion) 372 Expect(config.IsMinCLIVersion(actualVersion)).To(BeTrue()) 373 }) 374 375 It("returns true when the actual version is greater than the MinCLIVersion", func() { 376 actualVersion := "1.2.3+abc123" 377 minCLIVersion := "1.2.2" 378 config.SetMinCLIVersion(minCLIVersion) 379 Expect(config.IsMinCLIVersion(actualVersion)).To(BeTrue()) 380 }) 381 }) 382 })