// New returns a new logger (that writes to the specified file) & the open file handle // All log levels >= the specified level are written to the specified file. // User is responsible for closing the returned file handle, unless an error is returned. func New(level boshlog.LogLevel, filePath string, fileMode os.FileMode, fs boshsys.FileSystem) (boshlog.Logger, boshsys.File, error) { file, err := fs.OpenFile(filePath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, fileMode) if err != nil { return nil, file, bosherr.WrapErrorf(err, "Failed to open log file '%s'", filePath) } return boshlog.NewWriterLogger(level, file, file), file, nil }
func basicDeps() (boshlog.Logger, boshsys.FileSystem, boshsys.CmdRunner) { logger := boshlog.NewWriterLogger(boshlog.LevelDebug, os.Stderr, os.Stderr) fs := boshsys.NewOsFileSystem(logger) cmdRunner := boshsys.NewExecCmdRunner(logger) return logger, fs, cmdRunner }
func basicDeps() (boshlog.Logger, boshsys.FileSystem, boshsys.CmdRunner, boshuuid.Generator) { logger := boshlog.NewWriterLogger(boshlog.LevelDebug, os.Stderr, os.Stderr) fs := boshsys.NewOsFileSystem(logger) runner := boshsys.NewExecCmdRunner(logger) uuidGen := boshuuid.NewGenerator() return logger, fs, runner, uuidGen }
installationManifest biinstallmanifest.Manifest mockJobRenderer *mock_install.MockJobRenderer mockJobResolver *mock_install.MockJobResolver mockPackageCompiler *mock_install.MockPackageCompiler fakeExtractor *fakeblobextract.FakeExtractor mockRegistryServerManager *mock_registry.MockServerManager logger boshlog.Logger installer Installer target Target installedJob InstalledJob ) BeforeEach(func() { logger = boshlog.NewWriterLogger(boshlog.LevelDebug, GinkgoWriter, GinkgoWriter) mockJobRenderer = mock_install.NewMockJobRenderer(mockCtrl) mockJobResolver = mock_install.NewMockJobResolver(mockCtrl) mockPackageCompiler = mock_install.NewMockPackageCompiler(mockCtrl) fakeExtractor = &fakeblobextract.FakeExtractor{} mockRegistryServerManager = mock_registry.NewMockServerManager(mockCtrl) target = NewTarget("fake-installation-path") installationManifest = biinstallmanifest.Manifest{ Name: "fake-installation-name", Properties: biproperty.Map{}, } renderedCPIJob := NewRenderedJobRef("cpi", "fake-release-job-fingerprint", "fake-rendered-job-blobstore-id", "fake-rendered-job-blobstore-id") installedJob = NewInstalledJob(renderedCPIJob, "/extracted-release-path/cpi") })
func init() { Describe("App", func() { var ( baseDir string agentConfPath string agentConfJSON string app App ) BeforeEach(func() { var err error baseDir, err = ioutil.TempDir("", "go-agent-test") Expect(err).ToNot(HaveOccurred()) err = os.Mkdir(filepath.Join(baseDir, "bosh"), os.ModePerm) Expect(err).ToNot(HaveOccurred()) }) BeforeEach(func() { agentConfPath = filepath.Join(baseDir, "bosh", "agent.json") agentConfJSON = `{ "Infrastructure": { "Settings": { "Sources": [{ "Type": "CDROM", "FileName": "/fake-file-name" }] } } }` settingsPath := filepath.Join(baseDir, "bosh", "settings.json") settingsJSON := `{ "agent_id": "my-agent-id", "blobstore": { "options": { "bucket_name": "george", "encryption_key": "optional encryption key", "access_key_id": "optional access key id", "secret_access_key": "optional secret access key" }, "provider": "dummy" }, "disks": { "ephemeral": "/dev/sdb", "persistent": { "vol-xxxxxx": "/dev/sdf" }, "system": "/dev/sda1" }, "env": { "bosh": { "password": "******" } }, "networks": { "netA": { "default": ["dns", "gateway"], "ip": "ww.ww.ww.ww", "dns": [ "xx.xx.xx.xx", "yy.yy.yy.yy" ] }, "netB": { "dns": [ "zz.zz.zz.zz" ] } }, "Mbus": "https://*****:*****@0.0.0.0:6868", "ntp": [ "0.north-america.pool.ntp.org", "1.north-america.pool.ntp.org" ], "vm": { "name": "vm-abc-def" } }` err := ioutil.WriteFile(settingsPath, []byte(settingsJSON), 0640) Expect(err).ToNot(HaveOccurred()) }) JustBeforeEach(func() { err := ioutil.WriteFile(agentConfPath, []byte(agentConfJSON), 0640) Expect(err).ToNot(HaveOccurred()) logger := boshlog.NewLogger(boshlog.LevelNone) fakefs := boshsys.NewOsFileSystem(logger) app = New(logger, fakefs) }) AfterEach(func() { os.RemoveAll(baseDir) }) It("Sets up device path resolver on platform specific to infrastructure", func() { err := app.Setup([]string{"bosh-agent", "-P", "dummy", "-C", agentConfPath, "-b", baseDir}) Expect(err).ToNot(HaveOccurred()) Expect(app.GetPlatform().GetDevicePathResolver()).To(Equal(devicepathresolver.NewIdentityDevicePathResolver())) }) Context("when DevicePathResolutionType is 'virtio'", func() { BeforeEach(func() { agentConfJSON = `{ "Platform": { "Linux": { "DevicePathResolutionType": "virtio" } }, "Infrastructure": { "Settings": { "Sources": [{ "Type": "CDROM", "FileName": "/fake-file-name" }] } } }` }) It("uses a VirtioDevicePathResolver", func() { err := app.Setup([]string{"bosh-agent", "-P", "dummy", "-C", agentConfPath, "-b", baseDir}) Expect(err).ToNot(HaveOccurred()) logLevel, err := boshlog.Levelify("DEBUG") Expect(err).NotTo(HaveOccurred()) Expect(app.GetPlatform().GetDevicePathResolver()).To( BeAssignableToTypeOf(devicepathresolver.NewVirtioDevicePathResolver(nil, nil, boshlog.NewLogger(logLevel)))) }) }) Context("when DevicePathResolutionType is 'scsi'", func() { BeforeEach(func() { agentConfJSON = `{ "Platform": { "Linux": { "DevicePathResolutionType": "scsi" } }, "Infrastructure": { "Settings": { "Sources": [{ "Type": "CDROM", "FileName": "/fake-file-name" }] } } }` }) It("uses a VirtioDevicePathResolver", func() { err := app.Setup([]string{"bosh-agent", "-P", "dummy", "-C", agentConfPath, "-b", baseDir}) Expect(err).ToNot(HaveOccurred()) Expect(app.GetPlatform().GetDevicePathResolver()).To( BeAssignableToTypeOf(devicepathresolver.NewScsiDevicePathResolver(nil, nil, nil))) }) }) Context("logging stemcell version and git sha", func() { var ( logger boshlog.Logger outBuf *bytes.Buffer fakeFs boshsys.FileSystem stemcellVersionFilePath string stemcellSha1FilePath string ) JustBeforeEach(func() { outBuf = bytes.NewBufferString("") errBuf := bytes.NewBufferString("") logger = boshlog.NewWriterLogger(boshlog.LevelDebug, outBuf, errBuf) fakeFs = fakesys.NewFakeFileSystem() dirProvider := boshdirs.NewProvider(baseDir) stemcellVersionFilePath = filepath.Join(dirProvider.EtcDir(), "stemcell_version") stemcellSha1FilePath = filepath.Join(dirProvider.EtcDir(), "stemcell_git_sha1") app = New(logger, fakeFs) }) Context("when stemcell version and sha files are present", func() { It("should print out the stemcell version and sha in the logs", func() { fakeFs.WriteFileString(stemcellVersionFilePath, "version-blah") fakeFs.WriteFileString(stemcellSha1FilePath, "sha1-blah") app.Setup([]string{"bosh-agent", "-P", "dummy", "-C", agentConfPath, "-b", baseDir}) Expect(string(outBuf.Bytes())).To(ContainSubstring("Running on stemcell version 'version-blah' (git: sha1-blah)")) }) }) Context("when stemcell version file is NOT present", func() { It("should print out the sha in the logs", func() { fakeFs.WriteFileString(stemcellSha1FilePath, "sha1-blah") app.Setup([]string{"bosh-agent", "-P", "dummy", "-C", agentConfPath, "-b", baseDir}) Expect(string(outBuf.Bytes())).To(ContainSubstring("Running on stemcell version '?' (git: sha1-blah)")) }) }) Context("when sha version file is NOT present", func() { It("should print out the stemcell version in the logs", func() { fakeFs.WriteFileString(stemcellVersionFilePath, "version-blah") app.Setup([]string{"bosh-agent", "-P", "dummy", "-C", agentConfPath, "-b", baseDir}) Expect(string(outBuf.Bytes())).To(ContainSubstring("Running on stemcell version 'version-blah' (git: ?)")) }) }) Context("when stemcell version file is empty", func() { It("should print out the sha in the logs", func() { fakeFs.WriteFileString(stemcellVersionFilePath, "") fakeFs.WriteFileString(stemcellSha1FilePath, "sha1-blah") app.Setup([]string{"bosh-agent", "-P", "dummy", "-C", agentConfPath, "-b", baseDir}) Expect(string(outBuf.Bytes())).To(ContainSubstring("Running on stemcell version '?' (git: sha1-blah)")) }) }) Context("when sha version file is empty", func() { It("should print out the stemcell version in the logs", func() { fakeFs.WriteFileString(stemcellVersionFilePath, "version-blah") fakeFs.WriteFileString(stemcellSha1FilePath, "") app.Setup([]string{"bosh-agent", "-P", "dummy", "-C", agentConfPath, "-b", baseDir}) Expect(string(outBuf.Bytes())).To(ContainSubstring("Running on stemcell version 'version-blah' (git: ?)")) }) }) Context("when stemcell version and sha files are NOT present", func() { It("should print unknown version and sha in the logs", func() { app.Setup([]string{"bosh-agent", "-P", "dummy", "-C", agentConfPath, "-b", baseDir}) Expect(string(outBuf.Bytes())).To(ContainSubstring("Running on stemcell version '?' (git: ?)")) }) }) }) }) }
processConfigPath string jobSupervisor JobSupervisor runner boshsys.CmdRunner logOut *bytes.Buffer logErr *bytes.Buffer ) BeforeEach(func() { once.Do(func() { Expect(buildPipeExe()).To(Succeed()) }) const testExtPath = "testdata/job-service-wrapper" logOut = bytes.NewBufferString("") logErr = bytes.NewBufferString("") logger = boshlog.NewWriterLogger(boshlog.LevelDebug, logOut, logErr) fs = boshsys.NewOsFileSystem(logger) var err error basePath, err = ioutil.TempDir("", "") Expect(err).ToNot(HaveOccurred()) fs.MkdirAll(basePath, 0755) binPath := filepath.Join(basePath, "bosh", "bin") fs.MkdirAll(binPath, 0755) logDir = path.Join(basePath, "sys", "log") fs.MkdirAll(binPath, 0755) exePath = filepath.Join(binPath, "job-service-wrapper.exe")
var ( outBuffer *bytes.Buffer errBuffer *bytes.Buffer logger boshlog.Logger fakeSHA1Calculator *fakebicrypto.FakeSha1Calculator renderedJobList RenderedJobList renderedJobListCompressor RenderedJobListCompressor ) BeforeEach(func() { outBuffer = bytes.NewBufferString("") errBuffer = bytes.NewBufferString("") logger = boshlog.NewWriterLogger(boshlog.LevelDebug, outBuffer, errBuffer) fakeSHA1Calculator = fakebicrypto.NewFakeSha1Calculator() renderedJobList = NewRenderedJobList() }) Describe("Compress", func() { Context("with a real fs & compressor", func() { var ( fs boshsys.FileSystem cmdRunner boshsys.CmdRunner compressor boshcmd.Compressor )
package agentlogger_test import ( "bytes" "os" "syscall" "github.com/cloudfoundry/bosh-agent/infrastructure/agentlogger" "github.com/cloudfoundry/bosh-utils/logger" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" ) var _ = Describe("Signalable logger debug", func() { Describe("when SIGSEGV is recieved", func() { It("it dumps all goroutines to stderr", func() { errBuf := new(bytes.Buffer) outBuf := new(bytes.Buffer) signalChannel := make(chan os.Signal, 1) writerLogger := logger.NewWriterLogger(logger.LevelError, outBuf, errBuf) _, doneChannel := agentlogger.NewSignalableLogger(writerLogger, signalChannel) signalChannel <- syscall.SIGSEGV <-doneChannel Expect(errBuf).To(ContainSubstring("Dumping goroutines")) Expect(errBuf).To(MatchRegexp(`goroutine (\d+) \[(syscall|running)\]`)) }) }) })
logger boshlog.Logger stage Stage ui UI fakeTimeService *fakeclock.FakeClock uiOut, uiErr *bytes.Buffer ) BeforeEach(func() { uiOut = bytes.NewBufferString("") uiErr = bytes.NewBufferString("") logOutBuffer = bytes.NewBufferString("") logErrBuffer = bytes.NewBufferString("") logger = boshlog.NewWriterLogger(boshlog.LevelDebug, logOutBuffer, logErrBuffer) ui = NewWriterUI(uiOut, uiErr, logger) fakeTimeService = fakeclock.NewFakeClock(time.Now()) stage = NewStage(ui, fakeTimeService, logger) }) Describe("Perform", func() { It("prints a single-line stage", func() { actionsPerformed := []string{} err := stage.Perform("Simple stage 1", func() error { actionsPerformed = append(actionsPerformed, "1") fakeTimeService.Increment(time.Minute) return nil
}) It("returns error if server fails to listen", func() { listenerProvider = func(protocol, Iaddr string) (net.Listener, error) { return nil, errors.New("Fail!") } server := NewServer(10, listenerProvider, logger) err := server.Start(nil) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("Fail!")) }) It("logs parsing error to error log if parsing syslog message fails", func() { outBuf := bytes.NewBufferString("") errBuf := newLockedWriter(bytes.NewBufferString("")) logger := boshlog.NewWriterLogger(boshlog.LevelDebug, outBuf, errBuf) server = NewServer(serverPort, listenerProvider, logger) doneCh := make(chan struct{}) go server.Start(captureNMsgs(msgs, doneCh, 2)) conn, err := waitToDial() Expect(err).ToNot(HaveOccurred()) fmt.Fprintf(conn, "<38>Jan 1 00:00:00 localhost sshd[22636]: msg1\n") fmt.Fprintf(conn, "invalid-syslog-format\n") fmt.Fprintf(conn, "<38>Jan 1 00:00:00 localhost sshd[22636]: msg2\n") <-doneCh err = server.Stop()
func init() { Describe("natsHandler", func() { var ( settingsService *fakesettings.FakeSettingsService client *fakeyagnats.FakeYagnats logger boshlog.Logger handler boshhandler.Handler platform *fakeplatform.FakePlatform loggerOutBuf *bytes.Buffer loggerErrBuf *bytes.Buffer ) BeforeEach(func() { settingsService = &fakesettings.FakeSettingsService{ Settings: boshsettings.Settings{ AgentID: "my-agent-id", Mbus: "nats://*****:*****@127.0.0.1:1234", }, } loggerOutBuf = bytes.NewBufferString("") loggerErrBuf = bytes.NewBufferString("") logger = boshlog.NewWriterLogger(boshlog.LevelError, loggerOutBuf, loggerErrBuf) client = fakeyagnats.New() platform = fakeplatform.NewFakePlatform() handler = NewNatsHandler(settingsService, client, logger, platform) }) Describe("Start", func() { It("starts", func() { var receivedRequest boshhandler.Request handler.Start(func(req boshhandler.Request) (resp boshhandler.Response) { receivedRequest = req return boshhandler.NewValueResponse("expected value") }) defer handler.Stop() Expect(client.ConnectedConnectionProvider()).ToNot(BeNil()) Expect(client.SubscriptionCount()).To(Equal(1)) subscriptions := client.Subscriptions("agent.my-agent-id") Expect(len(subscriptions)).To(Equal(1)) expectedPayload := []byte(`{"method":"ping","arguments":["foo","bar"], "reply_to": "reply to me!"}`) subscription := subscriptions[0] subscription.Callback(&yagnats.Message{ Subject: "agent.my-agent-id", Payload: expectedPayload, }) Expect(receivedRequest).To(Equal(boshhandler.Request{ ReplyTo: "reply to me!", Method: "ping", Payload: expectedPayload, })) Expect(client.PublishedMessageCount()).To(Equal(1)) messages := client.PublishedMessages("reply to me!") Expect(len(messages)).To(Equal(1)) Expect(messages[0].Payload).To(Equal([]byte(`{"value":"expected value"}`))) }) It("cleans up ip-mac address cache for nats configured with ip address", func() { handler.Start(func(req boshhandler.Request) (resp boshhandler.Response) { return nil }) defer handler.Stop() Expect(platform.CleanedIPMacAddressCache).To(Equal("127.0.0.1")) Expect(client.ConnectedConnectionProvider()).ToNot(BeNil()) }) It("does not try to clean up ip-mac address cache for nats configured with hostname", func() { settingsService.Settings.Mbus = "nats://*****:*****@fake-hostname.com:1234" handler.Start(func(req boshhandler.Request) (resp boshhandler.Response) { return nil }) defer handler.Stop() Expect(platform.CleanedIPMacAddressCache).To(BeEmpty()) Expect(client.ConnectedConnectionProvider()).ToNot(BeNil()) }) It("logs error and proceeds if it fails to clean up ip-mac address cache for nats", func() { platform.CleanIPMacAddressCacheErr = errors.New("failed to run") handler.Start(func(req boshhandler.Request) (resp boshhandler.Response) { return nil }) defer handler.Stop() Expect(platform.CleanedIPMacAddressCache).To(Equal("127.0.0.1")) Expect(loggerErrBuf).To(ContainSubstring("ERROR - Cleaning ip-mac address cache for: 127.0.0.1")) Expect(client.ConnectedConnectionProvider()).ToNot(BeNil()) }) It("does not respond if the response is nil", func() { err := handler.Start(func(req boshhandler.Request) (resp boshhandler.Response) { return nil }) Expect(err).ToNot(HaveOccurred()) defer handler.Stop() subscription := client.Subscriptions("agent.my-agent-id")[0] subscription.Callback(&yagnats.Message{ Subject: "agent.my-agent-id", Payload: []byte(`{"method":"ping","arguments":["foo","bar"], "reply_to": "reply to me!"}`), }) Expect(client.PublishedMessageCount()).To(Equal(0)) }) It("responds with an error if the response is bigger than 1MB", func() { err := handler.Start(func(req boshhandler.Request) (resp boshhandler.Response) { // gets inflated by json.Marshal when enveloping size := 0 switch req.Method { case "small": size = 1024*1024 - 12 case "big": size = 1024 * 1024 default: panic("unknown request size") } chars := make([]byte, size) for i := range chars { chars[i] = 'A' } return boshhandler.NewValueResponse(string(chars)) }) Expect(err).ToNot(HaveOccurred()) defer handler.Stop() subscription := client.Subscriptions("agent.my-agent-id")[0] subscription.Callback(&yagnats.Message{ Subject: "agent.my-agent-id", Payload: []byte(`{"method":"small","arguments":[], "reply_to": "fake-reply-to"}`), }) subscription.Callback(&yagnats.Message{ Subject: "agent.my-agent-id", Payload: []byte(`{"method":"big","arguments":[], "reply_to": "fake-reply-to"}`), }) Expect(client.PublishedMessageCount()).To(Equal(1)) messages := client.PublishedMessages("fake-reply-to") Expect(len(messages)).To(Equal(2)) Expect(messages[0].Payload).To(MatchRegexp("value")) Expect(messages[1].Payload).To(Equal([]byte( `{"exception":{"message":"Response exceeded maximum allowed length"}}`))) }) It("can add additional handler funcs to receive requests", func() { var firstHandlerReq, secondHandlerRequest boshhandler.Request handler.Start(func(req boshhandler.Request) (resp boshhandler.Response) { firstHandlerReq = req return boshhandler.NewValueResponse("first-handler-resp") }) defer handler.Stop() handler.RegisterAdditionalFunc(func(req boshhandler.Request) (resp boshhandler.Response) { secondHandlerRequest = req return boshhandler.NewValueResponse("second-handler-resp") }) expectedPayload := []byte(`{"method":"ping","arguments":["foo","bar"], "reply_to": "fake-reply-to"}`) subscription := client.Subscriptions("agent.my-agent-id")[0] subscription.Callback(&yagnats.Message{ Subject: "agent.my-agent-id", Payload: expectedPayload, }) // Expected requests received by both handlers Expect(firstHandlerReq).To(Equal(boshhandler.Request{ ReplyTo: "fake-reply-to", Method: "ping", Payload: expectedPayload, })) Expect(secondHandlerRequest).To(Equal(boshhandler.Request{ ReplyTo: "fake-reply-to", Method: "ping", Payload: expectedPayload, })) // Bosh handler responses were sent Expect(client.PublishedMessageCount()).To(Equal(1)) messages := client.PublishedMessages("fake-reply-to") Expect(len(messages)).To(Equal(2)) Expect(messages[0].Payload).To(Equal([]byte(`{"value":"first-handler-resp"}`))) Expect(messages[1].Payload).To(Equal([]byte(`{"value":"second-handler-resp"}`))) }) It("has the correct connection info", func() { err := handler.Start(func(req boshhandler.Request) (res boshhandler.Response) { return }) Expect(err).ToNot(HaveOccurred()) defer handler.Stop() Expect(client.ConnectedConnectionProvider()).To(Equal(&yagnats.ConnectionInfo{ Addr: "127.0.0.1:1234", Username: "******", Password: "******", })) }) It("does not err when no username and password", func() { settingsService.Settings.Mbus = "nats://127.0.0.1:1234" handler = NewNatsHandler(settingsService, client, logger, platform) err := handler.Start(func(req boshhandler.Request) (res boshhandler.Response) { return }) Expect(err).ToNot(HaveOccurred()) defer handler.Stop() }) It("errs when has username without password", func() { settingsService.Settings.Mbus = "nats://[email protected]:1234" handler = NewNatsHandler(settingsService, client, logger, platform) err := handler.Start(func(req boshhandler.Request) (res boshhandler.Response) { return }) Expect(err).To(HaveOccurred()) defer handler.Stop() }) }) Describe("Send", func() { It("sends the message over nats to a subject that includes the target and topic", func() { errCh := make(chan error, 1) payload := map[string]string{"key1": "value1", "keyA": "valueA"} go func() { errCh <- handler.Send(boshhandler.HealthMonitor, boshhandler.Heartbeat, payload) }() var err error select { case err = <-errCh: } Expect(err).ToNot(HaveOccurred()) Expect(client.PublishedMessageCount()).To(Equal(1)) messages := client.PublishedMessages("hm.agent.heartbeat.my-agent-id") Expect(messages).To(HaveLen(1)) Expect(messages[0].Payload).To(Equal( []byte("{\"key1\":\"value1\",\"keyA\":\"valueA\"}"), )) }) }) }) }