Skip to content

Commit

Permalink
Update v2Actor to pass AccessToken
Browse files Browse the repository at this point in the history
Recently we changed `cf auth --client-credentials` to not save the
ClientSecret. This renders "refreshing" for client-credentials
impossible.

Streaming logs through the NOAA Client previously relied on refreshing
to get a new token. This change is to update it to pass the current
access token through by default.

A similar change could be made to v3action and v7action. We decided that
was out of scope for our current release patch.

[#165777485](https://www.pivotaltracker.com/story/show/165777485)

Co-authored-by: Brendan Smith <brsmith@pivotal.io>
Co-authored-by: Will Murphy <wmurphy@pivotal.io>
  • Loading branch information
3 people committed May 6, 2019
1 parent 9ecdaaf commit 4a2de69
Show file tree
Hide file tree
Showing 4 changed files with 125 additions and 7 deletions.
5 changes: 2 additions & 3 deletions actor/v2action/logging.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,7 @@ func (actor Actor) GetStreamingLogs(appGUID string, client NOAAClient) (<-chan *

ready := actor.setOnConnectBlocker(client)

// Do not pass in token because client should have a TokenRefresher set
incomingLogStream, incomingErrStream := client.TailingLogs(appGUID, "")
incomingLogStream, incomingErrStream := client.TailingLogs(appGUID, actor.Config.AccessToken())

outgoingLogStream, outgoingErrStream := actor.blockOnConnect(ready)

Expand All @@ -94,7 +93,7 @@ func (actor Actor) GetRecentLogsForApplicationByNameAndSpace(appName string, spa
return nil, allWarnings, err
}

noaaMessages, err := client.RecentLogs(app.GUID, "")
noaaMessages, err := client.RecentLogs(app.GUID, actor.Config.AccessToken())
if err != nil {
return nil, allWarnings, err
}
Expand Down
11 changes: 9 additions & 2 deletions actor/v2action/logging_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ var _ = Describe("Logging Actions", func() {
BeforeEach(func() {
actor, fakeCloudControllerClient, _, fakeConfig = NewTestActor()
fakeNOAAClient = new(v2actionfakes.FakeNOAAClient)
fakeConfig.AccessTokenReturns("AccessTokenForTest")
})

Describe("LogMessage", func() {
Expand Down Expand Up @@ -74,7 +75,7 @@ var _ = Describe("Logging Actions", func() {

fakeNOAAClient.TailingLogsStub = func(appGUID string, authToken string) (<-chan *events.LogMessage, <-chan error) {
Expect(appGUID).To(Equal(expectedAppGUID))
Expect(authToken).To(BeEmpty())
Expect(authToken).To(Equal("AccessTokenForTest"))

Expect(fakeNOAAClient.SetOnConnectCallbackCallCount()).To(Equal(1))
onConnectOrOnRetry := fakeNOAAClient.SetOnConnectCallbackArgsForCall(0)
Expand Down Expand Up @@ -358,6 +359,12 @@ var _ = Describe("Logging Actions", func() {
fakeNOAAClient.RecentLogsReturns(messages, nil)
})

It("passes a nonempty access token to the NOAA client", func() {
actor.GetRecentLogsForApplicationByNameAndSpace("some-app", "some-space-guid", fakeNOAAClient)
_, accessToken := fakeNOAAClient.RecentLogsArgsForCall(0)
Expect(accessToken).To(Equal("AccessTokenForTest"))
})

It("returns all the recent logs and warnings", func() {
messages, warnings, err := actor.GetRecentLogsForApplicationByNameAndSpace("some-app", "some-space-guid", fakeNOAAClient)
Expect(err).ToNot(HaveOccurred())
Expand Down Expand Up @@ -446,7 +453,7 @@ var _ = Describe("Logging Actions", func() {

fakeNOAAClient.TailingLogsStub = func(appGUID string, authToken string) (<-chan *events.LogMessage, <-chan error) {
Expect(appGUID).To(Equal(expectedAppGUID))
Expect(authToken).To(BeEmpty())
Expect(authToken).To(Equal("AccessTokenForTest"))

Expect(fakeNOAAClient.SetOnConnectCallbackCallCount()).To(Equal(1))
onConnectOrOnRetry := fakeNOAAClient.SetOnConnectCallbackArgsForCall(0)
Expand Down
59 changes: 57 additions & 2 deletions integration/v6/isolated/logs_command_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,13 @@ var _ = Describe("Logs Command", func() {
})
})

When("the environment is not setup correctly", func() {
When("not authenticated and not targeting an org or space", func() {
It("fails with the appropriate errors", func() {
helpers.CheckEnvironmentTargetedCorrectly(true, true, ReadOnlyOrg, "logs", "app-name")
})
})

When("the environment is set up correctly", func() {
When("authenticated as a user and targeting an org and space", func() {
var (
orgName string
spaceName string
Expand Down Expand Up @@ -112,4 +112,59 @@ var _ = Describe("Logs Command", func() {
})
})
})

When("authenticated as a client and targeting an org and space", func() {
var (
orgName string
spaceName string
clientName string
)

BeforeEach(func() {
orgName = helpers.NewOrgName()
spaceName = helpers.NewSpaceName()
clientName = helpers.LoginCFWithClientCredentials()
helpers.CreateOrgAndSpace(orgName, spaceName)
helpers.TargetOrgAndSpace(orgName, spaceName)
})

AfterEach(func() {
helpers.QuickDeleteOrg(orgName)
})

When("the specified app exists", func() {
var appName string

BeforeEach(func() {
appName = helpers.PrefixedRandomName("app")
helpers.WithHelloWorldApp(func(appDir string) {
Eventually(helpers.CF("push", appName, "-p", appDir, "-b", "staticfile_buildpack", "-u", "http")).Should(Exit(0))
})
})

Context("without the --recent flag", func() {
It("streams logs out to the screen", func() {
session := helpers.CF("logs", appName)
defer session.Terminate()

Eventually(session).Should(Say("Retrieving logs for app %s in org %s / space %s as %s...", appName, orgName, spaceName, clientName))

response, err := http.Get(fmt.Sprintf("http://%s.%s", appName, helpers.DefaultSharedDomain()))
Expect(err).NotTo(HaveOccurred())
Expect(response.StatusCode).To(Equal(http.StatusOK))
Eventually(session).Should(Say(`%s \[APP/PROC/WEB/0\]\s+OUT .*? \"GET / HTTP/1.1\" 200 \d+`, helpers.ISO8601Regex))
})
})

Context("with the --recent flag", func() {
It("displays the most recent logs and closes the stream", func() {
session := helpers.CF("logs", appName, "--recent")
Eventually(session).Should(Say("Retrieving logs for app %s in org %s / space %s as %s...", appName, orgName, spaceName, clientName))
Eventually(session).Should(Say(`%s \[API/\d+\]\s+OUT Created app with guid %s`, helpers.ISO8601Regex, helpers.GUIDRegex))
Eventually(session).Should(Exit(0))
})
})
})
})

})
57 changes: 57 additions & 0 deletions integration/v6/push/name_only_client_credentials_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package push

import (
"code.cloudfoundry.org/cli/integration/helpers"

. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
. "github.com/onsi/gomega/gbytes"
. "github.com/onsi/gomega/gexec"
)

var _ = Describe("push with only an app name when authenticated with client-credentials", func() {
var (
appName string
clientID string
)

BeforeEach(func() {
appName = helpers.NewAppName()
clientID = helpers.LoginCFWithClientCredentials()
helpers.TargetOrgAndSpace(organization, space)
})

AfterEach(func() {
helpers.LogoutCF()
})

Describe("app existence", func() {
When("the app does not exist", func() {
It("creates the app", func() {
helpers.WithHelloWorldApp(func(dir string) {
session := helpers.CustomCF(helpers.CFEnv{WorkingDirectory: dir}, PushCommandName, appName)
Eventually(session).Should(Say(`Pushing app %s to org %s / space %s as %s\.\.\.`, appName, organization, space, clientID))
Eventually(session).Should(Say(`Getting app info\.\.\.`))
Eventually(session).Should(Say(`Creating app with these attributes\.\.\.`))
Eventually(session).Should(Say(`\+\s+name:\s+%s`, appName))
Eventually(session).Should(Say(`\s+routes:`))
Eventually(session).Should(Say(`(?i)\+\s+%s.%s`, appName, helpers.DefaultSharedDomain()))
Eventually(session).Should(Say(`Mapping routes\.\.\.`))
Eventually(session).Should(Say(`Comparing local files to remote cache\.\.\.`))
Eventually(session).Should(Say(`Packaging files to upload\.\.\.`))
Eventually(session).Should(Say(`Uploading files\.\.\.`))
Eventually(session).Should(Say("100.00%"))
Eventually(session).Should(Say(`Waiting for API to complete processing files\.\.\.`))
helpers.ConfirmStagingLogs(session)
Eventually(session).Should(Say(`Waiting for app to start\.\.\.`))
Eventually(session).Should(Say(`requested state:\s+started`))
Eventually(session).Should(Exit(0))
})

session := helpers.CF("app", appName)
Eventually(session).Should(Say(`name:\s+%s`, appName))
Eventually(session).Should(Exit(0))
})
})
})
})

0 comments on commit 4a2de69

Please sign in to comment.