Repository: vmware-tanzu/octant
Pull request #1443 (2020-10-02 05:32:23)

Bump actions/setup-node from v2.1.1 to v2.1.2
Bumps [actions/setup-node](https://github.com/actions/setup-node) from v2.1.1 to v2.1.2.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a href="https://github.com/actions/setup-node/releases">actions/setup-node's releases</a>.</em></p>
<blockquote>
<h2>v2.1.2 (beta)</h2>
<ul>
<li>Updated communication with runner to use environment files rather then workflow commands</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a href="https://github.com/actions/setup-node/commit/c6fd00ceb9747fb23ffdf72987450a2664414867"><code>c6fd00c</code></a> Swap to env files (<a href="https://github-redirect.dependabot.com/actions/setup-node/issues/200">#200</a>)</li>
<li><a href="https://github.com/actions/setup-node/commit/c211e95e60c2a8db273e122ba1845305b1943494"><code>c211e95</code></a> Add <code>Licensed</code> To Help Verify Prod Licenses (<a href="https://github-redirect.dependabot.com/actions/setup-node/issues/180">#180</a>)</li>
<li><a href="https://github.com/actions/setup-node/commit/59e61b89511ed136a0b17773f07c349fa5c01e8b"><code>59e61b8</code></a> main workflow references</li>
<li>See full diff in <a href="https://github.com/actions/setup-node/compare/v2.1.1...c6fd00ceb9747fb23ffdf72987450a2664414867">compare view</a></li>
</ul>
</details>
<br />


Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)


</details>


Patch:
diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml
index d4923dce..52337ba3 100644
--- a/.github/workflows/lint.yaml
+++ b/.github/workflows/lint.yaml
@@ -26,7 +26,7 @@ jobs:
   eslint:
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/setup-node@v2.1.1
+      - uses: actions/setup-node@v2.1.2
         with:
           node-version: 10.x
       - uses: actions/checkout@v2
diff --git a/.github/workflows/nightly.yaml b/.github/workflows/nightly.yaml
index 5a9cc6fb..c595187c 100644
--- a/.github/workflows/nightly.yaml
+++ b/.github/workflows/nightly.yaml
@@ -7,7 +7,7 @@ jobs:
     name: Build nightly
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/setup-node@v2.1.1
+      - uses: actions/setup-node@v2.1.2
         with:
           node-version: 10.x
       - uses: actions/setup-go@v2
diff --git a/.github/workflows/preflight-checks.yaml b/.github/workflows/preflight-checks.yaml
index dc2ce004..3d75833a 100644
--- a/.github/workflows/preflight-checks.yaml
+++ b/.github/workflows/preflight-checks.yaml
@@ -21,7 +21,7 @@ jobs:
     runs-on: ${{ matrix.platform }}
     name: Golang tests on ${{ matrix.platform }}
     steps:
-      - uses: actions/setup-node@v2.1.1
+      - uses: actions/setup-node@v2.1.2
         with:
           node-version: 10.x
       - uses: actions/setup-go@v2
@@ -59,7 +59,7 @@ jobs:
     runs-on: ${{ matrix.platform }}
     name: Karma tests on ${{ matrix.platform }}
     steps:
-      - uses: actions/setup-node@v2.1.1
+      - uses: actions/setup-node@v2.1.2
         with:
           node-version: 10.x
       - uses: actions/checkout@v2
@@ -101,7 +101,7 @@ jobs:
     runs-on: ${{ matrix.platform }}
     name: Build on ${{ matrix.platform }}
     steps:
-      - uses: actions/setup-node@v2.1.1
+      - uses: actions/setup-node@v2.1.2
         with:
           node-version: 10.x
       - uses: actions/setup-go@v2
diff --git a/changelogs/unreleased/1441-GuessWhoSamFoo b/changelogs/unreleased/1441-GuessWhoSamFoo
new file mode 100644
index 00000000..aa6c53cc
--- /dev/null
+++ b/changelogs/unreleased/1441-GuessWhoSamFoo
@@ -0,0 +1,1 @@
+Fixed clientID not added to ActionRequest
diff --git a/cmd/octant-sample-plugin/main.go b/cmd/octant-sample-plugin/main.go
index bed24954..9e72e417 100644
--- a/cmd/octant-sample-plugin/main.go
+++ b/cmd/octant-sample-plugin/main.go
@@ -24,6 +24,8 @@ import (
 
 var pluginName = "plugin-name"
 
+const pluginActionName = "action.octant.dev/example"
+
 // This is a sample plugin showing the features of Octant's plugin API.
 func main() {
 	// Remove the prefix from the go logger since Octant will print logs with timestamps.
@@ -36,6 +38,7 @@ func main() {
 	capabilities := &plugin.Capabilities{
 		SupportsPrinterConfig: []schema.GroupVersionKind{podGVK},
 		SupportsTab:           []schema.GroupVersionKind{podGVK},
+		ActionNames:           []string{pluginActionName},
 		IsModule:              true,
 	}
 
@@ -44,6 +47,7 @@ func main() {
 		service.WithPrinter(handlePrint),
 		service.WithTabPrinter(handleTab),
 		service.WithNavigation(handleNavigation, initRoutes),
+		service.WithActionHandler(handleAction),
 	}
 
 	// Use the plugin service helper to register this plugin.
@@ -92,12 +96,6 @@ func handlePrint(request *service.PrintRequest) (plugin.PrintResponse, error) {
 	if request.Object == nil {
 		return plugin.PrintResponse{}, errors.Errorf("object is nil")
 	}
-
-	// Sending an alert needs a clientID from the request context
-	if n := time.Now(); n.Second() == 0 {
-		alert := action.CreateAlert(action.AlertTypeInfo, fmt.Sprintf("The time is %s", time.Now().String()), action.DefaultAlertExpiration)
-		request.DashboardClient.SendAlert(request.Context(), request.ClientID, alert)
-	}
 	// load an object from the cluster and use that object to create a response.
 
 	// Octant has a helper function to generate a key from an object. The key
@@ -146,7 +144,7 @@ func handlePrint(request *service.PrintRequest) (plugin.PrintResponse, error) {
 	}, nil
 }
 
-// handlePrint creates a navigation tree for this plugin. Navigation is dynamic and will
+// handleNavigation creates a navigation tree for this plugin. Navigation is dynamic and will
 // be called frequently from Octant. Navigation is a tree of `Navigation` structs.
 // The plugin can use whatever paths it likes since these paths can be namespaced to the
 // the plugin.
@@ -172,6 +170,23 @@ func handleNavigation(request *service.NavigationRequest) (navigation.Navigation
 	}, nil
 }
 
+// handleAction creates an action handler for this plugin. Actions send
+// a payload which are used to execute some task
+func handleAction(request *service.ActionRequest) error {
+	actionValue, err := request.Payload.String("action")
+	if err != nil {
+		return err
+	}
+
+	if actionValue == pluginActionName {
+		// Sending an alert needs a clientID from the request context
+		alert := action.CreateAlert(action.AlertTypeInfo, fmt.Sprintf("My client ID is: %s", request.ClientID), action.DefaultAlertExpiration)
+		request.DashboardClient.SendAlert(request.Context(), request.ClientID, alert)
+	}
+
+	return nil
+}
+
 // initRoutes routes for this plugin. In this example, there is a global catch all route
 // that will return the content for every single path.
 func initRoutes(router *service.Router) {
@@ -179,6 +194,16 @@ func initRoutes(router *service.Router) {
 		cardBody := component.NewText(fmt.Sprintf("hello from plugin: path %s", requestPath))
 		card := component.NewCard(component.TitleFromString(fmt.Sprintf("My Card - %s", name)))
 		card.SetBody(cardBody)
+
+		form := component.Form{Fields: []component.FormField{
+			component.NewFormFieldHidden("action", pluginActionName),
+		}}
+		testButton := component.Action{
+			Name:  "Test Button",
+			Title: "Test Button",
+			Form:  form,
+		}
+		card.AddAction(testButton)
 		cardList := component.NewCardList(name)
 		cardList.AddCard(*card)
 		cardList.SetAccessor(accessor)
diff --git a/internal/api/action_request_manager.go b/internal/api/action_request_manager.go
index 6a772bb3..d9ebb246 100644
--- a/internal/api/action_request_manager.go
+++ b/internal/api/action_request_manager.go
@@ -8,6 +8,7 @@ package api
 import (
 	"context"
 
+	ocontext "github.com/vmware-tanzu/octant/internal/context"
 	"github.com/vmware-tanzu/octant/internal/octant"
 	"github.com/vmware-tanzu/octant/pkg/action"
 )
@@ -43,7 +44,7 @@ func (a *ActionRequestManager) Handlers() []octant.ClientRequestHandler {
 
 // PerformAction is a handler than runs an action.
 func (a *ActionRequestManager) PerformAction(state octant.State, payload action.Payload) error {
-	ctx := context.TODO()
+	ctx := ocontext.WithWebsocketClientID(context.TODO(), state.GetClientID())
 
 	actionName, err := payload.String("action")
 	if err != nil {
diff --git a/internal/commands/dash.go b/internal/commands/dash.go
index 0683a3e7..78c61db7 100644
--- a/internal/commands/dash.go
+++ b/internal/commands/dash.go
@@ -22,6 +22,7 @@ import (
 	"github.com/vmware-tanzu/octant/internal/config"
 	ocontext "github.com/vmware-tanzu/octant/internal/context"
 	"github.com/vmware-tanzu/octant/internal/log"
+	pconfig "github.com/vmware-tanzu/octant/pkg/config"
 	"github.com/vmware-tanzu/octant/pkg/dash"
 )
 
@@ -146,7 +147,7 @@ func newOctantCmd(version string, gitCommit string, buildTime string) *cobra.Com
 	octantCmd.Flags().StringSlice("namespace-list", []string{}, "a list of namespaces to use on start")
 	octantCmd.Flags().StringP("plugin-path", "", "", "plugin path")
 	octantCmd.Flags().BoolP("verbose", "v", false, "turn on debug logging")
-	octantCmd.Flags().IntP("client-max-recv-msg-size", "", 1024*1024*16, "client max receiver message size")
+	octantCmd.Flags().IntP("client-max-recv-msg-size", "", pconfig.MaxMessageSize, "client max receiver message size")
 
 	octantCmd.Flags().StringP("accepted-hosts", "", "", "accepted hosts list [DEV]")
 	octantCmd.Flags().Float32P("client-qps", "", 200, "maximum QPS for client [DEV]")
diff --git a/pkg/config/config.go b/pkg/config/config.go
new file mode 100644
index 00000000..073f2051
--- /dev/null
+++ b/pkg/config/config.go
@@ -0,0 +1,9 @@
+/*
+Copyright (c) 2020 the Octant contributors. All Rights Reserved.
+SPDX-License-Identifier: Apache-2.0
+*/
+
+package config
+
+// MaxMessageSize is used to configure the default maximum grpc message size
+const MaxMessageSize int = 1024 * 1024 * 16
diff --git a/pkg/plugin/api/client.go b/pkg/plugin/api/client.go
index e36b7379..0a10a0a7 100644
--- a/pkg/plugin/api/client.go
+++ b/pkg/plugin/api/client.go
@@ -8,13 +8,14 @@ package api
 import (
 	"context"
 
-	"github.com/spf13/viper"
-
 	"google.golang.org/grpc"
 	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
 
+	"github.com/spf13/viper"
+
 	"github.com/vmware-tanzu/octant/internal/log"
 	"github.com/vmware-tanzu/octant/pkg/action"
+	"github.com/vmware-tanzu/octant/pkg/config"
 	"github.com/vmware-tanzu/octant/pkg/plugin/api/proto"
 	"github.com/vmware-tanzu/octant/pkg/store"
 )
@@ -54,6 +55,7 @@ var _ Service = (*Client)(nil)
 // address of the API.
 func NewClient(address string, options ...ClientOption) (*Client, error) {
 	client := &Client{}
+	viper.SetDefault("client-max-recv-msg-size", config.MaxMessageSize)
 
 	for _, option := range options {
 		option(client)
diff --git a/pkg/plugin/grpc.go b/pkg/plugin/grpc.go
index 271f42ed..497bed92 100644
--- a/pkg/plugin/grpc.go
+++ b/pkg/plugin/grpc.go
@@ -80,6 +80,7 @@ func (c *GRPCClient) Content(ctx context.Context, contentPath string) (component
 // HandleAction runs an action on a plugin.
 func (c *GRPCClient) HandleAction(ctx context.Context, actionName string, payload action.Payload) error {
 	err := c.run(func() error {
+		clientID := ocontext.WebsocketClientIDFrom(ctx)
 		data, err := json.Marshal(&payload)
 		if err != nil {
 			return err
@@ -88,6 +89,7 @@ func (c *GRPCClient) HandleAction(ctx context.Context, actionName string, payloa
 		req := &dashboard.HandleActionRequest{
 			ActionName: actionName,
 			Payload:    data,
+			ClientID:   clientID,
 		}
 
 		_, err = c.client.HandleAction(ctx, req, grpc.WaitForReady(true))


Test patch:
diff --git a/internal/api/action_request_manager_test.go b/internal/api/action_request_manager_test.go
index 4a7ba4bf..8e6946c2 100644
--- a/internal/api/action_request_manager_test.go
+++ b/internal/api/action_request_manager_test.go
@@ -36,6 +36,7 @@ func TestActionRequestManager_PerformAction(t *testing.T) {
 	state.EXPECT().
 		Dispatch(gomock.Any(), api.RequestPerformAction, payload).
 		Return(nil)
+	state.EXPECT().GetClientID()
 
 	require.NoError(t, manager.PerformAction(state, payload))
 }