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  })