Skip to content

Commit

Permalink
feat(cdk): improve honeyvent data for components (#1016)
Browse files Browse the repository at this point in the history
Improves how we send a Honeyvent for components, this change also moves the logic of
parsing flags and initializing CLI state to the PersistentPreRunE() func.

* ci: debug issue opening PR during release
* chore(cli): add missing copyright headers
* fix: pass parser error to honeyvent

Signed-off-by: Salim Afiune Maya <[email protected]>
  • Loading branch information
afiune committed Nov 11, 2022
1 parent daa9c27 commit 8204f09
Show file tree
Hide file tree
Showing 7 changed files with 116 additions and 69 deletions.
29 changes: 17 additions & 12 deletions cli/cmd/cli_state.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,18 +63,19 @@ type cliState struct {
Cache *diskv.Diskv
LwComponents *lwcomponent.State

id string
workers sync.WaitGroup
spinner *spinner.Spinner
jsonOutput bool
yamlOutput bool
csvOutput bool
nonInteractive bool
noCache bool
lqlOperator string
profileDetails map[string]interface{}
tokenCache api.TokenData
installedCmd bool
id string
workers sync.WaitGroup
spinner *spinner.Spinner
jsonOutput bool
yamlOutput bool
csvOutput bool
nonInteractive bool
noCache bool
lqlOperator string
profileDetails map[string]interface{}
tokenCache api.TokenData
installedCmd bool
componentParser componentArgParser
}

// NewDefaultState creates a new cliState with some defaults
Expand Down Expand Up @@ -430,6 +431,10 @@ func (c *cliState) envs() []string {
fmt.Sprintf("LW_NOCOLOR=%s", os.Getenv("NO_COLOR")),
fmt.Sprintf("LW_LOG=%s", c.LogLevel),
fmt.Sprintf("LW_JSON=%v", c.jsonOutput),

// Sends tracing information
fmt.Sprintf("LW_HONEYVENT_TRACE_ID=%s", c.Event.TraceID),
fmt.Sprintf("LW_HONEYVENT_PARENT_ID=%s", c.Event.SpanID),
}
}

