func NewFakePlatform() (platform *FakePlatform) { platform = new(FakePlatform) platform.Fs = fakesys.NewFakeFileSystem() platform.Runner = fakesys.NewFakeCmdRunner() platform.FakeCompressor = fakecmd.NewFakeCompressor() platform.FakeCopier = fakecmd.NewFakeCopier() platform.FakeVitalsService = fakevitals.NewFakeService() platform.DevicePathResolver = fakedpresolv.NewFakeDevicePathResolver() platform.AddUserToGroupsGroups = make(map[string][]string) platform.SetupSSHPublicKeys = make(map[string][]string) platform.UserPasswords = make(map[string]string) platform.ScsiDiskMap = make(map[string]string) platform.GetFileContentsFromDiskDiskPaths = []string{} platform.GetFileContentsFromDiskFileNames = [][]string{} platform.GetFileContentsFromDiskContents = map[string][]byte{} platform.GetFileContentsFromDiskErrs = map[string]error{} platform.certManager = new(fakecert.FakeManager) platform.SetupRawEphemeralDisksCallCount = 0 platform.SetupRawEphemeralDisksDevices = nil platform.SetupRawEphemeralDisksErr = nil platform.GetHostPublicKeyError = nil platform.SetupRootDiskCalledTimes = 0 platform.SetupRootDiskError = nil platform.IsPersistentDiskMountableErr = nil return }
func describeDummyPlatform() { var ( platform Platform collector boshstats.Collector fs boshsys.FileSystem cmdRunner boshsys.CmdRunner dirProvider boshdirs.Provider devicePathResolver boshdpresolv.DevicePathResolver logger boshlog.Logger ) BeforeEach(func() { collector = &fakestats.FakeCollector{} fs = fakesys.NewFakeFileSystem() cmdRunner = fakesys.NewFakeCmdRunner() dirProvider = boshdirs.NewProvider("/fake-dir") devicePathResolver = fakedpresolv.NewFakeDevicePathResolver() logger = boshlog.NewLogger(boshlog.LevelNone) }) JustBeforeEach(func() { platform = NewDummyPlatform( collector, fs, cmdRunner, dirProvider, devicePathResolver, logger, ) }) Describe("GetDefaultNetwork", func() { It("returns the contents of dummy-defaults-network-settings.json since that's what the dummy cpi writes", func() { settingsFilePath := "/fake-dir/bosh/dummy-default-network-settings.json" fs.WriteFileString(settingsFilePath, `{"IP": "1.2.3.4"}`) network, err := platform.GetDefaultNetwork() Expect(err).NotTo(HaveOccurred()) Expect(network.IP).To(Equal("1.2.3.4")) }) }) Describe("GetCertManager", func() { It("returs a dummy cert manager", func() { certManager := platform.GetCertManager() Expect(certManager.UpdateCertificates("")).Should(BeNil()) }) }) }
It("returns an error when deleting old certs fails", func() { fakeFs.RemoveAllError = errors.New("NOT ALLOW") fakeFs.WriteFileString(fmt.Sprintf("%s/bosh-trusted-cert-1.crt", certBasePath), "goodbye") fakeFs.SetGlob(fmt.Sprintf("%s/bosh-trusted-cert-*", certBasePath), []string{ fmt.Sprintf("%s/bosh-trusted-cert-1.crt", certBasePath), }) err := certManager.UpdateCertificates("") Expect(err).To(HaveOccurred()) }) } Context("Ubuntu", func() { BeforeEach(func() { fakeFs = fakesys.NewFakeFileSystem() fakeCmd = fakesys.NewFakeCmdRunner() fakeCmd.AddCmdResult("/usr/sbin/update-ca-certificates", fakesys.FakeCmdResult{ Stdout: "", Stderr: "", ExitStatus: 0, Sticky: true, }) certManager = cert.NewUbuntuCertManager(fakeFs, fakeCmd, log) }) SharedLinuxCertManagerExamples("/usr/local/share/ca-certificates", "/usr/sbin/update-ca-certificates") // TODO this test can be shared if there is a way to update existing FakeCmdRunner command specs It("executes update cert command", func() { fakeCmd = fakesys.NewFakeCmdRunner() fakeCmd.AddCmdResult("/usr/sbin/update-ca-certificates -f", fakesys.FakeCmdResult{
fs *fakesys.FakeFileSystem compressor *fakecmd.FakeCompressor packagesDir string blobstore *fakeblobstore.FakeBlobstore mockCompiledPackageRepo *mock_state_package.MockCompiledPackageRepo fakeExtractor *fakeblobextract.FakeExtractor dependency1 *birelpkg.Package dependency2 *birelpkg.Package ) BeforeEach(func() { logger = boshlog.NewLogger(boshlog.LevelNone) packagesDir = "fake-packages-dir" runner = fakesys.NewFakeCmdRunner() fs = fakesys.NewFakeFileSystem() compressor = fakecmd.NewFakeCompressor() fakeExtractor = &fakeblobextract.FakeExtractor{} blobstore = fakeblobstore.NewFakeBlobstore() blobstore.CreateFingerprint = "fake-fingerprint" blobstore.CreateBlobID = "fake-blob-id" mockCompiledPackageRepo = mock_state_package.NewMockCompiledPackageRepo(mockCtrl) dependency1 = &birelpkg.Package{ Name: "fake-package-name-dependency-1", Fingerprint: "fake-package-fingerprint-dependency-1", }
func init() { Describe("bootstrap", func() { Describe("Run", func() { var ( platform *fakeplatform.FakePlatform dirProvider boshdir.Provider settingsSource *fakeinf.FakeSettingsSource settingsService *fakesettings.FakeSettingsService ) BeforeEach(func() { platform = fakeplatform.NewFakePlatform() dirProvider = boshdir.NewProvider("/var/vcap") settingsSource = &fakeinf.FakeSettingsSource{} settingsService = &fakesettings.FakeSettingsService{} }) bootstrap := func() error { logger := boshlog.NewLogger(boshlog.LevelNone) return NewBootstrap(platform, dirProvider, settingsService, logger).Run() } It("sets up runtime configuration", func() { err := bootstrap() Expect(err).NotTo(HaveOccurred()) Expect(platform.SetupRuntimeConfigurationWasInvoked).To(BeTrue()) }) Describe("SSH tunnel setup for registry", func() { It("returns error without configuring ssh on the platform if getting public key fails", func() { settingsService.PublicKeyErr = errors.New("fake-get-public-key-err") err := bootstrap() Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("fake-get-public-key-err")) Expect(platform.SetupSSHCalled).To(BeFalse()) }) Context("when public key is not empty", func() { BeforeEach(func() { settingsService.PublicKey = "fake-public-key" }) It("gets the public key and sets up ssh via the platform", func() { err := bootstrap() Expect(err).NotTo(HaveOccurred()) Expect(platform.SetupSSHPublicKey).To(Equal("fake-public-key")) Expect(platform.SetupSSHUsername).To(Equal("vcap")) }) It("returns error if configuring ssh on the platform fails", func() { platform.SetupSSHErr = errors.New("fake-setup-ssh-err") err := bootstrap() Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("fake-setup-ssh-err")) }) }) Context("when public key key is empty", func() { BeforeEach(func() { settingsSource.PublicKey = "" }) It("gets the public key and does not setup SSH", func() { err := bootstrap() Expect(err).NotTo(HaveOccurred()) Expect(platform.SetupSSHCalled).To(BeFalse()) }) }) }) It("sets up hostname", func() { settingsService.Settings.AgentID = "foo-bar-baz-123" err := bootstrap() Expect(err).NotTo(HaveOccurred()) Expect(platform.SetupHostnameHostname).To(Equal("foo-bar-baz-123")) }) It("fetches initial settings", func() { err := bootstrap() Expect(err).NotTo(HaveOccurred()) Expect(settingsService.SettingsWereLoaded).To(BeTrue()) }) It("returns error from loading initial settings", func() { settingsService.LoadSettingsError = errors.New("fake-load-error") err := bootstrap() Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("fake-load-error")) }) It("sets up networking", func() { networks := boshsettings.Networks{ "bosh": boshsettings.Network{}, } settingsService.Settings.Networks = networks err := bootstrap() Expect(err).NotTo(HaveOccurred()) Expect(platform.SetupNetworkingNetworks).To(Equal(networks)) }) It("sets up ephemeral disk", func() { settingsService.Settings.Disks = boshsettings.Disks{ Ephemeral: "fake-ephemeral-disk-setting", } platform.GetEphemeralDiskPathRealPath = "/dev/sda" err := bootstrap() Expect(err).NotTo(HaveOccurred()) Expect(platform.SetupEphemeralDiskWithPathDevicePath).To(Equal("/dev/sda")) Expect(platform.GetEphemeralDiskPathSettings).To(Equal(boshsettings.DiskSettings{ VolumeID: "fake-ephemeral-disk-setting", Path: "fake-ephemeral-disk-setting", })) }) It("returns error if setting ephemeral disk fails", func() { platform.SetupEphemeralDiskWithPathErr = errors.New("fake-setup-ephemeral-disk-err") err := bootstrap() Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("fake-setup-ephemeral-disk-err")) }) It("sets up raw ephemeral disks if paths exist", func() { settingsService.Settings.Disks = boshsettings.Disks{ RawEphemeral: []boshsettings.DiskSettings{{Path: "/dev/xvdb"}, {Path: "/dev/xvdc"}}, } err := bootstrap() Expect(err).NotTo(HaveOccurred()) Expect(platform.SetupRawEphemeralDisksCallCount).To(Equal(1)) Expect(len(platform.SetupRawEphemeralDisksDevices)).To(Equal(2)) Expect(platform.SetupRawEphemeralDisksDevices[0].Path).To(Equal("/dev/xvdb")) Expect(platform.SetupRawEphemeralDisksDevices[1].Path).To(Equal("/dev/xvdc")) }) It("returns error if setting raw ephemeral disks fails", func() { platform.SetupRawEphemeralDisksErr = errors.New("fake-setup-raw-ephemeral-disks-err") err := bootstrap() Expect(platform.SetupRawEphemeralDisksCallCount).To(Equal(1)) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("fake-setup-raw-ephemeral-disks-err")) }) It("sets up data dir", func() { err := bootstrap() Expect(err).NotTo(HaveOccurred()) Expect(platform.SetupDataDirCalled).To(BeTrue()) }) It("returns error if set up of data dir fails", func() { platform.SetupDataDirErr = errors.New("fake-setup-data-dir-err") err := bootstrap() Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("fake-setup-data-dir-err")) }) It("sets up tmp dir", func() { err := bootstrap() Expect(err).NotTo(HaveOccurred()) Expect(platform.SetupTmpDirCalled).To(BeTrue()) }) It("returns error if set up of tmp dir fails", func() { platform.SetupTmpDirErr = errors.New("fake-setup-tmp-dir-err") err := bootstrap() Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("fake-setup-tmp-dir-err")) }) It("mounts persistent disk", func() { settingsService.Settings.Disks = boshsettings.Disks{ Persistent: map[string]interface{}{ "vol-123": map[string]interface{}{ "volume_id": "2", "path": "/dev/sdb", }, }, } err := bootstrap() Expect(err).NotTo(HaveOccurred()) Expect(platform.MountPersistentDiskSettings).To(Equal(boshsettings.DiskSettings{ ID: "vol-123", VolumeID: "2", Path: "/dev/sdb", })) Expect(platform.MountPersistentDiskMountPoint).To(Equal(dirProvider.StoreDir())) }) It("errors if there is more than one persistent disk", func() { settingsService.Settings.Disks = boshsettings.Disks{ Persistent: map[string]interface{}{ "vol-123": "/dev/sdb", "vol-456": "/dev/sdc", }, } err := bootstrap() Expect(err).To(HaveOccurred()) }) It("does not try to mount when no persistent disk", func() { settingsService.Settings.Disks = boshsettings.Disks{ Persistent: map[string]interface{}{}, } err := bootstrap() Expect(err).NotTo(HaveOccurred()) Expect(platform.MountPersistentDiskSettings).To(Equal(boshsettings.DiskSettings{})) Expect(platform.MountPersistentDiskMountPoint).To(Equal("")) }) It("grows the root filesystem", func() { err := bootstrap() Expect(err).NotTo(HaveOccurred()) Expect(platform.SetupRootDiskCalledTimes).To(Equal(1)) }) It("returns an error if growing the root filesystem fails", func() { platform.SetupRootDiskError = errors.New("growfs failed") err := bootstrap() Expect(err).To(HaveOccurred()) Expect(platform.SetupRootDiskCalledTimes).To(Equal(1)) Expect(err.Error()).To(ContainSubstring("growfs failed")) }) It("sets root and vcap passwords", func() { settingsService.Settings.Env.Bosh.Password = "******" settingsService.Settings.Env.Bosh.KeepRootPassword = false err := bootstrap() Expect(err).NotTo(HaveOccurred()) Expect(2).To(Equal(len(platform.UserPasswords))) Expect("some-encrypted-password").To(Equal(platform.UserPasswords["root"])) Expect("some-encrypted-password").To(Equal(platform.UserPasswords["vcap"])) }) It("does not change root password if keep_root_password is set to true", func() { settingsService.Settings.Env.Bosh.Password = "******" settingsService.Settings.Env.Bosh.KeepRootPassword = true err := bootstrap() Expect(err).NotTo(HaveOccurred()) Expect(1).To(Equal(len(platform.UserPasswords))) Expect("some-encrypted-password").ToNot(Equal(platform.UserPasswords["root"])) Expect("some-encrypted-password").To(Equal(platform.UserPasswords["vcap"])) }) It("does not set password if not provided", func() { settingsService.Settings.Env.Bosh.KeepRootPassword = false err := bootstrap() Expect(err).NotTo(HaveOccurred()) Expect(0).To(Equal(len(platform.UserPasswords))) }) It("sets ntp", func() { settingsService.Settings.Ntp = []string{ "0.north-america.pool.ntp.org", "1.north-america.pool.ntp.org", } err := bootstrap() Expect(err).NotTo(HaveOccurred()) Expect(2).To(Equal(len(platform.SetTimeWithNtpServersServers))) Expect("0.north-america.pool.ntp.org").To(Equal(platform.SetTimeWithNtpServersServers[0])) Expect("1.north-america.pool.ntp.org").To(Equal(platform.SetTimeWithNtpServersServers[1])) }) It("setups up monit user", func() { err := bootstrap() Expect(err).NotTo(HaveOccurred()) Expect(platform.SetupMonitUserSetup).To(BeTrue()) }) It("starts monit", func() { err := bootstrap() Expect(err).NotTo(HaveOccurred()) Expect(platform.StartMonitStarted).To(BeTrue()) }) }) Describe("Network setup exercised by Run", func() { var ( settingsJSON string fs *fakesys.FakeFileSystem platform boshplatform.Platform boot Bootstrap defaultNetworkResolver boshsettings.DefaultNetworkResolver logger boshlog.Logger dirProvider boshdirs.Provider interfaceAddrsProvider *fakeip.FakeInterfaceAddressesProvider ) writeNetworkDevice := func(iface string, macAddress string, isPhysical bool) string { interfacePath := fmt.Sprintf("/sys/class/net/%s", iface) fs.WriteFile(interfacePath, []byte{}) if isPhysical { fs.WriteFile(fmt.Sprintf("/sys/class/net/%s/device", iface), []byte{}) } fs.WriteFileString(fmt.Sprintf("/sys/class/net/%s/address", iface), fmt.Sprintf("%s\n", macAddress)) return interfacePath } stubInterfaces := func(interfaces [][]string) { var interfacePaths []string for _, iface := range interfaces { interfaceName := iface[0] interfaceMAC := iface[1] interfaceType := iface[2] isPhysical := interfaceType == "physical" interfacePaths = append(interfacePaths, writeNetworkDevice(interfaceName, interfaceMAC, isPhysical)) } fs.SetGlob("/sys/class/net/*", interfacePaths) } BeforeEach(func() { fs = fakesys.NewFakeFileSystem() runner := fakesys.NewFakeCmdRunner() dirProvider = boshdirs.NewProvider("/var/vcap/bosh") linuxOptions := boshplatform.LinuxOptions{ CreatePartitionIfNoEphemeralDisk: true, } logger = boshlog.NewLogger(boshlog.LevelNone) diskManager := fakedisk.NewFakeDiskManager() diskManager.FakeMountsSearcher.SearchMountsMounts = []boshdisk.Mount{ {MountPoint: "/", PartitionPath: "rootfs"}, {MountPoint: "/", PartitionPath: "/dev/vda1"}, } // for the GrowRootFS call to findRootDevicePath runner.AddCmdResult( "readlink -f /dev/vda1", fakesys.FakeCmdResult{Stdout: "/dev/vda1"}, ) // for the createEphemeralPartitionsOnRootDevice call to findRootDevicePath runner.AddCmdResult( "readlink -f /dev/vda1", fakesys.FakeCmdResult{Stdout: "/dev/vda1"}, ) diskManager.FakeRootDevicePartitioner.GetDeviceSizeInBytesSizes["/dev/vda"] = 1024 * 1024 * 1024 udev := boshudev.NewConcreteUdevDevice(runner, logger) linuxCdrom := boshcdrom.NewLinuxCdrom("/dev/sr0", udev, runner) linuxCdutil := boshcdrom.NewCdUtil(dirProvider.SettingsDir(), fs, linuxCdrom, logger) compressor := boshcmd.NewTarballCompressor(runner, fs) copier := boshcmd.NewCpCopier(runner, fs, logger) sigarCollector := boshsigar.NewSigarStatsCollector(&sigar.ConcreteSigar{}) vitalsService := boshvitals.NewService(sigarCollector, dirProvider) ipResolver := boship.NewResolver(boship.NetworkInterfaceToAddrsFunc) arping := bosharp.NewArping(runner, fs, logger, boshplatform.ArpIterations, boshplatform.ArpIterationDelay, boshplatform.ArpInterfaceCheckDelay) interfaceConfigurationCreator := boshnet.NewInterfaceConfigurationCreator(logger) interfaceAddrsProvider = &fakeip.FakeInterfaceAddressesProvider{} interfaceAddressesValidator := boship.NewInterfaceAddressesValidator(interfaceAddrsProvider) dnsValidator := boshnet.NewDNSValidator(fs) fs.WriteFileString("/etc/resolv.conf", "8.8.8.8 4.4.4.4") ubuntuNetManager := boshnet.NewUbuntuNetManager(fs, runner, ipResolver, interfaceConfigurationCreator, interfaceAddressesValidator, dnsValidator, arping, logger) ubuntuCertManager := boshcert.NewUbuntuCertManager(fs, runner, 1, logger) monitRetryable := boshplatform.NewMonitRetryable(runner) monitRetryStrategy := boshretry.NewAttemptRetryStrategy(10, 1*time.Second, monitRetryable, logger) devicePathResolver := devicepathresolver.NewIdentityDevicePathResolver() routesSearcher := boshnet.NewCmdRoutesSearcher(runner) defaultNetworkResolver = boshnet.NewDefaultNetworkResolver(routesSearcher, ipResolver) state, err := boshplatform.NewBootstrapState(fs, "/tmp/agent_state.json") Expect(err).NotTo(HaveOccurred()) platform = boshplatform.NewLinuxPlatform( fs, runner, sigarCollector, compressor, copier, dirProvider, vitalsService, linuxCdutil, diskManager, ubuntuNetManager, ubuntuCertManager, monitRetryStrategy, devicePathResolver, 500*time.Millisecond, state, linuxOptions, logger, defaultNetworkResolver, ) }) JustBeforeEach(func() { settingsPath := filepath.Join("bosh", "settings.json") var settings boshsettings.Settings json.Unmarshal([]byte(settingsJSON), &settings) settingsSource := fakeinf.FakeSettingsSource{ PublicKey: "123", SettingsValue: settings, } settingsService := boshsettings.NewService( platform.GetFs(), settingsPath, settingsSource, platform, logger, ) boot = NewBootstrap( platform, dirProvider, settingsService, logger, ) }) Context("when a single network configuration is provided, with a MAC address", func() { BeforeEach(func() { settingsJSON = `{ "networks": { "netA": { "default": ["dns", "gateway"], "ip": "2.2.2.2", "dns": [ "8.8.8.8", "4.4.4.4" ], "netmask": "255.255.255.0", "gateway": "2.2.2.0", "mac": "aa:bb:cc" } } }` }) Context("and no physical network interfaces exist", func() { Context("and a single virtual network interface exists", func() { BeforeEach(func() { stubInterfaces([][]string{[]string{"lo", "aa:bb:cc", "virtual"}}) }) It("raises an error", func() { err := boot.Run() Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("Number of network settings '1' is greater than the number of network devices '0")) }) }) }) Context("and a single physical network interface exists", func() { BeforeEach(func() { stubInterfaces([][]string{[]string{"eth0", "aa:bb:cc", "physical"}}) interfaceAddrsProvider.GetInterfaceAddresses = []boship.InterfaceAddress{ boship.NewSimpleInterfaceAddress("eth0", "2.2.2.2"), } }) It("succeeds", func() { err := boot.Run() Expect(err).NotTo(HaveOccurred()) }) }) Context("and extra physical network interfaces exist", func() { BeforeEach(func() { stubInterfaces([][]string{[]string{"eth0", "aa:bb:cc", "physical"}, []string{"eth1", "aa:bb:dd", "physical"}}) interfaceAddrsProvider.GetInterfaceAddresses = []boship.InterfaceAddress{ boship.NewSimpleInterfaceAddress("eth0", "2.2.2.2"), } }) It("succeeds", func() { err := boot.Run() Expect(err).NotTo(HaveOccurred()) }) }) Context("and extra virtual network interfaces exist", func() { BeforeEach(func() { stubInterfaces([][]string{[]string{"eth0", "aa:bb:cc", "physical"}, []string{"lo", "aa:bb:ee", "virtual"}}) interfaceAddrsProvider.GetInterfaceAddresses = []boship.InterfaceAddress{ boship.NewSimpleInterfaceAddress("eth0", "2.2.2.2"), } }) It("succeeds", func() { err := boot.Run() Expect(err).ToNot(HaveOccurred()) }) }) }) Context("when a single network configuration is provided, without a MAC address", func() { BeforeEach(func() { settingsJSON = `{ "networks": { "netA": { "default": ["dns", "gateway"], "ip": "2.2.2.2", "dns": [ "8.8.8.8", "4.4.4.4" ], "netmask": "255.255.255.0", "gateway": "2.2.2.0" } } }` }) Context("and no physical network interfaces exist", func() { Context("and a single virtual network interface exists", func() { BeforeEach(func() { stubInterfaces([][]string{[]string{"lo", "aa:bb:cc", "virtual"}}) }) It("raises an error", func() { err := boot.Run() Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("Number of network settings '1' is greater than the number of network devices '0")) }) }) }) Context("and a single physical network interface exists", func() { BeforeEach(func() { stubInterfaces([][]string{[]string{"eth0", "aa:bb:cc", "physical"}}) interfaceAddrsProvider.GetInterfaceAddresses = []boship.InterfaceAddress{ boship.NewSimpleInterfaceAddress("eth0", "2.2.2.2"), } }) It("succeeds", func() { err := boot.Run() Expect(err).NotTo(HaveOccurred()) }) }) Context("and extra physical network interfaces exist", func() { BeforeEach(func() { stubInterfaces([][]string{[]string{"eth0", "aa:bb:cc", "physical"}, []string{"eth1", "aa:bb:dd", "physical"}}) interfaceAddrsProvider.GetInterfaceAddresses = []boship.InterfaceAddress{ boship.NewSimpleInterfaceAddress("eth0", "2.2.2.2"), } }) It("succeeds", func() { err := boot.Run() Expect(err).NotTo(HaveOccurred()) }) }) Context("and an extra virtual network interface exists", func() { BeforeEach(func() { stubInterfaces([][]string{[]string{"eth0", "aa:bb:cc", "physical"}, []string{"lo", "aa:bb:dd", "virtual"}}) interfaceAddrsProvider.GetInterfaceAddresses = []boship.InterfaceAddress{ boship.NewSimpleInterfaceAddress("eth0", "2.2.2.2"), } }) It("succeeds", func() { err := boot.Run() Expect(err).NotTo(HaveOccurred()) }) }) }) Context("when two network configurations are provided", func() { BeforeEach(func() { settingsJSON = `{ "networks": { "netA": { "default": ["dns", "gateway"], "ip": "2.2.2.2", "dns": [ "8.8.8.8", "4.4.4.4" ], "netmask": "255.255.255.0", "gateway": "2.2.2.0", "mac": "aa:bb:cc" }, "netB": { "default": ["dns", "gateway"], "ip": "3.3.3.3", "dns": [ "8.8.8.8", "4.4.4.4" ], "netmask": "255.255.255.0", "gateway": "3.3.3.0", "mac": "" } } }` }) Context("and a single physical network interface exists", func() { BeforeEach(func() { stubInterfaces([][]string{[]string{"eth0", "aa:bb:cc", "physical"}}) }) It("raises an error", func() { err := boot.Run() Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("Number of network settings '2' is greater than the number of network devices '1")) }) }) Context("and two physical network interfaces with matching MAC addresses exist", func() { BeforeEach(func() { stubInterfaces([][]string{[]string{"eth0", "aa:bb:cc", "physical"}, []string{"eth1", "aa:bb:dd", "physical"}}) interfaceAddrsProvider.GetInterfaceAddresses = []boship.InterfaceAddress{ boship.NewSimpleInterfaceAddress("eth0", "2.2.2.2"), boship.NewSimpleInterfaceAddress("eth1", "3.3.3.3"), } }) It("succeeds", func() { err := boot.Run() Expect(err).ToNot(HaveOccurred()) }) }) }) }) }) }
Expect(content).To(ContainSubstring("double-nested-file")) Expect(dstDir + "/empty-dir").To(beDir()) Expect(dstDir + "/dir/empty-nested-dir").To(beDir()) }) It("returns error if the destination does not exist", func() { fs.RemoveAll(dstDir) err := compressor.DecompressFileToDir(fixtureSrcTgz(), dstDir, CompressorOptions{}) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring(dstDir)) }) It("uses no same owner option", func() { cmdRunner := fakesys.NewFakeCmdRunner() compressor := NewTarballCompressor(cmdRunner, fs) tarballPath := fixtureSrcTgz() err := compressor.DecompressFileToDir(tarballPath, dstDir, CompressorOptions{}) Expect(err).ToNot(HaveOccurred()) Expect(1).To(Equal(len(cmdRunner.RunCommands))) Expect(cmdRunner.RunCommands[0]).To(Equal( []string{ "tar", "--no-same-owner", "-xzvf", tarballPath, "-C", dstDir, }, )) })
func init() { Describe("Testing with Ginkgo", func() { It("linux format when using swap fs", func() { fakeRunner := fakesys.NewFakeCmdRunner() fakeFs := fakesys.NewFakeFileSystem() fakeRunner.AddCmdResult("blkid -p /dev/xvda1", fakesys.FakeCmdResult{Stdout: `xxxxx TYPE="ext4" yyyy zzzz`}) formatter := NewLinuxFormatter(fakeRunner, fakeFs) formatter.Format("/dev/xvda1", FileSystemSwap) Expect(2).To(Equal(len(fakeRunner.RunCommands))) Expect(fakeRunner.RunCommands[1]).To(Equal([]string{"mkswap", "/dev/xvda1"})) }) It("linux format when using swap fs and partition is swap", func() { fakeRunner := fakesys.NewFakeCmdRunner() fakeFs := fakesys.NewFakeFileSystem() fakeRunner.AddCmdResult("blkid -p /dev/xvda1", fakesys.FakeCmdResult{Stdout: `xxxxx TYPE="swap" yyyy zzzz`}) formatter := NewLinuxFormatter(fakeRunner, fakeFs) formatter.Format("/dev/xvda1", FileSystemSwap) Expect(1).To(Equal(len(fakeRunner.RunCommands))) Expect(fakeRunner.RunCommands[0]).To(Equal([]string{"blkid", "-p", "/dev/xvda1"})) }) It("linux format when using ext4 fs with lazy itable support", func() { fakeRunner := fakesys.NewFakeCmdRunner() fakeFs := fakesys.NewFakeFileSystem() fakeFs.WriteFile("/sys/fs/ext4/features/lazy_itable_init", []byte{}) fakeRunner.AddCmdResult("blkid -p /dev/xvda1", fakesys.FakeCmdResult{Stdout: `xxxxx TYPE="ext2" yyyy zzzz`}) formatter := NewLinuxFormatter(fakeRunner, fakeFs) formatter.Format("/dev/xvda2", FileSystemExt4) Expect(2).To(Equal(len(fakeRunner.RunCommands))) Expect(fakeRunner.RunCommands[1]).To(Equal([]string{"mke2fs", "-t", "ext4", "-j", "-E", "lazy_itable_init=1", "/dev/xvda2"})) }) It("linux format when using ext4 fs without lazy itable support", func() { fakeRunner := fakesys.NewFakeCmdRunner() fakeFs := fakesys.NewFakeFileSystem() fakeRunner.AddCmdResult("blkid -p /dev/xvda1", fakesys.FakeCmdResult{Stdout: `xxxxx TYPE="ext2" yyyy zzzz`}) formatter := NewLinuxFormatter(fakeRunner, fakeFs) formatter.Format("/dev/xvda2", FileSystemExt4) Expect(2).To(Equal(len(fakeRunner.RunCommands))) Expect(fakeRunner.RunCommands[1]).To(Equal([]string{"mke2fs", "-t", "ext4", "-j", "/dev/xvda2"})) }) It("linux format when using ext4 fs and partition is ext4", func() { fakeRunner := fakesys.NewFakeCmdRunner() fakeFs := fakesys.NewFakeFileSystem() fakeRunner.AddCmdResult("blkid -p /dev/xvda1", fakesys.FakeCmdResult{Stdout: `xxxxx TYPE="ext4" yyyy zzzz`}) formatter := NewLinuxFormatter(fakeRunner, fakeFs) formatter.Format("/dev/xvda1", FileSystemExt4) Expect(1).To(Equal(len(fakeRunner.RunCommands))) Expect(fakeRunner.RunCommands[0]).To(Equal([]string{"blkid", "-p", "/dev/xvda1"})) }) }) }
func describeDrbd() { var ( dualDCSupport *DualDCSupport cmdRunner *fakesys.FakeCmdRunner fs *fakesys.FakeFileSystem dirProvider boshdir.Provider specService *fakeas.FakeV1Service settingsService *fakesettings.FakeSettingsService logger boshlog.Logger spec boshas.V1ApplySpec ) BeforeEach(func() { fs = fakesys.NewFakeFileSystem() cmdRunner = fakesys.NewFakeCmdRunner() specService = fakeas.NewFakeV1Service() settingsService = &fakesettings.FakeSettingsService{} dirProvider = boshdir.NewProvider("/var/vcap") logger = boshlog.NewLogger(boshlog.LevelNone) dualDCSupport = NewDualDCSupport( cmdRunner, fs, dirProvider, specService, settingsService, logger, ) spec = boshas.V1ApplySpec{} spec.DrbdEnabled = true spec.Passive = "enabled" specService.Spec = spec }) Context("DNS updates", func() { It("", func() { s, e := specService.Get() fmt.Printf("spec: %#v, err: %v", s, e) }) }) Describe("Drbd", func() { It("renders config file", func() { expectedOutput := ` resource r0 { net { protocol A; shared-secret OIUncfjJsbhInuic1243d; verify-alg sha1; } disk { resync-rate 24M; } handlers { before-resync-target "/lib/drbd/snapshot-resync-target-lvm.sh"; after-resync-target "/lib/drbd/unsnapshot-resync-target-lvm.sh"; } startup { wfc-timeout 3; degr-wfc-timeout 3; outdated-wfc-timeout 2; } on dff85535-580a-4bfb-bf49-5efbc017b5bb { device drbd1; disk /dev/mapper/vgStoreData-StoreData; address 10.76.245.71:7789; meta-disk internal; } on host2 { device drbd1; disk /dev/mapper/vgStoreData-StoreData; address 10.92.245.71:7789; meta-disk internal; } } ` // TODO: fix the test - sort out the fakes // out := drbdConfig("A", "OIUncfjJsbhInuic1243d", "dff85535-580a-4bfb-bf49-5efbc017b5bb", "10.76.245.71", "10.92.245.71") Expect("").NotTo(Equal(expectedOutput)) }) }) }
func describeCentosNetManager() { var ( fs *fakesys.FakeFileSystem cmdRunner *fakesys.FakeCmdRunner ipResolver *fakeip.FakeResolver interfaceAddrsProvider *fakeip.FakeInterfaceAddressesProvider addressBroadcaster *fakearp.FakeAddressBroadcaster netManager Manager interfaceConfigurationCreator InterfaceConfigurationCreator ) BeforeEach(func() { fs = fakesys.NewFakeFileSystem() cmdRunner = fakesys.NewFakeCmdRunner() ipResolver = &fakeip.FakeResolver{} logger := boshlog.NewLogger(boshlog.LevelNone) interfaceConfigurationCreator = NewInterfaceConfigurationCreator(logger) interfaceAddrsProvider = &fakeip.FakeInterfaceAddressesProvider{} interfaceAddrsValidator := boship.NewInterfaceAddressesValidator(interfaceAddrsProvider) dnsValidator := NewDNSValidator(fs) addressBroadcaster = &fakearp.FakeAddressBroadcaster{} netManager = NewCentosNetManager( fs, cmdRunner, ipResolver, interfaceConfigurationCreator, interfaceAddrsValidator, dnsValidator, addressBroadcaster, logger, ) }) writeNetworkDevice := func(iface string, macAddress string, isPhysical bool) string { interfacePath := fmt.Sprintf("/sys/class/net/%s", iface) fs.WriteFile(interfacePath, []byte{}) if isPhysical { fs.WriteFile(fmt.Sprintf("/sys/class/net/%s/device", iface), []byte{}) } fs.WriteFileString(fmt.Sprintf("/sys/class/net/%s/address", iface), fmt.Sprintf("%s\n", macAddress)) return interfacePath } Describe("SetupNetworking", func() { var ( dhcpNetwork boshsettings.Network staticNetwork boshsettings.Network expectedNetworkConfigurationForStatic string expectedNetworkConfigurationForDHCP string expectedDhclientConfiguration string ) BeforeEach(func() { dhcpNetwork = boshsettings.Network{ Type: "dynamic", Default: []string{"dns"}, DNS: []string{"8.8.8.8", "9.9.9.9"}, Mac: "fake-dhcp-mac-address", } staticNetwork = boshsettings.Network{ Type: "manual", IP: "1.2.3.4", Netmask: "255.255.255.0", Gateway: "3.4.5.6", Mac: "fake-static-mac-address", } interfaceAddrsProvider.GetInterfaceAddresses = []boship.InterfaceAddress{ boship.NewSimpleInterfaceAddress("ethstatic", "1.2.3.4"), } fs.WriteFileString("/etc/resolv.conf", ` nameserver 8.8.8.8 nameserver 9.9.9.9 `) expectedNetworkConfigurationForStatic = `DEVICE=ethstatic BOOTPROTO=static IPADDR=1.2.3.4 NETMASK=255.255.255.0 BROADCAST=1.2.3.255 GATEWAY=3.4.5.6 ONBOOT=yes PEERDNS=no DNS1=8.8.8.8 DNS2=9.9.9.9 ` expectedNetworkConfigurationForDHCP = `DEVICE=ethdhcp BOOTPROTO=dhcp ONBOOT=yes PEERDNS=yes ` expectedDhclientConfiguration = `# Generated by bosh-agent option rfc3442-classless-static-routes code 121 = array of unsigned integer 8; send host-name "<hostname>"; request subnet-mask, broadcast-address, time-offset, routers, domain-name, domain-name-servers, domain-search, host-name, netbios-name-servers, netbios-scope, interface-mtu, rfc3442-classless-static-routes, ntp-servers; prepend domain-name-servers 8.8.8.8, 9.9.9.9; ` }) stubInterfacesWithVirtual := func(physicalInterfaces map[string]boshsettings.Network, virtualInterfaces []string) { interfacePaths := []string{} for iface, networkSettings := range physicalInterfaces { interfacePaths = append(interfacePaths, writeNetworkDevice(iface, networkSettings.Mac, true)) } for _, iface := range virtualInterfaces { interfacePaths = append(interfacePaths, writeNetworkDevice(iface, "virtual", false)) } fs.SetGlob("/sys/class/net/*", interfacePaths) } stubInterfaces := func(physicalInterfaces map[string]boshsettings.Network) { stubInterfacesWithVirtual(physicalInterfaces, nil) } It("writes a network script for static and dynamic interfaces", func() { stubInterfaces(map[string]boshsettings.Network{ "ethdhcp": dhcpNetwork, "ethstatic": staticNetwork, }) err := netManager.SetupNetworking(boshsettings.Networks{"dhcp-network": dhcpNetwork, "static-network": staticNetwork}, nil) Expect(err).ToNot(HaveOccurred()) staticConfig := fs.GetFileTestStat("/etc/sysconfig/network-scripts/ifcfg-ethstatic") Expect(staticConfig).ToNot(BeNil()) Expect(staticConfig.StringContents()).To(Equal(expectedNetworkConfigurationForStatic)) dhcpConfig := fs.GetFileTestStat("/etc/sysconfig/network-scripts/ifcfg-ethdhcp") Expect(dhcpConfig).ToNot(BeNil()) Expect(dhcpConfig.StringContents()).To(Equal(expectedNetworkConfigurationForDHCP)) }) It("returns errors from glob /sys/class/net/", func() { fs.GlobErr = errors.New("fs-glob-error") err := netManager.SetupNetworking(boshsettings.Networks{"dhcp-network": dhcpNetwork, "static-network": staticNetwork}, nil) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("fs-glob-error")) }) It("returns errors from writing the network configuration", func() { stubInterfaces(map[string]boshsettings.Network{ "dhcp": dhcpNetwork, "static": staticNetwork, }) fs.WriteFileError = errors.New("fs-write-file-error") err := netManager.SetupNetworking(boshsettings.Networks{"dhcp-network": dhcpNetwork, "static-network": staticNetwork}, nil) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("fs-write-file-error")) }) It("returns errors when it can't create network interface configurations", func() { stubInterfaces(map[string]boshsettings.Network{ "ethstatic": staticNetwork, }) staticNetwork.Netmask = "not an ip" //will cause InterfaceConfigurationCreator to fail err := netManager.SetupNetworking(boshsettings.Networks{"static-network": staticNetwork}, nil) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("Creating interface configurations")) }) It("wrtites a dhcp configuration if there are dhcp networks", func() { stubInterfaces(map[string]boshsettings.Network{ "ethdhcp": dhcpNetwork, "ethstatic": staticNetwork, }) err := netManager.SetupNetworking(boshsettings.Networks{"dhcp-network": dhcpNetwork, "static-network": staticNetwork}, nil) Expect(err).ToNot(HaveOccurred()) dhcpConfig := fs.GetFileTestStat("/etc/dhcp/dhclient.conf") Expect(dhcpConfig).ToNot(BeNil()) Expect(dhcpConfig.StringContents()).To(Equal(expectedDhclientConfiguration)) dhcpConfigSymlink := fs.GetFileTestStat("/etc/dhcp/dhclient-ethdhcp.conf") Expect(dhcpConfigSymlink).ToNot(BeNil()) Expect(dhcpConfigSymlink.SymlinkTarget).To(Equal("/etc/dhcp/dhclient.conf")) }) It("writes a dhcp configuration without prepended dns servers if there are no dns servers specified", func() { dhcpNetworkWithoutDNS := boshsettings.Network{ Type: "dynamic", Mac: "fake-dhcp-mac-address", } stubInterfaces(map[string]boshsettings.Network{ "ethdhcp": dhcpNetwork, }) err := netManager.SetupNetworking(boshsettings.Networks{"dhcp-network": dhcpNetworkWithoutDNS}, nil) Expect(err).ToNot(HaveOccurred()) dhcpConfig := fs.GetFileTestStat("/etc/dhcp/dhclient.conf") Expect(dhcpConfig).ToNot(BeNil()) Expect(dhcpConfig.StringContents()).To(Equal(`# Generated by bosh-agent option rfc3442-classless-static-routes code 121 = array of unsigned integer 8; send host-name "<hostname>"; request subnet-mask, broadcast-address, time-offset, routers, domain-name, domain-name-servers, domain-search, host-name, netbios-name-servers, netbios-scope, interface-mtu, rfc3442-classless-static-routes, ntp-servers; `)) dhcpConfigSymlink := fs.GetFileTestStat("/etc/dhcp/dhclient-ethdhcp.conf") Expect(dhcpConfigSymlink).ToNot(BeNil()) Expect(dhcpConfigSymlink.SymlinkTarget).To(Equal("/etc/dhcp/dhclient.conf")) }) It("returns an error if it can't write a dhcp configuration", func() { stubInterfaces(map[string]boshsettings.Network{ "ethdhcp": dhcpNetwork, "ethstatic": staticNetwork, }) fs.WriteFileErrors["/etc/dhcp/dhclient.conf"] = errors.New("dhclient.conf-write-error") err := netManager.SetupNetworking(boshsettings.Networks{"dhcp-network": dhcpNetwork, "static-network": staticNetwork}, nil) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("dhclient.conf-write-error")) }) It("returns an error if it can't symlink a dhcp configuration", func() { stubInterfaces(map[string]boshsettings.Network{ "ethdhcp": dhcpNetwork, "ethstatic": staticNetwork, }) fs.SymlinkError = errors.New("dhclient-ethdhcp.conf-symlink-error") err := netManager.SetupNetworking(boshsettings.Networks{"dhcp-network": dhcpNetwork, "static-network": staticNetwork}, nil) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("dhclient-ethdhcp.conf-symlink-error")) }) It("doesn't write a dhcp configuration if there are no dhcp networks", func() { stubInterfaces(map[string]boshsettings.Network{ "ethstatic": staticNetwork, }) err := netManager.SetupNetworking(boshsettings.Networks{"static-network": staticNetwork}, nil) Expect(err).ToNot(HaveOccurred()) dhcpConfig := fs.GetFileTestStat("/etc/dhcp/dhclient-ethdhcp.conf") Expect(dhcpConfig).To(BeNil()) }) It("restarts the networks if any ifconfig file changes", func() { changingStaticNetwork := boshsettings.Network{ Type: "manual", IP: "1.2.3.5", Netmask: "255.255.255.0", Gateway: "3.4.5.6", Mac: "ethstatict-that-changes", } stubInterfaces(map[string]boshsettings.Network{ "ethdhcp": dhcpNetwork, "ethstatic-that-changes": changingStaticNetwork, "ethstatic": staticNetwork, }) interfaceAddrsProvider.GetInterfaceAddresses = []boship.InterfaceAddress{ boship.NewSimpleInterfaceAddress("ethstatic", "1.2.3.4"), boship.NewSimpleInterfaceAddress("ethstatic-that-changes", "1.2.3.5"), } fs.WriteFileString("/etc/sysconfig/network-scripts/ifcfg-ethstatic", expectedNetworkConfigurationForStatic) fs.WriteFileString("/etc/dhcp/dhclient.conf", expectedDhclientConfiguration) err := netManager.SetupNetworking(boshsettings.Networks{ "dhcp-network": dhcpNetwork, "changing-static-network": changingStaticNetwork, "static-network": staticNetwork, }, nil) Expect(err).ToNot(HaveOccurred()) Expect(len(cmdRunner.RunCommands)).To(Equal(1)) Expect(cmdRunner.RunCommands[0]).To(Equal([]string{"service", "network", "restart"})) }) It("doesn't restart the networks if ifcfg and /etc/dhcp/dhclient.conf don't change", func() { stubInterfaces(map[string]boshsettings.Network{ "ethdhcp": dhcpNetwork, "ethstatic": staticNetwork, }) fs.WriteFileString("/etc/sysconfig/network-scripts/ifcfg-ethstatic", expectedNetworkConfigurationForStatic) fs.WriteFileString("/etc/sysconfig/network-scripts/ifcfg-ethdhcp", expectedNetworkConfigurationForDHCP) fs.WriteFileString("/etc/dhcp/dhclient.conf", expectedDhclientConfiguration) err := netManager.SetupNetworking(boshsettings.Networks{"dhcp-network": dhcpNetwork, "static-network": staticNetwork}, nil) Expect(err).ToNot(HaveOccurred()) networkConfig := fs.GetFileTestStat("/etc/sysconfig/network-scripts/ifcfg-ethstatic") Expect(networkConfig).ToNot(BeNil()) Expect(networkConfig.StringContents()).To(Equal(expectedNetworkConfigurationForStatic)) dhcpConfig := fs.GetFileTestStat("/etc/dhcp/dhclient.conf") Expect(dhcpConfig.StringContents()).To(Equal(expectedDhclientConfiguration)) Expect(len(cmdRunner.RunCommands)).To(Equal(0)) }) It("restarts the networks if /etc/dhcp/dhclient.conf changes", func() { stubInterfaces(map[string]boshsettings.Network{ "ethdhcp": dhcpNetwork, "ethstatic": staticNetwork, }) fs.WriteFileString("/etc/sysconfig/network-scripts/ifcfg-ethstatic", expectedNetworkConfigurationForStatic) err := netManager.SetupNetworking(boshsettings.Networks{"dhcp-network": dhcpNetwork, "static-network": staticNetwork}, nil) Expect(err).ToNot(HaveOccurred()) networkConfig := fs.GetFileTestStat("/etc/sysconfig/network-scripts/ifcfg-ethstatic") Expect(networkConfig).ToNot(BeNil()) Expect(networkConfig.StringContents()).To(Equal(expectedNetworkConfigurationForStatic)) Expect(len(cmdRunner.RunCommands)).To(Equal(1)) Expect(cmdRunner.RunCommands[0]).To(Equal([]string{"service", "network", "restart"})) }) Context("when manual networks were not configured with proper IP addresses", func() { BeforeEach(func() { interfaceAddrsProvider.GetInterfaceAddresses = []boship.InterfaceAddress{ boship.NewSimpleInterfaceAddress("ethstatic", "1.2.3.5"), } }) It("fails", func() { stubInterfaces(map[string]boshsettings.Network{ "ethstatic": staticNetwork, }) errCh := make(chan error) err := netManager.SetupNetworking(boshsettings.Networks{"static-network": staticNetwork}, errCh) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("Validating static network configuration")) }) }) Context("when dns is not properly configured", func() { BeforeEach(func() { fs.WriteFileString("/etc/resolv.conf", "") }) It("fails", func() { staticNetwork = boshsettings.Network{ Type: "manual", IP: "1.2.3.4", Default: []string{"dns"}, DNS: []string{"8.8.8.8"}, Netmask: "255.255.255.0", Gateway: "3.4.5.6", Mac: "fake-static-mac-address", } stubInterfaces(map[string]boshsettings.Network{ "ethstatic": staticNetwork, }) errCh := make(chan error) err := netManager.SetupNetworking(boshsettings.Networks{"static-network": staticNetwork}, errCh) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("Validating dns configuration")) }) }) It("broadcasts MAC addresses for all interfaces", func() { stubInterfaces(map[string]boshsettings.Network{ "ethdhcp": dhcpNetwork, "ethstatic": staticNetwork, }) errCh := make(chan error) err := netManager.SetupNetworking(boshsettings.Networks{"dhcp-network": dhcpNetwork, "static-network": staticNetwork}, errCh) Expect(err).ToNot(HaveOccurred()) broadcastErr := <-errCh // wait for all arpings Expect(broadcastErr).ToNot(HaveOccurred()) Expect(addressBroadcaster.BroadcastMACAddressesAddresses).To(Equal([]boship.InterfaceAddress{ boship.NewSimpleInterfaceAddress("ethstatic", "1.2.3.4"), boship.NewResolvingInterfaceAddress("ethdhcp", ipResolver), })) }) It("skips vip networks", func() { stubInterfaces(map[string]boshsettings.Network{ "ethdhcp": dhcpNetwork, "ethstatic": staticNetwork, }) vipNetwork := boshsettings.Network{ Type: "vip", Default: []string{"dns"}, DNS: []string{"4.4.4.4", "5.5.5.5"}, Mac: "fake-vip-mac-address", IP: "9.8.7.6", } err := netManager.SetupNetworking(boshsettings.Networks{ "dhcp-network": dhcpNetwork, "static-network": staticNetwork, "vip-network": vipNetwork, }, nil) Expect(err).ToNot(HaveOccurred()) networkConfig := fs.GetFileTestStat("/etc/sysconfig/network-scripts/ifcfg-ethstatic") Expect(networkConfig).ToNot(BeNil()) Expect(networkConfig.StringContents()).To(Equal(expectedNetworkConfigurationForStatic)) }) It("doesn't use vip networks dns", func() { stubInterfaces(map[string]boshsettings.Network{ "ethstatic": staticNetwork, }) vipNetwork := boshsettings.Network{ Type: "vip", Default: []string{"dns"}, DNS: []string{"4.4.4.4", "5.5.5.5"}, Mac: "fake-vip-mac-address", IP: "9.8.7.6", } err := netManager.SetupNetworking(boshsettings.Networks{ "vip-network": vipNetwork, "static-network": staticNetwork, }, nil) Expect(err).ToNot(HaveOccurred()) networkConfig := fs.GetFileTestStat("/etc/sysconfig/network-scripts/ifcfg-ethstatic") Expect(networkConfig).ToNot(BeNil()) Expect(networkConfig.StringContents()).ToNot(ContainSubstring("4.4.4.4")) Expect(networkConfig.StringContents()).ToNot(ContainSubstring("5.5.5.5")) }) Context("when no MAC address is provided in the settings", func() { var staticNetworkWithoutMAC boshsettings.Network BeforeEach(func() { staticNetworkWithoutMAC = boshsettings.Network{ Type: "manual", IP: "1.2.3.4", Netmask: "255.255.255.0", Gateway: "3.4.5.6", DNS: []string{"8.8.8.8", "9.9.9.9"}, Default: []string{"dns"}, } }) It("configures network for single device", func() { stubInterfaces( map[string]boshsettings.Network{ "ethstatic": staticNetwork, }, ) err := netManager.SetupNetworking(boshsettings.Networks{ "static-network": staticNetworkWithoutMAC, }, nil) Expect(err).ToNot(HaveOccurred()) networkConfig := fs.GetFileTestStat("/etc/sysconfig/network-scripts/ifcfg-ethstatic") Expect(networkConfig).ToNot(BeNil()) Expect(networkConfig.StringContents()).To(Equal(expectedNetworkConfigurationForStatic)) }) It("configures network for single device, when a virtual device is also present", func() { stubInterfacesWithVirtual( map[string]boshsettings.Network{ "ethstatic": staticNetwork, }, []string{"virtual"}, ) err := netManager.SetupNetworking(boshsettings.Networks{ "static-network": staticNetworkWithoutMAC, }, nil) Expect(err).ToNot(HaveOccurred()) physicalNetworkConfig := fs.GetFileTestStat("/etc/sysconfig/network-scripts/ifcfg-ethstatic") Expect(physicalNetworkConfig).ToNot(BeNil()) Expect(physicalNetworkConfig.StringContents()).To(Equal(expectedNetworkConfigurationForStatic)) virtualNetworkConfig := fs.GetFileTestStat("/etc/sysconfig/network-scripts/ifcfg-virtual") Expect(virtualNetworkConfig).To(BeNil()) }) }) }) Describe("GetConfiguredNetworkInterfaces", func() { Context("when there are network devices", func() { BeforeEach(func() { interfacePaths := []string{} interfacePaths = append(interfacePaths, writeNetworkDevice("fake-eth0", "aa:bb", true)) interfacePaths = append(interfacePaths, writeNetworkDevice("fake-eth1", "cc:dd", true)) interfacePaths = append(interfacePaths, writeNetworkDevice("fake-eth2", "ee:ff", true)) fs.SetGlob("/sys/class/net/*", interfacePaths) }) writeIfcgfFile := func(iface string) { fs.WriteFileString(fmt.Sprintf("/etc/sysconfig/network-scripts/ifcfg-%s", iface), "fake-config") } It("returns networks that have ifcfg config present", func() { writeIfcgfFile("fake-eth0") writeIfcgfFile("fake-eth2") interfaces, err := netManager.GetConfiguredNetworkInterfaces() Expect(err).ToNot(HaveOccurred()) Expect(interfaces).To(ConsistOf("fake-eth0", "fake-eth2")) }) }) Context("when there are no network devices", func() { It("returns empty list", func() { interfaces, err := netManager.GetConfiguredNetworkInterfaces() Expect(err).ToNot(HaveOccurred()) Expect(interfaces).To(Equal([]string{})) }) }) }) }
package disk_test import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" "errors" . "github.com/cloudfoundry/bosh-agent/platform/disk" fakesys "github.com/cloudfoundry/bosh-utils/system/fakes" ) var _ = Describe("Linux Formatter", func() { Describe("when using swap", func() { It("format as swap disk if partition has not been formatted", func() { fakeRunner := fakesys.NewFakeCmdRunner() fakeFs := fakesys.NewFakeFileSystem() fakeRunner.AddCmdResult("blkid -p /dev/xvda2", fakesys.FakeCmdResult{ExitStatus: 2, Error: errors.New("Exit code 2")}) formatter := NewLinuxFormatter(fakeRunner, fakeFs) formatter.Format("/dev/xvda2", FileSystemSwap) Expect(2).To(Equal(len(fakeRunner.RunCommands))) Expect(fakeRunner.RunCommands[1]).To(Equal([]string{"mkswap", "/dev/xvda2"})) }) It("reformats the partition if is not formatted as swap", func() { fakeRunner := fakesys.NewFakeCmdRunner() fakeFs := fakesys.NewFakeFileSystem() fakeRunner.AddCmdResult("blkid -p /dev/xvda1", fakesys.FakeCmdResult{Stdout: `xxxxx TYPE="ext4" yyyy zzzz`}) formatter := NewLinuxFormatter(fakeRunner, fakeFs)
func describeDummyPlatform() { var ( platform Platform collector boshstats.Collector fs *fakesys.FakeFileSystem cmdRunner boshsys.CmdRunner dirProvider boshdirs.Provider devicePathResolver boshdpresolv.DevicePathResolver logger boshlog.Logger ) BeforeEach(func() { collector = &fakestats.FakeCollector{} fs = fakesys.NewFakeFileSystem() cmdRunner = fakesys.NewFakeCmdRunner() dirProvider = boshdirs.NewProvider("/fake-dir") devicePathResolver = fakedpresolv.NewFakeDevicePathResolver() logger = boshlog.NewLogger(boshlog.LevelNone) }) JustBeforeEach(func() { platform = NewDummyPlatform( collector, fs, cmdRunner, dirProvider, devicePathResolver, logger, ) }) Describe("GetDefaultNetwork", func() { It("returns the contents of dummy-defaults-network-settings.json since that's what the dummy cpi writes", func() { settingsFilePath := "/fake-dir/bosh/dummy-default-network-settings.json" fs.WriteFileString(settingsFilePath, `{"IP": "1.2.3.4"}`) network, err := platform.GetDefaultNetwork() Expect(err).NotTo(HaveOccurred()) Expect(network.IP).To(Equal("1.2.3.4")) }) }) Describe("GetCertManager", func() { It("returs a dummy cert manager", func() { certManager := platform.GetCertManager() Expect(certManager.UpdateCertificates("")).Should(BeNil()) }) }) Describe("UnmountPersistentDisk", func() { Context("when there are two mounted persistent disks in the mounts json", func() { BeforeEach(func() { var mounts []mount mounts = append(mounts, mount{MountDir: "dir1", DiskCid: "cid1"}) mounts = append(mounts, mount{MountDir: "dir2", DiskCid: "cid2"}) mountsJSON, _ := json.Marshal(mounts) mountsPath := path.Join(dirProvider.BoshDir(), "mounts.json") fs.WriteFile(mountsPath, mountsJSON) }) It("removes one of the disks from the mounts json", func() { unmounted, err := platform.UnmountPersistentDisk(settings.DiskSettings{ID: "cid1"}) Expect(err).NotTo(HaveOccurred()) Expect(unmounted).To(Equal(true)) _, isMountPoint, err := platform.IsMountPoint("dir1") Expect(isMountPoint).To(Equal(false)) _, isMountPoint, err = platform.IsMountPoint("dir2") Expect(isMountPoint).To(Equal(true)) }) }) }) Describe("SetUserPassword", func() { It("writes the password to a file", func() { err := platform.SetUserPassword("user-name", "fake-password") Expect(err).NotTo(HaveOccurred()) userPasswordsPath := path.Join(dirProvider.BoshDir(), "user-name", CredentialFileName) password, err := fs.ReadFileString(userPasswordsPath) Expect(err).NotTo(HaveOccurred()) Expect(password).To(Equal("fake-password")) }) It("writes the passwords to different files for each user", func() { err := platform.SetUserPassword("user-name1", "fake-password1") Expect(err).NotTo(HaveOccurred()) err = platform.SetUserPassword("user-name2", "fake-password2") Expect(err).NotTo(HaveOccurred()) userPasswordsPath := path.Join(dirProvider.BoshDir(), "user-name1", CredentialFileName) password, err := fs.ReadFileString(userPasswordsPath) Expect(err).NotTo(HaveOccurred()) Expect(password).To(Equal("fake-password1")) userPasswordsPath = path.Join(dirProvider.BoshDir(), "user-name2", CredentialFileName) password, err = fs.ReadFileString(userPasswordsPath) Expect(err).NotTo(HaveOccurred()) Expect(password).To(Equal("fake-password2")) }) }) Describe("SetupDataDir", func() { It("creates a link from BASEDIR/sys to BASEDIR/data/sys", func() { err := platform.SetupDataDir() Expect(err).NotTo(HaveOccurred()) stat := fs.GetFileTestStat("/fake-dir/sys") Expect(stat).ToNot(BeNil()) Expect(stat.SymlinkTarget).To(Equal("/fake-dir/data/sys")) }) }) }
func describeUbuntuNetManager() { var ( fs *fakesys.FakeFileSystem cmdRunner *fakesys.FakeCmdRunner ipResolver *fakeip.FakeResolver addressBroadcaster *fakearp.FakeAddressBroadcaster interfaceAddrsProvider *fakeip.FakeInterfaceAddressesProvider netManager UbuntuNetManager interfaceConfigurationCreator InterfaceConfigurationCreator ) writeNetworkDevice := func(iface string, macAddress string, isPhysical bool) string { interfacePath := fmt.Sprintf("/sys/class/net/%s", iface) fs.WriteFile(interfacePath, []byte{}) if isPhysical { fs.WriteFile(fmt.Sprintf("/sys/class/net/%s/device", iface), []byte{}) } fs.WriteFileString(fmt.Sprintf("/sys/class/net/%s/address", iface), fmt.Sprintf("%s\n", macAddress)) return interfacePath } stubInterfacesWithVirtual := func(physicalInterfaces map[string]boshsettings.Network, virtualInterfaces []string) { interfacePaths := []string{} for iface, networkSettings := range physicalInterfaces { interfacePaths = append(interfacePaths, writeNetworkDevice(iface, networkSettings.Mac, true)) } for _, iface := range virtualInterfaces { interfacePaths = append(interfacePaths, writeNetworkDevice(iface, "virtual", false)) } fs.SetGlob("/sys/class/net/*", interfacePaths) } stubInterfaces := func(physicalInterfaces map[string]boshsettings.Network) { stubInterfacesWithVirtual(physicalInterfaces, nil) } BeforeEach(func() { fs = fakesys.NewFakeFileSystem() cmdRunner = fakesys.NewFakeCmdRunner() ipResolver = &fakeip.FakeResolver{} logger := boshlog.NewLogger(boshlog.LevelNone) interfaceConfigurationCreator = NewInterfaceConfigurationCreator(logger) addressBroadcaster = &fakearp.FakeAddressBroadcaster{} interfaceAddrsProvider = &fakeip.FakeInterfaceAddressesProvider{} interfaceAddrsValidator := boship.NewInterfaceAddressesValidator(interfaceAddrsProvider) dnsValidator := NewDNSValidator(fs) netManager = NewUbuntuNetManager( fs, cmdRunner, ipResolver, interfaceConfigurationCreator, interfaceAddrsValidator, dnsValidator, addressBroadcaster, logger, ).(UbuntuNetManager) }) Describe("ComputeNetworkConfig", func() { Context("when there is one manual network and neither is marked as default for DNS", func() { It("should use the manual network for DNS", func() { networks := boshsettings.Networks{ "manual": factory.Network{DNS: &[]string{"8.8.8.8"}}.Build(), } stubInterfaces(networks) _, _, dnsServers, err := netManager.ComputeNetworkConfig(networks) Expect(err).ToNot(HaveOccurred()) Expect(dnsServers).To(Equal([]string{"8.8.8.8"})) }) }) Context("when there is a vip network and a manual network and neither is marked as default for DNS", func() { It("should use the manual network for DNS", func() { networks := boshsettings.Networks{ "vip": boshsettings.Network{Type: "vip"}, "manual": factory.Network{Type: "manual", DNS: &[]string{"8.8.8.8"}}.Build(), } stubInterfaces(networks) _, _, dnsServers, err := netManager.ComputeNetworkConfig(networks) Expect(err).ToNot(HaveOccurred()) Expect(dnsServers).To(Equal([]string{"8.8.8.8"})) }) }) Context("when there is a vip network and a manual network and the manual network is marked as default for DNS", func() { It("should use the manual network for DNS", func() { networks := boshsettings.Networks{ "vip": boshsettings.Network{Type: "vip"}, "manual": factory.Network{Type: "manual", DNS: &[]string{"8.8.8.8"}, Default: []string{"dns"}}.Build(), } stubInterfaces(networks) _, _, dnsServers, err := netManager.ComputeNetworkConfig(networks) Expect(err).ToNot(HaveOccurred()) Expect(dnsServers).To(Equal([]string{"8.8.8.8"})) }) }) Context("when specified more than one DNS", func() { It("extracts all DNS servers from the network configured as default DNS", func() { networks := boshsettings.Networks{ "default": factory.Network{ IP: "10.10.0.32", Netmask: "255.255.255.0", Mac: "aa::bb::cc", Default: []string{"dns", "gateway"}, DNS: &[]string{"54.209.78.6", "127.0.0.5"}, Gateway: "10.10.0.1", }.Build(), } stubInterfaces(networks) staticInterfaceConfigurations, dhcpInterfaceConfigurations, dnsServers, err := netManager.ComputeNetworkConfig(networks) Expect(err).ToNot(HaveOccurred()) Expect(staticInterfaceConfigurations).To(Equal([]StaticInterfaceConfiguration{ { Name: "default", Address: "10.10.0.32", Netmask: "255.255.255.0", Network: "10.10.0.0", IsDefaultForGateway: true, Broadcast: "10.10.0.255", Mac: "aa::bb::cc", Gateway: "10.10.0.1", }, })) Expect(dhcpInterfaceConfigurations).To(BeEmpty()) Expect(dnsServers).To(Equal([]string{"54.209.78.6", "127.0.0.5"})) }) }) }) Describe("SetupNetworking", func() { var ( dhcpNetwork boshsettings.Network staticNetwork boshsettings.Network expectedNetworkConfigurationForStaticAndDhcp string ) BeforeEach(func() { dhcpNetwork = boshsettings.Network{ Type: "dynamic", Default: []string{"dns"}, DNS: []string{"8.8.8.8", "9.9.9.9"}, Mac: "fake-dhcp-mac-address", } staticNetwork = boshsettings.Network{ Type: "manual", IP: "1.2.3.4", Default: []string{"gateway"}, Netmask: "255.255.255.0", Gateway: "3.4.5.6", Mac: "fake-static-mac-address", } interfaceAddrsProvider.GetInterfaceAddresses = []boship.InterfaceAddress{ boship.NewSimpleInterfaceAddress("ethstatic", "1.2.3.4"), } fs.WriteFileString("/etc/resolv.conf", ` nameserver 8.8.8.8 nameserver 9.9.9.9 `) expectedNetworkConfigurationForStaticAndDhcp = `# Generated by bosh-agent auto lo iface lo inet loopback auto ethdhcp iface ethdhcp inet dhcp auto ethstatic iface ethstatic inet static address 1.2.3.4 network 1.2.3.0 netmask 255.255.255.0 broadcast 1.2.3.255 gateway 3.4.5.6 dns-nameservers 8.8.8.8 9.9.9.9` }) It("writes interfaces in /etc/network/interfaces in alphabetic order", func() { anotherDHCPNetwork := boshsettings.Network{ Type: "dynamic", Default: []string{"dns"}, DNS: []string{"8.8.8.8", "9.9.9.9"}, Mac: "fake-another-mac-address", } stubInterfaces(map[string]boshsettings.Network{ "ethstatic": staticNetwork, "ethdhcp1": dhcpNetwork, "ethdhcp0": anotherDHCPNetwork, }) err := netManager.SetupNetworking(boshsettings.Networks{ "dhcp-network-1": dhcpNetwork, "dhcp-network-2": anotherDHCPNetwork, "static-network": staticNetwork, }, nil) Expect(err).ToNot(HaveOccurred()) networkConfig := fs.GetFileTestStat("/etc/network/interfaces") Expect(networkConfig).ToNot(BeNil()) expectedNetworkConfigurationForStaticAndDhcp = `# Generated by bosh-agent auto lo iface lo inet loopback auto ethdhcp0 iface ethdhcp0 inet dhcp auto ethdhcp1 iface ethdhcp1 inet dhcp auto ethstatic iface ethstatic inet static address 1.2.3.4 network 1.2.3.0 netmask 255.255.255.0 broadcast 1.2.3.255 gateway 3.4.5.6 dns-nameservers 8.8.8.8 9.9.9.9` Expect(networkConfig.StringContents()).To(Equal(expectedNetworkConfigurationForStaticAndDhcp)) }) It("configures gateway, broadcast and dns for default network only", func() { staticNetwork = boshsettings.Network{ Type: "manual", IP: "1.2.3.4", Netmask: "255.255.255.0", Gateway: "3.4.5.6", Mac: "fake-static-mac-address", } secondStaticNetwork := boshsettings.Network{ Type: "manual", IP: "5.6.7.8", Netmask: "255.255.255.0", Gateway: "6.7.8.9", Mac: "second-fake-static-mac-address", DNS: []string{"8.8.8.8"}, Default: []string{"gateway", "dns"}, } stubInterfaces(map[string]boshsettings.Network{ "eth0": staticNetwork, "eth1": secondStaticNetwork, }) interfaceAddrsProvider.GetInterfaceAddresses = []boship.InterfaceAddress{ boship.NewSimpleInterfaceAddress("eth0", "1.2.3.4"), boship.NewSimpleInterfaceAddress("eth1", "5.6.7.8"), } err := netManager.SetupNetworking(boshsettings.Networks{ "static-1": staticNetwork, "static-2": secondStaticNetwork, }, nil) Expect(err).ToNot(HaveOccurred()) networkConfig := fs.GetFileTestStat("/etc/network/interfaces") Expect(networkConfig).ToNot(BeNil()) Expect(networkConfig.StringContents()).To(Equal(`# Generated by bosh-agent auto lo iface lo inet loopback auto eth0 iface eth0 inet static address 1.2.3.4 network 1.2.3.0 netmask 255.255.255.0 auto eth1 iface eth1 inet static address 5.6.7.8 network 5.6.7.0 netmask 255.255.255.0 broadcast 5.6.7.255 gateway 6.7.8.9 dns-nameservers 8.8.8.8`)) }) It("writes /etc/network/interfaces without dns-namservers if there are no dns servers", func() { staticNetworkWithoutDNS := boshsettings.Network{ Type: "manual", IP: "1.2.3.4", Default: []string{"gateway"}, Netmask: "255.255.255.0", Gateway: "3.4.5.6", Mac: "fake-static-mac-address", } stubInterfaces(map[string]boshsettings.Network{ "ethstatic": staticNetworkWithoutDNS, }) err := netManager.SetupNetworking(boshsettings.Networks{"static-network": staticNetworkWithoutDNS}, nil) Expect(err).ToNot(HaveOccurred()) networkConfig := fs.GetFileTestStat("/etc/network/interfaces") Expect(networkConfig).ToNot(BeNil()) Expect(networkConfig.StringContents()).To(Equal(`# Generated by bosh-agent auto lo iface lo inet loopback auto ethstatic iface ethstatic inet static address 1.2.3.4 network 1.2.3.0 netmask 255.255.255.0 broadcast 1.2.3.255 gateway 3.4.5.6 `)) }) It("returns errors from glob /sys/class/net/", func() { fs.GlobErr = errors.New("fs-glob-error") err := netManager.SetupNetworking(boshsettings.Networks{"dhcp-network": dhcpNetwork, "static-network": staticNetwork}, nil) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("fs-glob-error")) }) It("returns errors from writing the network configuration", func() { stubInterfaces(map[string]boshsettings.Network{ "dhcp": dhcpNetwork, "static": staticNetwork, }) fs.WriteFileError = errors.New("fs-write-file-error") err := netManager.SetupNetworking(boshsettings.Networks{"dhcp-network": dhcpNetwork, "static-network": staticNetwork}, nil) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("fs-write-file-error")) }) It("returns errors when it can't creating network interface configurations", func() { stubInterfaces(map[string]boshsettings.Network{ "ethdhcp": dhcpNetwork, "ethstatic": staticNetwork, }) staticNetwork.Netmask = "not an ip" //will cause InterfaceConfigurationCreator to fail err := netManager.SetupNetworking(boshsettings.Networks{"static-network": staticNetwork}, nil) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("Creating interface configurations")) }) It("writes a dhcp configuration if there are dhcp networks", func() { stubInterfaces(map[string]boshsettings.Network{ "ethdhcp": dhcpNetwork, "ethstatic": staticNetwork, }) err := netManager.SetupNetworking(boshsettings.Networks{"dhcp-network": dhcpNetwork, "static-network": staticNetwork}, nil) Expect(err).ToNot(HaveOccurred()) dhcpConfig := fs.GetFileTestStat("/etc/dhcp/dhclient.conf") Expect(dhcpConfig).ToNot(BeNil()) Expect(dhcpConfig.StringContents()).To(Equal(`# Generated by bosh-agent option rfc3442-classless-static-routes code 121 = array of unsigned integer 8; send host-name "<hostname>"; request subnet-mask, broadcast-address, time-offset, routers, domain-name, domain-name-servers, domain-search, host-name, netbios-name-servers, netbios-scope, interface-mtu, rfc3442-classless-static-routes, ntp-servers; prepend domain-name-servers 8.8.8.8, 9.9.9.9; `)) }) It("writes a dhcp configuration without prepended dns servers if there are no dns servers specified", func() { dhcpNetworkWithoutDNS := boshsettings.Network{ Type: "dynamic", Mac: "fake-dhcp-mac-address", } stubInterfaces(map[string]boshsettings.Network{ "ethdhcp": dhcpNetwork, }) err := netManager.SetupNetworking(boshsettings.Networks{"dhcp-network": dhcpNetworkWithoutDNS}, nil) Expect(err).ToNot(HaveOccurred()) dhcpConfig := fs.GetFileTestStat("/etc/dhcp/dhclient.conf") Expect(dhcpConfig).ToNot(BeNil()) Expect(dhcpConfig.StringContents()).To(Equal(`# Generated by bosh-agent option rfc3442-classless-static-routes code 121 = array of unsigned integer 8; send host-name "<hostname>"; request subnet-mask, broadcast-address, time-offset, routers, domain-name, domain-name-servers, domain-search, host-name, netbios-name-servers, netbios-scope, interface-mtu, rfc3442-classless-static-routes, ntp-servers; `)) }) It("returns an error if it can't write a dhcp configuration", func() { stubInterfaces(map[string]boshsettings.Network{ "ethdhcp": dhcpNetwork, "ethstatic": staticNetwork, }) fs.WriteFileErrors["/etc/dhcp/dhclient.conf"] = errors.New("dhclient.conf-write-error") err := netManager.SetupNetworking(boshsettings.Networks{"dhcp-network": dhcpNetwork, "static-network": staticNetwork}, nil) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("dhclient.conf-write-error")) }) It("doesn't write a dhcp configuration if there are no dhcp networks", func() { stubInterfaces(map[string]boshsettings.Network{ "ethstatic": staticNetwork, }) err := netManager.SetupNetworking(boshsettings.Networks{"static-network": staticNetwork}, nil) Expect(err).ToNot(HaveOccurred()) dhcpConfig := fs.GetFileTestStat("/etc/dhcp/dhclient.conf") Expect(dhcpConfig).To(BeNil()) }) It("restarts the networks if /etc/network/interfaces changes", func() { initialDhcpConfig := `# Generated by bosh-agent option rfc3442-classless-static-routes code 121 = array of unsigned integer 8; send host-name "<hostname>"; request subnet-mask, broadcast-address, time-offset, routers, domain-name, domain-name-servers, domain-search, host-name, netbios-name-servers, netbios-scope, interface-mtu, rfc3442-classless-static-routes, ntp-servers; prepend domain-name-servers 8.8.8.8, 9.9.9.9; ` stubInterfaces(map[string]boshsettings.Network{ "ethdhcp": dhcpNetwork, "ethstatic": staticNetwork, }) fs.WriteFileString("/etc/dhcp/dhclient.conf", initialDhcpConfig) err := netManager.SetupNetworking(boshsettings.Networks{"dhcp-network": dhcpNetwork, "static-network": staticNetwork}, nil) Expect(err).ToNot(HaveOccurred()) Expect(len(cmdRunner.RunCommands)).To(Equal(5)) Expect(cmdRunner.RunCommands[0]).To(Equal([]string{"pkill", "dhclient"})) Expect(cmdRunner.RunCommands[1:3]).To(ContainElement([]string{"resolvconf", "-d", "ethdhcp.dhclient"})) Expect(cmdRunner.RunCommands[1:3]).To(ContainElement([]string{"resolvconf", "-d", "ethstatic.dhclient"})) Expect(cmdRunner.RunCommands[3]).To(Equal([]string{"ifdown", "--force", "ethdhcp", "ethstatic"})) Expect(cmdRunner.RunCommands[4]).To(Equal([]string{"ifup", "--force", "ethdhcp", "ethstatic"})) }) It("doesn't restart the networks if /etc/network/interfaces and /etc/dhcp/dhclient.conf don't change", func() { initialDhcpConfig := `# Generated by bosh-agent option rfc3442-classless-static-routes code 121 = array of unsigned integer 8; send host-name "<hostname>"; request subnet-mask, broadcast-address, time-offset, routers, domain-name, domain-name-servers, domain-search, host-name, netbios-name-servers, netbios-scope, interface-mtu, rfc3442-classless-static-routes, ntp-servers; prepend domain-name-servers 8.8.8.8, 9.9.9.9; ` stubInterfaces(map[string]boshsettings.Network{ "ethdhcp": dhcpNetwork, "ethstatic": staticNetwork, }) fs.WriteFileString("/etc/network/interfaces", expectedNetworkConfigurationForStaticAndDhcp) fs.WriteFileString("/etc/dhcp/dhclient.conf", initialDhcpConfig) err := netManager.SetupNetworking(boshsettings.Networks{"dhcp-network": dhcpNetwork, "static-network": staticNetwork}, nil) Expect(err).ToNot(HaveOccurred()) networkConfig := fs.GetFileTestStat("/etc/network/interfaces") Expect(networkConfig.StringContents()).To(Equal(expectedNetworkConfigurationForStaticAndDhcp)) dhcpConfig := fs.GetFileTestStat("/etc/dhcp/dhclient.conf") Expect(dhcpConfig.StringContents()).To(Equal(initialDhcpConfig)) Expect(len(cmdRunner.RunCommands)).To(Equal(0)) }) It("restarts the networks if /etc/dhcp/dhclient.conf changes", func() { stubInterfaces(map[string]boshsettings.Network{ "ethdhcp": dhcpNetwork, "ethstatic": staticNetwork, }) fs.WriteFileString("/etc/network/interfaces", expectedNetworkConfigurationForStaticAndDhcp) err := netManager.SetupNetworking(boshsettings.Networks{"dhcp-network": dhcpNetwork, "static-network": staticNetwork}, nil) Expect(err).ToNot(HaveOccurred()) networkConfig := fs.GetFileTestStat("/etc/network/interfaces") Expect(networkConfig.StringContents()).To(Equal(expectedNetworkConfigurationForStaticAndDhcp)) Expect(len(cmdRunner.RunCommands)).To(Equal(5)) Expect(cmdRunner.RunCommands[0]).To(Equal([]string{"pkill", "dhclient"})) Expect(cmdRunner.RunCommands[1:3]).To(ContainElement([]string{"resolvconf", "-d", "ethdhcp.dhclient"})) Expect(cmdRunner.RunCommands[1:3]).To(ContainElement([]string{"resolvconf", "-d", "ethstatic.dhclient"})) Expect(cmdRunner.RunCommands[3]).To(Equal([]string{"ifdown", "--force", "ethdhcp", "ethstatic"})) Expect(cmdRunner.RunCommands[4]).To(Equal([]string{"ifup", "--force", "ethdhcp", "ethstatic"})) }) It("broadcasts MAC addresses for all interfaces", func() { stubInterfaces(map[string]boshsettings.Network{ "ethdhcp": dhcpNetwork, "ethstatic": staticNetwork, }) errCh := make(chan error) err := netManager.SetupNetworking(boshsettings.Networks{"dhcp-network": dhcpNetwork, "static-network": staticNetwork}, errCh) Expect(err).ToNot(HaveOccurred()) broadcastErr := <-errCh // wait for all arpings Expect(broadcastErr).ToNot(HaveOccurred()) Expect(addressBroadcaster.BroadcastMACAddressesAddresses).To(Equal([]boship.InterfaceAddress{ boship.NewSimpleInterfaceAddress("ethstatic", "1.2.3.4"), boship.NewResolvingInterfaceAddress("ethdhcp", ipResolver), })) }) It("skips vip networks", func() { stubInterfaces(map[string]boshsettings.Network{ "ethdhcp": dhcpNetwork, "ethstatic": staticNetwork, }) vipNetwork := boshsettings.Network{ Type: "vip", Default: []string{"dns"}, DNS: []string{"8.8.8.8", "9.9.9.9"}, Mac: "fake-vip-mac-address", IP: "9.8.7.6", } err := netManager.SetupNetworking(boshsettings.Networks{ "dhcp-network": dhcpNetwork, "static-network": staticNetwork, "vip-network": vipNetwork, }, nil) Expect(err).ToNot(HaveOccurred()) networkConfig := fs.GetFileTestStat("/etc/network/interfaces") Expect(networkConfig).ToNot(BeNil()) Expect(networkConfig.StringContents()).To(Equal(expectedNetworkConfigurationForStaticAndDhcp)) }) Context("when manual networks were not configured with proper IP addresses", func() { BeforeEach(func() { interfaceAddrsProvider.GetInterfaceAddresses = []boship.InterfaceAddress{ boship.NewSimpleInterfaceAddress("ethstatic", "1.2.3.5"), } }) It("fails", func() { stubInterfaces(map[string]boshsettings.Network{ "ethstatic": staticNetwork, }) errCh := make(chan error) err := netManager.SetupNetworking(boshsettings.Networks{"static-network": staticNetwork}, errCh) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("Validating static network configuration")) }) }) Context("when dns is not properly configured", func() { BeforeEach(func() { fs.WriteFileString("/etc/resolv.conf", "") }) It("fails", func() { staticNetwork = boshsettings.Network{ Type: "manual", IP: "1.2.3.4", Default: []string{"dns"}, DNS: []string{"8.8.8.8"}, Netmask: "255.255.255.0", Gateway: "3.4.5.6", Mac: "fake-static-mac-address", } stubInterfaces(map[string]boshsettings.Network{ "ethstatic": staticNetwork, }) errCh := make(chan error) err := netManager.SetupNetworking(boshsettings.Networks{"static-network": staticNetwork}, errCh) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("Validating dns configuration")) }) }) Context("when no MAC address is provided in the settings", func() { It("configures network for single device", func() { staticNetworkWithoutMAC := boshsettings.Network{ Type: "manual", IP: "2.2.2.2", Default: []string{"gateway"}, Netmask: "255.255.255.0", Gateway: "3.4.5.6", } stubInterfaces( map[string]boshsettings.Network{ "ethstatic": staticNetwork, }, ) interfaceAddrsProvider.GetInterfaceAddresses = []boship.InterfaceAddress{ boship.NewSimpleInterfaceAddress("ethstatic", "2.2.2.2"), } err := netManager.SetupNetworking(boshsettings.Networks{ "static-network": staticNetworkWithoutMAC, }, nil) Expect(err).ToNot(HaveOccurred()) networkConfig := fs.GetFileTestStat("/etc/network/interfaces") Expect(networkConfig).ToNot(BeNil()) expectedNetworkConfiguration := `# Generated by bosh-agent auto lo iface lo inet loopback auto ethstatic iface ethstatic inet static address 2.2.2.2 network 2.2.2.0 netmask 255.255.255.0 broadcast 2.2.2.255 gateway 3.4.5.6 ` Expect(networkConfig.StringContents()).To(Equal(expectedNetworkConfiguration)) }) It("configures network for a single physical device, when a virtual device is also present", func() { staticNetworkWithoutMAC := boshsettings.Network{ Type: "manual", IP: "2.2.2.2", Default: []string{"gateway"}, Netmask: "255.255.255.0", Gateway: "3.4.5.6", } stubInterfacesWithVirtual( map[string]boshsettings.Network{ "ethstatic": staticNetwork, }, []string{"virtual"}, ) interfaceAddrsProvider.GetInterfaceAddresses = []boship.InterfaceAddress{ boship.NewSimpleInterfaceAddress("ethstatic", "2.2.2.2"), } err := netManager.SetupNetworking(boshsettings.Networks{ "static-network": staticNetworkWithoutMAC, }, nil) Expect(err).ToNot(HaveOccurred()) networkConfig := fs.GetFileTestStat("/etc/network/interfaces") Expect(networkConfig).ToNot(BeNil()) expectedNetworkConfiguration := `# Generated by bosh-agent auto lo iface lo inet loopback auto ethstatic iface ethstatic inet static address 2.2.2.2 network 2.2.2.0 netmask 255.255.255.0 broadcast 2.2.2.255 gateway 3.4.5.6 ` Expect(networkConfig.StringContents()).To(Equal(expectedNetworkConfiguration)) }) }) }) Describe("GetConfiguredNetworkInterfaces", func() { Context("when there are network devices", func() { BeforeEach(func() { interfacePaths := []string{} interfacePaths = append(interfacePaths, writeNetworkDevice("fake-eth0", "aa:bb", true)) interfacePaths = append(interfacePaths, writeNetworkDevice("fake-eth1", "cc:dd", true)) interfacePaths = append(interfacePaths, writeNetworkDevice("fake-eth2", "ee:ff", true)) fs.SetGlob("/sys/class/net/*", interfacePaths) }) It("returns networks that are defined in /etc/network/interfaces", func() { cmdRunner.AddCmdResult("ifup --no-act fake-eth0", fakesys.FakeCmdResult{ Stdout: "", Stderr: "ifup: interface fake-eth0 already configured", ExitStatus: 0, }) cmdRunner.AddCmdResult("ifup --no-act fake-eth1", fakesys.FakeCmdResult{ Stdout: "", Stderr: "Ignoring unknown interface fake-eth1=fake-eth1.", ExitStatus: 0, }) cmdRunner.AddCmdResult("ifup --no-act fake-eth2", fakesys.FakeCmdResult{ Stdout: "", Stderr: "ifup: interface fake-eth2 already configured", ExitStatus: 0, }) interfaces, err := netManager.GetConfiguredNetworkInterfaces() Expect(err).ToNot(HaveOccurred()) Expect(interfaces).To(ConsistOf("fake-eth0", "fake-eth2")) }) }) Context("when there are no network devices", func() { It("returns empty list", func() { interfaces, err := netManager.GetConfiguredNetworkInterfaces() Expect(err).ToNot(HaveOccurred()) Expect(interfaces).To(Equal([]string{})) }) }) }) }
func describeDummyPlatform() { var ( platform Platform collector boshstats.Collector fs *fakesys.FakeFileSystem cmdRunner boshsys.CmdRunner dirProvider boshdirs.Provider devicePathResolver boshdpresolv.DevicePathResolver logger boshlog.Logger ) BeforeEach(func() { collector = &fakestats.FakeCollector{} fs = fakesys.NewFakeFileSystem() cmdRunner = fakesys.NewFakeCmdRunner() dirProvider = boshdirs.NewProvider("/fake-dir") devicePathResolver = fakedpresolv.NewFakeDevicePathResolver() logger = boshlog.NewLogger(boshlog.LevelNone) }) JustBeforeEach(func() { platform = NewDummyPlatform( collector, fs, cmdRunner, dirProvider, devicePathResolver, logger, ) }) Describe("GetDefaultNetwork", func() { It("returns the contents of dummy-defaults-network-settings.json since that's what the dummy cpi writes", func() { settingsFilePath := "/fake-dir/bosh/dummy-default-network-settings.json" fs.WriteFileString(settingsFilePath, `{"IP": "1.2.3.4"}`) network, err := platform.GetDefaultNetwork() Expect(err).NotTo(HaveOccurred()) Expect(network.IP).To(Equal("1.2.3.4")) }) }) Describe("GetCertManager", func() { It("returns a dummy cert manager", func() { certManager := platform.GetCertManager() Expect(certManager.UpdateCertificates("")).Should(BeNil()) }) }) Describe("MountPersistentDisk", func() { var diskSettings boshsettings.DiskSettings var mountsPath, managedSettingsPath, formattedDisksPath string BeforeEach(func() { diskSettings = boshsettings.DiskSettings{ID: "somediskid"} mountsPath = filepath.Join(dirProvider.BoshDir(), "mounts.json") managedSettingsPath = filepath.Join(dirProvider.BoshDir(), "managed_disk_settings.json") formattedDisksPath = filepath.Join(dirProvider.BoshDir(), "formatted_disks.json") }) It("Mounts a persistent disk", func() { mountsContent, _ := fs.ReadFileString(mountsPath) Expect(mountsContent).To(Equal("")) err := platform.MountPersistentDisk(diskSettings, "/dev/potato") Expect(err).NotTo(HaveOccurred()) mountsContent, _ = fs.ReadFileString(mountsPath) Expect(mountsContent).To(Equal(`[{"MountDir":"/dev/potato","DiskCid":"somediskid"}]`)) }) It("Updates the managed disk settings", func() { lastMountedCid, _ := fs.ReadFileString(managedSettingsPath) Expect(lastMountedCid).To(Equal("")) err := platform.MountPersistentDisk(diskSettings, "/dev/potato") Expect(err).NotTo(HaveOccurred()) lastMountedCid, _ = fs.ReadFileString(managedSettingsPath) Expect(lastMountedCid).To(Equal("somediskid")) }) It("Updates the formatted disks", func() { formattedDisks, _ := fs.ReadFileString(formattedDisksPath) Expect(formattedDisks).To(Equal("")) err := platform.MountPersistentDisk(diskSettings, "/dev/potato") Expect(err).NotTo(HaveOccurred()) formattedDisks, _ = fs.ReadFileString(formattedDisksPath) Expect(formattedDisks).To(Equal(`[{"DiskCid":"somediskid"}]`)) }) Context("Device has already been mounted as expected", func() { BeforeEach(func() { fs.WriteFileString(managedSettingsPath, "somediskid") fs.WriteFileString(mountsPath, `[{"MountDir":"/dev/potato","DiskCid":"somediskid"}]`) }) It("Does not mount in new location", func() { err := platform.MountPersistentDisk(diskSettings, "/dev/potato") Expect(err).NotTo(HaveOccurred()) mountsContent, _ := fs.ReadFileString(mountsPath) Expect(mountsContent).To(Equal(`[{"MountDir":"/dev/potato","DiskCid":"somediskid"}]`)) }) }) }) Describe("UnmountPersistentDisk", func() { Context("when there are two mounted persistent disks in the mounts json", func() { BeforeEach(func() { var mounts []mount mounts = append(mounts, mount{MountDir: "dir1", DiskCid: "cid1"}) mounts = append(mounts, mount{MountDir: "dir2", DiskCid: "cid2"}) mountsJSON, err := json.Marshal(mounts) Expect(err).NotTo(HaveOccurred()) mountsPath := filepath.Join(dirProvider.BoshDir(), "mounts.json") fs.WriteFile(mountsPath, mountsJSON) }) It("removes one of the disks from the mounts json", func() { unmounted, err := platform.UnmountPersistentDisk(settings.DiskSettings{ID: "cid1"}) Expect(err).NotTo(HaveOccurred()) Expect(unmounted).To(Equal(true)) _, isMountPoint, err := platform.IsMountPoint("dir1") Expect(err).NotTo(HaveOccurred()) Expect(isMountPoint).To(Equal(false)) _, isMountPoint, err = platform.IsMountPoint("dir2") Expect(err).NotTo(HaveOccurred()) Expect(isMountPoint).To(Equal(true)) }) }) }) Describe("SetDiskAssociations", func() { It("writes the associations to the file", func() { diskName1 := "disk1" diskName2 := "disk2" err := platform.AssociateDisk(diskName1, boshsettings.DiskSettings{}) Expect(err).NotTo(HaveOccurred()) err = platform.AssociateDisk(diskName2, boshsettings.DiskSettings{}) Expect(err).NotTo(HaveOccurred()) diskAssociationsPath := filepath.Join(dirProvider.BoshDir(), "disk_associations.json") actualDiskNames := []string{} fileContent, err := fs.ReadFile(diskAssociationsPath) Expect(err).NotTo(HaveOccurred()) err = json.Unmarshal(fileContent, &actualDiskNames) Expect(err).NotTo(HaveOccurred()) Expect(actualDiskNames).To(ConsistOf([]string{ diskName1, diskName2, })) }) }) Describe("IsPersistentDiskMountable", func() { BeforeEach(func() { formattedDisksPath := filepath.Join(dirProvider.BoshDir(), "formatted_disks.json") fs.WriteFileString(formattedDisksPath, `[{"DiskCid": "my-disk-id"}]`) }) Context("when disk has been formatted", func() { It("returns true with no error", func() { diskSettings := boshsettings.DiskSettings{ID: "my-disk-id"} mountable, err := platform.IsPersistentDiskMountable(diskSettings) Expect(err).ToNot(HaveOccurred()) Expect(mountable).To(Equal(true)) }) }) Context("when disk has NOT been formatted", func() { It("returns false with no error", func() { diskSettings := boshsettings.DiskSettings{ID: "some-other-disk-id"} mountable, err := platform.IsPersistentDiskMountable(diskSettings) Expect(err).ToNot(HaveOccurred()) Expect(mountable).To(Equal(false)) }) }) }) Describe("SetUserPassword", func() { It("writes the password to a file", func() { err := platform.SetUserPassword("user-name", "fake-password") Expect(err).NotTo(HaveOccurred()) userPasswordsPath := filepath.Join(dirProvider.BoshDir(), "user-name", CredentialFileName) password, err := fs.ReadFileString(userPasswordsPath) Expect(err).NotTo(HaveOccurred()) Expect(password).To(Equal("fake-password")) }) It("writes the passwords to different files for each user", func() { err := platform.SetUserPassword("user-name1", "fake-password1") Expect(err).NotTo(HaveOccurred()) err = platform.SetUserPassword("user-name2", "fake-password2") Expect(err).NotTo(HaveOccurred()) userPasswordsPath := filepath.Join(dirProvider.BoshDir(), "user-name1", CredentialFileName) password, err := fs.ReadFileString(userPasswordsPath) Expect(err).NotTo(HaveOccurred()) Expect(password).To(Equal("fake-password1")) userPasswordsPath = filepath.Join(dirProvider.BoshDir(), "user-name2", CredentialFileName) password, err = fs.ReadFileString(userPasswordsPath) Expect(err).NotTo(HaveOccurred()) Expect(password).To(Equal("fake-password2")) }) }) Describe("SetupDataDir", func() { It("creates a link from BASEDIR/sys to BASEDIR/data/sys", func() { err := platform.SetupDataDir() Expect(err).NotTo(HaveOccurred()) stat := fs.GetFileTestStat(filepath.Clean("/fake-dir/sys")) Expect(stat).ToNot(BeNil()) Expect(stat.SymlinkTarget).To(Equal("/fake-dir/data/sys")) }) }) Describe("SetupBlobsDir", func() { It("creates a blobs folder under BASEDIR/DATADIR with correct permissions", func() { err := platform.SetupBlobsDir() Expect(err).NotTo(HaveOccurred()) stat := fs.GetFileTestStat(filepath.Clean("/fake-dir/data/blobs")) Expect(stat.FileType).To(Equal(fakesys.FakeFileTypeDir)) Expect(stat.FileMode).To(Equal(os.FileMode(0700))) }) }) }
func describeDummyPlatform() { var ( platform Platform collector boshstats.Collector fs boshsys.FileSystem cmdRunner boshsys.CmdRunner dirProvider boshdirs.Provider devicePathResolver boshdpresolv.DevicePathResolver logger boshlog.Logger ) BeforeEach(func() { collector = &fakestats.FakeCollector{} fs = fakesys.NewFakeFileSystem() cmdRunner = fakesys.NewFakeCmdRunner() dirProvider = boshdirs.NewProvider("/fake-dir") devicePathResolver = fakedpresolv.NewFakeDevicePathResolver() logger = boshlog.NewLogger(boshlog.LevelNone) }) JustBeforeEach(func() { platform = NewDummyPlatform( collector, fs, cmdRunner, dirProvider, devicePathResolver, logger, ) }) Describe("GetDefaultNetwork", func() { It("returns the contents of dummy-defaults-network-settings.json since that's what the dummy cpi writes", func() { settingsFilePath := "/fake-dir/bosh/dummy-default-network-settings.json" fs.WriteFileString(settingsFilePath, `{"IP": "1.2.3.4"}`) network, err := platform.GetDefaultNetwork() Expect(err).NotTo(HaveOccurred()) Expect(network.IP).To(Equal("1.2.3.4")) }) }) Describe("GetCertManager", func() { It("returs a dummy cert manager", func() { certManager := platform.GetCertManager() Expect(certManager.UpdateCertificates("")).Should(BeNil()) }) }) Describe("UnmountPersistentDisk", func() { Context("when there are two mounted persistent disks in the mounts json", func() { BeforeEach(func() { var mounts []mount mounts = append(mounts, mount{MountDir: "dir1", DiskCid: "cid1"}) mounts = append(mounts, mount{MountDir: "dir2", DiskCid: "cid2"}) mountsJSON, _ := json.Marshal(mounts) mountsPath := path.Join(dirProvider.BoshDir(), "mounts.json") fs.WriteFile(mountsPath, mountsJSON) }) It("removes one of the disks from the mounts json", func() { unmounted, err := platform.UnmountPersistentDisk(settings.DiskSettings{ID: "cid1"}) Expect(err).NotTo(HaveOccurred()) Expect(unmounted).To(Equal(true)) Expect(platform.IsMountPoint("dir1")).To(Equal(false)) Expect(platform.IsMountPoint("dir2")).To(Equal(true)) }) }) }) }
. "github.com/onsi/gomega" fakes "github.com/cloudfoundry/bosh-utils/system/fakes" boshlog "github.com/cloudfoundry/bosh-utils/logger" ) var _ = Describe("ConcreteUdevDevice", func() { var ( cmdRunner *fakes.FakeCmdRunner udev ConcreteUdevDevice logger boshlog.Logger ) BeforeEach(func() { cmdRunner = fakes.NewFakeCmdRunner() logger = boshlog.NewLogger(boshlog.LevelNone) }) JustBeforeEach(func() { udev = NewConcreteUdevDevice(cmdRunner, logger) }) Describe("#Settle", func() { Context("if `udevadm` is a runnable command", func() { BeforeEach(func() { cmdRunner.AvailableCommands["udevadm"] = true }) It("runs `udevadm settle`", func() { err := udev.Settle()