From 430cc33558bc2904e938f1c12fac84045f358291 Mon Sep 17 00:00:00 2001 From: Aphral Griffin Date: Mon, 27 Mar 2023 15:31:08 +0100 Subject: [PATCH 01/15] move dynamic-agent.conf to /var/lib/nginx-agent --- README.md | 2 +- examples/grafana-metrics/nginx-agent.conf | 2 +- nginx-agent.conf | 2 +- scripts/packages/postinstall.sh | 2 +- scripts/packages/preinstall.sh | 26 ++++++++++++++----- sdk/proto/events/event.proto | 22 ++++++++-------- src/core/config/defaults.go | 2 +- test/integration/api/nginx-agent.conf | 2 +- .../install/install_uninstall_test.go | 2 +- .../agent/sdk/v2/proto/events/event.proto | 22 ++++++++-------- .../agent/sdk/v2/proto/events/event.proto | 22 ++++++++-------- .../agent/v2/src/core/config/defaults.go | 2 +- .../agent/sdk/v2/proto/events/event.proto | 22 ++++++++-------- 13 files changed, 71 insertions(+), 59 deletions(-) diff --git a/README.md b/README.md index 5f29d0321..1d9f18a45 100644 --- a/README.md +++ b/README.md @@ -152,7 +152,7 @@ sudo cp /nginx-agent.conf /etc/nginx-agent/ ``` Create the `agent-dynamic.conf` file in the `/etc/nginx-agent/` directory, which is required for NGINX Agent to run. ``` -sudo touch /etc/nginx-agent/agent-dynamic.conf +sudo touch /var/lib/nginx-agent/agent-dynamic.conf ``` ### Enabling the gRPC interface diff --git a/examples/grafana-metrics/nginx-agent.conf b/examples/grafana-metrics/nginx-agent.conf index 48464cd82..d310f1866 100644 --- a/examples/grafana-metrics/nginx-agent.conf +++ b/examples/grafana-metrics/nginx-agent.conf @@ -5,7 +5,7 @@ # # This file is to track agent configuration values that are meant to be statically set. There # are additional agent configuration values that are set via the API and agent install script -# which can be found in /etc/nginx-agent/agent-dynamic.conf. +# which can be found in /var/lib/nginx-agent/agent-dynamic.conf. api: # port to expose http api diff --git a/nginx-agent.conf b/nginx-agent.conf index 6be903301..adee227ab 100644 --- a/nginx-agent.conf +++ b/nginx-agent.conf @@ -5,7 +5,7 @@ # # This file is to track agent configuration values that are meant to be statically set. There # are additional agent configuration values that are set via the API and agent install script -# which can be found in /etc/nginx-agent/agent-dynamic.conf. +# which can be found in /var/lib/nginx-agent/agent-dynamic.conf. log: # set log level (panic, fatal, error, info, debug, trace; default "info") diff --git a/scripts/packages/postinstall.sh b/scripts/packages/postinstall.sh index 6a7993e7b..b7c92f499 100755 --- a/scripts/packages/postinstall.sh +++ b/scripts/packages/postinstall.sh @@ -185,7 +185,7 @@ add_default_config_file() { # # This file is to track agent configuration values that are meant to be statically set. There # are additional agent configuration values that are set via the API and agent install script -# which can be found in /etc/nginx-agent/agent-dynamic.conf. +# which can be found in /var/lib/nginx-agent/agent-dynamic.conf. # specify the server grpc port to connect to server: diff --git a/scripts/packages/preinstall.sh b/scripts/packages/preinstall.sh index 16db11f60..3a1593f14 100644 --- a/scripts/packages/preinstall.sh +++ b/scripts/packages/preinstall.sh @@ -24,14 +24,19 @@ export AGENT_GROUP="${AGENT_GROUP:-$(id -ng)}" if [ "$ID" = "freebsd" ]; then AGENT_CONFIG_FILE=${AGENT_CONFIG_FILE:-"/usr/local/etc/nginx-agent/nginx-agent.conf"} - AGENT_DYNAMIC_CONFIG_DIR="/usr/local/etc/nginx-agent" + AGENT_DYNAMIC_CONFIG_DIR="/usr/local/var/lib/nginx-agent" + # Old location of agent-dynamic.conf + OLD_DYNAMIC_CONFIG_DIR="/usr/local/etc/nginx-agent" mkdir -p /var/log/nginx-agent/ else - AGENT_CONFIG_FILE=${AGENT_CONFIG_FILE:-"/etc/nginx-agent/nginx-agent.conf"} - AGENT_DYNAMIC_CONFIG_DIR="/etc/nginx-agent" + AGENT_CONFIG_FILE=${AGENT_CONFIG_FILE:-"/var/lib/nginx-agent/nginx-agent.conf"} + AGENT_DYNAMIC_CONFIG_DIR="/var/lib/nginx-agent" + # Old location of agent-dynamic.conf + OLD_DYNAMIC_CONFIG_DIR="/etc/nginx-agent" fi AGENT_DYNAMIC_CONFIG_FILE="${AGENT_DYNAMIC_CONFIG_DIR}/agent-dynamic.conf" +OLD_DYNAMIC_CONFIG_FILE="${OLD_DYNAMIC_CONFIG_DIR}/agent-dynamic.conf" AGENT_DYNAMIC_CONFIG_COMMENT="# # dynamic-agent.conf # @@ -77,10 +82,17 @@ ensure_sudo() { load_config_values() { # If the file doesn't exist attempt to create it if [ ! -f "$AGENT_DYNAMIC_CONFIG_FILE" ]; then - printf "Could not find %s ... Creating file\n" ${AGENT_DYNAMIC_CONFIG_FILE} - mkdir -p ${AGENT_DYNAMIC_CONFIG_DIR} - printf "%s" "${AGENT_DYNAMIC_CONFIG_COMMENT}" | tee ${AGENT_DYNAMIC_CONFIG_FILE} > /dev/null - printf "Successfully created %s\n" "${AGENT_DYNAMIC_CONFIG_FILE}" + + if [ -f "$OLD_DYNAMIC_CONFIG_FILE" ]; then + mkdir -p ${AGENT_DYNAMIC_CONFIG_DIR} + ln "$OLD_DYNAMIC_CONFIG_FILE" "$AGENT_DYNAMIC_CONFIG_FILE" + else + printf "Could not find %s ... Creating file\n" ${AGENT_DYNAMIC_CONFIG_FILE} + mkdir -p ${AGENT_DYNAMIC_CONFIG_DIR} + printf "%s" "${AGENT_DYNAMIC_CONFIG_COMMENT}" | tee ${AGENT_DYNAMIC_CONFIG_FILE} > /dev/null + printf "Successfully created %s\n" "${AGENT_DYNAMIC_CONFIG_FILE}" + fi + fi # Check if there are existing values diff --git a/sdk/proto/events/event.proto b/sdk/proto/events/event.proto index 3357643af..61324fc70 100644 --- a/sdk/proto/events/event.proto +++ b/sdk/proto/events/event.proto @@ -34,17 +34,17 @@ message Event { ActivityEvent ActivityEvent = 2 [(gogoproto.jsontag) = "activity_event"]; // Activity event /** - * While generating the SecurityViolationEvent, the Metadata for a SecurityViolationEvent - * would look as shown below: - * - Module = Agent - * - UUID = A UUID generated by the Agent for the EventReport - * - CorrelationID = The UUID will be used as the Correlation ID to track the EventReport - * - Timestamp = The timestamp when NGINX Agent received the violation event - * - EventLevel = All the SecurityViolationEvent would be generated at an ERROR_EVENT_LEVEL ("ERROR") level - * In future, the levels might be dynamically chosen based on Request Outcome of SecurityViolationEvent - * - Type = NGINX_EVENT_TYPE ("Nginx") - * - Category = APP_PROTECT_CATEGORY ("AppProtect") - */ + * While generating the SecurityViolationEvent, the Metadata for a SecurityViolationEvent + * would look as shown below: + * - Module = Agent + * - UUID = A UUID generated by the Agent for the EventReport + * - CorrelationID = The UUID will be used as the Correlation ID to track the EventReport + * - Timestamp = The timestamp when NGINX Agent received the violation event + * - EventLevel = All the SecurityViolationEvent would be generated at an ERROR_EVENT_LEVEL ("ERROR") level + * In future, the levels might be dynamically chosen based on Request Outcome of SecurityViolationEvent + * - Type = NGINX_EVENT_TYPE ("Nginx") + * - Category = APP_PROTECT_CATEGORY ("AppProtect") + */ SecurityViolationEvent SecurityViolationEvent = 3 [(gogoproto.jsontag) = "security_violation_event"]; // Security violation event } diff --git a/src/core/config/defaults.go b/src/core/config/defaults.go index 5450c6e41..d27c27256 100644 --- a/src/core/config/defaults.go +++ b/src/core/config/defaults.go @@ -80,7 +80,7 @@ var ( const ( DynamicConfigFileName = "agent-dynamic.conf" - DynamicConfigFileAbsPath = "/etc/nginx-agent/agent-dynamic.conf" + DynamicConfigFileAbsPath = "/var/lib/nginx-agent/agent-dynamic.conf" ConfigFileName = "nginx-agent.conf" ConfigFileType = "yaml" EnvPrefix = "nms" diff --git a/test/integration/api/nginx-agent.conf b/test/integration/api/nginx-agent.conf index b0212e62f..4c6129f0d 100644 --- a/test/integration/api/nginx-agent.conf +++ b/test/integration/api/nginx-agent.conf @@ -5,7 +5,7 @@ # # This file is to track agent configuration values that are meant to be statically set. There # are additional agent configuration values that are set via the API and agent install script -# which can be found in /etc/nginx-agent/agent-dynamic.conf. +# which can be found in /var/lib/nginx-agent/agent-dynamic.conf. api: # port to expose http api diff --git a/test/integration/install/install_uninstall_test.go b/test/integration/install/install_uninstall_test.go index b3d2908f0..a03edb4a5 100644 --- a/test/integration/install/install_uninstall_test.go +++ b/test/integration/install/install_uninstall_test.go @@ -47,7 +47,7 @@ func TestAgentManualInstallUninstall(t *testing.T) { expectedAgentPaths := map[string]string{ "AgentConfigFile": "/etc/nginx-agent/nginx-agent.conf", - "AgentDynamicConfigFile": "/etc/nginx-agent/agent-dynamic.conf", + "AgentDynamicConfigFile": "/var/lib/nginx-agent/agent-dynamic.conf", } // Check the environment variable $PACKAGE_NAME is set diff --git a/test/integration/vendor/github.com/nginx/agent/sdk/v2/proto/events/event.proto b/test/integration/vendor/github.com/nginx/agent/sdk/v2/proto/events/event.proto index 3357643af..61324fc70 100644 --- a/test/integration/vendor/github.com/nginx/agent/sdk/v2/proto/events/event.proto +++ b/test/integration/vendor/github.com/nginx/agent/sdk/v2/proto/events/event.proto @@ -34,17 +34,17 @@ message Event { ActivityEvent ActivityEvent = 2 [(gogoproto.jsontag) = "activity_event"]; // Activity event /** - * While generating the SecurityViolationEvent, the Metadata for a SecurityViolationEvent - * would look as shown below: - * - Module = Agent - * - UUID = A UUID generated by the Agent for the EventReport - * - CorrelationID = The UUID will be used as the Correlation ID to track the EventReport - * - Timestamp = The timestamp when NGINX Agent received the violation event - * - EventLevel = All the SecurityViolationEvent would be generated at an ERROR_EVENT_LEVEL ("ERROR") level - * In future, the levels might be dynamically chosen based on Request Outcome of SecurityViolationEvent - * - Type = NGINX_EVENT_TYPE ("Nginx") - * - Category = APP_PROTECT_CATEGORY ("AppProtect") - */ + * While generating the SecurityViolationEvent, the Metadata for a SecurityViolationEvent + * would look as shown below: + * - Module = Agent + * - UUID = A UUID generated by the Agent for the EventReport + * - CorrelationID = The UUID will be used as the Correlation ID to track the EventReport + * - Timestamp = The timestamp when NGINX Agent received the violation event + * - EventLevel = All the SecurityViolationEvent would be generated at an ERROR_EVENT_LEVEL ("ERROR") level + * In future, the levels might be dynamically chosen based on Request Outcome of SecurityViolationEvent + * - Type = NGINX_EVENT_TYPE ("Nginx") + * - Category = APP_PROTECT_CATEGORY ("AppProtect") + */ SecurityViolationEvent SecurityViolationEvent = 3 [(gogoproto.jsontag) = "security_violation_event"]; // Security violation event } diff --git a/test/performance/vendor/github.com/nginx/agent/sdk/v2/proto/events/event.proto b/test/performance/vendor/github.com/nginx/agent/sdk/v2/proto/events/event.proto index 3357643af..61324fc70 100644 --- a/test/performance/vendor/github.com/nginx/agent/sdk/v2/proto/events/event.proto +++ b/test/performance/vendor/github.com/nginx/agent/sdk/v2/proto/events/event.proto @@ -34,17 +34,17 @@ message Event { ActivityEvent ActivityEvent = 2 [(gogoproto.jsontag) = "activity_event"]; // Activity event /** - * While generating the SecurityViolationEvent, the Metadata for a SecurityViolationEvent - * would look as shown below: - * - Module = Agent - * - UUID = A UUID generated by the Agent for the EventReport - * - CorrelationID = The UUID will be used as the Correlation ID to track the EventReport - * - Timestamp = The timestamp when NGINX Agent received the violation event - * - EventLevel = All the SecurityViolationEvent would be generated at an ERROR_EVENT_LEVEL ("ERROR") level - * In future, the levels might be dynamically chosen based on Request Outcome of SecurityViolationEvent - * - Type = NGINX_EVENT_TYPE ("Nginx") - * - Category = APP_PROTECT_CATEGORY ("AppProtect") - */ + * While generating the SecurityViolationEvent, the Metadata for a SecurityViolationEvent + * would look as shown below: + * - Module = Agent + * - UUID = A UUID generated by the Agent for the EventReport + * - CorrelationID = The UUID will be used as the Correlation ID to track the EventReport + * - Timestamp = The timestamp when NGINX Agent received the violation event + * - EventLevel = All the SecurityViolationEvent would be generated at an ERROR_EVENT_LEVEL ("ERROR") level + * In future, the levels might be dynamically chosen based on Request Outcome of SecurityViolationEvent + * - Type = NGINX_EVENT_TYPE ("Nginx") + * - Category = APP_PROTECT_CATEGORY ("AppProtect") + */ SecurityViolationEvent SecurityViolationEvent = 3 [(gogoproto.jsontag) = "security_violation_event"]; // Security violation event } diff --git a/test/performance/vendor/github.com/nginx/agent/v2/src/core/config/defaults.go b/test/performance/vendor/github.com/nginx/agent/v2/src/core/config/defaults.go index 5450c6e41..d27c27256 100644 --- a/test/performance/vendor/github.com/nginx/agent/v2/src/core/config/defaults.go +++ b/test/performance/vendor/github.com/nginx/agent/v2/src/core/config/defaults.go @@ -80,7 +80,7 @@ var ( const ( DynamicConfigFileName = "agent-dynamic.conf" - DynamicConfigFileAbsPath = "/etc/nginx-agent/agent-dynamic.conf" + DynamicConfigFileAbsPath = "/var/lib/nginx-agent/agent-dynamic.conf" ConfigFileName = "nginx-agent.conf" ConfigFileType = "yaml" EnvPrefix = "nms" diff --git a/vendor/github.com/nginx/agent/sdk/v2/proto/events/event.proto b/vendor/github.com/nginx/agent/sdk/v2/proto/events/event.proto index 3357643af..61324fc70 100644 --- a/vendor/github.com/nginx/agent/sdk/v2/proto/events/event.proto +++ b/vendor/github.com/nginx/agent/sdk/v2/proto/events/event.proto @@ -34,17 +34,17 @@ message Event { ActivityEvent ActivityEvent = 2 [(gogoproto.jsontag) = "activity_event"]; // Activity event /** - * While generating the SecurityViolationEvent, the Metadata for a SecurityViolationEvent - * would look as shown below: - * - Module = Agent - * - UUID = A UUID generated by the Agent for the EventReport - * - CorrelationID = The UUID will be used as the Correlation ID to track the EventReport - * - Timestamp = The timestamp when NGINX Agent received the violation event - * - EventLevel = All the SecurityViolationEvent would be generated at an ERROR_EVENT_LEVEL ("ERROR") level - * In future, the levels might be dynamically chosen based on Request Outcome of SecurityViolationEvent - * - Type = NGINX_EVENT_TYPE ("Nginx") - * - Category = APP_PROTECT_CATEGORY ("AppProtect") - */ + * While generating the SecurityViolationEvent, the Metadata for a SecurityViolationEvent + * would look as shown below: + * - Module = Agent + * - UUID = A UUID generated by the Agent for the EventReport + * - CorrelationID = The UUID will be used as the Correlation ID to track the EventReport + * - Timestamp = The timestamp when NGINX Agent received the violation event + * - EventLevel = All the SecurityViolationEvent would be generated at an ERROR_EVENT_LEVEL ("ERROR") level + * In future, the levels might be dynamically chosen based on Request Outcome of SecurityViolationEvent + * - Type = NGINX_EVENT_TYPE ("Nginx") + * - Category = APP_PROTECT_CATEGORY ("AppProtect") + */ SecurityViolationEvent SecurityViolationEvent = 3 [(gogoproto.jsontag) = "security_violation_event"]; // Security violation event } From 4cea561364475aa6c4ff5b4a06af8da75675bfa6 Mon Sep 17 00:00:00 2001 From: Aphral Griffin Date: Mon, 27 Mar 2023 15:44:02 +0100 Subject: [PATCH 02/15] revert accidental change --- scripts/packages/preinstall.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/packages/preinstall.sh b/scripts/packages/preinstall.sh index 3a1593f14..f1317f446 100644 --- a/scripts/packages/preinstall.sh +++ b/scripts/packages/preinstall.sh @@ -29,8 +29,8 @@ if [ "$ID" = "freebsd" ]; then OLD_DYNAMIC_CONFIG_DIR="/usr/local/etc/nginx-agent" mkdir -p /var/log/nginx-agent/ else - AGENT_CONFIG_FILE=${AGENT_CONFIG_FILE:-"/var/lib/nginx-agent/nginx-agent.conf"} - AGENT_DYNAMIC_CONFIG_DIR="/var/lib/nginx-agent" + AGENT_CONFIG_FILE=${AGENT_CONFIG_FILE:-"/etc/nginx-agent/nginx-agent.conf"} + AGENT_DYNAMIC_CONFIG_DIR="/var/lib/nginx-agent" # Old location of agent-dynamic.conf OLD_DYNAMIC_CONFIG_DIR="/etc/nginx-agent" fi From fb331196549386b1035ab245df3fb0d7e44b186f Mon Sep 17 00:00:00 2001 From: Aphral Griffin Date: Mon, 27 Mar 2023 15:48:02 +0100 Subject: [PATCH 03/15] formatting --- scripts/packages/preinstall.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/scripts/packages/preinstall.sh b/scripts/packages/preinstall.sh index f1317f446..091c077fb 100644 --- a/scripts/packages/preinstall.sh +++ b/scripts/packages/preinstall.sh @@ -30,7 +30,7 @@ if [ "$ID" = "freebsd" ]; then mkdir -p /var/log/nginx-agent/ else AGENT_CONFIG_FILE=${AGENT_CONFIG_FILE:-"/etc/nginx-agent/nginx-agent.conf"} - AGENT_DYNAMIC_CONFIG_DIR="/var/lib/nginx-agent" + AGENT_DYNAMIC_CONFIG_DIR="/var/lib/nginx-agent" # Old location of agent-dynamic.conf OLD_DYNAMIC_CONFIG_DIR="/etc/nginx-agent" fi @@ -82,7 +82,6 @@ ensure_sudo() { load_config_values() { # If the file doesn't exist attempt to create it if [ ! -f "$AGENT_DYNAMIC_CONFIG_FILE" ]; then - if [ -f "$OLD_DYNAMIC_CONFIG_FILE" ]; then mkdir -p ${AGENT_DYNAMIC_CONFIG_DIR} ln "$OLD_DYNAMIC_CONFIG_FILE" "$AGENT_DYNAMIC_CONFIG_FILE" From d2e9f19b00978edae51dfb6da3e661d6d0f7fe03 Mon Sep 17 00:00:00 2001 From: Aphral Griffin Date: Fri, 31 Mar 2023 15:23:42 +0100 Subject: [PATCH 04/15] update getting started guide with new location of agent-dynamic.conf --- hugo/content/getting-started.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hugo/content/getting-started.md b/hugo/content/getting-started.md index 891baf883..a6f800e67 100644 --- a/hugo/content/getting-started.md +++ b/hugo/content/getting-started.md @@ -42,9 +42,9 @@ If it doesn't already exist, create the `/etc/nginx-agent/` directory and copy t sudo mkdir /etc/nginx-agent sudo cp /nginx-agent.conf /etc/nginx-agent/ ``` -Create the `agent-dynamic.conf` file in the `/etc/nginx-agent/` directory, which is required for NGINX Agent to run. +Create the `agent-dynamic.conf` file in the `/var/lib/nginx-agent/` directory, which is required for NGINX Agent to run. ``` -sudo touch /etc/nginx-agent/agent-dynamic.conf +sudo touch /var/lib/nginx-agent/agent-dynamic.conf ``` ### Enable the gRPC interface From 9fb8c70eac0b612201bc55bc1538f15a8263cb0b Mon Sep 17 00:00:00 2001 From: Aphral Griffin Date: Thu, 6 Apr 2023 10:09:02 +0100 Subject: [PATCH 05/15] fix freebsd agent install --- scripts/packages/preinstall.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/scripts/packages/preinstall.sh b/scripts/packages/preinstall.sh index 091c077fb..c2c1ed076 100644 --- a/scripts/packages/preinstall.sh +++ b/scripts/packages/preinstall.sh @@ -35,6 +35,8 @@ else OLD_DYNAMIC_CONFIG_DIR="/etc/nginx-agent" fi +OLD_FREE_BSD_FILE="/etc/nginx-agent/agent-dynamic.conf" +NEW_FREE_BSD_FILE="/var/lib/nginx-agent/agent-dynamic.conf" AGENT_DYNAMIC_CONFIG_FILE="${AGENT_DYNAMIC_CONFIG_DIR}/agent-dynamic.conf" OLD_DYNAMIC_CONFIG_FILE="${OLD_DYNAMIC_CONFIG_DIR}/agent-dynamic.conf" AGENT_DYNAMIC_CONFIG_COMMENT="# @@ -85,6 +87,9 @@ load_config_values() { if [ -f "$OLD_DYNAMIC_CONFIG_FILE" ]; then mkdir -p ${AGENT_DYNAMIC_CONFIG_DIR} ln "$OLD_DYNAMIC_CONFIG_FILE" "$AGENT_DYNAMIC_CONFIG_FILE" + if [ "$ID" = "freebsd" ]; then + ln "$OLD_FREE_BSD_FILE" "$NEW_FREE_BSD_FILE" + fi else printf "Could not find %s ... Creating file\n" ${AGENT_DYNAMIC_CONFIG_FILE} mkdir -p ${AGENT_DYNAMIC_CONFIG_DIR} From 02d6547d1b6ea52243c3ef7b85c8cc687b2c28df Mon Sep 17 00:00:00 2001 From: Aphral Griffin Date: Thu, 6 Apr 2023 15:47:29 +0100 Subject: [PATCH 06/15] change config location for freebsd and fix unit tests --- scripts/packages/preinstall.sh | 26 ++++++----------------- sdk/client/commander_test.go | 39 ++++++++++++++++++++-------------- 2 files changed, 29 insertions(+), 36 deletions(-) diff --git a/scripts/packages/preinstall.sh b/scripts/packages/preinstall.sh index c2c1ed076..b6eb97632 100644 --- a/scripts/packages/preinstall.sh +++ b/scripts/packages/preinstall.sh @@ -22,23 +22,12 @@ export AGENT_GROUP="${AGENT_GROUP:-$(id -ng)}" # shellcheck source=/dev/null . /etc/os-release -if [ "$ID" = "freebsd" ]; then - AGENT_CONFIG_FILE=${AGENT_CONFIG_FILE:-"/usr/local/etc/nginx-agent/nginx-agent.conf"} - AGENT_DYNAMIC_CONFIG_DIR="/usr/local/var/lib/nginx-agent" - # Old location of agent-dynamic.conf - OLD_DYNAMIC_CONFIG_DIR="/usr/local/etc/nginx-agent" - mkdir -p /var/log/nginx-agent/ -else - AGENT_CONFIG_FILE=${AGENT_CONFIG_FILE:-"/etc/nginx-agent/nginx-agent.conf"} - AGENT_DYNAMIC_CONFIG_DIR="/var/lib/nginx-agent" - # Old location of agent-dynamic.conf - OLD_DYNAMIC_CONFIG_DIR="/etc/nginx-agent" -fi - -OLD_FREE_BSD_FILE="/etc/nginx-agent/agent-dynamic.conf" -NEW_FREE_BSD_FILE="/var/lib/nginx-agent/agent-dynamic.conf" -AGENT_DYNAMIC_CONFIG_FILE="${AGENT_DYNAMIC_CONFIG_DIR}/agent-dynamic.conf" -OLD_DYNAMIC_CONFIG_FILE="${OLD_DYNAMIC_CONFIG_DIR}/agent-dynamic.conf" +AGENT_CONFIG_FILE=${AGENT_CONFIG_FILE:-"/etc/nginx-agent/nginx-agent.conf"} +AGENT_DYNAMIC_CONFIG_DIR="/var/lib/nginx-agent" + +AGENT_DYNAMIC_CONFIG_FILE="/var/lib/nginx-agent/agent-dynamic.conf" +# Old location of agent-dynamic.conf +OLD_DYNAMIC_CONFIG_FILE="/etc/nginx-agent/agent-dynamic.conf" AGENT_DYNAMIC_CONFIG_COMMENT="# # dynamic-agent.conf # @@ -87,9 +76,6 @@ load_config_values() { if [ -f "$OLD_DYNAMIC_CONFIG_FILE" ]; then mkdir -p ${AGENT_DYNAMIC_CONFIG_DIR} ln "$OLD_DYNAMIC_CONFIG_FILE" "$AGENT_DYNAMIC_CONFIG_FILE" - if [ "$ID" = "freebsd" ]; then - ln "$OLD_FREE_BSD_FILE" "$NEW_FREE_BSD_FILE" - fi else printf "Could not find %s ... Creating file\n" ${AGENT_DYNAMIC_CONFIG_FILE} mkdir -p ${AGENT_DYNAMIC_CONFIG_DIR} diff --git a/sdk/client/commander_test.go b/sdk/client/commander_test.go index b6d3ec795..1834ad154 100644 --- a/sdk/client/commander_test.go +++ b/sdk/client/commander_test.go @@ -613,10 +613,12 @@ func (c *mockCommanderService) Download(request *proto.DownloadRequest, server p for { data := <-c.downloadChannel fmt.Printf("Download Send: %v\n", data) - err := server.Send(data) - if err != nil { - fmt.Printf("Download Send Error: %v\n", err) - return err + if data != nil { + err := server.Send(data) + if err != nil { + fmt.Printf("Download Send Error: %v\n", err) + return err + } } } } @@ -661,26 +663,31 @@ func (c *mockCommanderService) ensureHandler() *handler { func (h *handler) recvHandle(server proto.Commander_CommandChannelServer, wg *sync.WaitGroup) { for { cmd, err := server.Recv() - fmt.Printf("Recv Command: %v\n", cmd) - if err != nil { - fmt.Printf("Recv Command Error: %v\n", err) - wg.Done() - return + if cmd != nil { + fmt.Printf("Recv Command: %v\n", cmd) + if err != nil { + fmt.Printf("Recv Command Error: %v\n", err) + wg.Done() + return + } + h.fromClient <- cmd } - h.fromClient <- cmd } } func (h *handler) sendHandle(server proto.Commander_CommandChannelServer, wg *sync.WaitGroup) { for { cmd := <-h.toClient - err := server.Send(cmd) - fmt.Printf("Send Command: %v\n", cmd) - if err != nil { - fmt.Printf("Send Command Error: %v\n", err) - wg.Done() - return + if cmd != nil { + err := server.Send(cmd) + fmt.Printf("Send Command: %v\n", cmd) + if err != nil { + fmt.Printf("Send Command Error: %v\n", err) + wg.Done() + return + } } + } } From f0e6de0af180f4c47b7b2db46bd7027dfea5108e Mon Sep 17 00:00:00 2001 From: Aphral Griffin Date: Fri, 7 Apr 2023 11:00:09 +0100 Subject: [PATCH 07/15] possible unit test fix --- sdk/client/commander_test.go | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/sdk/client/commander_test.go b/sdk/client/commander_test.go index 1834ad154..ea13547fd 100644 --- a/sdk/client/commander_test.go +++ b/sdk/client/commander_test.go @@ -85,7 +85,9 @@ func TestCommander_Recv(t *testing.T) { select { case actual := <-commanderClient.Recv(): - assert.Equal(t, "1234", actual.Meta().MessageId) + if actual != nil { + assert.Equal(t, "1234", actual.Meta().MessageId) + } case <-time.After(1 * time.Second): t.Fatalf("No message received from commander") } @@ -112,7 +114,9 @@ func TestCommander_Send(t *testing.T) { select { case actual := <-commandService.handler.fromClient: - assert.Equal(t, "1234", actual.GetMeta().MessageId) + if actual != nil { + assert.Equal(t, "1234", actual.GetMeta().MessageId) + } case <-time.After(1 * time.Second): t.Fatalf("No message received from commander") } @@ -249,7 +253,9 @@ func TestCommander_Recv_Reconnect(t *testing.T) { select { case actual := <-commanderClient.Recv(): - assert.Equal(t, "1234", actual.Meta().MessageId) + if actual != nil { + assert.Equal(t, "1234", actual.Meta().MessageId) + } case <-time.After(1 * time.Second): t.Fatalf("No message received from commander") } From 9af0bbfc10f4eaaf617ca7d65d0953ae124d266d Mon Sep 17 00:00:00 2001 From: Aphral Griffin Date: Tue, 11 Apr 2023 10:59:42 +0100 Subject: [PATCH 08/15] change location of agent dynamic file in freebsd --- main.go | 7 ++++++- scripts/packages/preinstall.sh | 21 +++++++++++++++------ src/core/config/config.go | 13 +++++++++++-- src/core/config/defaults.go | 1 + 4 files changed, 33 insertions(+), 9 deletions(-) diff --git a/main.go b/main.go index 373436939..a4d49ad8a 100644 --- a/main.go +++ b/main.go @@ -11,6 +11,7 @@ import ( "context" "os" "os/signal" + "runtime" "strconv" "strings" "syscall" @@ -42,7 +43,11 @@ func init() { config.SetVersion(version, commit) config.SetDefaults() config.RegisterFlags() - configPath, err := config.RegisterConfigFile(config.DynamicConfigFileAbsPath, config.ConfigFileName, config.ConfigFilePaths()...) + dynamicConfigPath := config.DynamicConfigFileAbsPath + if runtime.GOOS == "freebsd"{ + dynamicConfigPath = config.DynamicConfigFileAbsFreeBsdPath + } + configPath, err := config.RegisterConfigFile(dynamicConfigPath, config.ConfigFileName, config.ConfigFilePaths()...) if err != nil { log.Fatalf("Failed to load configuration file: %v", err) } diff --git a/scripts/packages/preinstall.sh b/scripts/packages/preinstall.sh index b6eb97632..e1238a329 100644 --- a/scripts/packages/preinstall.sh +++ b/scripts/packages/preinstall.sh @@ -22,12 +22,21 @@ export AGENT_GROUP="${AGENT_GROUP:-$(id -ng)}" # shellcheck source=/dev/null . /etc/os-release -AGENT_CONFIG_FILE=${AGENT_CONFIG_FILE:-"/etc/nginx-agent/nginx-agent.conf"} -AGENT_DYNAMIC_CONFIG_DIR="/var/lib/nginx-agent" - -AGENT_DYNAMIC_CONFIG_FILE="/var/lib/nginx-agent/agent-dynamic.conf" -# Old location of agent-dynamic.conf -OLD_DYNAMIC_CONFIG_FILE="/etc/nginx-agent/agent-dynamic.conf" +if [ "$ID" = "freebsd" ]; then + AGENT_CONFIG_FILE=${AGENT_CONFIG_FILE:-"/usr/local/etc/nginx-agent/nginx-agent.conf"} + AGENT_DYNAMIC_CONFIG_DIR="/var/db/nginx-agent" + # Old location of agent-dynamic.conf + OLD_DYNAMIC_CONFIG_DIR="/etc/nginx-agent" + mkdir -p /var/log/nginx-agent/ +else + AGENT_CONFIG_FILE=${AGENT_CONFIG_FILE:-"/etc/nginx-agent/nginx-agent.conf"} + AGENT_DYNAMIC_CONFIG_DIR="/var/lib/nginx-agent" + # Old location of agent-dynamic.conf + OLD_DYNAMIC_CONFIG_DIR="/etc/nginx-agent" +fi + +AGENT_DYNAMIC_CONFIG_FILE="${AGENT_DYNAMIC_CONFIG_DIR}/agent-dynamic.conf" +OLD_DYNAMIC_CONFIG_FILE="${OLD_DYNAMIC_CONFIG_DIR}/agent-dynamic.conf" AGENT_DYNAMIC_CONFIG_COMMENT="# # dynamic-agent.conf # diff --git a/src/core/config/config.go b/src/core/config/config.go index 34aa9168d..2d5f8e608 100644 --- a/src/core/config/config.go +++ b/src/core/config/config.go @@ -13,6 +13,7 @@ import ( "os" "path/filepath" "reflect" + "runtime" "sort" "strings" "time" @@ -235,7 +236,11 @@ func UpdateAgentConfig(systemId string, updateTags []string, updateFeatures []st // already set. dynamicCfgPath := Viper.GetString(DynamicConfigPathKey) if dynamicCfgPath == "" { - dynamicCfgPath = DynamicConfigFileAbsPath + if runtime.GOOS == "freebsd"{ + dynamicCfgPath = DynamicConfigFileAbsFreeBsdPath + }else{ + dynamicCfgPath = DynamicConfigFileAbsPath + } } // Overwrite existing nginx-agent.conf with updated config @@ -334,7 +339,11 @@ func LoadPropertiesFromFile(cfg string) error { // already set. dynamicCfgPath := Viper.GetString(DynamicConfigPathKey) if dynamicCfgPath == "" { - dynamicCfgPath = DynamicConfigFileAbsPath + if runtime.GOOS == "freebsd"{ + dynamicCfgPath = DynamicConfigFileAbsFreeBsdPath + }else{ + dynamicCfgPath = DynamicConfigFileAbsPath + } } dynamicCfgDir, dynamicCfgFile := filepath.Split(dynamicCfgPath) diff --git a/src/core/config/defaults.go b/src/core/config/defaults.go index 1bf44a5d8..e4342fd57 100644 --- a/src/core/config/defaults.go +++ b/src/core/config/defaults.go @@ -83,6 +83,7 @@ var ( const ( DynamicConfigFileName = "agent-dynamic.conf" DynamicConfigFileAbsPath = "/var/lib/nginx-agent/agent-dynamic.conf" + DynamicConfigFileAbsFreeBsdPath = "/var/db/nginx-agent/agent-dynamic.conf" ConfigFileName = "nginx-agent.conf" ConfigFileType = "yaml" EnvPrefix = "nms" From 2fdbdf5a330b3990fadb7ff25fd1926d5996105e Mon Sep 17 00:00:00 2001 From: Aphral Griffin Date: Tue, 11 Apr 2023 11:15:56 +0100 Subject: [PATCH 09/15] make deps --- .../nginx/agent/v2/src/core/config/config.go | 13 +++++++++++-- .../nginx/agent/v2/src/core/config/defaults.go | 1 + 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/test/performance/vendor/github.com/nginx/agent/v2/src/core/config/config.go b/test/performance/vendor/github.com/nginx/agent/v2/src/core/config/config.go index 34aa9168d..2d5f8e608 100644 --- a/test/performance/vendor/github.com/nginx/agent/v2/src/core/config/config.go +++ b/test/performance/vendor/github.com/nginx/agent/v2/src/core/config/config.go @@ -13,6 +13,7 @@ import ( "os" "path/filepath" "reflect" + "runtime" "sort" "strings" "time" @@ -235,7 +236,11 @@ func UpdateAgentConfig(systemId string, updateTags []string, updateFeatures []st // already set. dynamicCfgPath := Viper.GetString(DynamicConfigPathKey) if dynamicCfgPath == "" { - dynamicCfgPath = DynamicConfigFileAbsPath + if runtime.GOOS == "freebsd"{ + dynamicCfgPath = DynamicConfigFileAbsFreeBsdPath + }else{ + dynamicCfgPath = DynamicConfigFileAbsPath + } } // Overwrite existing nginx-agent.conf with updated config @@ -334,7 +339,11 @@ func LoadPropertiesFromFile(cfg string) error { // already set. dynamicCfgPath := Viper.GetString(DynamicConfigPathKey) if dynamicCfgPath == "" { - dynamicCfgPath = DynamicConfigFileAbsPath + if runtime.GOOS == "freebsd"{ + dynamicCfgPath = DynamicConfigFileAbsFreeBsdPath + }else{ + dynamicCfgPath = DynamicConfigFileAbsPath + } } dynamicCfgDir, dynamicCfgFile := filepath.Split(dynamicCfgPath) diff --git a/test/performance/vendor/github.com/nginx/agent/v2/src/core/config/defaults.go b/test/performance/vendor/github.com/nginx/agent/v2/src/core/config/defaults.go index 1bf44a5d8..e4342fd57 100644 --- a/test/performance/vendor/github.com/nginx/agent/v2/src/core/config/defaults.go +++ b/test/performance/vendor/github.com/nginx/agent/v2/src/core/config/defaults.go @@ -83,6 +83,7 @@ var ( const ( DynamicConfigFileName = "agent-dynamic.conf" DynamicConfigFileAbsPath = "/var/lib/nginx-agent/agent-dynamic.conf" + DynamicConfigFileAbsFreeBsdPath = "/var/db/nginx-agent/agent-dynamic.conf" ConfigFileName = "nginx-agent.conf" ConfigFileType = "yaml" EnvPrefix = "nms" From de750c3bafb9d28644b2e9dafd73f211123ba5a5 Mon Sep 17 00:00:00 2001 From: Aphral Griffin Date: Tue, 11 Apr 2023 11:19:03 +0100 Subject: [PATCH 10/15] make deps --- main.go | 2 +- src/core/config/config.go | 8 ++++---- src/core/config/defaults.go | 14 +++++++------- .../nginx/agent/v2/src/core/config/config.go | 8 ++++---- .../nginx/agent/v2/src/core/config/defaults.go | 14 +++++++------- 5 files changed, 23 insertions(+), 23 deletions(-) diff --git a/main.go b/main.go index a4d49ad8a..2c802eb0a 100644 --- a/main.go +++ b/main.go @@ -44,7 +44,7 @@ func init() { config.SetDefaults() config.RegisterFlags() dynamicConfigPath := config.DynamicConfigFileAbsPath - if runtime.GOOS == "freebsd"{ + if runtime.GOOS == "freebsd" { dynamicConfigPath = config.DynamicConfigFileAbsFreeBsdPath } configPath, err := config.RegisterConfigFile(dynamicConfigPath, config.ConfigFileName, config.ConfigFilePaths()...) diff --git a/src/core/config/config.go b/src/core/config/config.go index 2d5f8e608..508bce77d 100644 --- a/src/core/config/config.go +++ b/src/core/config/config.go @@ -236,9 +236,9 @@ func UpdateAgentConfig(systemId string, updateTags []string, updateFeatures []st // already set. dynamicCfgPath := Viper.GetString(DynamicConfigPathKey) if dynamicCfgPath == "" { - if runtime.GOOS == "freebsd"{ + if runtime.GOOS == "freebsd" { dynamicCfgPath = DynamicConfigFileAbsFreeBsdPath - }else{ + } else { dynamicCfgPath = DynamicConfigFileAbsPath } } @@ -339,9 +339,9 @@ func LoadPropertiesFromFile(cfg string) error { // already set. dynamicCfgPath := Viper.GetString(DynamicConfigPathKey) if dynamicCfgPath == "" { - if runtime.GOOS == "freebsd"{ + if runtime.GOOS == "freebsd" { dynamicCfgPath = DynamicConfigFileAbsFreeBsdPath - }else{ + } else { dynamicCfgPath = DynamicConfigFileAbsPath } } diff --git a/src/core/config/defaults.go b/src/core/config/defaults.go index e4342fd57..a89563bbf 100644 --- a/src/core/config/defaults.go +++ b/src/core/config/defaults.go @@ -81,14 +81,14 @@ var ( ) const ( - DynamicConfigFileName = "agent-dynamic.conf" - DynamicConfigFileAbsPath = "/var/lib/nginx-agent/agent-dynamic.conf" + DynamicConfigFileName = "agent-dynamic.conf" + DynamicConfigFileAbsPath = "/var/lib/nginx-agent/agent-dynamic.conf" DynamicConfigFileAbsFreeBsdPath = "/var/db/nginx-agent/agent-dynamic.conf" - ConfigFileName = "nginx-agent.conf" - ConfigFileType = "yaml" - EnvPrefix = "nms" - ConfigPathKey = "path" - DynamicConfigPathKey = "dynamic-config-path" + ConfigFileName = "nginx-agent.conf" + ConfigFileType = "yaml" + EnvPrefix = "nms" + ConfigPathKey = "path" + DynamicConfigPathKey = "dynamic-config-path" CloudAccountIdKey = "cloudaccountid" LocationKey = "location" diff --git a/test/performance/vendor/github.com/nginx/agent/v2/src/core/config/config.go b/test/performance/vendor/github.com/nginx/agent/v2/src/core/config/config.go index 2d5f8e608..508bce77d 100644 --- a/test/performance/vendor/github.com/nginx/agent/v2/src/core/config/config.go +++ b/test/performance/vendor/github.com/nginx/agent/v2/src/core/config/config.go @@ -236,9 +236,9 @@ func UpdateAgentConfig(systemId string, updateTags []string, updateFeatures []st // already set. dynamicCfgPath := Viper.GetString(DynamicConfigPathKey) if dynamicCfgPath == "" { - if runtime.GOOS == "freebsd"{ + if runtime.GOOS == "freebsd" { dynamicCfgPath = DynamicConfigFileAbsFreeBsdPath - }else{ + } else { dynamicCfgPath = DynamicConfigFileAbsPath } } @@ -339,9 +339,9 @@ func LoadPropertiesFromFile(cfg string) error { // already set. dynamicCfgPath := Viper.GetString(DynamicConfigPathKey) if dynamicCfgPath == "" { - if runtime.GOOS == "freebsd"{ + if runtime.GOOS == "freebsd" { dynamicCfgPath = DynamicConfigFileAbsFreeBsdPath - }else{ + } else { dynamicCfgPath = DynamicConfigFileAbsPath } } diff --git a/test/performance/vendor/github.com/nginx/agent/v2/src/core/config/defaults.go b/test/performance/vendor/github.com/nginx/agent/v2/src/core/config/defaults.go index e4342fd57..a89563bbf 100644 --- a/test/performance/vendor/github.com/nginx/agent/v2/src/core/config/defaults.go +++ b/test/performance/vendor/github.com/nginx/agent/v2/src/core/config/defaults.go @@ -81,14 +81,14 @@ var ( ) const ( - DynamicConfigFileName = "agent-dynamic.conf" - DynamicConfigFileAbsPath = "/var/lib/nginx-agent/agent-dynamic.conf" + DynamicConfigFileName = "agent-dynamic.conf" + DynamicConfigFileAbsPath = "/var/lib/nginx-agent/agent-dynamic.conf" DynamicConfigFileAbsFreeBsdPath = "/var/db/nginx-agent/agent-dynamic.conf" - ConfigFileName = "nginx-agent.conf" - ConfigFileType = "yaml" - EnvPrefix = "nms" - ConfigPathKey = "path" - DynamicConfigPathKey = "dynamic-config-path" + ConfigFileName = "nginx-agent.conf" + ConfigFileType = "yaml" + EnvPrefix = "nms" + ConfigPathKey = "path" + DynamicConfigPathKey = "dynamic-config-path" CloudAccountIdKey = "cloudaccountid" LocationKey = "location" From 1e419fa9a4322ee1e9f4d4df0498f17c8d0032b8 Mon Sep 17 00:00:00 2001 From: oliveromahony Date: Tue, 11 Apr 2023 12:00:32 +0100 Subject: [PATCH 11/15] added wg.Done to functions --- sdk/client/commander_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sdk/client/commander_test.go b/sdk/client/commander_test.go index ea13547fd..7da6162c9 100644 --- a/sdk/client/commander_test.go +++ b/sdk/client/commander_test.go @@ -677,6 +677,7 @@ func (h *handler) recvHandle(server proto.Commander_CommandChannelServer, wg *sy return } h.fromClient <- cmd + wg.Done() } } } @@ -692,8 +693,8 @@ func (h *handler) sendHandle(server proto.Commander_CommandChannelServer, wg *sy wg.Done() return } + wg.Done() } - } } From b38d2c3412367f698ee293b6bdae30c3763225df Mon Sep 17 00:00:00 2001 From: Aphral Griffin Date: Wed, 12 Apr 2023 10:47:58 +0100 Subject: [PATCH 12/15] Remove nging-agent directories when uninstalled --- scripts/packages/postremove.sh | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/scripts/packages/postremove.sh b/scripts/packages/postremove.sh index a8e050073..92c24d1e2 100755 --- a/scripts/packages/postremove.sh +++ b/scripts/packages/postremove.sh @@ -7,13 +7,23 @@ if [ "$ID" = "freebsd" ]; then echo "Stop and remove nginx-agent service" service nginx-agent onestop >/dev/null 2>&1 || true sysrc -x nginx_agent_enable >/dev/null 2>&1 || true + echo "Removing etc directory" + rm -rf "/usr/local/etc/nginx-agent" + echo "Removing db directory" + rm -rf "/var/db/nginx-agent" elif command -V systemctl >/dev/null 2>&1; then echo "Stop and disable nginx-agent service" systemctl stop nginx-agent >/dev/null 2>&1 || true systemctl disable nginx-agent >/dev/null 2>&1 || true echo "Running daemon-reload" systemctl daemon-reload || true + echo "Removing etc directory" + rm -rf "/etc/nginx-agent" + echo "Removing lib directory" + rm -rf "/var/lib/nginx-agent" fi echo "Removing run directory" rm -rf "/var/run/nginx-agent" +echo "Removing log directory" +rm -rf "/var/log/nginx-agent" From 1cd4915e85bde1ab135ba2225a73f82ec9ca3012 Mon Sep 17 00:00:00 2001 From: Aphral Griffin Date: Tue, 18 Apr 2023 11:52:57 +0100 Subject: [PATCH 13/15] make deps --- sdk/proto/events/event.proto | 22 +++++++++---------- .../agent/sdk/v2/proto/events/event.proto | 22 +++++++++---------- .../agent/sdk/v2/proto/events/event.proto | 22 +++++++++---------- .../agent/sdk/v2/proto/events/event.proto | 22 +++++++++---------- 4 files changed, 44 insertions(+), 44 deletions(-) diff --git a/sdk/proto/events/event.proto b/sdk/proto/events/event.proto index 3357643af..61324fc70 100644 --- a/sdk/proto/events/event.proto +++ b/sdk/proto/events/event.proto @@ -34,17 +34,17 @@ message Event { ActivityEvent ActivityEvent = 2 [(gogoproto.jsontag) = "activity_event"]; // Activity event /** - * While generating the SecurityViolationEvent, the Metadata for a SecurityViolationEvent - * would look as shown below: - * - Module = Agent - * - UUID = A UUID generated by the Agent for the EventReport - * - CorrelationID = The UUID will be used as the Correlation ID to track the EventReport - * - Timestamp = The timestamp when NGINX Agent received the violation event - * - EventLevel = All the SecurityViolationEvent would be generated at an ERROR_EVENT_LEVEL ("ERROR") level - * In future, the levels might be dynamically chosen based on Request Outcome of SecurityViolationEvent - * - Type = NGINX_EVENT_TYPE ("Nginx") - * - Category = APP_PROTECT_CATEGORY ("AppProtect") - */ + * While generating the SecurityViolationEvent, the Metadata for a SecurityViolationEvent + * would look as shown below: + * - Module = Agent + * - UUID = A UUID generated by the Agent for the EventReport + * - CorrelationID = The UUID will be used as the Correlation ID to track the EventReport + * - Timestamp = The timestamp when NGINX Agent received the violation event + * - EventLevel = All the SecurityViolationEvent would be generated at an ERROR_EVENT_LEVEL ("ERROR") level + * In future, the levels might be dynamically chosen based on Request Outcome of SecurityViolationEvent + * - Type = NGINX_EVENT_TYPE ("Nginx") + * - Category = APP_PROTECT_CATEGORY ("AppProtect") + */ SecurityViolationEvent SecurityViolationEvent = 3 [(gogoproto.jsontag) = "security_violation_event"]; // Security violation event } diff --git a/test/integration/vendor/github.com/nginx/agent/sdk/v2/proto/events/event.proto b/test/integration/vendor/github.com/nginx/agent/sdk/v2/proto/events/event.proto index 3357643af..61324fc70 100644 --- a/test/integration/vendor/github.com/nginx/agent/sdk/v2/proto/events/event.proto +++ b/test/integration/vendor/github.com/nginx/agent/sdk/v2/proto/events/event.proto @@ -34,17 +34,17 @@ message Event { ActivityEvent ActivityEvent = 2 [(gogoproto.jsontag) = "activity_event"]; // Activity event /** - * While generating the SecurityViolationEvent, the Metadata for a SecurityViolationEvent - * would look as shown below: - * - Module = Agent - * - UUID = A UUID generated by the Agent for the EventReport - * - CorrelationID = The UUID will be used as the Correlation ID to track the EventReport - * - Timestamp = The timestamp when NGINX Agent received the violation event - * - EventLevel = All the SecurityViolationEvent would be generated at an ERROR_EVENT_LEVEL ("ERROR") level - * In future, the levels might be dynamically chosen based on Request Outcome of SecurityViolationEvent - * - Type = NGINX_EVENT_TYPE ("Nginx") - * - Category = APP_PROTECT_CATEGORY ("AppProtect") - */ + * While generating the SecurityViolationEvent, the Metadata for a SecurityViolationEvent + * would look as shown below: + * - Module = Agent + * - UUID = A UUID generated by the Agent for the EventReport + * - CorrelationID = The UUID will be used as the Correlation ID to track the EventReport + * - Timestamp = The timestamp when NGINX Agent received the violation event + * - EventLevel = All the SecurityViolationEvent would be generated at an ERROR_EVENT_LEVEL ("ERROR") level + * In future, the levels might be dynamically chosen based on Request Outcome of SecurityViolationEvent + * - Type = NGINX_EVENT_TYPE ("Nginx") + * - Category = APP_PROTECT_CATEGORY ("AppProtect") + */ SecurityViolationEvent SecurityViolationEvent = 3 [(gogoproto.jsontag) = "security_violation_event"]; // Security violation event } diff --git a/test/performance/vendor/github.com/nginx/agent/sdk/v2/proto/events/event.proto b/test/performance/vendor/github.com/nginx/agent/sdk/v2/proto/events/event.proto index 3357643af..61324fc70 100644 --- a/test/performance/vendor/github.com/nginx/agent/sdk/v2/proto/events/event.proto +++ b/test/performance/vendor/github.com/nginx/agent/sdk/v2/proto/events/event.proto @@ -34,17 +34,17 @@ message Event { ActivityEvent ActivityEvent = 2 [(gogoproto.jsontag) = "activity_event"]; // Activity event /** - * While generating the SecurityViolationEvent, the Metadata for a SecurityViolationEvent - * would look as shown below: - * - Module = Agent - * - UUID = A UUID generated by the Agent for the EventReport - * - CorrelationID = The UUID will be used as the Correlation ID to track the EventReport - * - Timestamp = The timestamp when NGINX Agent received the violation event - * - EventLevel = All the SecurityViolationEvent would be generated at an ERROR_EVENT_LEVEL ("ERROR") level - * In future, the levels might be dynamically chosen based on Request Outcome of SecurityViolationEvent - * - Type = NGINX_EVENT_TYPE ("Nginx") - * - Category = APP_PROTECT_CATEGORY ("AppProtect") - */ + * While generating the SecurityViolationEvent, the Metadata for a SecurityViolationEvent + * would look as shown below: + * - Module = Agent + * - UUID = A UUID generated by the Agent for the EventReport + * - CorrelationID = The UUID will be used as the Correlation ID to track the EventReport + * - Timestamp = The timestamp when NGINX Agent received the violation event + * - EventLevel = All the SecurityViolationEvent would be generated at an ERROR_EVENT_LEVEL ("ERROR") level + * In future, the levels might be dynamically chosen based on Request Outcome of SecurityViolationEvent + * - Type = NGINX_EVENT_TYPE ("Nginx") + * - Category = APP_PROTECT_CATEGORY ("AppProtect") + */ SecurityViolationEvent SecurityViolationEvent = 3 [(gogoproto.jsontag) = "security_violation_event"]; // Security violation event } diff --git a/vendor/github.com/nginx/agent/sdk/v2/proto/events/event.proto b/vendor/github.com/nginx/agent/sdk/v2/proto/events/event.proto index 3357643af..61324fc70 100644 --- a/vendor/github.com/nginx/agent/sdk/v2/proto/events/event.proto +++ b/vendor/github.com/nginx/agent/sdk/v2/proto/events/event.proto @@ -34,17 +34,17 @@ message Event { ActivityEvent ActivityEvent = 2 [(gogoproto.jsontag) = "activity_event"]; // Activity event /** - * While generating the SecurityViolationEvent, the Metadata for a SecurityViolationEvent - * would look as shown below: - * - Module = Agent - * - UUID = A UUID generated by the Agent for the EventReport - * - CorrelationID = The UUID will be used as the Correlation ID to track the EventReport - * - Timestamp = The timestamp when NGINX Agent received the violation event - * - EventLevel = All the SecurityViolationEvent would be generated at an ERROR_EVENT_LEVEL ("ERROR") level - * In future, the levels might be dynamically chosen based on Request Outcome of SecurityViolationEvent - * - Type = NGINX_EVENT_TYPE ("Nginx") - * - Category = APP_PROTECT_CATEGORY ("AppProtect") - */ + * While generating the SecurityViolationEvent, the Metadata for a SecurityViolationEvent + * would look as shown below: + * - Module = Agent + * - UUID = A UUID generated by the Agent for the EventReport + * - CorrelationID = The UUID will be used as the Correlation ID to track the EventReport + * - Timestamp = The timestamp when NGINX Agent received the violation event + * - EventLevel = All the SecurityViolationEvent would be generated at an ERROR_EVENT_LEVEL ("ERROR") level + * In future, the levels might be dynamically chosen based on Request Outcome of SecurityViolationEvent + * - Type = NGINX_EVENT_TYPE ("Nginx") + * - Category = APP_PROTECT_CATEGORY ("AppProtect") + */ SecurityViolationEvent SecurityViolationEvent = 3 [(gogoproto.jsontag) = "security_violation_event"]; // Security violation event } From 60d2e50a3c3d9d3ddcf7fb74bd16dd28aa2b33cf Mon Sep 17 00:00:00 2001 From: Aphral Griffin Date: Tue, 18 Apr 2023 17:28:59 +0100 Subject: [PATCH 14/15] PR feedback --- scripts/packages/postremove.sh | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/scripts/packages/postremove.sh b/scripts/packages/postremove.sh index 92c24d1e2..75e8379dc 100755 --- a/scripts/packages/postremove.sh +++ b/scripts/packages/postremove.sh @@ -7,9 +7,9 @@ if [ "$ID" = "freebsd" ]; then echo "Stop and remove nginx-agent service" service nginx-agent onestop >/dev/null 2>&1 || true sysrc -x nginx_agent_enable >/dev/null 2>&1 || true - echo "Removing etc directory" + echo "Removing /usr/local/etc/nginx-agent directory" rm -rf "/usr/local/etc/nginx-agent" - echo "Removing db directory" + echo "Removing /var/db/nginx-agent directory" rm -rf "/var/db/nginx-agent" elif command -V systemctl >/dev/null 2>&1; then echo "Stop and disable nginx-agent service" @@ -17,13 +17,13 @@ elif command -V systemctl >/dev/null 2>&1; then systemctl disable nginx-agent >/dev/null 2>&1 || true echo "Running daemon-reload" systemctl daemon-reload || true - echo "Removing etc directory" + echo "Removing /etc/nginx-agent directory" rm -rf "/etc/nginx-agent" - echo "Removing lib directory" + echo "Removing /var/lib/nginx-agent directory" rm -rf "/var/lib/nginx-agent" fi -echo "Removing run directory" +echo "Removing /var/run/nginx-agent directory" rm -rf "/var/run/nginx-agent" -echo "Removing log directory" +echo "Removing /var/log/nginx-agent directory" rm -rf "/var/log/nginx-agent" From 117108bc652c1293c4df8b8667a02f88d13884d1 Mon Sep 17 00:00:00 2001 From: Aphral Griffin Date: Wed, 19 Apr 2023 09:03:06 +0100 Subject: [PATCH 15/15] vendoring issues --- test/integration/go.sum | 4 + .../github.com/go-logr/logr/.golangci.yaml | 3 - .../vendor/github.com/go-logr/logr/discard.go | 32 +--- .../github.com/go-logr/logr/funcr/funcr.go | 27 ++- .../vendor/github.com/go-logr/logr/logr.go | 166 +++++++++++------- .../vendor/github.com/imdario/mergo/map.go | 4 +- .../vendor/github.com/imdario/mergo/merge.go | 45 +++-- .../vendor/github.com/imdario/mergo/mergo.go | 9 +- .../github.com/spf13/cobra/.golangci.yml | 2 +- .../vendor/github.com/spf13/cobra/Makefile | 8 +- .../vendor/github.com/spf13/cobra/README.md | 4 +- .../github.com/spf13/cobra/active_help.go | 2 +- .../vendor/github.com/spf13/cobra/args.go | 4 +- .../spf13/cobra/bash_completions.go | 4 +- .../spf13/cobra/bash_completionsV2.go | 71 +++++--- .../vendor/github.com/spf13/cobra/cobra.go | 6 +- .../vendor/github.com/spf13/cobra/command.go | 54 ++++-- .../github.com/spf13/cobra/command_notwin.go | 2 +- .../github.com/spf13/cobra/command_win.go | 2 +- .../github.com/spf13/cobra/completions.go | 13 +- .../spf13/cobra/fish_completions.go | 78 ++++++-- .../github.com/spf13/cobra/flag_groups.go | 2 +- .../spf13/cobra/powershell_completions.go | 27 ++- .../spf13/cobra/projects_using_cobra.md | 6 +- .../spf13/cobra/shell_completions.go | 2 +- .../spf13/cobra/shell_completions.md | 30 ++-- .../github.com/spf13/cobra/user_guide.md | 37 +++- .../github.com/spf13/cobra/zsh_completions.go | 17 +- test/integration/vendor/modules.txt | 8 +- 29 files changed, 443 insertions(+), 226 deletions(-) diff --git a/test/integration/go.sum b/test/integration/go.sum index b60be7d91..6bb411af2 100644 --- a/test/integration/go.sum +++ b/test/integration/go.sum @@ -203,6 +203,7 @@ github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTg github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= +github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= @@ -342,6 +343,7 @@ github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1: github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.15 h1:M8XP7IuFNsqUx6VPK2P9OSmsYsI/YFaGil0uD21V3dM= +github.com/imdario/mergo v0.3.15/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= @@ -401,6 +403,7 @@ github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovk github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.18 h1:DOKFKCQ7FNG2L1rbrmstDN4QVRdS89Nkh85u68Uwp98= +github.com/mattn/go-isatty v0.0.18/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-shellwords v1.0.12 h1:M2zGm7EW6UQJvDeQxo4T51eKPurbeFbe8WtebGE2xrk= @@ -566,6 +569,7 @@ github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w= github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU= github.com/spf13/cobra v0.0.1/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= +github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= github.com/spf13/jwalterweatherman v0.0.0-20141219030609-3d60171a6431/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= diff --git a/test/integration/vendor/github.com/go-logr/logr/.golangci.yaml b/test/integration/vendor/github.com/go-logr/logr/.golangci.yaml index 94ff801df..0cffafa7b 100644 --- a/test/integration/vendor/github.com/go-logr/logr/.golangci.yaml +++ b/test/integration/vendor/github.com/go-logr/logr/.golangci.yaml @@ -6,7 +6,6 @@ linters: disable-all: true enable: - asciicheck - - deadcode - errcheck - forcetypeassert - gocritic @@ -18,10 +17,8 @@ linters: - misspell - revive - staticcheck - - structcheck - typecheck - unused - - varcheck issues: exclude-use-default: false diff --git a/test/integration/vendor/github.com/go-logr/logr/discard.go b/test/integration/vendor/github.com/go-logr/logr/discard.go index 9d92a38f1..99fe8be93 100644 --- a/test/integration/vendor/github.com/go-logr/logr/discard.go +++ b/test/integration/vendor/github.com/go-logr/logr/discard.go @@ -20,35 +20,5 @@ package logr // used whenever the caller is not interested in the logs. Logger instances // produced by this function always compare as equal. func Discard() Logger { - return Logger{ - level: 0, - sink: discardLogSink{}, - } -} - -// discardLogSink is a LogSink that discards all messages. -type discardLogSink struct{} - -// Verify that it actually implements the interface -var _ LogSink = discardLogSink{} - -func (l discardLogSink) Init(RuntimeInfo) { -} - -func (l discardLogSink) Enabled(int) bool { - return false -} - -func (l discardLogSink) Info(int, string, ...interface{}) { -} - -func (l discardLogSink) Error(error, string, ...interface{}) { -} - -func (l discardLogSink) WithValues(...interface{}) LogSink { - return l -} - -func (l discardLogSink) WithName(string) LogSink { - return l + return New(nil) } diff --git a/test/integration/vendor/github.com/go-logr/logr/funcr/funcr.go b/test/integration/vendor/github.com/go-logr/logr/funcr/funcr.go index 7accdb0c4..e52f0cd01 100644 --- a/test/integration/vendor/github.com/go-logr/logr/funcr/funcr.go +++ b/test/integration/vendor/github.com/go-logr/logr/funcr/funcr.go @@ -21,13 +21,13 @@ limitations under the License. // github.com/go-logr/logr.LogSink with output through an arbitrary // "write" function. See New and NewJSON for details. // -// Custom LogSinks +// # Custom LogSinks // // For users who need more control, a funcr.Formatter can be embedded inside // your own custom LogSink implementation. This is useful when the LogSink // needs to implement additional methods, for example. // -// Formatting +// # Formatting // // This will respect logr.Marshaler, fmt.Stringer, and error interfaces for // values which are being logged. When rendering a struct, funcr will use Go's @@ -37,6 +37,7 @@ package funcr import ( "bytes" "encoding" + "encoding/json" "fmt" "path/filepath" "reflect" @@ -217,7 +218,7 @@ func newFormatter(opts Options, outfmt outputFormat) Formatter { prefix: "", values: nil, depth: 0, - opts: opts, + opts: &opts, } return f } @@ -231,7 +232,7 @@ type Formatter struct { values []interface{} valuesStr string depth int - opts Options + opts *Options } // outputFormat indicates which outputFormat to use. @@ -447,6 +448,7 @@ func (f Formatter) prettyWithFlags(value interface{}, flags uint32, depth int) s if flags&flagRawStruct == 0 { buf.WriteByte('{') } + printComma := false // testing i>0 is not enough because of JSON omitted fields for i := 0; i < t.NumField(); i++ { fld := t.Field(i) if fld.PkgPath != "" { @@ -478,9 +480,10 @@ func (f Formatter) prettyWithFlags(value interface{}, flags uint32, depth int) s if omitempty && isEmpty(v.Field(i)) { continue } - if i > 0 { + if printComma { buf.WriteByte(',') } + printComma = true // if we got here, we are rendering a field if fld.Anonymous && fld.Type.Kind() == reflect.Struct && name == "" { buf.WriteString(f.prettyWithFlags(v.Field(i).Interface(), flags|flagRawStruct, depth+1)) continue @@ -500,6 +503,20 @@ func (f Formatter) prettyWithFlags(value interface{}, flags uint32, depth int) s } return buf.String() case reflect.Slice, reflect.Array: + // If this is outputing as JSON make sure this isn't really a json.RawMessage. + // If so just emit "as-is" and don't pretty it as that will just print + // it as [X,Y,Z,...] which isn't terribly useful vs the string form you really want. + if f.outputFormat == outputJSON { + if rm, ok := value.(json.RawMessage); ok { + // If it's empty make sure we emit an empty value as the array style would below. + if len(rm) > 0 { + buf.Write(rm) + } else { + buf.WriteString("null") + } + return buf.String() + } + } buf.WriteByte('[') for i := 0; i < v.Len(); i++ { if i > 0 { diff --git a/test/integration/vendor/github.com/go-logr/logr/logr.go b/test/integration/vendor/github.com/go-logr/logr/logr.go index c3b56b3d2..e027aea3f 100644 --- a/test/integration/vendor/github.com/go-logr/logr/logr.go +++ b/test/integration/vendor/github.com/go-logr/logr/logr.go @@ -21,7 +21,7 @@ limitations under the License. // to back that API. Packages in the Go ecosystem can depend on this package, // while callers can implement logging with whatever backend is appropriate. // -// Usage +// # Usage // // Logging is done using a Logger instance. Logger is a concrete type with // methods, which defers the actual logging to a LogSink interface. The main @@ -30,16 +30,20 @@ limitations under the License. // "structured logging". // // With Go's standard log package, we might write: -// log.Printf("setting target value %s", targetValue) +// +// log.Printf("setting target value %s", targetValue) // // With logr's structured logging, we'd write: -// logger.Info("setting target", "value", targetValue) +// +// logger.Info("setting target", "value", targetValue) // // Errors are much the same. Instead of: -// log.Printf("failed to open the pod bay door for user %s: %v", user, err) +// +// log.Printf("failed to open the pod bay door for user %s: %v", user, err) // // We'd write: -// logger.Error(err, "failed to open the pod bay door", "user", user) +// +// logger.Error(err, "failed to open the pod bay door", "user", user) // // Info() and Error() are very similar, but they are separate methods so that // LogSink implementations can choose to do things like attach additional @@ -47,7 +51,7 @@ limitations under the License. // always logged, regardless of the current verbosity. If there is no error // instance available, passing nil is valid. // -// Verbosity +// # Verbosity // // Often we want to log information only when the application in "verbose // mode". To write log lines that are more verbose, Logger has a V() method. @@ -58,20 +62,22 @@ limitations under the License. // Error messages do not have a verbosity level and are always logged. // // Where we might have written: -// if flVerbose >= 2 { -// log.Printf("an unusual thing happened") -// } +// +// if flVerbose >= 2 { +// log.Printf("an unusual thing happened") +// } // // We can write: -// logger.V(2).Info("an unusual thing happened") // -// Logger Names +// logger.V(2).Info("an unusual thing happened") +// +// # Logger Names // // Logger instances can have name strings so that all messages logged through // that instance have additional context. For example, you might want to add // a subsystem name: // -// logger.WithName("compactor").Info("started", "time", time.Now()) +// logger.WithName("compactor").Info("started", "time", time.Now()) // // The WithName() method returns a new Logger, which can be passed to // constructors or other functions for further use. Repeated use of WithName() @@ -82,25 +88,27 @@ limitations under the License. // joining operation (e.g. whitespace, commas, periods, slashes, brackets, // quotes, etc). // -// Saved Values +// # Saved Values // // Logger instances can store any number of key/value pairs, which will be // logged alongside all messages logged through that instance. For example, // you might want to create a Logger instance per managed object: // // With the standard log package, we might write: -// log.Printf("decided to set field foo to value %q for object %s/%s", -// targetValue, object.Namespace, object.Name) +// +// log.Printf("decided to set field foo to value %q for object %s/%s", +// targetValue, object.Namespace, object.Name) // // With logr we'd write: -// // Elsewhere: set up the logger to log the object name. -// obj.logger = mainLogger.WithValues( -// "name", obj.name, "namespace", obj.namespace) // -// // later on... -// obj.logger.Info("setting foo", "value", targetValue) +// // Elsewhere: set up the logger to log the object name. +// obj.logger = mainLogger.WithValues( +// "name", obj.name, "namespace", obj.namespace) +// +// // later on... +// obj.logger.Info("setting foo", "value", targetValue) // -// Best Practices +// # Best Practices // // Logger has very few hard rules, with the goal that LogSink implementations // might have a lot of freedom to differentiate. There are, however, some @@ -124,15 +132,15 @@ limitations under the License. // around. For cases where passing a logger is optional, a pointer to Logger // should be used. // -// Key Naming Conventions +// # Key Naming Conventions // // Keys are not strictly required to conform to any specification or regex, but // it is recommended that they: -// * be human-readable and meaningful (not auto-generated or simple ordinals) -// * be constant (not dependent on input data) -// * contain only printable characters -// * not contain whitespace or punctuation -// * use lower case for simple keys and lowerCamelCase for more complex ones +// - be human-readable and meaningful (not auto-generated or simple ordinals) +// - be constant (not dependent on input data) +// - contain only printable characters +// - not contain whitespace or punctuation +// - use lower case for simple keys and lowerCamelCase for more complex ones // // These guidelines help ensure that log data is processed properly regardless // of the log implementation. For example, log implementations will try to @@ -141,51 +149,54 @@ limitations under the License. // While users are generally free to use key names of their choice, it's // generally best to avoid using the following keys, as they're frequently used // by implementations: -// * "caller": the calling information (file/line) of a particular log line -// * "error": the underlying error value in the `Error` method -// * "level": the log level -// * "logger": the name of the associated logger -// * "msg": the log message -// * "stacktrace": the stack trace associated with a particular log line or -// error (often from the `Error` message) -// * "ts": the timestamp for a log line +// - "caller": the calling information (file/line) of a particular log line +// - "error": the underlying error value in the `Error` method +// - "level": the log level +// - "logger": the name of the associated logger +// - "msg": the log message +// - "stacktrace": the stack trace associated with a particular log line or +// error (often from the `Error` message) +// - "ts": the timestamp for a log line // // Implementations are encouraged to make use of these keys to represent the // above concepts, when necessary (for example, in a pure-JSON output form, it // would be necessary to represent at least message and timestamp as ordinary // named values). // -// Break Glass +// # Break Glass // // Implementations may choose to give callers access to the underlying // logging implementation. The recommended pattern for this is: -// // Underlier exposes access to the underlying logging implementation. -// // Since callers only have a logr.Logger, they have to know which -// // implementation is in use, so this interface is less of an abstraction -// // and more of way to test type conversion. -// type Underlier interface { -// GetUnderlying() -// } +// +// // Underlier exposes access to the underlying logging implementation. +// // Since callers only have a logr.Logger, they have to know which +// // implementation is in use, so this interface is less of an abstraction +// // and more of way to test type conversion. +// type Underlier interface { +// GetUnderlying() +// } // // Logger grants access to the sink to enable type assertions like this: -// func DoSomethingWithImpl(log logr.Logger) { -// if underlier, ok := log.GetSink()(impl.Underlier) { -// implLogger := underlier.GetUnderlying() -// ... -// } -// } +// +// func DoSomethingWithImpl(log logr.Logger) { +// if underlier, ok := log.GetSink().(impl.Underlier); ok { +// implLogger := underlier.GetUnderlying() +// ... +// } +// } // // Custom `With*` functions can be implemented by copying the complete // Logger struct and replacing the sink in the copy: -// // WithFooBar changes the foobar parameter in the log sink and returns a -// // new logger with that modified sink. It does nothing for loggers where -// // the sink doesn't support that parameter. -// func WithFoobar(log logr.Logger, foobar int) logr.Logger { -// if foobarLogSink, ok := log.GetSink()(FoobarSink); ok { -// log = log.WithSink(foobarLogSink.WithFooBar(foobar)) -// } -// return log -// } +// +// // WithFooBar changes the foobar parameter in the log sink and returns a +// // new logger with that modified sink. It does nothing for loggers where +// // the sink doesn't support that parameter. +// func WithFoobar(log logr.Logger, foobar int) logr.Logger { +// if foobarLogSink, ok := log.GetSink().(FoobarSink); ok { +// log = log.WithSink(foobarLogSink.WithFooBar(foobar)) +// } +// return log +// } // // Don't use New to construct a new Logger with a LogSink retrieved from an // existing Logger. Source code attribution might not work correctly and @@ -201,11 +212,14 @@ import ( ) // New returns a new Logger instance. This is primarily used by libraries -// implementing LogSink, rather than end users. +// implementing LogSink, rather than end users. Passing a nil sink will create +// a Logger which discards all log lines. func New(sink LogSink) Logger { logger := Logger{} logger.setSink(sink) - sink.Init(runtimeInfo) + if sink != nil { + sink.Init(runtimeInfo) + } return logger } @@ -244,7 +258,7 @@ type Logger struct { // Enabled tests whether this Logger is enabled. For example, commandline // flags might be used to set the logging verbosity and disable some info logs. func (l Logger) Enabled() bool { - return l.sink.Enabled(l.level) + return l.sink != nil && l.sink.Enabled(l.level) } // Info logs a non-error message with the given key/value pairs as context. @@ -254,6 +268,9 @@ func (l Logger) Enabled() bool { // information. The key/value pairs must alternate string keys and arbitrary // values. func (l Logger) Info(msg string, keysAndValues ...interface{}) { + if l.sink == nil { + return + } if l.Enabled() { if withHelper, ok := l.sink.(CallStackHelperLogSink); ok { withHelper.GetCallStackHelper()() @@ -273,6 +290,9 @@ func (l Logger) Info(msg string, keysAndValues ...interface{}) { // triggered this log line, if present. The err parameter is optional // and nil may be passed instead of an error instance. func (l Logger) Error(err error, msg string, keysAndValues ...interface{}) { + if l.sink == nil { + return + } if withHelper, ok := l.sink.(CallStackHelperLogSink); ok { withHelper.GetCallStackHelper()() } @@ -284,6 +304,9 @@ func (l Logger) Error(err error, msg string, keysAndValues ...interface{}) { // level means a log message is less important. Negative V-levels are treated // as 0. func (l Logger) V(level int) Logger { + if l.sink == nil { + return l + } if level < 0 { level = 0 } @@ -294,6 +317,9 @@ func (l Logger) V(level int) Logger { // WithValues returns a new Logger instance with additional key/value pairs. // See Info for documentation on how key/value pairs work. func (l Logger) WithValues(keysAndValues ...interface{}) Logger { + if l.sink == nil { + return l + } l.setSink(l.sink.WithValues(keysAndValues...)) return l } @@ -304,6 +330,9 @@ func (l Logger) WithValues(keysAndValues ...interface{}) Logger { // contain only letters, digits, and hyphens (see the package documentation for // more information). func (l Logger) WithName(name string) Logger { + if l.sink == nil { + return l + } l.setSink(l.sink.WithName(name)) return l } @@ -324,6 +353,9 @@ func (l Logger) WithName(name string) Logger { // WithCallDepth(1) because it works with implementions that support the // CallDepthLogSink and/or CallStackHelperLogSink interfaces. func (l Logger) WithCallDepth(depth int) Logger { + if l.sink == nil { + return l + } if withCallDepth, ok := l.sink.(CallDepthLogSink); ok { l.setSink(withCallDepth.WithCallDepth(depth)) } @@ -345,6 +377,9 @@ func (l Logger) WithCallDepth(depth int) Logger { // implementation does not support either of these, the original Logger will be // returned. func (l Logger) WithCallStackHelper() (func(), Logger) { + if l.sink == nil { + return func() {}, l + } var helper func() if withCallDepth, ok := l.sink.(CallDepthLogSink); ok { l.setSink(withCallDepth.WithCallDepth(1)) @@ -357,6 +392,11 @@ func (l Logger) WithCallStackHelper() (func(), Logger) { return helper, l } +// IsZero returns true if this logger is an uninitialized zero value +func (l Logger) IsZero() bool { + return l.sink == nil +} + // contextKey is how we find Loggers in a context.Context. type contextKey struct{} @@ -442,7 +482,7 @@ type LogSink interface { WithName(name string) LogSink } -// CallDepthLogSink represents a Logger that knows how to climb the call stack +// CallDepthLogSink represents a LogSink that knows how to climb the call stack // to identify the original call site and can offset the depth by a specified // number of frames. This is useful for users who have helper functions // between the "real" call site and the actual calls to Logger methods. @@ -467,7 +507,7 @@ type CallDepthLogSink interface { WithCallDepth(depth int) LogSink } -// CallStackHelperLogSink represents a Logger that knows how to climb +// CallStackHelperLogSink represents a LogSink that knows how to climb // the call stack to identify the original call site and can skip // intermediate helper functions if they mark themselves as // helper. Go's testing package uses that approach. diff --git a/test/integration/vendor/github.com/imdario/mergo/map.go b/test/integration/vendor/github.com/imdario/mergo/map.go index f739255af..b50d5c2a4 100644 --- a/test/integration/vendor/github.com/imdario/mergo/map.go +++ b/test/integration/vendor/github.com/imdario/mergo/map.go @@ -58,7 +58,7 @@ func deepMap(dst, src reflect.Value, visited map[uintptr]*visit, depth int, conf } fieldName := field.Name fieldName = changeInitialCase(fieldName, unicode.ToLower) - if v, ok := dstMap[fieldName]; !ok || (isEmptyValue(reflect.ValueOf(v)) || overwrite) { + if v, ok := dstMap[fieldName]; !ok || (isEmptyValue(reflect.ValueOf(v), !config.ShouldNotDereference) || overwrite) { dstMap[fieldName] = src.Field(i).Interface() } } @@ -142,7 +142,7 @@ func MapWithOverwrite(dst, src interface{}, opts ...func(*Config)) error { func _map(dst, src interface{}, opts ...func(*Config)) error { if dst != nil && reflect.ValueOf(dst).Kind() != reflect.Ptr { - return ErrNonPointerAgument + return ErrNonPointerArgument } var ( vDst, vSrc reflect.Value diff --git a/test/integration/vendor/github.com/imdario/mergo/merge.go b/test/integration/vendor/github.com/imdario/mergo/merge.go index 1bf26cfe5..0ef9b2138 100644 --- a/test/integration/vendor/github.com/imdario/mergo/merge.go +++ b/test/integration/vendor/github.com/imdario/mergo/merge.go @@ -40,6 +40,7 @@ func isExportedComponent(field *reflect.StructField) bool { type Config struct { Transformers Transformers Overwrite bool + ShouldNotDereference bool AppendSlice bool TypeCheck bool overwriteWithEmptyValue bool @@ -95,7 +96,7 @@ func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, co } } } else { - if dst.CanSet() && (isReflectNil(dst) || overwrite) && (!isEmptyValue(src) || overwriteWithEmptySrc) { + if dst.CanSet() && (isReflectNil(dst) || overwrite) && (!isEmptyValue(src, !config.ShouldNotDereference) || overwriteWithEmptySrc) { dst.Set(src) } } @@ -110,7 +111,7 @@ func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, co } if src.Kind() != reflect.Map { - if overwrite { + if overwrite && dst.CanSet() { dst.Set(src) } return @@ -162,7 +163,7 @@ func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, co dstSlice = reflect.ValueOf(dstElement.Interface()) } - if (!isEmptyValue(src) || overwriteWithEmptySrc || overwriteSliceWithEmptySrc) && (overwrite || isEmptyValue(dst)) && !config.AppendSlice && !sliceDeepCopy { + if (!isEmptyValue(src, !config.ShouldNotDereference) || overwriteWithEmptySrc || overwriteSliceWithEmptySrc) && (overwrite || isEmptyValue(dst, !config.ShouldNotDereference)) && !config.AppendSlice && !sliceDeepCopy { if typeCheck && srcSlice.Type() != dstSlice.Type() { return fmt.Errorf("cannot override two slices with different type (%s, %s)", srcSlice.Type(), dstSlice.Type()) } @@ -194,11 +195,17 @@ func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, co dst.SetMapIndex(key, dstSlice) } } - if dstElement.IsValid() && !isEmptyValue(dstElement) && (reflect.TypeOf(srcElement.Interface()).Kind() == reflect.Map || reflect.TypeOf(srcElement.Interface()).Kind() == reflect.Slice) { - continue + + if dstElement.IsValid() && !isEmptyValue(dstElement, !config.ShouldNotDereference) { + if reflect.TypeOf(srcElement.Interface()).Kind() == reflect.Slice { + continue + } + if reflect.TypeOf(srcElement.Interface()).Kind() == reflect.Map && reflect.TypeOf(dstElement.Interface()).Kind() == reflect.Map { + continue + } } - if srcElement.IsValid() && ((srcElement.Kind() != reflect.Ptr && overwrite) || !dstElement.IsValid() || isEmptyValue(dstElement)) { + if srcElement.IsValid() && ((srcElement.Kind() != reflect.Ptr && overwrite) || !dstElement.IsValid() || isEmptyValue(dstElement, !config.ShouldNotDereference)) { if dst.IsNil() { dst.Set(reflect.MakeMap(dst.Type())) } @@ -219,7 +226,7 @@ func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, co if !dst.CanSet() { break } - if (!isEmptyValue(src) || overwriteWithEmptySrc || overwriteSliceWithEmptySrc) && (overwrite || isEmptyValue(dst)) && !config.AppendSlice && !sliceDeepCopy { + if (!isEmptyValue(src, !config.ShouldNotDereference) || overwriteWithEmptySrc || overwriteSliceWithEmptySrc) && (overwrite || isEmptyValue(dst, !config.ShouldNotDereference)) && !config.AppendSlice && !sliceDeepCopy { dst.Set(src) } else if config.AppendSlice { if src.Type() != dst.Type() { @@ -254,12 +261,18 @@ func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, co if src.Kind() != reflect.Interface { if dst.IsNil() || (src.Kind() != reflect.Ptr && overwrite) { - if dst.CanSet() && (overwrite || isEmptyValue(dst)) { + if dst.CanSet() && (overwrite || isEmptyValue(dst, !config.ShouldNotDereference)) { dst.Set(src) } } else if src.Kind() == reflect.Ptr { - if err = deepMerge(dst.Elem(), src.Elem(), visited, depth+1, config); err != nil { - return + if !config.ShouldNotDereference { + if err = deepMerge(dst.Elem(), src.Elem(), visited, depth+1, config); err != nil { + return + } + } else { + if overwriteWithEmptySrc || (overwrite && !src.IsNil()) || dst.IsNil() { + dst.Set(src) + } } } else if dst.Elem().Type() == src.Type() { if err = deepMerge(dst.Elem(), src, visited, depth+1, config); err != nil { @@ -272,7 +285,7 @@ func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, co } if dst.IsNil() || overwrite { - if dst.CanSet() && (overwrite || isEmptyValue(dst)) { + if dst.CanSet() && (overwrite || isEmptyValue(dst, !config.ShouldNotDereference)) { dst.Set(src) } break @@ -285,7 +298,7 @@ func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, co break } default: - mustSet := (isEmptyValue(dst) || overwrite) && (!isEmptyValue(src) || overwriteWithEmptySrc) + mustSet := (isEmptyValue(dst, !config.ShouldNotDereference) || overwrite) && (!isEmptyValue(src, !config.ShouldNotDereference) || overwriteWithEmptySrc) if mustSet { if dst.CanSet() { dst.Set(src) @@ -336,6 +349,12 @@ func WithOverrideEmptySlice(config *Config) { config.overwriteSliceWithEmptyValue = true } +// WithoutDereference prevents dereferencing pointers when evaluating whether they are empty +// (i.e. a non-nil pointer is never considered empty). +func WithoutDereference(config *Config) { + config.ShouldNotDereference = true +} + // WithAppendSlice will make merge append slices instead of overwriting it. func WithAppendSlice(config *Config) { config.AppendSlice = true @@ -354,7 +373,7 @@ func WithSliceDeepCopy(config *Config) { func merge(dst, src interface{}, opts ...func(*Config)) error { if dst != nil && reflect.ValueOf(dst).Kind() != reflect.Ptr { - return ErrNonPointerAgument + return ErrNonPointerArgument } var ( vDst, vSrc reflect.Value diff --git a/test/integration/vendor/github.com/imdario/mergo/mergo.go b/test/integration/vendor/github.com/imdario/mergo/mergo.go index d2af2a95f..0a721e2d8 100644 --- a/test/integration/vendor/github.com/imdario/mergo/mergo.go +++ b/test/integration/vendor/github.com/imdario/mergo/mergo.go @@ -20,7 +20,7 @@ var ( ErrNotSupported = errors.New("only structs, maps, and slices are supported") ErrExpectedMapAsDestination = errors.New("dst was expected to be a map") ErrExpectedStructAsDestination = errors.New("dst was expected to be a struct") - ErrNonPointerAgument = errors.New("dst must be a pointer") + ErrNonPointerArgument = errors.New("dst must be a pointer") ) // During deepMerge, must keep track of checks that are @@ -34,7 +34,7 @@ type visit struct { } // From src/pkg/encoding/json/encode.go. -func isEmptyValue(v reflect.Value) bool { +func isEmptyValue(v reflect.Value, shouldDereference bool) bool { switch v.Kind() { case reflect.Array, reflect.Map, reflect.Slice, reflect.String: return v.Len() == 0 @@ -50,7 +50,10 @@ func isEmptyValue(v reflect.Value) bool { if v.IsNil() { return true } - return isEmptyValue(v.Elem()) + if shouldDereference { + return isEmptyValue(v.Elem(), shouldDereference) + } + return false case reflect.Func: return v.IsNil() case reflect.Invalid: diff --git a/test/integration/vendor/github.com/spf13/cobra/.golangci.yml b/test/integration/vendor/github.com/spf13/cobra/.golangci.yml index 439d3e1de..2578d94b5 100644 --- a/test/integration/vendor/github.com/spf13/cobra/.golangci.yml +++ b/test/integration/vendor/github.com/spf13/cobra/.golangci.yml @@ -1,4 +1,4 @@ -# Copyright 2013-2022 The Cobra Authors +# Copyright 2013-2023 The Cobra Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/test/integration/vendor/github.com/spf13/cobra/Makefile b/test/integration/vendor/github.com/spf13/cobra/Makefile index c433a01bc..0da8d7aa0 100644 --- a/test/integration/vendor/github.com/spf13/cobra/Makefile +++ b/test/integration/vendor/github.com/spf13/cobra/Makefile @@ -5,10 +5,6 @@ ifeq (, $(shell which golangci-lint)) $(warning "could not find golangci-lint in $(PATH), run: curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh") endif -ifeq (, $(shell which richgo)) -$(warning "could not find richgo in $(PATH), run: go install github.com/kyoh86/richgo@latest") -endif - .PHONY: fmt lint test install_deps clean default: all @@ -25,6 +21,10 @@ lint: test: install_deps $(info ******************** running tests ********************) + go test -v ./... + +richtest: install_deps + $(info ******************** running tests with kyoh86/richgo ********************) richgo test -v ./... install_deps: diff --git a/test/integration/vendor/github.com/spf13/cobra/README.md b/test/integration/vendor/github.com/spf13/cobra/README.md index 7cc726beb..592c0b8ab 100644 --- a/test/integration/vendor/github.com/spf13/cobra/README.md +++ b/test/integration/vendor/github.com/spf13/cobra/README.md @@ -1,4 +1,4 @@ -![cobra logo](https://cloud.githubusercontent.com/assets/173412/10886352/ad566232-814f-11e5-9cd0-aa101788c117.png) +![cobra logo](assets/CobraMain.png) Cobra is a library for creating powerful modern CLI applications. @@ -6,7 +6,7 @@ Cobra is used in many Go projects such as [Kubernetes](https://kubernetes.io/), [Hugo](https://gohugo.io), and [GitHub CLI](https://github.com/cli/cli) to name a few. [This list](./projects_using_cobra.md) contains a more extensive list of projects using Cobra. -[![](https://img.shields.io/github/workflow/status/spf13/cobra/Test?longCache=tru&label=Test&logo=github%20actions&logoColor=fff)](https://github.com/spf13/cobra/actions?query=workflow%3ATest) +[![](https://img.shields.io/github/actions/workflow/status/spf13/cobra/test.yml?branch=main&longCache=true&label=Test&logo=github%20actions&logoColor=fff)](https://github.com/spf13/cobra/actions?query=workflow%3ATest) [![Go Reference](https://pkg.go.dev/badge/github.com/spf13/cobra.svg)](https://pkg.go.dev/github.com/spf13/cobra) [![Go Report Card](https://goreportcard.com/badge/github.com/spf13/cobra)](https://goreportcard.com/report/github.com/spf13/cobra) [![Slack](https://img.shields.io/badge/Slack-cobra-brightgreen)](https://gophers.slack.com/archives/CD3LP1199) diff --git a/test/integration/vendor/github.com/spf13/cobra/active_help.go b/test/integration/vendor/github.com/spf13/cobra/active_help.go index 95e03aecb..2d0239437 100644 --- a/test/integration/vendor/github.com/spf13/cobra/active_help.go +++ b/test/integration/vendor/github.com/spf13/cobra/active_help.go @@ -1,4 +1,4 @@ -// Copyright 2013-2022 The Cobra Authors +// Copyright 2013-2023 The Cobra Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/test/integration/vendor/github.com/spf13/cobra/args.go b/test/integration/vendor/github.com/spf13/cobra/args.go index 2c1f99e78..e79ec33a8 100644 --- a/test/integration/vendor/github.com/spf13/cobra/args.go +++ b/test/integration/vendor/github.com/spf13/cobra/args.go @@ -1,4 +1,4 @@ -// Copyright 2013-2022 The Cobra Authors +// Copyright 2013-2023 The Cobra Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -21,7 +21,7 @@ import ( type PositionalArgs func(cmd *Command, args []string) error -// Legacy arg validation has the following behaviour: +// legacyArgs validation has the following behaviour: // - root commands with no subcommands can take arbitrary arguments // - root commands with subcommands will do subcommand validity checking // - subcommands will always accept arbitrary arguments diff --git a/test/integration/vendor/github.com/spf13/cobra/bash_completions.go b/test/integration/vendor/github.com/spf13/cobra/bash_completions.go index 3acdb2797..10c78847d 100644 --- a/test/integration/vendor/github.com/spf13/cobra/bash_completions.go +++ b/test/integration/vendor/github.com/spf13/cobra/bash_completions.go @@ -1,4 +1,4 @@ -// Copyright 2013-2022 The Cobra Authors +// Copyright 2013-2023 The Cobra Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -532,7 +532,7 @@ func writeLocalNonPersistentFlag(buf io.StringWriter, flag *pflag.Flag) { } } -// Setup annotations for go completions for registered flags +// prepareCustomAnnotationsForFlags setup annotations for go completions for registered flags func prepareCustomAnnotationsForFlags(cmd *Command) { flagCompletionMutex.RLock() defer flagCompletionMutex.RUnlock() diff --git a/test/integration/vendor/github.com/spf13/cobra/bash_completionsV2.go b/test/integration/vendor/github.com/spf13/cobra/bash_completionsV2.go index bb4b71892..19b09560c 100644 --- a/test/integration/vendor/github.com/spf13/cobra/bash_completionsV2.go +++ b/test/integration/vendor/github.com/spf13/cobra/bash_completionsV2.go @@ -1,4 +1,4 @@ -// Copyright 2013-2022 The Cobra Authors +// Copyright 2013-2023 The Cobra Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -38,7 +38,7 @@ func genBashComp(buf io.StringWriter, name string, includeDesc bool) { __%[1]s_debug() { - if [[ -n ${BASH_COMP_DEBUG_FILE:-} ]]; then + if [[ -n ${BASH_COMP_DEBUG_FILE-} ]]; then echo "$*" >> "${BASH_COMP_DEBUG_FILE}" fi } @@ -65,7 +65,7 @@ __%[1]s_get_completion_results() { lastChar=${lastParam:$((${#lastParam}-1)):1} __%[1]s_debug "lastParam ${lastParam}, lastChar ${lastChar}" - if [ -z "${cur}" ] && [ "${lastChar}" != "=" ]; then + if [[ -z ${cur} && ${lastChar} != = ]]; then # If the last parameter is complete (there is a space following it) # We add an extra empty parameter so we can indicate this to the go method. __%[1]s_debug "Adding extra empty parameter" @@ -75,7 +75,7 @@ __%[1]s_get_completion_results() { # When completing a flag with an = (e.g., %[1]s -n=) # bash focuses on the part after the =, so we need to remove # the flag part from $cur - if [[ "${cur}" == -*=* ]]; then + if [[ ${cur} == -*=* ]]; then cur="${cur#*=}" fi @@ -87,7 +87,7 @@ __%[1]s_get_completion_results() { directive=${out##*:} # Remove the directive out=${out%%:*} - if [ "${directive}" = "${out}" ]; then + if [[ ${directive} == "${out}" ]]; then # There is not directive specified directive=0 fi @@ -101,22 +101,36 @@ __%[1]s_process_completion_results() { local shellCompDirectiveNoFileComp=%[5]d local shellCompDirectiveFilterFileExt=%[6]d local shellCompDirectiveFilterDirs=%[7]d + local shellCompDirectiveKeepOrder=%[8]d - if [ $((directive & shellCompDirectiveError)) -ne 0 ]; then + if (((directive & shellCompDirectiveError) != 0)); then # Error code. No completion. __%[1]s_debug "Received error from custom completion go code" return else - if [ $((directive & shellCompDirectiveNoSpace)) -ne 0 ]; then - if [[ $(type -t compopt) = "builtin" ]]; then + if (((directive & shellCompDirectiveNoSpace) != 0)); then + if [[ $(type -t compopt) == builtin ]]; then __%[1]s_debug "Activating no space" compopt -o nospace else __%[1]s_debug "No space directive not supported in this version of bash" fi fi - if [ $((directive & shellCompDirectiveNoFileComp)) -ne 0 ]; then - if [[ $(type -t compopt) = "builtin" ]]; then + if (((directive & shellCompDirectiveKeepOrder) != 0)); then + if [[ $(type -t compopt) == builtin ]]; then + # no sort isn't supported for bash less than < 4.4 + if [[ ${BASH_VERSINFO[0]} -lt 4 || ( ${BASH_VERSINFO[0]} -eq 4 && ${BASH_VERSINFO[1]} -lt 4 ) ]]; then + __%[1]s_debug "No sort directive not supported in this version of bash" + else + __%[1]s_debug "Activating keep order" + compopt -o nosort + fi + else + __%[1]s_debug "No sort directive not supported in this version of bash" + fi + fi + if (((directive & shellCompDirectiveNoFileComp) != 0)); then + if [[ $(type -t compopt) == builtin ]]; then __%[1]s_debug "Activating no file completion" compopt +o default else @@ -130,7 +144,7 @@ __%[1]s_process_completion_results() { local activeHelp=() __%[1]s_extract_activeHelp - if [ $((directive & shellCompDirectiveFilterFileExt)) -ne 0 ]; then + if (((directive & shellCompDirectiveFilterFileExt) != 0)); then # File extension filtering local fullFilter filter filteringCmd @@ -143,13 +157,12 @@ __%[1]s_process_completion_results() { filteringCmd="_filedir $fullFilter" __%[1]s_debug "File filtering command: $filteringCmd" $filteringCmd - elif [ $((directive & shellCompDirectiveFilterDirs)) -ne 0 ]; then + elif (((directive & shellCompDirectiveFilterDirs) != 0)); then # File completion for directories only - # Use printf to strip any trailing newline local subdir - subdir=$(printf "%%s" "${completions[0]}") - if [ -n "$subdir" ]; then + subdir=${completions[0]} + if [[ -n $subdir ]]; then __%[1]s_debug "Listing directories in $subdir" pushd "$subdir" >/dev/null 2>&1 && _filedir -d && popd >/dev/null 2>&1 || return else @@ -164,7 +177,7 @@ __%[1]s_process_completion_results() { __%[1]s_handle_special_char "$cur" = # Print the activeHelp statements before we finish - if [ ${#activeHelp[*]} -ne 0 ]; then + if ((${#activeHelp[*]} != 0)); then printf "\n"; printf "%%s\n" "${activeHelp[@]}" printf "\n" @@ -184,21 +197,21 @@ __%[1]s_process_completion_results() { # Separate activeHelp lines from real completions. # Fills the $activeHelp and $completions arrays. __%[1]s_extract_activeHelp() { - local activeHelpMarker="%[8]s" + local activeHelpMarker="%[9]s" local endIndex=${#activeHelpMarker} while IFS='' read -r comp; do - if [ "${comp:0:endIndex}" = "$activeHelpMarker" ]; then + if [[ ${comp:0:endIndex} == $activeHelpMarker ]]; then comp=${comp:endIndex} __%[1]s_debug "ActiveHelp found: $comp" - if [ -n "$comp" ]; then + if [[ -n $comp ]]; then activeHelp+=("$comp") fi else # Not an activeHelp line but a normal completion completions+=("$comp") fi - done < <(printf "%%s\n" "${out}") + done <<<"${out}" } __%[1]s_handle_completion_types() { @@ -254,7 +267,7 @@ __%[1]s_handle_standard_completion_case() { done < <(printf "%%s\n" "${completions[@]}") # If there is a single completion left, remove the description text - if [ ${#COMPREPLY[*]} -eq 1 ]; then + if ((${#COMPREPLY[*]} == 1)); then __%[1]s_debug "COMPREPLY[0]: ${COMPREPLY[0]}" comp="${COMPREPLY[0]%%%%$tab*}" __%[1]s_debug "Removed description from single completion, which is now: ${comp}" @@ -271,8 +284,8 @@ __%[1]s_handle_special_char() if [[ "$comp" == *${char}* && "$COMP_WORDBREAKS" == *${char}* ]]; then local word=${comp%%"${comp##*${char}}"} local idx=${#COMPREPLY[*]} - while [[ $((--idx)) -ge 0 ]]; do - COMPREPLY[$idx]=${COMPREPLY[$idx]#"$word"} + while ((--idx >= 0)); do + COMPREPLY[idx]=${COMPREPLY[idx]#"$word"} done fi } @@ -298,7 +311,7 @@ __%[1]s_format_comp_descriptions() # Make sure we can fit a description of at least 8 characters # if we are to align the descriptions. - if [[ $maxdesclength -gt 8 ]]; then + if ((maxdesclength > 8)); then # Add the proper number of spaces to align the descriptions for ((i = ${#comp} ; i < longest ; i++)); do comp+=" " @@ -310,8 +323,8 @@ __%[1]s_format_comp_descriptions() # If there is enough space for any description text, # truncate the descriptions that are too long for the shell width - if [ $maxdesclength -gt 0 ]; then - if [ ${#desc} -gt $maxdesclength ]; then + if ((maxdesclength > 0)); then + if ((${#desc} > maxdesclength)); then desc=${desc:0:$(( maxdesclength - 1 ))} desc+="…" fi @@ -332,9 +345,9 @@ __start_%[1]s() # Call _init_completion from the bash-completion package # to prepare the arguments properly if declare -F _init_completion >/dev/null 2>&1; then - _init_completion -n "=:" || return + _init_completion -n =: || return else - __%[1]s_init_completion -n "=:" || return + __%[1]s_init_completion -n =: || return fi __%[1]s_debug @@ -361,7 +374,7 @@ fi # ex: ts=4 sw=4 et filetype=sh `, name, compCmd, ShellCompDirectiveError, ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp, - ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs, + ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs, ShellCompDirectiveKeepOrder, activeHelpMarker)) } diff --git a/test/integration/vendor/github.com/spf13/cobra/cobra.go b/test/integration/vendor/github.com/spf13/cobra/cobra.go index fe44bc8a0..b07b44a0c 100644 --- a/test/integration/vendor/github.com/spf13/cobra/cobra.go +++ b/test/integration/vendor/github.com/spf13/cobra/cobra.go @@ -1,4 +1,4 @@ -// Copyright 2013-2022 The Cobra Authors +// Copyright 2013-2023 The Cobra Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -167,8 +167,8 @@ func appendIfNotPresent(s, stringToAppend string) string { // rpad adds padding to the right of a string. func rpad(s string, padding int) string { - template := fmt.Sprintf("%%-%ds", padding) - return fmt.Sprintf(template, s) + formattedString := fmt.Sprintf("%%-%ds", padding) + return fmt.Sprintf(formattedString, s) } // tmpl executes the given template text on data, writing the result to w. diff --git a/test/integration/vendor/github.com/spf13/cobra/command.go b/test/integration/vendor/github.com/spf13/cobra/command.go index 6ff47dd5c..01f7c6f1c 100644 --- a/test/integration/vendor/github.com/spf13/cobra/command.go +++ b/test/integration/vendor/github.com/spf13/cobra/command.go @@ -1,4 +1,4 @@ -// Copyright 2013-2022 The Cobra Authors +// Copyright 2013-2023 The Cobra Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -35,7 +35,7 @@ const FlagSetByCobraAnnotation = "cobra_annotation_flag_set_by_cobra" // FParseErrWhitelist configures Flag parse errors to be ignored type FParseErrWhitelist flag.ParseErrorsWhitelist -// Structure to manage groups for commands +// Group Structure to manage groups for commands type Group struct { ID string Title string @@ -47,7 +47,7 @@ type Group struct { // definition to ensure usability. type Command struct { // Use is the one-line usage message. - // Recommended syntax is as follow: + // Recommended syntax is as follows: // [ ] identifies an optional argument. Arguments that are not enclosed in brackets are required. // ... indicates that you can specify multiple values for the previous argument. // | indicates mutually exclusive information. You can use the argument to the left of the separator or the @@ -321,7 +321,7 @@ func (c *Command) SetHelpCommand(cmd *Command) { c.helpCommand = cmd } -// SetHelpCommandGroup sets the group id of the help command. +// SetHelpCommandGroupID sets the group id of the help command. func (c *Command) SetHelpCommandGroupID(groupID string) { if c.helpCommand != nil { c.helpCommand.GroupID = groupID @@ -330,7 +330,7 @@ func (c *Command) SetHelpCommandGroupID(groupID string) { c.helpCommandGroupID = groupID } -// SetCompletionCommandGroup sets the group id of the completion command. +// SetCompletionCommandGroupID sets the group id of the completion command. func (c *Command) SetCompletionCommandGroupID(groupID string) { // completionCommandGroupID is used if no completion command is defined by the user c.Root().completionCommandGroupID = groupID @@ -655,20 +655,44 @@ Loop: // argsMinusFirstX removes only the first x from args. Otherwise, commands that look like // openshift admin policy add-role-to-user admin my-user, lose the admin argument (arg[4]). -func argsMinusFirstX(args []string, x string) []string { - for i, y := range args { - if x == y { - ret := []string{} - ret = append(ret, args[:i]...) - ret = append(ret, args[i+1:]...) - return ret +// Special care needs to be taken not to remove a flag value. +func (c *Command) argsMinusFirstX(args []string, x string) []string { + if len(args) == 0 { + return args + } + c.mergePersistentFlags() + flags := c.Flags() + +Loop: + for pos := 0; pos < len(args); pos++ { + s := args[pos] + switch { + case s == "--": + // -- means we have reached the end of the parseable args. Break out of the loop now. + break Loop + case strings.HasPrefix(s, "--") && !strings.Contains(s, "=") && !hasNoOptDefVal(s[2:], flags): + fallthrough + case strings.HasPrefix(s, "-") && !strings.Contains(s, "=") && len(s) == 2 && !shortHasNoOptDefVal(s[1:], flags): + // This is a flag without a default value, and an equal sign is not used. Increment pos in order to skip + // over the next arg, because that is the value of this flag. + pos++ + continue + case !strings.HasPrefix(s, "-"): + // This is not a flag or a flag value. Check to see if it matches what we're looking for, and if so, + // return the args, excluding the one at this position. + if s == x { + ret := []string{} + ret = append(ret, args[:pos]...) + ret = append(ret, args[pos+1:]...) + return ret + } } } return args } func isFlagArg(arg string) bool { - return ((len(arg) >= 3 && arg[1] == '-') || + return ((len(arg) >= 3 && arg[0:2] == "--") || (len(arg) >= 2 && arg[0] == '-' && arg[1] != '-')) } @@ -686,7 +710,7 @@ func (c *Command) Find(args []string) (*Command, []string, error) { cmd := c.findNext(nextSubCmd) if cmd != nil { - return innerfind(cmd, argsMinusFirstX(innerArgs, nextSubCmd)) + return innerfind(cmd, c.argsMinusFirstX(innerArgs, nextSubCmd)) } return c, innerArgs } @@ -1272,7 +1296,7 @@ func (c *Command) AllChildCommandsHaveGroup() bool { return true } -// ContainGroups return if groupID exists in the list of command groups. +// ContainsGroup return if groupID exists in the list of command groups. func (c *Command) ContainsGroup(groupID string) bool { for _, x := range c.commandgroups { if x.ID == groupID { diff --git a/test/integration/vendor/github.com/spf13/cobra/command_notwin.go b/test/integration/vendor/github.com/spf13/cobra/command_notwin.go index 2b77f8f01..307f0c127 100644 --- a/test/integration/vendor/github.com/spf13/cobra/command_notwin.go +++ b/test/integration/vendor/github.com/spf13/cobra/command_notwin.go @@ -1,4 +1,4 @@ -// Copyright 2013-2022 The Cobra Authors +// Copyright 2013-2023 The Cobra Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/test/integration/vendor/github.com/spf13/cobra/command_win.go b/test/integration/vendor/github.com/spf13/cobra/command_win.go index 520f23abf..adbef395c 100644 --- a/test/integration/vendor/github.com/spf13/cobra/command_win.go +++ b/test/integration/vendor/github.com/spf13/cobra/command_win.go @@ -1,4 +1,4 @@ -// Copyright 2013-2022 The Cobra Authors +// Copyright 2013-2023 The Cobra Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/test/integration/vendor/github.com/spf13/cobra/completions.go b/test/integration/vendor/github.com/spf13/cobra/completions.go index e8a0206db..ee38c4d0b 100644 --- a/test/integration/vendor/github.com/spf13/cobra/completions.go +++ b/test/integration/vendor/github.com/spf13/cobra/completions.go @@ -1,4 +1,4 @@ -// Copyright 2013-2022 The Cobra Authors +// Copyright 2013-2023 The Cobra Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -77,6 +77,10 @@ const ( // obtain the same behavior but only for flags. ShellCompDirectiveFilterDirs + // ShellCompDirectiveKeepOrder indicates that the shell should preserve the order + // in which the completions are provided + ShellCompDirectiveKeepOrder + // =========================================================================== // All directives using iota should be above this one. @@ -159,6 +163,9 @@ func (d ShellCompDirective) string() string { if d&ShellCompDirectiveFilterDirs != 0 { directives = append(directives, "ShellCompDirectiveFilterDirs") } + if d&ShellCompDirectiveKeepOrder != 0 { + directives = append(directives, "ShellCompDirectiveKeepOrder") + } if len(directives) == 0 { directives = append(directives, "ShellCompDirectiveDefault") } @@ -169,7 +176,7 @@ func (d ShellCompDirective) string() string { return strings.Join(directives, ", ") } -// Adds a special hidden command that can be used to request custom completions. +// initCompleteCmd adds a special hidden command that can be used to request custom completions. func (c *Command) initCompleteCmd(args []string) { completeCmd := &Command{ Use: fmt.Sprintf("%s [command-line]", ShellCompRequestCmd), @@ -727,7 +734,7 @@ to enable it. You can execute the following once: To load completions in your current shell session: - source <(%[1]s completion zsh); compdef _%[1]s %[1]s + source <(%[1]s completion zsh) To load completions for every new session, execute once: diff --git a/test/integration/vendor/github.com/spf13/cobra/fish_completions.go b/test/integration/vendor/github.com/spf13/cobra/fish_completions.go index 97112a17b..12ca0d2b1 100644 --- a/test/integration/vendor/github.com/spf13/cobra/fish_completions.go +++ b/test/integration/vendor/github.com/spf13/cobra/fish_completions.go @@ -1,4 +1,4 @@ -// Copyright 2013-2022 The Cobra Authors +// Copyright 2013-2023 The Cobra Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -53,7 +53,7 @@ function __%[1]s_perform_completion __%[1]s_debug "last arg: $lastArg" # Disable ActiveHelp which is not supported for fish shell - set -l requestComp "%[9]s=0 $args[1] %[3]s $args[2..-1] $lastArg" + set -l requestComp "%[10]s=0 $args[1] %[3]s $args[2..-1] $lastArg" __%[1]s_debug "Calling $requestComp" set -l results (eval $requestComp 2> /dev/null) @@ -89,6 +89,60 @@ function __%[1]s_perform_completion printf "%%s\n" "$directiveLine" end +# this function limits calls to __%[1]s_perform_completion, by caching the result behind $__%[1]s_perform_completion_once_result +function __%[1]s_perform_completion_once + __%[1]s_debug "Starting __%[1]s_perform_completion_once" + + if test -n "$__%[1]s_perform_completion_once_result" + __%[1]s_debug "Seems like a valid result already exists, skipping __%[1]s_perform_completion" + return 0 + end + + set --global __%[1]s_perform_completion_once_result (__%[1]s_perform_completion) + if test -z "$__%[1]s_perform_completion_once_result" + __%[1]s_debug "No completions, probably due to a failure" + return 1 + end + + __%[1]s_debug "Performed completions and set __%[1]s_perform_completion_once_result" + return 0 +end + +# this function is used to clear the $__%[1]s_perform_completion_once_result variable after completions are run +function __%[1]s_clear_perform_completion_once_result + __%[1]s_debug "" + __%[1]s_debug "========= clearing previously set __%[1]s_perform_completion_once_result variable ==========" + set --erase __%[1]s_perform_completion_once_result + __%[1]s_debug "Succesfully erased the variable __%[1]s_perform_completion_once_result" +end + +function __%[1]s_requires_order_preservation + __%[1]s_debug "" + __%[1]s_debug "========= checking if order preservation is required ==========" + + __%[1]s_perform_completion_once + if test -z "$__%[1]s_perform_completion_once_result" + __%[1]s_debug "Error determining if order preservation is required" + return 1 + end + + set -l directive (string sub --start 2 $__%[1]s_perform_completion_once_result[-1]) + __%[1]s_debug "Directive is: $directive" + + set -l shellCompDirectiveKeepOrder %[9]d + set -l keeporder (math (math --scale 0 $directive / $shellCompDirectiveKeepOrder) %% 2) + __%[1]s_debug "Keeporder is: $keeporder" + + if test $keeporder -ne 0 + __%[1]s_debug "This does require order preservation" + return 0 + end + + __%[1]s_debug "This doesn't require order preservation" + return 1 +end + + # This function does two things: # - Obtain the completions and store them in the global __%[1]s_comp_results # - Return false if file completion should be performed @@ -99,17 +153,17 @@ function __%[1]s_prepare_completions # Start fresh set --erase __%[1]s_comp_results - set -l results (__%[1]s_perform_completion) - __%[1]s_debug "Completion results: $results" + __%[1]s_perform_completion_once + __%[1]s_debug "Completion results: $__%[1]s_perform_completion_once_result" - if test -z "$results" + if test -z "$__%[1]s_perform_completion_once_result" __%[1]s_debug "No completion, probably due to a failure" # Might as well do file completion, in case it helps return 1 end - set -l directive (string sub --start 2 $results[-1]) - set --global __%[1]s_comp_results $results[1..-2] + set -l directive (string sub --start 2 $__%[1]s_perform_completion_once_result[-1]) + set --global __%[1]s_comp_results $__%[1]s_perform_completion_once_result[1..-2] __%[1]s_debug "Completions are: $__%[1]s_comp_results" __%[1]s_debug "Directive is: $directive" @@ -205,13 +259,17 @@ end # Remove any pre-existing completions for the program since we will be handling all of them. complete -c %[2]s -e +# this will get called after the two calls below and clear the $__%[1]s_perform_completion_once_result global +complete -c %[2]s -n '__%[1]s_clear_perform_completion_once_result' # The call to __%[1]s_prepare_completions will setup __%[1]s_comp_results # which provides the program's completion choices. -complete -c %[2]s -n '__%[1]s_prepare_completions' -f -a '$__%[1]s_comp_results' - +# If this doesn't require order preservation, we don't use the -k flag +complete -c %[2]s -n 'not __%[1]s_requires_order_preservation && __%[1]s_prepare_completions' -f -a '$__%[1]s_comp_results' +# otherwise we use the -k flag +complete -k -c %[2]s -n '__%[1]s_requires_order_preservation && __%[1]s_prepare_completions' -f -a '$__%[1]s_comp_results' `, nameForVar, name, compCmd, ShellCompDirectiveError, ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp, - ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs, activeHelpEnvVar(name))) + ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs, ShellCompDirectiveKeepOrder, activeHelpEnvVar(name))) } // GenFishCompletion generates fish completion file and writes to the passed writer. diff --git a/test/integration/vendor/github.com/spf13/cobra/flag_groups.go b/test/integration/vendor/github.com/spf13/cobra/flag_groups.go index 9c377aaf9..b35fde155 100644 --- a/test/integration/vendor/github.com/spf13/cobra/flag_groups.go +++ b/test/integration/vendor/github.com/spf13/cobra/flag_groups.go @@ -1,4 +1,4 @@ -// Copyright 2013-2022 The Cobra Authors +// Copyright 2013-2023 The Cobra Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/test/integration/vendor/github.com/spf13/cobra/powershell_completions.go b/test/integration/vendor/github.com/spf13/cobra/powershell_completions.go index 004de42e4..177d2755f 100644 --- a/test/integration/vendor/github.com/spf13/cobra/powershell_completions.go +++ b/test/integration/vendor/github.com/spf13/cobra/powershell_completions.go @@ -1,4 +1,4 @@ -// Copyright 2013-2022 The Cobra Authors +// Copyright 2013-2023 The Cobra Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -77,6 +77,7 @@ filter __%[1]s_escapeStringWithSpecialChars { $ShellCompDirectiveNoFileComp=%[6]d $ShellCompDirectiveFilterFileExt=%[7]d $ShellCompDirectiveFilterDirs=%[8]d + $ShellCompDirectiveKeepOrder=%[9]d # Prepare the command to request completions for the program. # Split the command at the first space to separate the program and arguments. @@ -106,13 +107,22 @@ filter __%[1]s_escapeStringWithSpecialChars { # If the last parameter is complete (there is a space following it) # We add an extra empty parameter so we can indicate this to the go method. __%[1]s_debug "Adding extra empty parameter" -`+" # We need to use `\"`\" to pass an empty argument a \"\" or '' does not work!!!"+` -`+" $RequestComp=\"$RequestComp\" + ' `\"`\"'"+` + # PowerShell 7.2+ changed the way how the arguments are passed to executables, + # so for pre-7.2 or when Legacy argument passing is enabled we need to use +`+" # `\"`\" to pass an empty argument, a \"\" or '' does not work!!!"+` + if ($PSVersionTable.PsVersion -lt [version]'7.2.0' -or + ($PSVersionTable.PsVersion -lt [version]'7.3.0' -and -not [ExperimentalFeature]::IsEnabled("PSNativeCommandArgumentPassing")) -or + (($PSVersionTable.PsVersion -ge [version]'7.3.0' -or [ExperimentalFeature]::IsEnabled("PSNativeCommandArgumentPassing")) -and + $PSNativeCommandArgumentPassing -eq 'Legacy')) { +`+" $RequestComp=\"$RequestComp\" + ' `\"`\"'"+` + } else { + $RequestComp="$RequestComp" + ' ""' + } } __%[1]s_debug "Calling $RequestComp" # First disable ActiveHelp which is not supported for Powershell - $env:%[9]s=0 + $env:%[10]s=0 #call the command store the output in $out and redirect stderr and stdout to null # $Out is an array contains each line per element @@ -137,7 +147,7 @@ filter __%[1]s_escapeStringWithSpecialChars { } $Longest = 0 - $Values = $Out | ForEach-Object { + [Array]$Values = $Out | ForEach-Object { #Split the output in name and description `+" $Name, $Description = $_.Split(\"`t\",2)"+` __%[1]s_debug "Name: $Name Description: $Description" @@ -182,6 +192,11 @@ filter __%[1]s_escapeStringWithSpecialChars { } } + # we sort the values in ascending order by name if keep order isn't passed + if (($Directive -band $ShellCompDirectiveKeepOrder) -eq 0 ) { + $Values = $Values | Sort-Object -Property Name + } + if (($Directive -band $ShellCompDirectiveNoFileComp) -ne 0 ) { __%[1]s_debug "ShellCompDirectiveNoFileComp is called" @@ -267,7 +282,7 @@ filter __%[1]s_escapeStringWithSpecialChars { Register-ArgumentCompleter -CommandName '%[1]s' -ScriptBlock $__%[2]sCompleterBlock `, name, nameForVar, compCmd, ShellCompDirectiveError, ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp, - ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs, activeHelpEnvVar(name))) + ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs, ShellCompDirectiveKeepOrder, activeHelpEnvVar(name))) } func (c *Command) genPowerShellCompletion(w io.Writer, includeDesc bool) error { diff --git a/test/integration/vendor/github.com/spf13/cobra/projects_using_cobra.md b/test/integration/vendor/github.com/spf13/cobra/projects_using_cobra.md index 6865f88e7..8a291eb20 100644 --- a/test/integration/vendor/github.com/spf13/cobra/projects_using_cobra.md +++ b/test/integration/vendor/github.com/spf13/cobra/projects_using_cobra.md @@ -1,11 +1,13 @@ ## Projects using Cobra - [Allero](https://github.com/allero-io/allero) +- [Arewefastyet](https://benchmark.vitess.io) - [Arduino CLI](https://github.com/arduino/arduino-cli) - [Bleve](https://blevesearch.com/) - [Cilium](https://cilium.io/) - [CloudQuery](https://github.com/cloudquery/cloudquery) - [CockroachDB](https://www.cockroachlabs.com/) +- [Constellation](https://github.com/edgelesssys/constellation) - [Cosmos SDK](https://github.com/cosmos/cosmos-sdk) - [Datree](https://github.com/datreeio/datree) - [Delve](https://github.com/derekparker/delve) @@ -25,7 +27,7 @@ - [Istio](https://istio.io) - [Kool](https://github.com/kool-dev/kool) - [Kubernetes](https://kubernetes.io/) -- [Kubescape](https://github.com/armosec/kubescape) +- [Kubescape](https://github.com/kubescape/kubescape) - [KubeVirt](https://github.com/kubevirt/kubevirt) - [Linkerd](https://linkerd.io/) - [Mattermost-server](https://github.com/mattermost/mattermost-server) @@ -51,10 +53,12 @@ - [Random](https://github.com/erdaltsksn/random) - [Rclone](https://rclone.org/) - [Scaleway CLI](https://github.com/scaleway/scaleway-cli) +- [Sia](https://github.com/SiaFoundation/siad) - [Skaffold](https://skaffold.dev/) - [Tendermint](https://github.com/tendermint/tendermint) - [Twitch CLI](https://github.com/twitchdev/twitch-cli) - [UpCloud CLI (`upctl`)](https://github.com/UpCloudLtd/upcloud-cli) +- [Vitess](https://vitess.io) - VMware's [Tanzu Community Edition](https://github.com/vmware-tanzu/community-edition) & [Tanzu Framework](https://github.com/vmware-tanzu/tanzu-framework) - [Werf](https://werf.io/) - [ZITADEL](https://github.com/zitadel/zitadel) diff --git a/test/integration/vendor/github.com/spf13/cobra/shell_completions.go b/test/integration/vendor/github.com/spf13/cobra/shell_completions.go index 126e83c30..b035742d3 100644 --- a/test/integration/vendor/github.com/spf13/cobra/shell_completions.go +++ b/test/integration/vendor/github.com/spf13/cobra/shell_completions.go @@ -1,4 +1,4 @@ -// Copyright 2013-2022 The Cobra Authors +// Copyright 2013-2023 The Cobra Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/test/integration/vendor/github.com/spf13/cobra/shell_completions.md b/test/integration/vendor/github.com/spf13/cobra/shell_completions.md index 553ee5df8..065c0621d 100644 --- a/test/integration/vendor/github.com/spf13/cobra/shell_completions.md +++ b/test/integration/vendor/github.com/spf13/cobra/shell_completions.md @@ -71,7 +71,7 @@ PowerShell: `,cmd.Root().Name()), DisableFlagsInUseLine: true, ValidArgs: []string{"bash", "zsh", "fish", "powershell"}, - Args: cobra.ExactValidArgs(1), + Args: cobra.MatchAll(cobra.ExactArgs(1), cobra.OnlyValidArgs), Run: func(cmd *cobra.Command, args []string) { switch args[0] { case "bash": @@ -162,16 +162,7 @@ cmd := &cobra.Command{ } ``` -The aliases are not shown to the user on tab completion, but they are accepted as valid nouns by -the completion algorithm if entered manually, e.g. in: - -```bash -$ kubectl get rc [tab][tab] -backend frontend database -``` - -Note that without declaring `rc` as an alias, the completion algorithm would not know to show the list of -replication controllers following `rc`. +The aliases are shown to the user on tab completion only if no completions were found within sub-commands or `ValidArgs`. ### Dynamic completion of nouns @@ -237,6 +228,10 @@ ShellCompDirectiveFilterFileExt // return []string{"themes"}, ShellCompDirectiveFilterDirs // ShellCompDirectiveFilterDirs + +// ShellCompDirectiveKeepOrder indicates that the shell should preserve the order +// in which the completions are provided +ShellCompDirectiveKeepOrder ``` ***Note***: When using the `ValidArgsFunction`, Cobra will call your registered function after having parsed all flags and arguments provided in the command-line. You therefore don't need to do this parsing yourself. For example, when a user calls `helm status --namespace my-rook-ns [tab][tab]`, Cobra will call your registered `ValidArgsFunction` after having parsed the `--namespace` flag, as it would have done when calling the `RunE` function. @@ -385,6 +380,19 @@ or ```go ValidArgs: []string{"bash\tCompletions for bash", "zsh\tCompletions for zsh"} ``` + +If you don't want to show descriptions in the completions, you can add `--no-descriptions` to the default `completion` command to disable them, like: + +```bash +$ source <(helm completion bash) +$ helm completion [tab][tab] +bash (generate autocompletion script for bash) powershell (generate autocompletion script for powershell) +fish (generate autocompletion script for fish) zsh (generate autocompletion script for zsh) + +$ source <(helm completion bash --no-descriptions) +$ helm completion [tab][tab] +bash fish powershell zsh +``` ## Bash completions ### Dependencies diff --git a/test/integration/vendor/github.com/spf13/cobra/user_guide.md b/test/integration/vendor/github.com/spf13/cobra/user_guide.md index e55367e85..85201d840 100644 --- a/test/integration/vendor/github.com/spf13/cobra/user_guide.md +++ b/test/integration/vendor/github.com/spf13/cobra/user_guide.md @@ -188,6 +188,37 @@ var versionCmd = &cobra.Command{ } ``` +### Organizing subcommands + +A command may have subcommands which in turn may have other subcommands. This is achieved by using +`AddCommand`. In some cases, especially in larger applications, each subcommand may be defined in +its own go package. + +The suggested approach is for the parent command to use `AddCommand` to add its most immediate +subcommands. For example, consider the following directory structure: + +```text +├── cmd +│   ├── root.go +│   └── sub1 +│   ├── sub1.go +│   └── sub2 +│   ├── leafA.go +│   ├── leafB.go +│   └── sub2.go +└── main.go +``` + +In this case: + +* The `init` function of `root.go` adds the command defined in `sub1.go` to the root command. +* The `init` function of `sub1.go` adds the command defined in `sub2.go` to the sub1 command. +* The `init` function of `sub2.go` adds the commands defined in `leafA.go` and `leafB.go` to the + sub2 command. + +This approach ensures the subcommands are always included at compile time while avoiding cyclic +references. + ### Returning and handling errors If you wish to return an error to the caller of a command, `RunE` can be used. @@ -313,8 +344,8 @@ rootCmd.MarkFlagsRequiredTogether("username", "password") You can also prevent different flags from being provided together if they represent mutually exclusive options such as specifying an output format as either `--json` or `--yaml` but never both: ```go -rootCmd.Flags().BoolVar(&u, "json", false, "Output in JSON") -rootCmd.Flags().BoolVar(&pw, "yaml", false, "Output in YAML") +rootCmd.Flags().BoolVar(&ofJson, "json", false, "Output in JSON") +rootCmd.Flags().BoolVar(&ofYaml, "yaml", false, "Output in YAML") rootCmd.MarkFlagsMutuallyExclusive("json", "yaml") ``` @@ -349,7 +380,7 @@ shown below: ```go var cmd = &cobra.Command{ Short: "hello", - Args: MatchAll(ExactArgs(2), OnlyValidArgs), + Args: cobra.MatchAll(cobra.ExactArgs(2), cobra.OnlyValidArgs), Run: func(cmd *cobra.Command, args []string) { fmt.Println("Hello, World!") }, diff --git a/test/integration/vendor/github.com/spf13/cobra/zsh_completions.go b/test/integration/vendor/github.com/spf13/cobra/zsh_completions.go index 84cec76fd..1856e4c7f 100644 --- a/test/integration/vendor/github.com/spf13/cobra/zsh_completions.go +++ b/test/integration/vendor/github.com/spf13/cobra/zsh_completions.go @@ -1,4 +1,4 @@ -// Copyright 2013-2022 The Cobra Authors +// Copyright 2013-2023 The Cobra Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -90,6 +90,7 @@ func genZshComp(buf io.StringWriter, name string, includeDesc bool) { compCmd = ShellCompNoDescRequestCmd } WriteStringAndCheck(buf, fmt.Sprintf(`#compdef %[1]s +compdef _%[1]s %[1]s # zsh completion for %-36[1]s -*- shell-script -*- @@ -108,8 +109,9 @@ _%[1]s() local shellCompDirectiveNoFileComp=%[5]d local shellCompDirectiveFilterFileExt=%[6]d local shellCompDirectiveFilterDirs=%[7]d + local shellCompDirectiveKeepOrder=%[8]d - local lastParam lastChar flagPrefix requestComp out directive comp lastComp noSpace + local lastParam lastChar flagPrefix requestComp out directive comp lastComp noSpace keepOrder local -a completions __%[1]s_debug "\n========= starting completion logic ==========" @@ -177,7 +179,7 @@ _%[1]s() return fi - local activeHelpMarker="%[8]s" + local activeHelpMarker="%[9]s" local endIndex=${#activeHelpMarker} local startIndex=$((${#activeHelpMarker}+1)) local hasActiveHelp=0 @@ -227,6 +229,11 @@ _%[1]s() noSpace="-S ''" fi + if [ $((directive & shellCompDirectiveKeepOrder)) -ne 0 ]; then + __%[1]s_debug "Activating keep order." + keepOrder="-V" + fi + if [ $((directive & shellCompDirectiveFilterFileExt)) -ne 0 ]; then # File extension filtering local filteringCmd @@ -262,7 +269,7 @@ _%[1]s() return $result else __%[1]s_debug "Calling _describe" - if eval _describe "completions" completions $flagPrefix $noSpace; then + if eval _describe $keepOrder "completions" completions $flagPrefix $noSpace; then __%[1]s_debug "_describe found some completions" # Return the success of having called _describe @@ -296,6 +303,6 @@ if [ "$funcstack[1]" = "_%[1]s" ]; then fi `, name, compCmd, ShellCompDirectiveError, ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp, - ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs, + ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs, ShellCompDirectiveKeepOrder, activeHelpMarker)) } diff --git a/test/integration/vendor/modules.txt b/test/integration/vendor/modules.txt index e54495b60..90b4b0c5e 100644 --- a/test/integration/vendor/modules.txt +++ b/test/integration/vendor/modules.txt @@ -231,7 +231,7 @@ github.com/fsnotify/fsnotify # github.com/fvbommel/sortorder v1.0.2 ## explicit; go 1.13 github.com/fvbommel/sortorder -# github.com/go-logr/logr v1.2.3 +# github.com/go-logr/logr v1.2.4 ## explicit; go 1.16 github.com/go-logr/logr github.com/go-logr/logr/funcr @@ -333,7 +333,7 @@ github.com/hashicorp/hcl/hcl/token github.com/hashicorp/hcl/json/parser github.com/hashicorp/hcl/json/scanner github.com/hashicorp/hcl/json/token -# github.com/imdario/mergo v0.3.14 +# github.com/imdario/mergo v0.3.15 ## explicit; go 1.13 github.com/imdario/mergo # github.com/inconshreveable/mousetrap v1.1.0 @@ -368,7 +368,7 @@ github.com/magiconair/properties # github.com/mattn/go-colorable v0.1.13 ## explicit; go 1.15 github.com/mattn/go-colorable -# github.com/mattn/go-isatty v0.0.17 +# github.com/mattn/go-isatty v0.0.18 ## explicit; go 1.15 github.com/mattn/go-isatty # github.com/mattn/go-runewidth v0.0.14 @@ -592,7 +592,7 @@ github.com/spf13/afero/mem # github.com/spf13/cast v1.5.0 ## explicit; go 1.18 github.com/spf13/cast -# github.com/spf13/cobra v1.6.1 +# github.com/spf13/cobra v1.7.0 ## explicit; go 1.15 github.com/spf13/cobra # github.com/spf13/jwalterweatherman v1.1.0