Skip to content

Commit

Permalink
Merge pull request #616 from cloudfoundry/director-fetch-logs-support…
Browse files Browse the repository at this point in the history
…s-system-and-all

Add --system and --all-logs support to bosh logs --director
  • Loading branch information
klakin-pivotal authored Mar 29, 2023
2 parents 91bd3c7 + 87b99be commit 92c513d
Show file tree
Hide file tree
Showing 6 changed files with 88 additions and 155 deletions.
28 changes: 23 additions & 5 deletions cmd/logs.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,25 @@ func buildTailCmd(opts LogsOpts) []string {
return cmd
}

func buildLogTypeArgument(opts LogsOpts) string {
var logTypes []string
if opts.All {
logTypes = append(logTypes, "agent")
logTypes = append(logTypes, "job")
logTypes = append(logTypes, "system")
} else {
if opts.Agent {
logTypes = append(logTypes, "agent")
} else if opts.System {
logTypes = append(logTypes, "system")
} else {
logTypes = append(logTypes, "job")
}
}
logType := strings.Join(logTypes, ",")
return logType
}

func (c LogsCmd) fetch(opts LogsOpts) error {
slug := opts.Args.Slug
name := c.deployment.Name()
Expand All @@ -141,7 +160,8 @@ func (c LogsCmd) fetch(opts LogsOpts) error {
name += "." + slug.IndexOrID()
}

result, err := c.deployment.FetchLogs(slug, opts.Filters, opts.Agent, opts.System, opts.All)
logType := buildLogTypeArgument(opts)
result, err := c.deployment.FetchLogs(slug, opts.Filters, logType)
if err != nil {
return err
}
Expand Down Expand Up @@ -238,10 +258,8 @@ func (c EnvLogsCmd) tail(opts LogsOpts, connOpts boshssh.ConnectionOpts, sshResu
}

func (c EnvLogsCmd) fetch(opts LogsOpts, connOpts boshssh.ConnectionOpts, sshResult boshdir.SSHResult, agentClient biagentclient.AgentClient) error {
logType := "job"
if opts.Agent {
logType = "agent"
}
logType := buildLogTypeArgument(opts)

bundleLogsResult, err := agentClient.BundleLogs(sshResult.Hosts[0].Username, logType, opts.Filters)
if err != nil {
return err
Expand Down
58 changes: 42 additions & 16 deletions cmd/logs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,12 +79,10 @@ var _ = Describe("Logs", func() {

Expect(deployment.FetchLogsCallCount()).To(Equal(1))

slug, filters, agent, system, all := deployment.FetchLogsArgsForCall(0)
slug, filters, logTypes := deployment.FetchLogsArgsForCall(0)
Expect(slug).To(Equal(boshdir.NewAllOrInstanceGroupOrInstanceSlug("job", "index")))
Expect(filters).To(BeEmpty())
Expect(agent).To(BeFalse())
Expect(system).To(BeFalse())
Expect(all).To(BeFalse())
Expect(logTypes).To(Equal("job"))

Expect(downloader.DownloadCallCount()).To(Equal(1))

Expand All @@ -106,12 +104,10 @@ var _ = Describe("Logs", func() {

Expect(deployment.FetchLogsCallCount()).To(Equal(1))

slug, filters, agent, system, all := deployment.FetchLogsArgsForCall(0)
slug, filters, logTypes := deployment.FetchLogsArgsForCall(0)
Expect(slug).To(Equal(boshdir.NewAllOrInstanceGroupOrInstanceSlug("job", "index")))
Expect(filters).To(Equal([]string{"filter1", "filter2"}))
Expect(agent).To(BeTrue())
Expect(system).To(BeFalse())
Expect(all).To(BeFalse())
Expect(logTypes).To(Equal("agent"))
})

It("fetches system logs and allows custom filters", func() {
Expand All @@ -125,12 +121,10 @@ var _ = Describe("Logs", func() {

Expect(deployment.FetchLogsCallCount()).To(Equal(1))

slug, filters, agent, system, all := deployment.FetchLogsArgsForCall(0)
slug, filters, logTypes := deployment.FetchLogsArgsForCall(0)
Expect(slug).To(Equal(boshdir.NewAllOrInstanceGroupOrInstanceSlug("job", "index")))
Expect(filters).To(Equal([]string{"filter1", "filter2"}))
Expect(agent).To(BeFalse())
Expect(system).To(BeTrue())
Expect(all).To(BeFalse())
Expect(logTypes).To(Equal("system"))
})

It("fetches all logs and allows custom filters", func() {
Expand All @@ -144,12 +138,10 @@ var _ = Describe("Logs", func() {

Expect(deployment.FetchLogsCallCount()).To(Equal(1))

slug, filters, agent, system, all := deployment.FetchLogsArgsForCall(0)
slug, filters, logTypes := deployment.FetchLogsArgsForCall(0)
Expect(slug).To(Equal(boshdir.NewAllOrInstanceGroupOrInstanceSlug("job", "index")))
Expect(filters).To(Equal([]string{"filter1", "filter2"}))
Expect(agent).To(BeFalse())
Expect(system).To(BeFalse())
Expect(all).To(BeTrue())
Expect(logTypes).To(Equal("agent,job,system"))
})

It("fetches logs for more than one instance", func() {
Expand Down Expand Up @@ -669,6 +661,40 @@ var _ = Describe("Logs", func() {
Expect(command.Run(opts)).ToNot(HaveOccurred())
})

It("bundles system logs", func() {
opts.Filters = []string{}
opts.System = true

agentClient.EXPECT().BundleLogs(
gomock.Eq(ExpUsername),
gomock.Eq("system"),
gomock.Eq([]string{}),
).
Return(bundleResult, nil).
Times(1)
agentClient.EXPECT().RemoveFile(gomock.Any()).
Times(1)

Expect(command.Run(opts)).ToNot(HaveOccurred())
})

It("bundles all logs", func() {
opts.Filters = []string{}
opts.All = true

agentClient.EXPECT().BundleLogs(
gomock.Eq(ExpUsername),
gomock.Eq("agent,job,system"),
gomock.Eq([]string{}),
).
Return(bundleResult, nil).
Times(1)
agentClient.EXPECT().RemoveFile(gomock.Any()).
Times(1)

Expect(command.Run(opts)).ToNot(HaveOccurred())
})

It("returns error if bundling logs failed", func() {
agentClient.EXPECT().BundleLogs(gomock.Any(), gomock.Any(), gomock.Any()).Return(agentclient.BundleLogsResult{}, errors.New("fake-logs-err"))

Expand Down
23 changes: 4 additions & 19 deletions director/deployment.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,8 @@ func (d DeploymentImpl) Manifest() (string, error) {
return resp.Manifest, nil
}

func (d DeploymentImpl) FetchLogs(slug AllOrInstanceGroupOrInstanceSlug, filters []string, agent bool, system bool, allLogs bool) (LogsResult, error) {
blobID, sha1, err := d.client.FetchLogs(d.name, slug.Name(), slug.IndexOrID(), filters, agent, system, allLogs)
func (d DeploymentImpl) FetchLogs(slug AllOrInstanceGroupOrInstanceSlug, filters []string, logTypes string) (LogsResult, error) {
blobID, sha1, err := d.client.FetchLogs(d.name, slug.Name(), slug.IndexOrID(), filters, logTypes)
if err != nil {
return LogsResult{}, err
}
Expand Down Expand Up @@ -254,7 +254,7 @@ func (d DeploymentImpl) Variables() ([]VariableResult, error) {
return response, nil
}

func (c Client) FetchLogs(deploymentName, instance, indexOrID string, filters []string, agent bool, system bool, allLogs bool) (string, string, error) {
func (c Client) FetchLogs(deploymentName, instance, indexOrID string, filters []string, logTypes string) (string, string, error) {
if len(deploymentName) == 0 {
return "", "", bosherr.Error("Expected non-empty deployment name")
}
Expand All @@ -273,22 +273,7 @@ func (c Client) FetchLogs(deploymentName, instance, indexOrID string, filters []
query.Add("filters", strings.Join(filters, ","))
}

var logTypes []string
if allLogs {
logTypes = append(logTypes, "agent")
logTypes = append(logTypes, "job")
logTypes = append(logTypes, "system")
} else {
if agent {
logTypes = append(logTypes, "agent")
} else if system {
logTypes = append(logTypes, "system")
} else {
logTypes = append(logTypes, "job")
}
}

query.Add("type", strings.Join(logTypes, ","))
query.Add("type", logTypes)

path := fmt.Sprintf("/deployments/%s/jobs/%s/%s/logs?%s",
deploymentName, instance, indexOrID, query.Encode())
Expand Down
108 changes: 8 additions & 100 deletions director/deployment_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -194,12 +194,12 @@ var _ = Describe("Deployment", func() {
),
)

result, err := deployment.FetchLogs(NewAllOrInstanceGroupOrInstanceSlug("job", "id"), nil, false, false, false)
result, err := deployment.FetchLogs(NewAllOrInstanceGroupOrInstanceSlug("job", "id"), nil, "job")
Expect(err).ToNot(HaveOccurred())
Expect(result).To(Equal(LogsResult{BlobstoreID: "logs-blob-id", SHA1: ""}))
})

It("returns logs result for all deplotment", func() {
It("returns logs result for all jobs", func() {
ConfigureTaskResult(
ghttp.CombineHandlers(
ghttp.VerifyRequest("GET", "/deployments/dep/jobs/*/*/logs", "type=job"),
Expand All @@ -216,15 +216,15 @@ var _ = Describe("Deployment", func() {
),
)

result, err := deployment.FetchLogs(NewAllOrInstanceGroupOrInstanceSlug("", ""), nil, false, false, false)
result, err := deployment.FetchLogs(NewAllOrInstanceGroupOrInstanceSlug("", ""), nil, "job")
Expect(err).ToNot(HaveOccurred())
Expect(result).To(Equal(LogsResult{BlobstoreID: "logs-blob-id", SHA1: ""}))
})

It("is able to apply filters and fetch agent logs", func() {
It("is able to apply filters and passes through the log type params when fetching logs", func() {
ConfigureTaskResult(
ghttp.CombineHandlers(
ghttp.VerifyRequest("GET", "/deployments/dep/jobs/job/id/logs", "type=agent&filters=f1,f2"),
ghttp.VerifyRequest("GET", "/deployments/dep/jobs/job/id/logs", "type=log%20type%20here&filters=f1,f2"),
ghttp.VerifyBasicAuth("username", "password"),
),
``,
Expand All @@ -239,99 +239,7 @@ var _ = Describe("Deployment", func() {
)

result, err := deployment.FetchLogs(
NewAllOrInstanceGroupOrInstanceSlug("job", "id"), []string{"f1", "f2"}, true, false, false)
Expect(err).ToNot(HaveOccurred())
Expect(result).To(Equal(LogsResult{BlobstoreID: "logs-blob-id", SHA1: ""}))
})

It("is correctly fetches job, agent, and system logs when --all is passed", func() {
ConfigureTaskResult(
ghttp.CombineHandlers(
ghttp.VerifyRequest("GET", "/deployments/dep/jobs/job/id/logs", "type=agent,job,system"),
ghttp.VerifyBasicAuth("username", "password"),
),
``,
server,
)

server.AppendHandlers(
ghttp.CombineHandlers(
ghttp.VerifyRequest("GET", "/tasks/123"),
ghttp.RespondWith(http.StatusOK, `{"result":"logs-blob-id"}`),
),
)

result, err := deployment.FetchLogs(
NewAllOrInstanceGroupOrInstanceSlug("job", "id"), nil, false, false, true)
Expect(err).ToNot(HaveOccurred())
Expect(result).To(Equal(LogsResult{BlobstoreID: "logs-blob-id", SHA1: ""}))
})

It("is correctly only fetches system logs when --system is passed", func() {
ConfigureTaskResult(
ghttp.CombineHandlers(
ghttp.VerifyRequest("GET", "/deployments/dep/jobs/job/id/logs", "type=system"),
ghttp.VerifyBasicAuth("username", "password"),
),
``,
server,
)

server.AppendHandlers(
ghttp.CombineHandlers(
ghttp.VerifyRequest("GET", "/tasks/123"),
ghttp.RespondWith(http.StatusOK, `{"result":"logs-blob-id"}`),
),
)

result, err := deployment.FetchLogs(
NewAllOrInstanceGroupOrInstanceSlug("job", "id"), nil, false, true, false)
Expect(err).ToNot(HaveOccurred())
Expect(result).To(Equal(LogsResult{BlobstoreID: "logs-blob-id", SHA1: ""}))
})

It("is correctly only fetches agent logs when --agent is passed", func() {
ConfigureTaskResult(
ghttp.CombineHandlers(
ghttp.VerifyRequest("GET", "/deployments/dep/jobs/job/id/logs", "type=agent"),
ghttp.VerifyBasicAuth("username", "password"),
),
``,
server,
)

server.AppendHandlers(
ghttp.CombineHandlers(
ghttp.VerifyRequest("GET", "/tasks/123"),
ghttp.RespondWith(http.StatusOK, `{"result":"logs-blob-id"}`),
),
)

result, err := deployment.FetchLogs(
NewAllOrInstanceGroupOrInstanceSlug("job", "id"), nil, true, false, false)
Expect(err).ToNot(HaveOccurred())
Expect(result).To(Equal(LogsResult{BlobstoreID: "logs-blob-id", SHA1: ""}))
})

It("is correctly only fetches job logs when no flags are passed", func() {
ConfigureTaskResult(
ghttp.CombineHandlers(
ghttp.VerifyRequest("GET", "/deployments/dep/jobs/job/id/logs", "type=job"),
ghttp.VerifyBasicAuth("username", "password"),
),
``,
server,
)

server.AppendHandlers(
ghttp.CombineHandlers(
ghttp.VerifyRequest("GET", "/tasks/123"),
ghttp.RespondWith(http.StatusOK, `{"result":"logs-blob-id"}`),
),
)

result, err := deployment.FetchLogs(
NewAllOrInstanceGroupOrInstanceSlug("job", "id"), nil, false, false, false)
NewAllOrInstanceGroupOrInstanceSlug("job", "id"), []string{"f1", "f2"}, "log type here")
Expect(err).ToNot(HaveOccurred())
Expect(result).To(Equal(LogsResult{BlobstoreID: "logs-blob-id", SHA1: ""}))
})
Expand All @@ -348,15 +256,15 @@ var _ = Describe("Deployment", func() {

AppendBadRequest(ghttp.VerifyRequest("GET", "/tasks/123"), server)

_, err := deployment.FetchLogs(NewAllOrInstanceGroupOrInstanceSlug("job", "id"), nil, false, false, false)
_, err := deployment.FetchLogs(NewAllOrInstanceGroupOrInstanceSlug("job", "id"), nil, "job")
Expect(err).To(HaveOccurred())
Expect(err.Error()).To(ContainSubstring("Finding task '123'"))
})

It("returns error if response is non-200", func() {
AppendBadRequest(ghttp.VerifyRequest("GET", "/deployments/dep/jobs/job/id/logs", "type=job"), server)

_, err := deployment.FetchLogs(NewAllOrInstanceGroupOrInstanceSlug("job", "id"), nil, false, false, false)
_, err := deployment.FetchLogs(NewAllOrInstanceGroupOrInstanceSlug("job", "id"), nil, "job")
Expect(err).To(HaveOccurred())
Expect(err.Error()).To(ContainSubstring("Fetching logs"))
})
Expand Down
Loading

0 comments on commit 92c513d

Please sign in to comment.