github.com/mook-as/cf-cli@v7.0.0-beta.28.0.20200120190804-b91c115fae48+incompatible/cf/configuration/coreconfig/config_repository.go (about) 1 package coreconfig 2 3 import ( 4 "strings" 5 "sync" 6 7 "code.cloudfoundry.org/cli/cf/configuration" 8 "code.cloudfoundry.org/cli/cf/models" 9 "code.cloudfoundry.org/cli/version" 10 "github.com/blang/semver" 11 ) 12 13 type ConfigRepository struct { 14 CFCLIVersion string 15 data *Data 16 mutex *sync.RWMutex 17 initOnce *sync.Once 18 persistor configuration.Persistor 19 onError func(error) 20 } 21 22 type CCInfo struct { 23 APIVersion string `json:"api_version"` 24 AuthorizationEndpoint string `json:"authorization_endpoint"` 25 DopplerEndpoint string `json:"doppler_logging_endpoint"` 26 MinCLIVersion string `json:"min_cli_version"` 27 MinRecommendedCLIVersion string `json:"min_recommended_cli_version"` 28 SSHOAuthClient string `json:"app_ssh_oauth_client"` 29 RoutingAPIEndpoint string `json:"routing_endpoint"` 30 } 31 32 func NewRepositoryFromFilepath(filepath string, errorHandler func(error)) Repository { 33 if errorHandler == nil { 34 return nil 35 } 36 return NewRepositoryFromPersistor(configuration.NewDiskPersistor(filepath), errorHandler) 37 } 38 39 func NewRepositoryFromPersistor(persistor configuration.Persistor, errorHandler func(error)) Repository { 40 data := NewData() 41 if !persistor.Exists() { 42 //set default plugin repo 43 data.PluginRepos = append(data.PluginRepos, models.PluginRepo{ 44 Name: "CF-Community", 45 URL: "https://plugins.cloudfoundry.org", 46 }) 47 } 48 49 return &ConfigRepository{ 50 data: data, 51 mutex: new(sync.RWMutex), 52 initOnce: new(sync.Once), 53 persistor: persistor, 54 onError: errorHandler, 55 } 56 } 57 58 type Reader interface { 59 APIEndpoint() string 60 APIVersion() string 61 HasAPIEndpoint() bool 62 63 AuthenticationEndpoint() string 64 DopplerEndpoint() string 65 UaaEndpoint() string 66 RoutingAPIEndpoint() string 67 AccessToken() string 68 UAAOAuthClient() string 69 UAAOAuthClientSecret() string 70 SSHOAuthClient() string 71 RefreshToken() string 72 73 OrganizationFields() models.OrganizationFields 74 HasOrganization() bool 75 76 SpaceFields() models.SpaceFields 77 HasSpace() bool 78 79 Username() string 80 UserGUID() string 81 UserEmail() string 82 IsLoggedIn() bool 83 IsSSLDisabled() bool 84 IsMinAPIVersion(semver.Version) bool 85 IsMinCLIVersion(string) bool 86 MinCLIVersion() string 87 MinRecommendedCLIVersion() string 88 CLIVersion() string 89 90 AsyncTimeout() uint 91 Trace() string 92 93 ColorEnabled() string 94 95 Locale() string 96 97 PluginRepos() []models.PluginRepo 98 } 99 100 //go:generate counterfeiter . ReadWriter 101 102 type ReadWriter interface { 103 Reader 104 ClearSession() 105 SetAccessToken(string) 106 SetAPIEndpoint(string) 107 SetAPIVersion(string) 108 SetAsyncTimeout(uint) 109 SetAuthenticationEndpoint(string) 110 SetCLIVersion(string) 111 SetColorEnabled(string) 112 SetDopplerEndpoint(string) 113 SetLocale(string) 114 SetMinCLIVersion(string) 115 SetMinRecommendedCLIVersion(string) 116 SetOrganizationFields(models.OrganizationFields) 117 SetPluginRepo(models.PluginRepo) 118 SetRefreshToken(string) 119 SetRoutingAPIEndpoint(string) 120 SetSpaceFields(models.SpaceFields) 121 SetSSHOAuthClient(string) 122 SetSSLDisabled(bool) 123 SetTrace(string) 124 SetUaaEndpoint(string) 125 SetUAAGrantType(string) 126 SetUAAOAuthClient(string) 127 SetUAAOAuthClientSecret(string) 128 UAAGrantType() string 129 UnSetPluginRepo(int) 130 } 131 132 //go:generate counterfeiter . Repository 133 134 type Repository interface { 135 ReadWriter 136 Close() 137 } 138 139 // ACCESS CONTROL 140 141 func (c *ConfigRepository) init() { 142 c.initOnce.Do(func() { 143 err := c.persistor.Load(c.data) 144 if err != nil { 145 c.onError(err) 146 } 147 }) 148 } 149 150 func (c *ConfigRepository) read(cb func()) { 151 c.mutex.RLock() 152 defer c.mutex.RUnlock() 153 c.init() 154 155 cb() 156 } 157 158 func (c *ConfigRepository) write(cb func()) { 159 c.mutex.Lock() 160 defer c.mutex.Unlock() 161 c.init() 162 163 cb() 164 165 err := c.persistor.Save(c.data) 166 if err != nil { 167 c.onError(err) 168 } 169 } 170 171 // CLOSERS 172 173 func (c *ConfigRepository) Close() { 174 c.read(func() { 175 // perform a read to ensure write lock has been cleared 176 }) 177 } 178 179 // GETTERS 180 181 func (c *ConfigRepository) APIVersion() (apiVersion string) { 182 c.read(func() { 183 apiVersion = c.data.APIVersion 184 }) 185 return 186 } 187 188 func (c *ConfigRepository) AuthenticationEndpoint() (authEndpoint string) { 189 c.read(func() { 190 authEndpoint = c.data.AuthorizationEndpoint 191 }) 192 return 193 } 194 195 func (c *ConfigRepository) DopplerEndpoint() (dopplerEndpoint string) { 196 c.read(func() { 197 dopplerEndpoint = c.data.DopplerEndPoint 198 }) 199 200 return 201 } 202 203 func (c *ConfigRepository) UaaEndpoint() (uaaEndpoint string) { 204 c.read(func() { 205 uaaEndpoint = c.data.UaaEndpoint 206 }) 207 return 208 } 209 210 func (c *ConfigRepository) RoutingAPIEndpoint() (routingAPIEndpoint string) { 211 c.read(func() { 212 routingAPIEndpoint = c.data.RoutingAPIEndpoint 213 }) 214 return 215 } 216 217 func (c *ConfigRepository) APIEndpoint() string { 218 var apiEndpoint string 219 c.read(func() { 220 apiEndpoint = c.data.Target 221 }) 222 apiEndpoint = strings.TrimRight(apiEndpoint, "/") 223 224 return apiEndpoint 225 } 226 227 func (c *ConfigRepository) HasAPIEndpoint() (hasEndpoint bool) { 228 c.read(func() { 229 hasEndpoint = c.data.APIVersion != "" && c.data.Target != "" 230 }) 231 return 232 } 233 234 func (c *ConfigRepository) AccessToken() (accessToken string) { 235 c.read(func() { 236 accessToken = c.data.AccessToken 237 }) 238 return 239 } 240 241 func (c *ConfigRepository) UAAOAuthClient() (clientID string) { 242 c.read(func() { 243 clientID = c.data.UAAOAuthClient 244 }) 245 return 246 } 247 248 func (c *ConfigRepository) UAAOAuthClientSecret() (clientID string) { 249 c.read(func() { 250 clientID = c.data.UAAOAuthClientSecret 251 }) 252 return 253 } 254 255 func (c *ConfigRepository) SSHOAuthClient() (clientID string) { 256 c.read(func() { 257 clientID = c.data.SSHOAuthClient 258 }) 259 return 260 } 261 262 func (c *ConfigRepository) RefreshToken() (refreshToken string) { 263 c.read(func() { 264 refreshToken = c.data.RefreshToken 265 }) 266 return 267 } 268 269 func (c *ConfigRepository) OrganizationFields() (org models.OrganizationFields) { 270 c.read(func() { 271 org = c.data.OrganizationFields 272 }) 273 return 274 } 275 276 func (c *ConfigRepository) SpaceFields() (space models.SpaceFields) { 277 c.read(func() { 278 space = c.data.SpaceFields 279 }) 280 return 281 } 282 283 func (c *ConfigRepository) UserEmail() (email string) { 284 c.read(func() { 285 email = NewTokenInfo(c.data.AccessToken).Email 286 }) 287 return 288 } 289 290 func (c *ConfigRepository) UserGUID() (guid string) { 291 c.read(func() { 292 guid = NewTokenInfo(c.data.AccessToken).UserGUID 293 }) 294 return 295 } 296 297 func (c *ConfigRepository) Username() (name string) { 298 c.read(func() { 299 t := NewTokenInfo(c.data.AccessToken) 300 if t.Username != "" { 301 name = t.Username 302 } else { 303 name = t.ClientID 304 } 305 }) 306 return 307 } 308 309 func (c *ConfigRepository) IsLoggedIn() (loggedIn bool) { 310 c.read(func() { 311 loggedIn = c.data.AccessToken != "" 312 }) 313 return 314 } 315 316 func (c *ConfigRepository) HasOrganization() (hasOrg bool) { 317 c.read(func() { 318 hasOrg = c.data.OrganizationFields.GUID != "" && c.data.OrganizationFields.Name != "" 319 }) 320 return 321 } 322 323 func (c *ConfigRepository) HasSpace() (hasSpace bool) { 324 c.read(func() { 325 hasSpace = c.data.SpaceFields.GUID != "" && c.data.SpaceFields.Name != "" 326 }) 327 return 328 } 329 330 func (c *ConfigRepository) IsSSLDisabled() (isSSLDisabled bool) { 331 c.read(func() { 332 isSSLDisabled = c.data.SSLDisabled 333 }) 334 return 335 } 336 337 // SetCLIVersion should only be used in testing 338 func (c *ConfigRepository) SetCLIVersion(v string) { 339 c.CFCLIVersion = v 340 } 341 342 func (c *ConfigRepository) CLIVersion() string { 343 if c.CFCLIVersion == "" { 344 return version.VersionString() 345 } else { 346 return c.CFCLIVersion 347 } 348 } 349 350 func (c *ConfigRepository) IsMinAPIVersion(requiredVersion semver.Version) bool { 351 var apiVersion string 352 c.read(func() { 353 apiVersion = c.data.APIVersion 354 }) 355 356 actualVersion, err := semver.Make(apiVersion) 357 if err != nil { 358 return false 359 } 360 return actualVersion.GTE(requiredVersion) 361 } 362 363 func (c *ConfigRepository) IsMinCLIVersion(checkVersion string) bool { 364 if checkVersion == version.DefaultVersion { 365 return true 366 } 367 var minCLIVersion string 368 c.read(func() { 369 minCLIVersion = c.data.MinCLIVersion 370 }) 371 if minCLIVersion == "" { 372 return true 373 } 374 375 actualVersion, err := semver.Make(checkVersion) 376 if err != nil { 377 return false 378 } 379 requiredVersion, err := semver.Make(minCLIVersion) 380 if err != nil { 381 return false 382 } 383 return actualVersion.GTE(requiredVersion) 384 } 385 386 func (c *ConfigRepository) MinCLIVersion() (minCLIVersion string) { 387 c.read(func() { 388 minCLIVersion = c.data.MinCLIVersion 389 }) 390 return 391 } 392 393 func (c *ConfigRepository) MinRecommendedCLIVersion() (minRecommendedCLIVersion string) { 394 c.read(func() { 395 minRecommendedCLIVersion = c.data.MinRecommendedCLIVersion 396 }) 397 return 398 } 399 400 func (c *ConfigRepository) AsyncTimeout() (timeout uint) { 401 c.read(func() { 402 timeout = c.data.AsyncTimeout 403 }) 404 return 405 } 406 407 func (c *ConfigRepository) Trace() (trace string) { 408 c.read(func() { 409 trace = c.data.Trace 410 }) 411 return 412 } 413 414 func (c *ConfigRepository) ColorEnabled() (enabled string) { 415 c.read(func() { 416 enabled = c.data.ColorEnabled 417 }) 418 return 419 } 420 421 func (c *ConfigRepository) Locale() (locale string) { 422 c.read(func() { 423 locale = c.data.Locale 424 }) 425 return 426 } 427 428 func (c *ConfigRepository) PluginRepos() (repos []models.PluginRepo) { 429 c.read(func() { 430 repos = c.data.PluginRepos 431 }) 432 return 433 } 434 435 // SETTERS 436 437 func (c *ConfigRepository) ClearSession() { 438 c.write(func() { 439 c.data.AccessToken = "" 440 c.data.RefreshToken = "" 441 c.data.OrganizationFields = models.OrganizationFields{} 442 c.data.SpaceFields = models.SpaceFields{} 443 }) 444 } 445 446 func (c *ConfigRepository) SetAPIEndpoint(endpoint string) { 447 c.write(func() { 448 c.data.Target = endpoint 449 }) 450 } 451 452 func (c *ConfigRepository) SetAPIVersion(version string) { 453 c.write(func() { 454 c.data.APIVersion = version 455 }) 456 } 457 458 func (c *ConfigRepository) SetMinCLIVersion(version string) { 459 c.write(func() { 460 c.data.MinCLIVersion = version 461 }) 462 } 463 464 func (c *ConfigRepository) SetMinRecommendedCLIVersion(version string) { 465 c.write(func() { 466 c.data.MinRecommendedCLIVersion = version 467 }) 468 } 469 470 func (c *ConfigRepository) SetAuthenticationEndpoint(endpoint string) { 471 c.write(func() { 472 c.data.AuthorizationEndpoint = endpoint 473 }) 474 } 475 476 func (c *ConfigRepository) SetDopplerEndpoint(endpoint string) { 477 c.write(func() { 478 c.data.DopplerEndPoint = endpoint 479 }) 480 } 481 482 func (c *ConfigRepository) SetUaaEndpoint(uaaEndpoint string) { 483 c.write(func() { 484 c.data.UaaEndpoint = uaaEndpoint 485 }) 486 } 487 488 func (c *ConfigRepository) SetRoutingAPIEndpoint(routingAPIEndpoint string) { 489 c.write(func() { 490 c.data.RoutingAPIEndpoint = routingAPIEndpoint 491 }) 492 } 493 494 func (c *ConfigRepository) SetAccessToken(token string) { 495 c.write(func() { 496 c.data.AccessToken = token 497 }) 498 } 499 500 func (c *ConfigRepository) SetUAAOAuthClient(clientID string) { 501 c.write(func() { 502 c.data.UAAOAuthClient = clientID 503 }) 504 } 505 506 func (c *ConfigRepository) SetUAAOAuthClientSecret(clientID string) { 507 c.write(func() { 508 c.data.UAAOAuthClientSecret = clientID 509 }) 510 } 511 512 func (c *ConfigRepository) SetSSHOAuthClient(clientID string) { 513 c.write(func() { 514 c.data.SSHOAuthClient = clientID 515 }) 516 } 517 518 func (c *ConfigRepository) SetRefreshToken(token string) { 519 c.write(func() { 520 c.data.RefreshToken = token 521 }) 522 } 523 524 func (c *ConfigRepository) SetOrganizationFields(org models.OrganizationFields) { 525 c.write(func() { 526 c.data.OrganizationFields = org 527 }) 528 } 529 530 func (c *ConfigRepository) SetSpaceFields(space models.SpaceFields) { 531 c.write(func() { 532 c.data.SpaceFields = space 533 }) 534 } 535 536 func (c *ConfigRepository) SetSSLDisabled(disabled bool) { 537 c.write(func() { 538 c.data.SSLDisabled = disabled 539 }) 540 } 541 542 func (c *ConfigRepository) SetAsyncTimeout(timeout uint) { 543 c.write(func() { 544 c.data.AsyncTimeout = timeout 545 }) 546 } 547 548 func (c *ConfigRepository) SetTrace(value string) { 549 c.write(func() { 550 c.data.Trace = value 551 }) 552 } 553 554 func (c *ConfigRepository) SetColorEnabled(enabled string) { 555 c.write(func() { 556 c.data.ColorEnabled = enabled 557 }) 558 } 559 560 func (c *ConfigRepository) SetLocale(locale string) { 561 c.write(func() { 562 c.data.Locale = locale 563 }) 564 } 565 566 func (c *ConfigRepository) SetPluginRepo(repo models.PluginRepo) { 567 c.write(func() { 568 c.data.PluginRepos = append(c.data.PluginRepos, repo) 569 }) 570 } 571 572 func (c *ConfigRepository) UnSetPluginRepo(index int) { 573 c.write(func() { 574 c.data.PluginRepos = append(c.data.PluginRepos[:index], c.data.PluginRepos[index+1:]...) 575 }) 576 } 577 578 func (c *ConfigRepository) UAAGrantType() string { 579 grantType := "" 580 c.read(func() { 581 grantType = c.data.UAAGrantType 582 }) 583 return grantType 584 } 585 586 func (c *ConfigRepository) SetUAAGrantType(grantType string) { 587 c.write(func() { 588 c.data.UAAGrantType = grantType 589 }) 590 }