Expand Down
26 changes: 3 additions & 23 deletions cli/cmd/component.go
Original file line number Diff line number Diff line change
Expand Up @@ -164,35 +164,15 @@ func (c *cliState) LoadComponents() {
DisableFlagParsing: true,
DisableFlagsInUseLine: true,
RunE: func(cmd *cobra.Command, args []string) error {

// Split args into those handled by the CLI and those
// we pass to the component
argParser := componentArgParser{}
argParser.parseArgs(cmd.Flags(), args)
err := cmd.Flags().Parse(argParser.cliArgs)

// We call initConfig() again after global flags have been parsed.
initConfig()

if err != nil {
cli.Log.Debugw("unable to parse global flags",
"provided_flags", argParser.cliArgs, "error", err)
}

// The root command's persistent pre-run will not have created
// a client or done migrations
if err := rootPersistentPreRunE(); err != nil {
return err
}

cli.Log.Debugw("running component", "component", cmd.Use,
"args", argParser.componentArgs, "cli_flags", argParser.cliArgs)
"args", cli.componentParser.componentArgs,
"cli_flags", cli.componentParser.cliArgs)
f, ok := cli.LwComponents.GetComponent(cmd.Use)
if ok {
// @afiune what if the component needs other env variables
envs := []string{fmt.Sprintf("LW_COMPONENT_NAME=%s", cmd.Use)}
envs = append(envs, c.envs()...)
return f.RunAndOutput(argParser.componentArgs, envs...)
return f.RunAndOutput(cli.componentParser.componentArgs, envs...)
}

// We will land here only if we couldn't run the component, which is not
Expand Down
17 changes: 17 additions & 0 deletions cli/cmd/component_args.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,20 @@
//
// Copyright:: Copyright 2022, Lacework Inc.
// License:: Apache License, Version 2.0
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

package cmd

import (
Expand Down
17 changes: 17 additions & 0 deletions cli/cmd/component_args_test.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,20 @@
//
// Copyright:: Copyright 2022, Lacework Inc.
// License:: Apache License, Version 2.0
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

package cmd

import (
Expand Down
1 change: 1 addition & 0 deletions cli/cmd/honeyvent.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ type Honeyvent struct {
DurationMs int64 `json:"duration_ms,omitempty"`
Error string `json:"error,omitempty"`
InstallMethod string `json:"install_method,omitempty"`
Component string `json:"component,omitempty"`

// tracing data for multiple events, this is useful for specific features
// within the Lacework CLI such as daily version check, polling mechanism, etc.
Expand Down
92 changes: 58 additions & 34 deletions cli/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,19 +33,6 @@ import (
"github.com/lacework/go-sdk/lwlogger"
)

func rootPersistentPreRunE() error {
if err := cli.NewClient(); err != nil {
if !strings.Contains(err.Error(), "Invalid Account") {
return err
}

if err := cli.Migrations(); err != nil {
return err
}
}
return nil
}

var (
// the global cli state with defaults
cli = NewDefaultState()
Expand All @@ -66,27 +53,10 @@ Start by configuring the Lacework CLI with the command:
This will prompt you for your Lacework account and a set of API access keys.`,
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
cli.Log.Debugw("updating honeyvent", "dataset", HoneyDataset)
cli.Event.Command = cmd.CommandPath()
cli.Event.Args = args
cli.Event.Flags = parseFlags(os.Args[1:])
cli.SendHoneyvent()

switch cmd.Use {
case "help [command]", "configure", "version", "docs <directory>", "generate-pkg-manifest":
return nil
default:
// @afiune no need to create a client for any configure command
if cmd.HasParent() && cmd.Parent().Use == "configure" {
return nil
}
// @dhazekamp no need to create a client for any component command
// this will be handled via the components RunE
if isComponent(cmd.Annotations) {
return nil
}
return rootPersistentPreRunE()
if isComponent(cmd.Annotations) {
return componentPersistentPreRun(cmd, args)
}
return cliPersistentPreRun(cmd, args)
},
PersistentPostRunE: func(cmd *cobra.Command, _ []string) error {
// skip daily version check if the user is running the version command
Expand All @@ -106,6 +76,61 @@ This will prompt you for your Lacework account and a set of API access keys.`,
}
)

func cliPersistentPreRun(cmd *cobra.Command, args []string) error {
cli.Log.Debugw("updating honeyvent", "dataset", HoneyDataset)
cli.Event.Command = cmd.CommandPath()
cli.Event.Args = args
cli.Event.Flags = parseFlags(os.Args[1:])
cli.SendHoneyvent()

switch cmd.Use {
case "help [command]", "configure", "version", "docs <directory>", "generate-pkg-manifest":
return nil
default:
// @afiune no need to create a client for any configure command
if cmd.HasParent() && cmd.Parent().Use == "configure" {
return nil
}
if err := cli.NewClient(); err != nil {
if !strings.Contains(err.Error(), "Invalid Account") {
return err
}

if err := cli.Migrations(); err != nil {
return err
}
}
}
return nil
}

func componentPersistentPreRun(cmd *cobra.Command, args []string) error {
cli.Event.Command = cmd.CommandPath()
cli.Event.Component = cmd.Use
cli.Event.Flags = parseFlags(os.Args[1:])
defer cli.SendHoneyvent()

// For components, we disable flag parsing, therefore we
// split args into those handled by the CLI and those
// we pass to the component manually
cli.componentParser.parseArgs(cmd.Flags(), args)
cli.Event.Args = cli.componentParser.componentArgs
err := cmd.Flags().Parse(cli.componentParser.cliArgs)

// We call initConfig() again after global flags have been parsed.
initConfig()

if err != nil {
cli.Event.Error = err.Error()
cli.Log.Debugw("unable to parse global flags", "error", err,
"provided_flags", cli.componentParser.cliArgs)
}

cli.Log.Debugw("honeyvent updated", "dataset", HoneyDataset)

return cli.NewClient()
}

// Execute adds all child commands to the root command and sets flags appropriately.
// This is called by main.main(). It only needs to happen once to the rootCmd.
func Execute() (err error) {
Expand Down Expand Up @@ -280,7 +305,6 @@ func initConfig() {
cli.Log.Debugw("configuration file not found")
} else {
// the config file was found but another error was produced
errcheckWARN(rootCmd.Help())
exitwith(errors.Wrap(err, "unable to read in config file ~/.lacework.toml"))
}
} else {
Expand Down
3 changes: 3 additions & 0 deletions scripts/release.sh
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,9 @@ open_pull_request() {
curl -XPOST -H "Authorization: token $GITHUB_TOKEN" --data "@$_body" \
https://api.github.com/repos/${org_name}/${project_name}/pulls > $_pr

# @afiune just to debug the issue where the field `html_url` comes as `null`
echo "$_pr" | jq .

_pr_url=$(jq .html_url $_pr)
log ""
log "It is time to review the release!"
Expand Down

0 comments on commit 8204f09

Please sign in to comment.