func describeConfigDriveMetadataService() { var ( metadataService MetadataService resolver *fakeinf.FakeDNSResolver platform *fakeplatform.FakePlatform logger boshlog.Logger ) updateMetadata := func(metadataContents MetadataContentsType) { metadataJSON, err := json.Marshal(metadataContents) Expect(err).ToNot(HaveOccurred()) platform.SetGetFilesContentsFromDisk("/fake-disk-path-1/fake-metadata-path", metadataJSON, nil) Expect(metadataService.IsAvailable()).To(BeTrue()) } updateUserdata := func(userdataContents string) { platform.SetGetFilesContentsFromDisk("/fake-disk-path-1/fake-userdata-path", []byte(userdataContents), nil) Expect(metadataService.IsAvailable()).To(BeTrue()) } BeforeEach(func() { resolver = &fakeinf.FakeDNSResolver{} platform = fakeplatform.NewFakePlatform() logger = boshlog.NewLogger(boshlog.LevelNone) diskPaths := []string{ "/fake-disk-path-1", "/fake-disk-path-2", } metadataService = NewConfigDriveMetadataService( resolver, platform, diskPaths, "fake-metadata-path", "fake-userdata-path", logger, ) userdataContents := fmt.Sprintf(`{"server":{"name":"fake-server-name"},"registry":{"endpoint":"fake-registry-endpoint"}}`) platform.SetGetFilesContentsFromDisk("/fake-disk-path-1/fake-userdata-path", []byte(userdataContents), nil) metadata := MetadataContentsType{ PublicKeys: map[string]PublicKeyType{ "0": PublicKeyType{ "openssh-key": "fake-openssh-key", }, }, InstanceID: "fake-instance-id", } updateMetadata(metadata) }) Describe("GetNetworks", func() { It("returns the network settings", func() { userdataContents := ` { "networks": { "network_1": {"type": "manual", "ip": "1.2.3.4", "netmask": "2.3.4.5", "gateway": "3.4.5.6", "default": ["dns"], "dns": ["8.8.8.8"], "mac": "fake-mac-address-1"}, "network_2": {"type": "dynamic", "default": ["dns"], "dns": ["8.8.8.8"], "mac": "fake-mac-address-2"} } }` updateUserdata(userdataContents) networks, err := metadataService.GetNetworks() Expect(err).ToNot(HaveOccurred()) Expect(networks).To(Equal(boshsettings.Networks{ "network_1": boshsettings.Network{ Type: "manual", IP: "1.2.3.4", Netmask: "2.3.4.5", Gateway: "3.4.5.6", Default: []string{"dns"}, DNS: []string{"8.8.8.8"}, Mac: "fake-mac-address-1", }, "network_2": boshsettings.Network{ Type: "dynamic", Default: []string{"dns"}, DNS: []string{"8.8.8.8"}, Mac: "fake-mac-address-2", }, })) }) It("returns a nil Networks if the settings are missing (from an old CPI version)", func() { userdataContents := `{}` updateUserdata(userdataContents) networks, err := metadataService.GetNetworks() Expect(err).ToNot(HaveOccurred()) Expect(networks).To(BeNil()) }) }) Describe("IsAvailable", func() { It("return true when it can load successfully", func() { Expect(metadataService.IsAvailable()).To(BeTrue()) }) It("returns an error if it fails to read meta-data.json from disk", func() { platform.SetGetFilesContentsFromDisk("/fake-disk-path-1/fake-metadata-path", []byte{}, errors.New("fake-read-disk-error")) Expect(metadataService.IsAvailable()).To(BeFalse()) }) It("tries to load meta-data.json from potential disk locations", func() { platform.SetGetFilesContentsFromDisk("/fake-disk-path-1/fake-metadata-path", []byte{}, errors.New("fake-read-disk-error")) Expect(metadataService.IsAvailable()).To(BeFalse()) Expect(platform.GetFileContentsFromDiskDiskPaths).To(ContainElement("/fake-disk-path-1")) Expect(platform.GetFileContentsFromDiskDiskPaths).To(ContainElement("/fake-disk-path-2")) }) It("returns an error if it fails to parse meta-data.json contents", func() { platform.SetGetFilesContentsFromDisk("/fake-disk-path-1/fake-metadata-path", []byte("broken"), nil) Expect(metadataService.IsAvailable()).To(BeFalse()) }) It("returns an error if it fails to read user_data from disk", func() { platform.SetGetFilesContentsFromDisk("/fake-disk-path-1/fake-userdata-path", []byte{}, errors.New("fake-read-disk-error")) Expect(metadataService.IsAvailable()).To(BeFalse()) }) It("returns an error if it fails to parse user_data contents", func() { platform.SetGetFilesContentsFromDisk("/fake-disk-path-1/fake-userdata-path", []byte("broken"), nil) Expect(metadataService.IsAvailable()).To(BeFalse()) }) Context("when disk paths are not given", func() { It("returns false", func() { metadataService = NewConfigDriveMetadataService( resolver, platform, []string{}, "fake-metadata-path", "fake-userdata-path", logger, ) Expect(metadataService.IsAvailable()).To(BeFalse()) }) }) }) Describe("GetPublicKey", func() { It("returns public key", func() { value, err := metadataService.GetPublicKey() Expect(err).ToNot(HaveOccurred()) Expect(value).To(Equal("fake-openssh-key")) }) It("returns an error if it fails to get ssh key", func() { updateMetadata(MetadataContentsType{}) value, err := metadataService.GetPublicKey() Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("Failed to load openssh-key from config drive metadata service")) Expect(value).To(Equal("")) }) }) Describe("GetInstanceID", func() { It("returns instance id", func() { value, err := metadataService.GetInstanceID() Expect(err).ToNot(HaveOccurred()) Expect(value).To(Equal("fake-instance-id")) }) It("returns an error if it fails to get instance id", func() { updateMetadata(MetadataContentsType{}) value, err := metadataService.GetInstanceID() Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("Failed to load instance-id from config drive metadata service")) Expect(value).To(Equal("")) }) }) Describe("GetServerName", func() { It("returns server name", func() { value, err := metadataService.GetServerName() Expect(err).ToNot(HaveOccurred()) Expect(value).To(Equal("fake-server-name")) }) It("returns an error if it fails to get server name", func() { updateUserdata("{}") value, err := metadataService.GetServerName() Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("Failed to load server name from config drive metadata service")) Expect(value).To(Equal("")) }) }) Describe("GetRegistryEndpoint", func() { It("returns an error if it fails to get registry endpoint", func() { updateUserdata("{}") value, err := metadataService.GetRegistryEndpoint() Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("Failed to load registry endpoint from config drive metadata service")) Expect(value).To(Equal("")) }) Context("when user_data does not contain a dns server", func() { It("returns registry endpoint", func() { value, err := metadataService.GetRegistryEndpoint() Expect(err).ToNot(HaveOccurred()) Expect(value).To(Equal("fake-registry-endpoint")) }) }) Context("when user_data contains a dns server", func() { BeforeEach(func() { userdataContents := fmt.Sprintf( `{"server":{"name":"%s"},"registry":{"endpoint":"%s"},"dns":{"nameserver":["%s"]}}`, "fake-server-name", "http://fake-registry.com", "fake-dns-server-ip", ) updateUserdata(userdataContents) }) Context("when registry endpoint is successfully resolved", func() { BeforeEach(func() { resolver.RegisterRecord(fakeinf.FakeDNSRecord{ DNSServers: []string{"fake-dns-server-ip"}, Host: "http://fake-registry.com", IP: "http://fake-registry-ip", }) }) It("returns the successfully resolved registry endpoint", func() { endpoint, err := metadataService.GetRegistryEndpoint() Expect(err).ToNot(HaveOccurred()) Expect(endpoint).To(Equal("http://fake-registry-ip")) }) }) Context("when registry endpoint is not successfully resolved", func() { BeforeEach(func() { resolver.LookupHostErr = errors.New("fake-lookup-host-err") }) It("returns error because it failed to resolve registry endpoint", func() { endpoint, err := metadataService.GetRegistryEndpoint() Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("fake-lookup-host-err")) Expect(endpoint).To(BeEmpty()) }) }) }) }) }
func describeHTTPMetadataService() { var ( dnsResolver *fakeinf.FakeDNSResolver platform *fakeplat.FakePlatform logger boshlog.Logger metadataService MetadataService ) BeforeEach(func() { dnsResolver = &fakeinf.FakeDNSResolver{} platform = fakeplat.NewFakePlatform() logger = boshlog.NewLogger(boshlog.LevelNone) metadataService = NewHTTPMetadataService("fake-metadata-host", dnsResolver, platform, logger) }) ItEnsuresMinimalNetworkSetup := func(subject func() (string, error)) { Context("when no networks are configured", func() { BeforeEach(func() { platform.GetConfiguredNetworkInterfacesInterfaces = []string{} }) It("sets up DHCP network", func() { _, err := subject() Expect(err).ToNot(HaveOccurred()) Expect(platform.SetupNetworkingCalled).To(BeTrue()) Expect(platform.SetupNetworkingNetworks).To(Equal(boshsettings.Networks{ "eth0": boshsettings.Network{ Type: "dynamic", }, })) }) Context("when setting up DHCP fails", func() { BeforeEach(func() { platform.SetupNetworkingErr = errors.New("fake-network-error") }) It("returns an error", func() { _, err := subject() Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("fake-network-error")) }) }) }) } Describe("IsAvailable", func() { It("returns true", func() { Expect(metadataService.IsAvailable()).To(BeTrue()) }) }) Describe("GetPublicKey", func() { var ( ts *httptest.Server ) BeforeEach(func() { handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { GinkgoRecover() Expect(r.Method).To(Equal("GET")) Expect(r.URL.Path).To(Equal("/latest/meta-data/public-keys/0/openssh-key")) w.Write([]byte("fake-public-key")) }) ts = httptest.NewServer(handler) metadataService = NewHTTPMetadataService(ts.URL, dnsResolver, platform, logger) }) AfterEach(func() { ts.Close() }) ItEnsuresMinimalNetworkSetup(func() (string, error) { return metadataService.GetPublicKey() }) It("returns fetched public key", func() { publicKey, err := metadataService.GetPublicKey() Expect(err).NotTo(HaveOccurred()) Expect(publicKey).To(Equal("fake-public-key")) }) }) Describe("GetInstanceID", func() { var ( ts *httptest.Server ) BeforeEach(func() { handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { GinkgoRecover() Expect(r.Method).To(Equal("GET")) Expect(r.URL.Path).To(Equal("/latest/meta-data/instance-id")) w.Write([]byte("fake-instance-id")) }) ts = httptest.NewServer(handler) metadataService = NewHTTPMetadataService(ts.URL, dnsResolver, platform, logger) }) AfterEach(func() { ts.Close() }) ItEnsuresMinimalNetworkSetup(func() (string, error) { return metadataService.GetInstanceID() }) It("returns fetched instance id", func() { publicKey, err := metadataService.GetInstanceID() Expect(err).NotTo(HaveOccurred()) Expect(publicKey).To(Equal("fake-instance-id")) }) }) Describe("GetServerName", func() { var ( ts *httptest.Server serverName *string ) handlerFunc := func(w http.ResponseWriter, r *http.Request) { GinkgoRecover() Expect(r.Method).To(Equal("GET")) Expect(r.URL.Path).To(Equal("/latest/user-data")) var jsonStr string if serverName == nil { jsonStr = `{}` } else { jsonStr = fmt.Sprintf(`{"server":{"name":"%s"}}`, *serverName) } w.Write([]byte(jsonStr)) } BeforeEach(func() { serverName = nil handler := http.HandlerFunc(handlerFunc) ts = httptest.NewServer(handler) metadataService = NewHTTPMetadataService(ts.URL, dnsResolver, platform, logger) }) AfterEach(func() { ts.Close() }) Context("when the server name is present in the JSON", func() { BeforeEach(func() { name := "fake-server-name" serverName = &name }) It("returns the server name", func() { name, err := metadataService.GetServerName() Expect(err).ToNot(HaveOccurred()) Expect(name).To(Equal("fake-server-name")) }) ItEnsuresMinimalNetworkSetup(func() (string, error) { return metadataService.GetServerName() }) }) Context("when the server name is not present in the JSON", func() { BeforeEach(func() { serverName = nil }) It("returns an error", func() { name, err := metadataService.GetServerName() Expect(err).To(HaveOccurred()) Expect(name).To(BeEmpty()) }) }) }) Describe("GetRegistryEndpoint", func() { var ( ts *httptest.Server registryURL *string dnsServer *string ) handlerFunc := func(w http.ResponseWriter, r *http.Request) { GinkgoRecover() Expect(r.Method).To(Equal("GET")) Expect(r.URL.Path).To(Equal("/latest/user-data")) var jsonStr string if dnsServer == nil { jsonStr = fmt.Sprintf(`{"registry":{"endpoint":"%s"}}`, *registryURL) } else { jsonStr = fmt.Sprintf(`{ "registry":{"endpoint":"%s"}, "dns":{"nameserver":["%s"]} }`, *registryURL, *dnsServer) } w.Write([]byte(jsonStr)) } BeforeEach(func() { url := "http://fake-registry.com" registryURL = &url dnsServer = nil handler := http.HandlerFunc(handlerFunc) ts = httptest.NewServer(handler) metadataService = NewHTTPMetadataService(ts.URL, dnsResolver, platform, logger) }) AfterEach(func() { ts.Close() }) ItEnsuresMinimalNetworkSetup(func() (string, error) { return metadataService.GetRegistryEndpoint() }) Context("when metadata contains a dns server", func() { BeforeEach(func() { server := "fake-dns-server-ip" dnsServer = &server }) Context("when registry endpoint is successfully resolved", func() { BeforeEach(func() { dnsResolver.RegisterRecord(fakeinf.FakeDNSRecord{ DNSServers: []string{"fake-dns-server-ip"}, Host: "http://fake-registry.com", IP: "http://fake-registry-ip", }) }) It("returns the successfully resolved registry endpoint", func() { endpoint, err := metadataService.GetRegistryEndpoint() Expect(err).ToNot(HaveOccurred()) Expect(endpoint).To(Equal("http://fake-registry-ip")) }) }) Context("when registry endpoint is not successfully resolved", func() { BeforeEach(func() { dnsResolver.LookupHostErr = errors.New("fake-lookup-host-err") }) It("returns error because it failed to resolve registry endpoint", func() { endpoint, err := metadataService.GetRegistryEndpoint() Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("fake-lookup-host-err")) Expect(endpoint).To(BeEmpty()) }) }) }) Context("when metadata does not contain dns servers", func() { It("returns fetched registry endpoint", func() { endpoint, err := metadataService.GetRegistryEndpoint() Expect(err).NotTo(HaveOccurred()) Expect(endpoint).To(Equal("http://fake-registry.com")) }) }) }) Describe("GetNetworks", func() { It("returns nil networks, since you don't need them for bootstrapping since your network must be set up before you can get the metadata", func() { Expect(metadataService.GetNetworks()).To(BeNil()) }) }) }
It("returns the successfully resolved registry endpoint with port", func() { resolvedEndpoint, err := registryEndpointResolver.LookupHost(dnsServers, "http://fake-registry.com:8877") Expect(err).ToNot(HaveOccurred()) Expect(resolvedEndpoint).To(Equal("http://fake-registry-ip:8877")) }) }) Context("when registry endpoint does not have a port", func() { It("returns the successfully resolved registry endpoint", func() { resolvedEndpoint, err := registryEndpointResolver.LookupHost(dnsServers, "http://fake-registry.com") Expect(err).ToNot(HaveOccurred()) Expect(resolvedEndpoint).To(Equal("http://fake-registry-ip")) }) }) }) Context("when registry endpoint is not successfully resolved", func() { BeforeEach(func() { delegate.LookupHostErr = errors.New("fake-lookup-host-err") }) It("returns error because it failed to resolve registry endpoint", func() { resolvedEndpoint, err := registryEndpointResolver.LookupHost(dnsServers, "http://fake-registry.com") Expect(resolvedEndpoint).To(BeEmpty()) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("fake-lookup-host-err")) }) }) }) })