diff --git a/Dockerfile b/Dockerfile index bd5dc97d..4c73888f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -26,6 +26,12 @@ COPY .mk/ .mk/ # Build collector RUN GOARCH=$TARGETARCH make compile +# Install oc to allow collector to run commands +RUN set -x; \ + OC_TAR_URL="https://mirror.openshift.com/pub/openshift-v4/$(uname -m)/clients/ocp/latest/openshift-client-linux.tar.gz" && \ + curl -L -q -o /tmp/oc.tar.gz "$OC_TAR_URL" && \ + tar -C /tmp -xvf /tmp/oc.tar.gz oc kubectl + # Embedd commands in case users want to pull it from collector image RUN USER=netobserv VERSION=main make oc-commands @@ -35,7 +41,11 @@ RUN mkdir -p output # Create final image from ubi + built binary and command FROM --platform=$TARGETPLATFORM registry.access.redhat.com/ubi9/ubi:9.4 WORKDIR / + +COPY --from=builder /opt/app-root/build . COPY --from=builder /opt/app-root/build . +COPY --from=builder /tmp/oc /usr/bin/oc +COPY --from=builder /tmp/kubectl /usr/bin/kubectl COPY --from=builder --chown=65532:65532 /opt/app-root/output /output USER 65532:65532 diff --git a/cmd/flow_capture.go b/cmd/flow_capture.go index a30ee1b1..ddd4c06a 100644 --- a/cmd/flow_capture.go +++ b/cmd/flow_capture.go @@ -147,16 +147,20 @@ func runFlowCaptureOnAddr(port int, filename string) { // terminate capture if max bytes reached totalBytes = totalBytes + int64(bytes) if totalBytes > maxBytes { - log.Infof("Capture reached %s, exiting now...", sizestr.ToString(maxBytes)) - return + if exit := onLimitReached(); exit { + log.Infof("Capture reached %s, exiting now...", sizestr.ToString(maxBytes)) + return + } } // terminate capture if max time reached now := currentTime() duration := now.Sub(startupTime) if int(duration) > int(maxTime) { - log.Infof("Capture reached %s, exiting now...", maxTime) - return + if exit := onLimitReached(); exit { + log.Infof("Capture reached %s, exiting now...", sizestr.ToString(maxBytes)) + return + } } captureStarted = true @@ -241,7 +245,7 @@ func toSize(fieldName string) int { func updateTable() { // don't refresh terminal too often to avoid blinking now := currentTime() - if int(now.Sub(lastRefresh)) > int(maxRefreshRate) { + if !captureEnded && int(now.Sub(lastRefresh)) > int(maxRefreshRate) { lastRefresh = now resetTerminal() @@ -251,12 +255,18 @@ func updateTable() { fmt.Printf("Log level: %s ", logLevel) fmt.Printf("Duration: %s ", duration.Round(time.Second)) fmt.Printf("Capture size: %s\n", sizestr.ToString(totalBytes)) - if len(strings.TrimSpace(filter)) > 0 { - fmt.Printf("Filters: %s\n", filter) + if len(strings.TrimSpace(options)) > 0 { + fmt.Printf("Options: %s\n", options) + } + if strings.Contains(options, "background=true") { + fmt.Printf("Showing last: %d\n", flowsToShow) + fmt.Printf("Display: %s\n", strings.Join(display, ",")) + fmt.Printf("Enrichment: %s\n", strings.Join(enrichement, ",")) + } else { + fmt.Printf("Showing last: %d Use Up / Down keyboard arrows to increase / decrease limit\n", flowsToShow) + fmt.Printf("Display: %s Use Left / Right keyboard arrows to cycle views\n", strings.Join(display, ",")) + fmt.Printf("Enrichment: %s Use Page Up / Page Down keyboard keys to cycle enrichment scopes\n", strings.Join(enrichement, ",")) } - fmt.Printf("Showing last: %d Use Up / Down keyboard arrows to increase / decrease limit\n", flowsToShow) - fmt.Printf("Display: %s Use Left / Right keyboard arrows to cycle views\n", strings.Join(display, ",")) - fmt.Printf("Enrichment: %s Use Page Up / Page Down keyboard keys to cycle enrichment scopes\n", strings.Join(enrichement, ",")) } if slices.Contains(display, rawDisplay) { @@ -393,7 +403,6 @@ func updateTable() { fmt.Printf("Type anything to filter incoming flows in view\n") } } - } } diff --git a/cmd/packet_capture.go b/cmd/packet_capture.go index 706fd3e5..6cec6a8f 100644 --- a/cmd/packet_capture.go +++ b/cmd/packet_capture.go @@ -157,8 +157,10 @@ func runPacketCaptureOnAddr(port int, filename string) { // terminate capture if max bytes reached totalBytes = totalBytes + int64(len(fp.GenericMap.Value)) if totalBytes > maxBytes { - log.Infof("Capture reached %s, exiting now...", sizestr.ToString(maxBytes)) - return + if exit := onLimitReached(); exit { + log.Infof("Capture reached %s, exiting now...", sizestr.ToString(maxBytes)) + return + } } totalPackets = totalPackets + 1 @@ -166,8 +168,10 @@ func runPacketCaptureOnAddr(port int, filename string) { now := currentTime() duration := now.Sub(startupTime) if int(duration) > int(maxTime) { - log.Infof("Capture reached %s, exiting now...", maxTime) - return + if exit := onLimitReached(); exit { + log.Infof("Capture reached %s, exiting now...", maxTime) + return + } } captureStarted = true diff --git a/cmd/root.go b/cmd/root.go index c0990de0..6e55b004 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -24,7 +24,7 @@ var ( logLevel string ports []int nodes []string - filter string + options string maxTime time.Duration maxBytes int64 @@ -56,6 +56,7 @@ var ( captureType = "Flow" outputBuffer *bytes.Buffer captureStarted = false + captureEnded = false stopReceived = false keyboardError = "" ) @@ -71,7 +72,7 @@ func init() { rootCmd.PersistentFlags().StringVarP(&logLevel, "loglevel", "l", "info", "Log level") rootCmd.PersistentFlags().IntSliceVarP(&ports, "ports", "", []int{9999}, "TCP ports to listen") rootCmd.PersistentFlags().StringSliceVarP(&nodes, "nodes", "", []string{""}, "Node names per port (optionnal)") - rootCmd.PersistentFlags().StringVarP(&filter, "filter", "", "", "Filter(s)") + rootCmd.PersistentFlags().StringVarP(&options, "options", "", "", "Options(s)") rootCmd.PersistentFlags().DurationVarP(&maxTime, "maxtime", "", 5*time.Minute, "Maximum capture time") rootCmd.PersistentFlags().Int64VarP(&maxBytes, "maxbytes", "", 50000000, "Maximum capture bytes") @@ -100,10 +101,22 @@ func initConfig() { log.Fatalf("specified nodes names doesn't match ports length") } - log.Infof("Running network-observability-cli\nLog level: %s\nFilter(s): %s", logLevel, filter) + printBanner() + log.Infof("Log level: %s\nOption(s): %s", logLevel, options) showKernelVersion() } +func printBanner() { + fmt.Print(` +------------------------------------------------------------------------ + _ _ _ _ ___ _ ___ + | \| |___| |_ ___| |__ ___ ___ _ ___ __ / __| | |_ _| + | .' / -_) _/ _ \ '_ (_-/dev/null || which kubectl 2>/dev/null ) -K8S_CLI_BIN=$( basename "${K8S_CLI_BIN_PATH}" ) +K8S_CLI_BIN_PATH=$(which oc 2>/dev/null || which kubectl 2>/dev/null) +K8S_CLI_BIN=$(basename "${K8S_CLI_BIN_PATH}") + +# namespace for this run +namespace="netobserv-cli" + +if [ -n "$NETOBSERV_NAMESPACE" ]; then + echo "using custom namespace $NETOBSERV_NAMESPACE" + namespace="$NETOBSERV_NAMESPACE" +fi + +# collector target host +targetHost="collector.$namespace.svc.cluster.local" # eBPF agent image to use agentImg="quay.io/netobserv/netobserv-ebpf-agent:main" @@ -31,6 +47,7 @@ function loadYAMLs() { if [ -f ./res/namespace.yml ]; then namespaceYAML="$(cat ./res/namespace.yml)" fi + namespaceYAML="${namespaceYAML/"{{NAME}}"/${namespace}}" saYAML=' saYAMLContent @@ -38,6 +55,7 @@ function loadYAMLs() { if [ -f ./res/service-account.yml ]; then saYAML="$(cat ./res/service-account.yml)" fi + saYAML="${saYAML//"{{NAMESPACE}}"/${namespace}}" flowAgentYAML=' flowAgentYAMLContent @@ -45,6 +63,8 @@ function loadYAMLs() { if [ -f ./res/flow-capture.yml ]; then flowAgentYAML="$(cat ./res/flow-capture.yml)" fi + flowAgentYAML="${flowAgentYAML/"{{NAMESPACE}}"/${namespace}}" + flowAgentYAML="${flowAgentYAML/"{{TARGET_HOST}}"/${targetHost}}" flowAgentYAML="${flowAgentYAML/"{{AGENT_IMAGE_URL}}"/${agentImg}}" packetAgentYAML=' @@ -53,6 +73,8 @@ function loadYAMLs() { if [ -f ./res/packet-capture.yml ]; then packetAgentYAML="$(cat ./res/packet-capture.yml)" fi + packetAgentYAML="${packetAgentYAML/"{{NAMESPACE}}"/${namespace}}" + packetAgentYAML="${packetAgentYAML/"{{TARGET_HOST}}"/${targetHost}}" packetAgentYAML="${packetAgentYAML/"{{AGENT_IMAGE_URL}}"/${agentImg}}" collectorServiceYAML=' @@ -61,19 +83,29 @@ function loadYAMLs() { if [ -f ./res/collector-service.yml ]; then collectorServiceYAML="$(cat ./res/collector-service.yml)" fi + collectorServiceYAML="${collectorServiceYAML/"{{NAMESPACE}}"/${namespace}}" } function clusterIsReady() { - # use oc whoami as connectivity check by default and fallback to kubectl get all if needed - K8S_CLI_CONNECTIVITY="${K8S_CLI_BIN} whoami" - if [ "${K8S_CLI_BIN}" = "kubectl" ]; then - K8S_CLI_CONNECTIVITY="${K8S_CLI_BIN} get all" - fi - if ${K8S_CLI_CONNECTIVITY} 2>&1 || ${K8S_CLI_BIN} cluster-info | grep -q "Kubernetes control plane"; then - return 0 - else - return 1 - fi + # use oc whoami as connectivity check by default and fallback to kubectl get all if needed + K8S_CLI_CONNECTIVITY="${K8S_CLI_BIN} whoami" + if [ "${K8S_CLI_BIN}" = "kubectl" ]; then + K8S_CLI_CONNECTIVITY="${K8S_CLI_BIN} get all" + fi + if ${K8S_CLI_CONNECTIVITY} 2>&1 || ${K8S_CLI_BIN} cluster-info | grep -q "Kubernetes control plane"; then + return 0 + else + return 1 + fi +} + +function namespaceFound() { + # ensure namespace doesn't exist, else we should not override content + if ${K8S_CLI_BIN} get namespace "$namespace" --ignore-not-found=true | grep -q "$namespace"; then + return 0 + else + return 1 + fi } FLOWS_MANIFEST_FILE="flow-capture.yml" @@ -94,11 +126,17 @@ function setup { exit 1 fi + if namespaceFound; then + printf "%s namespace already exists. Ensure someone else is not running another capture on this cluster. Else use 'oc netobserv cleanup' to remove the namespace first.\n" "$namespace" >&2 + skipCleanup="true" + exit 1 + fi + # load yaml files loadYAMLs # apply yamls - echo "creating netobserv-cli namespace" + echo "creating $namespace namespace" echo "$namespaceYAML" | ${K8S_CLI_BIN} apply -f - echo "creating service account" @@ -111,51 +149,83 @@ function setup { shift echo "creating flow-capture agents:" if [[ ! -d ${MANIFEST_OUTPUT_PATH} ]]; then - mkdir -p ${MANIFEST_OUTPUT_PATH} > /dev/null + mkdir -p ${MANIFEST_OUTPUT_PATH} >/dev/null fi manifest="${MANIFEST_OUTPUT_PATH}/${FLOWS_MANIFEST_FILE}" - echo "${flowAgentYAML}" > ${manifest} + echo "${flowAgentYAML}" >${manifest} options="$*" check_args_and_apply "$options" "$manifest" "flows" elif [ "$1" = "packets" ]; then shift echo "creating packet-capture agents" if [[ ! -d ${MANIFEST_OUTPUT_PATH} ]]; then - mkdir -p ${MANIFEST_OUTPUT_PATH} > /dev/null + mkdir -p ${MANIFEST_OUTPUT_PATH} >/dev/null fi manifest="${MANIFEST_OUTPUT_PATH}/${PACKETS_MANIFEST_FILE}" - echo "${packetAgentYAML}" > ${manifest} + echo "${packetAgentYAML}" >${manifest} options="$*" check_args_and_apply "$options" "$manifest" "packets" fi } +function follow { + ${K8S_CLI_BIN} logs collector -n "$namespace" -f +} + function copyOutput { echo "Copying collector output files..." mkdir -p ./output - ${K8S_CLI_BIN} cp -n netobserv-cli collector:output ./output + ${K8S_CLI_BIN} cp -n "$namespace" collector:output ./output +} + +function deleteDaemonset { + printf "\nDeleting daemonset... " + ${K8S_CLI_BIN} delete daemonset netobserv-cli -n "$namespace" --ignore-not-found=true +} + +function deletePod { + printf "\nDeleting pod... " + ${K8S_CLI_BIN} delete pod collector -n "$namespace" --ignore-not-found=true +} + +function deleteNamespace { + printf "\nDeleting namespace... " + ${K8S_CLI_BIN} delete namespace "$namespace" --ignore-not-found=true } function cleanup { + if [[ "$runBackground" == "true" || "$skipCleanup" == "true" ]]; then + return + fi + # shellcheck disable=SC2034 if clusterIsReady; then if [ "$captureStarted" = false ]; then - echo "Can't copy since capture didn't start" + echo "Copy skipped" elif [[ "$isE2E" = true || "$copy" = true ]]; then copyOutput elif [ "$copy" = "prompt" ]; then while true; do - read -rp "Copy the capture output locally ?" yn - case $yn in - [Yy]* ) copyOutput; break;; - [Nn]* ) echo "copy skipped"; break;; - * ) echo "Please answer yes or no.";; - esac + read -rp "Copy the capture output locally ?" yn + case $yn in + [Yy]*) + copyOutput + break + ;; + [Nn]*) + echo "copy skipped" + break + ;; + *) echo "Please answer yes or no." ;; + esac done fi - printf "\nCleaning up... " - ${K8S_CLI_BIN} delete namespace netobserv-cli + printf "\nCleaning up..." + deleteDaemonset + deletePod + deleteNamespace + printf "\n" else echo "Cleanup namespace skipped" return @@ -167,6 +237,7 @@ function common_usage { echo " --log-level: components logs (default: info)" echo " --max-time: maximum capture time (default: 5m)" echo " --max-bytes: maximum capture bytes (default: 50000000 = 50MB)" + echo " --background: run in background (default: false)" echo " --copy: copy the output files locally (default: prompt)" # filters echo " --direction: filter direction (default: n/a)" @@ -279,11 +350,11 @@ function edit_manifest() { yq e --inplace ".spec.template.spec.containers[0].env[] |= select(.name==\"FILTER_ACTION\").value|=\"$2\"" "$3" ;; "filter_tcp_flags") - yq e --inplace ".spec.template.spec.containers[0].env[] |= select(.name==\"FILTER_TCP_FLAGS\").value|=\"$2\"" "$3" - ;; - "filter_pkt_drops") - yq e --inplace ".spec.template.spec.containers[0].env[] |= select(.name==\"FILTER_DROPS\").value|=\"$2\"" "$3" - ;; + yq e --inplace ".spec.template.spec.containers[0].env[] |= select(.name==\"FILTER_TCP_FLAGS\").value|=\"$2\"" "$3" + ;; + "filter_pkt_drops") + yq e --inplace ".spec.template.spec.containers[0].env[] |= select(.name==\"FILTER_DROPS\").value|=\"$2\"" "$3" + ;; "log_level") yq e --inplace ".spec.template.spec.containers[0].env[] |= select(.name==\"LOG_LEVEL\").value|=\"$2\"" "$3" ;; @@ -295,183 +366,191 @@ function edit_manifest() { #$2: manifest #$3: either flows or packets function check_args_and_apply() { - # Iterate through the command-line arguments - for option in $1; do - key="${option%%=*}" - value="${option#*=}" - case "$key" in - --copy) # Copy or skip without prompt - if [[ "$value" == "true" || "$value" == "false" || "$value" == "prompt" ]]; then - echo "param: $key, param_value: $value" - copy="$value" - else - echo "invalid value for --copy" - fi - ;; - --interfaces) # Interfaces - edit_manifest "interfaces" "$value" "$2" - ;; - --enable_pktdrop) # Enable packet drop - if [[ "$3" == "flows" ]]; then - if [[ "$value" == "true" || "$value" == "false" ]]; then - edit_manifest "pktdrop_enable" "$value" "$2" - else - echo "invalid value for --enable_pktdrop" - fi - else - echo "--enable_pktdrop is invalid option for packets" - exit 1 - fi - ;; - --enable_dns) # Enable DNS - if [[ "$3" == "flows" ]]; then - if [[ "$value" == "true" || "$value" == "false" ]]; then - edit_manifest "dns_enable" "$value" "$2" - else - echo "invalid value for --enable_dns" - fi - else - echo "--enable_dns is invalid option for packets" - exit 1 - fi - ;; - --enable_rtt) # Enable RTT - if [[ "$3" == "flows" ]]; then - if [[ "$value" == "true" || "$value" == "false" ]]; then - edit_manifest "rtt_enable" "$value" "$2" - else - echo "invalid value for --enable_rtt" - fi - else - echo "--enable_rtt is invalid option for packets" - exit 1 - fi - ;; - --enable_network_events) # Enable Network events monitoring - if [[ "$3" == "flows" ]]; then - if [[ "$value" == "true" || "$value" == "false" ]]; then - edit_manifest "network_events_enable" "$value" "$2" - else - echo "invalid value for --enable_network_events" - fi - else - echo "--enable_network_events is invalid option for packets" - exit 1 - fi - ;; - --enable_filter) # Enable flow filter - if [[ "$3" == "flows" ]]; then - if [[ "$value" == "true" || "$value" == "false" ]]; then - edit_manifest "filter_enable" "$value" "$2" - else - echo "invalid value for --enable_filter" - fi - else - echo "--enable_filter is invalid option for packets" - exit 1 - fi - ;; - --direction) # Configure filter direction - if [[ "$value" == "Ingress" || "$value" == "Egress" ]]; then - edit_manifest "filter_direction" "$value" "$2" - else - echo "invalid value for --direction" - fi - ;; - --cidr) # Configure flow CIDR - edit_manifest "filter_cidr" "$value" "$2" - ;; - --protocol) # Configure filter protocol - if [[ "$value" == "TCP" || "$value" == "UDP" || "$value" == "SCTP" || "$value" == "ICMP" || "$value" == "ICMPv6" ]]; then - edit_manifest "filter_protocol" "$value" "$2" - else - echo "invalid value for --protocol" - fi - ;; - --sport) # Configure filter source port - edit_manifest "filter_sport" "$value" "$2" - ;; - --dport) # Configure filter destination port - edit_manifest "filter_dport" "$value" "$2" - ;; - --port) # Configure filter port - edit_manifest "filter_port" "$value" "$2" - ;; - --sport_range) # Configure filter source port range - edit_manifest "filter_sport_range" "$value" "$2" - ;; - --dport_range) # Configure filter destination port range - edit_manifest "filter_dport_range" "$value" "$2" - ;; - --port_range) # Configure filter port range - edit_manifest "filter_port_range" "$value" "$2" - ;; - --sports) # Configure filter source two ports using "," - edit_manifest "filter_sports" "$value" "$2" - ;; - --dports) # Configure filter destination two ports using "," - edit_manifest "filter_dports" "$value" "$2" - ;; - --ports) # Configure filter on two ports usig "," can either be srcport or dstport - edit_manifest "filter_ports" "$value" "$2" - ;; - --tcp_flags) # Configure filter TCP flags - if [[ "$value" == "SYN" || "$value" == "SYN-ACK" || "$value" == "ACK" || "$value" == "FIN" || "$value" == "RST" || "$value" == "FIN-ACK" || "$value" == "RST-ACK" || "$value" == "PSH" || "$value" == "URG" || "$value" == "ECE" || "$value" == "CWR" ]]; then - edit_manifest "filter_tcp_flags" "$value" "$2" - else - echo "invalid value for --tcp_flags" - fi - ;; - --drops) # Filter packet drops - if [[ "$value" == "true" || "$value" == "false" ]]; then - edit_manifest "filter_pkt_drops" "$value" "$2" - else - echo "invalid value for --drops" - fi - ;; - --icmp_type) # ICMP type - edit_manifest "filter_icmp_type" "$value" "$2" - ;; - --icmp_code) # ICMP code - edit_manifest "filter_icmp_code" "$value" "$2" - ;; - --peer_ip) # Peer IP - edit_manifest "filter_peer_ip" "$value" "$2" - ;; - --action) # Filter action - if [[ "$value" == "Accept" || "$value" == "Reject" ]]; then - edit_manifest "filter_action" "$value" "$2" - else - echo "invalid value for --action" - fi - ;; - --log-level) # Log level - if [[ "$value" == "trace" || "$value" == "debug" || "$value" == "info" || "$value" == "warn" || "$value" == "error" || "$value" == "fatal" || "$value" == "panic" ]]; then - edit_manifest "log_level" "$value" "$2" - logLevel=$value - filter=${filter/$key=$logLevel/} - else - echo "invalid value for --action" - fi - ;; - --max-time) # Max time - echo "param: $key, param_value: $value" - maxTime=$value - filter=${filter/$key=$maxTime/} - ;; - --max-bytes) # Max bytes - echo "param: $key, param_value: $value" - maxBytes=$value - filter=${filter/$key=$maxBytes/} - ;; - *) # Invalid option - echo "Invalid option: $key" >&2 - exit 1 - ;; - esac - done + # Iterate through the command-line arguments + for option in $1; do + key="${option%%=*}" + value="${option#*=}" + case "$key" in + --background) # Run command in background + if [[ "$value" == "true" || "$value" == "false" ]]; then + echo "param: $key, param_value: $value" + runBackground="$value" + else + echo "invalid value for --background" + fi + ;; + --copy) # Copy or skip without prompt + if [[ "$value" == "true" || "$value" == "false" || "$value" == "prompt" ]]; then + echo "param: $key, param_value: $value" + copy="$value" + else + echo "invalid value for --copy" + fi + ;; + --interfaces) # Interfaces + edit_manifest "interfaces" "$value" "$2" + ;; + --enable_pktdrop) # Enable packet drop + if [[ "$3" == "flows" ]]; then + if [[ "$value" == "true" || "$value" == "false" ]]; then + edit_manifest "pktdrop_enable" "$value" "$2" + else + echo "invalid value for --enable_pktdrop" + fi + else + echo "--enable_pktdrop is invalid option for packets" + exit 1 + fi + ;; + --enable_dns) # Enable DNS + if [[ "$3" == "flows" ]]; then + if [[ "$value" == "true" || "$value" == "false" ]]; then + edit_manifest "dns_enable" "$value" "$2" + else + echo "invalid value for --enable_dns" + fi + else + echo "--enable_dns is invalid option for packets" + exit 1 + fi + ;; + --enable_rtt) # Enable RTT + if [[ "$3" == "flows" ]]; then + if [[ "$value" == "true" || "$value" == "false" ]]; then + edit_manifest "rtt_enable" "$value" "$2" + else + echo "invalid value for --enable_rtt" + fi + else + echo "--enable_rtt is invalid option for packets" + exit 1 + fi + ;; + --enable_network_events) # Enable Network events monitoring + if [[ "$3" == "flows" ]]; then + if [[ "$value" == "true" || "$value" == "false" ]]; then + edit_manifest "network_events_enable" "$value" "$2" + else + echo "invalid value for --enable_network_events" + fi + else + echo "--enable_network_events is invalid option for packets" + exit 1 + fi + ;; + --enable_filter) # Enable flow filter + if [[ "$3" == "flows" ]]; then + if [[ "$value" == "true" || "$value" == "false" ]]; then + edit_manifest "filter_enable" "$value" "$2" + else + echo "invalid value for --enable_filter" + fi + else + echo "--enable_filter is invalid option for packets" + exit 1 + fi + ;; + --direction) # Configure filter direction + if [[ "$value" == "Ingress" || "$value" == "Egress" ]]; then + edit_manifest "filter_direction" "$value" "$2" + else + echo "invalid value for --direction" + fi + ;; + --cidr) # Configure flow CIDR + edit_manifest "filter_cidr" "$value" "$2" + ;; + --protocol) # Configure filter protocol + if [[ "$value" == "TCP" || "$value" == "UDP" || "$value" == "SCTP" || "$value" == "ICMP" || "$value" == "ICMPv6" ]]; then + edit_manifest "filter_protocol" "$value" "$2" + else + echo "invalid value for --protocol" + fi + ;; + --sport) # Configure filter source port + edit_manifest "filter_sport" "$value" "$2" + ;; + --dport) # Configure filter destination port + edit_manifest "filter_dport" "$value" "$2" + ;; + --port) # Configure filter port + edit_manifest "filter_port" "$value" "$2" + ;; + --sport_range) # Configure filter source port range + edit_manifest "filter_sport_range" "$value" "$2" + ;; + --dport_range) # Configure filter destination port range + edit_manifest "filter_dport_range" "$value" "$2" + ;; + --port_range) # Configure filter port range + edit_manifest "filter_port_range" "$value" "$2" + ;; + --sports) # Configure filter source two ports using "," + edit_manifest "filter_sports" "$value" "$2" + ;; + --dports) # Configure filter destination two ports using "," + edit_manifest "filter_dports" "$value" "$2" + ;; + --ports) # Configure filter on two ports usig "," can either be srcport or dstport + edit_manifest "filter_ports" "$value" "$2" + ;; + --tcp_flags) # Configure filter TCP flags + if [[ "$value" == "SYN" || "$value" == "SYN-ACK" || "$value" == "ACK" || "$value" == "FIN" || "$value" == "RST" || "$value" == "FIN-ACK" || "$value" == "RST-ACK" || "$value" == "PSH" || "$value" == "URG" || "$value" == "ECE" || "$value" == "CWR" ]]; then + edit_manifest "filter_tcp_flags" "$value" "$2" + else + echo "invalid value for --tcp_flags" + fi + ;; + --drops) # Filter packet drops + if [[ "$value" == "true" || "$value" == "false" ]]; then + edit_manifest "filter_pkt_drops" "$value" "$2" + else + echo "invalid value for --drops" + fi + ;; + --icmp_type) # ICMP type + edit_manifest "filter_icmp_type" "$value" "$2" + ;; + --icmp_code) # ICMP code + edit_manifest "filter_icmp_code" "$value" "$2" + ;; + --peer_ip) # Peer IP + edit_manifest "filter_peer_ip" "$value" "$2" + ;; + --action) # Filter action + if [[ "$value" == "Accept" || "$value" == "Reject" ]]; then + edit_manifest "filter_action" "$value" "$2" + else + echo "invalid value for --action" + fi + ;; + --log-level) # Log level + if [[ "$value" == "trace" || "$value" == "debug" || "$value" == "info" || "$value" == "warn" || "$value" == "error" || "$value" == "fatal" || "$value" == "panic" ]]; then + edit_manifest "log_level" "$value" "$2" + logLevel=$value + filter=${filter/$key=$logLevel/} + else + echo "invalid value for --action" + fi + ;; + --max-time) # Max time + echo "param: $key, param_value: $value" + maxTime=$value + filter=${filter/$key=$maxTime/} + ;; + --max-bytes) # Max bytes + echo "param: $key, param_value: $value" + maxBytes=$value + filter=${filter/$key=$maxBytes/} + ;; + *) # Invalid option + echo "Invalid option: $key" >&2 + exit 1 + ;; + esac + done - ${K8S_CLI_BIN} apply -f "$2" - ${K8S_CLI_BIN} rollout status daemonset netobserv-cli -n netobserv-cli --timeout 60s - rm -rf ${MANIFEST_OUTPUT_PATH} -} \ No newline at end of file + ${K8S_CLI_BIN} apply -f "$2" + ${K8S_CLI_BIN} rollout status daemonset netobserv-cli -n "$namespace" --timeout 60s + rm -rf ${MANIFEST_OUTPUT_PATH} +}