Compare commits

..

No commits in common. "master" and "v0.18.2" have entirely different histories.

71 changed files with 1024 additions and 1521 deletions

View File

@ -66,5 +66,5 @@ For example, `action required: change the API interface of the rule engine`.
--> -->
```release-note ```release-note
NONE
``` ```

View File

@ -1,12 +0,0 @@
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
open-pull-requests-limit: 10
groups:
actions:
update-types:
- "minor"
- "patch"

View File

@ -19,44 +19,19 @@ jobs:
with: with:
arch: ${{ matrix.arch }} arch: ${{ matrix.arch }}
paths-filter:
runs-on: ubuntu-latest
outputs:
docker_needs_build: ${{ steps.filter.outputs.docker }}
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
id: filter
with:
filters: |
docker:
- 'docker/**'
build-images-dev:
needs: [build-test-dev,paths-filter]
if: needs.paths-filter.outputs.docker_needs_build == 'true'
strategy:
matrix:
arch: [ amd64, arm64 ]
uses: ./.github/workflows/reusable_build_push_images.yml
with:
arch: ${{ matrix.arch }}
push: false
secrets: inherit
gomodtidy: gomodtidy:
name: Enforce go.mod tidiness name: Enforce go.mod tidiness
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 # v3.5.0
with: with:
ref: "${{ github.event.pull_request.head.sha }}" ref: "${{ github.event.pull_request.head.sha }}"
repository: ${{github.event.pull_request.head.repo.full_name}} repository: ${{github.event.pull_request.head.repo.full_name}}
persist-credentials: false persist-credentials: false
- name: Setup Go - name: Setup Go
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5 uses: actions/setup-go@v4
with: with:
go-version-file: 'go.mod' go-version-file: 'go.mod'

View File

@ -18,19 +18,18 @@ jobs:
arch: ${{ matrix.arch }} arch: ${{ matrix.arch }}
push-images-master: push-images-master:
needs: build-test-master
strategy: strategy:
matrix: matrix:
arch: [amd64, arm64] arch: [amd64, arm64]
uses: ./.github/workflows/reusable_build_push_images.yml uses: ./.github/workflows/reusable_build_push_images.yml
needs: build-test-master
with: with:
arch: ${{ matrix.arch }} arch: ${{ matrix.arch }}
push: true
secrets: inherit secrets: inherit
images-master: images-master:
needs: push-images-master
uses: ./.github/workflows/reusable_manifest_images.yml uses: ./.github/workflows/reusable_manifest_images.yml
needs: push-images-master
secrets: inherit secrets: inherit

View File

@ -19,21 +19,20 @@ jobs:
arch: ${{ matrix.arch }} arch: ${{ matrix.arch }}
push-images-release: push-images-release:
needs: build-test-release
strategy: strategy:
matrix: matrix:
arch: [amd64, arm64] arch: [amd64, arm64]
uses: ./.github/workflows/reusable_build_push_images.yml uses: ./.github/workflows/reusable_build_push_images.yml
needs: build-test-release
with: with:
arch: ${{ matrix.arch }} arch: ${{ matrix.arch }}
tag: ${{ github.ref_name }} tag: ${{ github.ref_name }}
is_latest: true is_latest: true
push: true
secrets: inherit secrets: inherit
images-release: images-release:
needs: push-images-release
uses: ./.github/workflows/reusable_manifest_images.yml uses: ./.github/workflows/reusable_manifest_images.yml
needs: push-images-release
with: with:
tag: ${{ github.ref_name }} tag: ${{ github.ref_name }}
is_latest: true is_latest: true
@ -44,7 +43,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 uses: actions/checkout@v4
with: with:
fetch-depth: 0 fetch-depth: 0
@ -52,12 +51,12 @@ jobs:
run: git fetch --prune --force --tags run: git fetch --prune --force --tags
- name: Setup Go - name: Setup Go
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5 uses: actions/setup-go@v4
with: with:
go-version-file: 'go.mod' go-version-file: 'go.mod'
- name: Install GoReleaser - name: Install GoReleaser
uses: goreleaser/goreleaser-action@9c156ee8a17a598857849441385a2041ef570552 # v6.3.0 uses: goreleaser/goreleaser-action@v5
with: with:
install-only: true install-only: true

View File

@ -21,27 +21,22 @@ on:
required: false required: false
type: boolean type: boolean
default: false default: false
push:
description: Whether to also push images
required: false
type: boolean
default: false
jobs: jobs:
build-images: build-images:
runs-on: ${{ (inputs.arch == 'arm64' && 'ubuntu-22.04-arm') || 'ubuntu-22.04' }} runs-on: ${{ (inputs.arch == 'arm64' && 'actuated-arm64-8cpu-16gb') || 'ubuntu-latest' }}
env: env:
GIT_BRANCH: ${{ inputs.branch }} GIT_BRANCH: ${{ inputs.branch }}
GIT_TAG: ${{ inputs.tag }} GIT_TAG: ${{ inputs.tag }}
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
- name: Create download folder - name: Create download folder
run: mkdir -p build-${{ inputs.arch }} run: mkdir -p build-${{ inputs.arch }}
- name: Download Driverkit - name: Download Driverkit
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2
with: with:
name: driverkit-${{ inputs.arch }} name: driverkit-${{ inputs.arch }}
path: build-${{ inputs.arch }} path: build-${{ inputs.arch }}
@ -50,23 +45,17 @@ jobs:
run: chmod +x build-${{ inputs.arch }}/driverkit run: chmod +x build-${{ inputs.arch }}/driverkit
- name: Set up Docker Buildx - name: Set up Docker Buildx
uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1 uses: docker/setup-buildx-action@f95db51fddba0c2d1ec667646a06c2ce06100226 # v3.0.0
- name: Login to Docker Hub - name: Login to Docker Hub
if: inputs.push uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0
uses: docker/login-action@184bdaa0721073962dff0199f1fb9940f07167d1 # v3.5.0
with: with:
username: ${{ secrets.DOCKERHUB_USER }} username: ${{ secrets.DOCKERHUB_USER }}
password: ${{ secrets.DOCKERHUB_SECRET }} password: ${{ secrets.DOCKERHUB_SECRET }}
- name: Build and Push docker images - name: Build and Push docker images
if: inputs.push
run: make push/all run: make push/all
- name: Build docker images
if: inputs.push == false
run: make image/all
- name: Push latest images if needed - name: Push latest images if needed
if: inputs.push && inputs.is_latest if: inputs.is_latest
run: make push/latest run: make push/latest

View File

@ -10,15 +10,15 @@ on:
jobs: jobs:
build-test: build-test:
# See https://github.com/actions/runner/issues/409#issuecomment-1158849936 # See https://github.com/actions/runner/issues/409#issuecomment-1158849936
runs-on: ${{ (inputs.arch == 'arm64' && 'ubuntu-22.04-arm') || 'ubuntu-22.04' }} runs-on: ${{ (inputs.arch == 'arm64' && 'actuated-arm64-8cpu-16gb') || 'ubuntu-latest' }}
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 uses: actions/checkout@v4
with: with:
fetch-depth: 0 fetch-depth: 0
- name: Setup Go - name: Setup Go
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5 uses: actions/setup-go@v4
with: with:
go-version-file: 'go.mod' go-version-file: 'go.mod'
@ -40,7 +40,7 @@ jobs:
run: make integration_test run: make integration_test
- name: Upload driverkit - name: Upload driverkit
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
with: with:
name: driverkit-${{ inputs.arch }} name: driverkit-${{ inputs.arch }}
path: | path: |

View File

@ -26,13 +26,13 @@ jobs:
GIT_TAG: ${{ inputs.tag }} GIT_TAG: ${{ inputs.tag }}
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
- name: Set up Docker Buildx - name: Set up Docker Buildx
uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1 uses: docker/setup-buildx-action@f95db51fddba0c2d1ec667646a06c2ce06100226 # v3.0.0
- name: Login to Docker Hub - name: Login to Docker Hub
uses: docker/login-action@184bdaa0721073962dff0199f1fb9940f07167d1 # v3.5.0 uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0
with: with:
username: ${{ secrets.DOCKERHUB_USER }} username: ${{ secrets.DOCKERHUB_USER }}
password: ${{ secrets.DOCKERHUB_SECRET }} password: ${{ secrets.DOCKERHUB_SECRET }}

View File

@ -1,5 +1,3 @@
version: 2
project_name: driverkit project_name: driverkit
builds: builds:
- id: "driverkit" - id: "driverkit"

2
OWNERS
View File

@ -4,7 +4,5 @@ approvers:
- fededp - fededp
- EXONER4TED - EXONER4TED
- lowaiz - lowaiz
- LucaGuerra
emeritus_approvers: emeritus_approvers:
- fntlnz - fntlnz

View File

@ -1,6 +1,6 @@
# Release Process # Release Process
Our release process is fully automated using [Github actions](.github/workflows/release.yml) and [goreleaser](https://github.com/goreleaser/goreleaser) tool for artifacts. Our release process is based upon [CircleCI](https://app.circleci.com/pipelines/github/falcosecurity/driverkit) and [goreleaser](https://github.com/goreleaser/goreleaser) tool for artifacts.
When we release we do the following process: When we release we do the following process:

View File

@ -19,6 +19,8 @@ package cmd
import ( import (
"bytes" "bytes"
"io"
"io/ioutil"
"os" "os"
"path/filepath" "path/filepath"
"runtime" "runtime"
@ -130,8 +132,6 @@ var tests = []testCase{
"ubuntu-aws", "ubuntu-aws",
"--output-module", "--output-module",
"/tmp/falco-ubuntu-aws.ko", "/tmp/falco-ubuntu-aws.ko",
"--output-probe",
"/tmp/falco-ubuntu-aws.o",
"--loglevel", "--loglevel",
"debug", "debug",
}, },
@ -144,7 +144,6 @@ var tests = []testCase{
env: map[string]string{ env: map[string]string{
"DRIVERKIT_KERNELVERSION": "59", "DRIVERKIT_KERNELVERSION": "59",
"DRIVERKIT_OUTPUT_MODULE": "/tmp/falco-ubuntu-aws.ko", "DRIVERKIT_OUTPUT_MODULE": "/tmp/falco-ubuntu-aws.ko",
"DRIVERKIT_OUTPUT_PROBE": "/tmp/falco-ubuntu-aws.o",
}, },
args: []string{ args: []string{
"docker", "docker",
@ -316,14 +315,9 @@ var tests = []testCase{
func run(t *testing.T, test testCase) { func run(t *testing.T, test testCase) {
// Setup // Setup
configOpts, err := NewConfigOptions() c := NewRootCmd()
assert.NilError(t, err) b := bytes.NewBufferString("")
rootOpts, err := NewRootOptions() c.SetOutput(b)
assert.NilError(t, err)
var buf bytes.Buffer
configOpts.setOutput(&buf, true)
c := NewRootCmd(configOpts, rootOpts)
c.SetOutput(&buf)
if len(test.args) == 0 || (test.args[0] != "__complete" && test.args[0] != "__completeNoDesc" && test.args[0] != "help" && test.args[0] != "completion") { if len(test.args) == 0 || (test.args[0] != "__complete" && test.args[0] != "__completeNoDesc" && test.args[0] != "help" && test.args[0] != "completion") {
test.args = append(test.args, "--dryrun") test.args = append(test.args, "--dryrun")
} }
@ -334,18 +328,19 @@ func run(t *testing.T, test testCase) {
} }
} }
// Test // Test
err = c.Execute() err := c.Execute()
if err != nil { if err != nil {
if test.expect.err == "" { if test.expect.err == "" {
t.Fatalf("error executing CLI: %v", err) t.Fatalf("error executing CLI: %v", err)
} else { } else {
assert.Error(t, err, test.expect.err) assert.Error(t, err, test.expect.err)
} }
// Exactly same behavior as rootCmd.Start(), but here we use ERROR instead of FATAL to avoid leaving
configOpts.Printer.Logger.Error("error executing driverkit", configOpts.Printer.Logger.Args("err", err.Error()))
} }
out := buf.String() out, err := io.ReadAll(b)
res := stripansi.Strip(out) if err != nil {
t.Fatalf("error reading CLI output: %v", err)
}
res := stripansi.Strip(string(out))
assert.Equal(t, test.expect.out, res) assert.Equal(t, test.expect.out, res)
// Teardown // Teardown
for k := range test.env { for k := range test.env {
@ -370,7 +365,7 @@ type testTemplateData struct {
} }
func readTemplateFile(t *testing.T, s string) string { func readTemplateFile(t *testing.T, s string) string {
out, err := os.ReadFile("testdata/templates/" + s) out, err := ioutil.ReadFile("testdata/templates/" + s)
assert.NilError(t, err) assert.NilError(t, err)
return string(out) return string(out)
} }

View File

@ -17,7 +17,6 @@ package cmd
import ( import (
"bytes" "bytes"
"fmt" "fmt"
"github.com/spf13/pflag"
"os" "os"
"strings" "strings"
"text/template" "text/template"
@ -47,12 +46,12 @@ func validateArgs() cobra.PositionalArgs {
if len(args) == 0 { if len(args) == 0 {
return nil return nil
} }
return cobra.MatchAll(cobra.ExactArgs(1), cobra.OnlyValidArgs)(c, args) return cobra.ExactValidArgs(1)(c, args)
} }
} }
// NewCompletionCmd ... // NewCompletionCmd ...
func NewCompletionCmd(_ *ConfigOptions, _ *RootOptions, _ *pflag.FlagSet) *cobra.Command { func NewCompletionCmd() *cobra.Command {
var long bytes.Buffer var long bytes.Buffer
tmpl := template.Must(template.New("long").Parse(longUsageTemplate)) tmpl := template.Must(template.New("long").Parse(longUsageTemplate))
tmpl.Execute(&long, map[string]interface{}{ tmpl.Execute(&long, map[string]interface{}{
@ -66,23 +65,25 @@ func NewCompletionCmd(_ *ConfigOptions, _ *RootOptions, _ *pflag.FlagSet) *cobra
Args: validateArgs(), Args: validateArgs(),
ValidArgs: cmdArgs, ValidArgs: cmdArgs,
DisableAutoGenTag: true, DisableAutoGenTag: true,
RunE: func(c *cobra.Command, args []string) error { Run: func(c *cobra.Command, args []string) {
if len(args) == 0 { if len(args) == 0 {
return c.Help() c.Help()
return
} }
arg := args[0] arg := args[0]
switch arg { switch arg {
case "bash": case "bash":
return c.Root().GenBashCompletion(os.Stdout) c.Root().GenBashCompletion(os.Stdout)
break
case "zsh": case "zsh":
return c.Root().GenZshCompletion(os.Stdout) c.Root().GenZshCompletion(os.Stdout)
break
case "fish": case "fish":
return c.Root().GenFishCompletion(os.Stdout, true) c.Root().GenFishCompletion(os.Stdout, true)
case "help": case "help":
return c.Help() c.Help()
} }
return nil
}, },
} }

View File

@ -15,141 +15,51 @@ limitations under the License.
package cmd package cmd
import ( import (
"errors" "fmt"
"github.com/falcosecurity/falcoctl/pkg/output" "log/slog"
"github.com/mitchellh/go-homedir"
"github.com/spf13/pflag"
"github.com/spf13/viper"
"io"
"os" "os"
"strings"
"github.com/creasty/defaults" "github.com/creasty/defaults"
"github.com/falcosecurity/driverkit/validate" "github.com/falcosecurity/driverkit/validate"
"github.com/go-playground/validator/v10" "github.com/go-playground/validator/v10"
"github.com/pterm/pterm"
) )
var validProcessors = []string{"docker", "kubernetes", "kubernetes-in-cluster", "local"} var validProcessors = []string{"docker", "kubernetes", "kubernetes-in-cluster", "local"}
var aliasProcessors = []string{"docker", "k8s", "k8s-ic"} var aliasProcessors = []string{"docker", "k8s", "k8s-ic"}
var configOptions *ConfigOptions
// ConfigOptions represent the persistent configuration flags of driverkit. // ConfigOptions represent the persistent configuration flags of driverkit.
type ConfigOptions struct { type ConfigOptions struct {
configFile string ConfigFile string
LogLevel string `validate:"loglevel" name:"log level" default:"INFO"`
Timeout int `validate:"number,min=30" default:"120" name:"timeout"` Timeout int `validate:"number,min=30" default:"120" name:"timeout"`
ProxyURL string `validate:"omitempty,proxy" name:"proxy url"` ProxyURL string `validate:"omitempty,proxy" name:"proxy url"`
dryRun bool DryRun bool
// Printer used by all commands to output messages. configErrors bool
Printer *output.Printer
// writer is used to write the output of the printer.
writer io.Writer
logLevel *output.LogLevel
disableStyling bool
}
func (co *ConfigOptions) initPrinter() {
// DisableStyling is only enforced by tests.
if co.disableStyling {
pterm.DisableStyling()
}
co.Printer = output.NewPrinter(co.logLevel.ToPtermLogLevel(), pterm.LogFormatterColorful, co.writer)
if co.disableStyling {
// Disable time print for tests
co.Printer.Logger = co.Printer.Logger.WithTime(false)
}
}
// Called by tests to disable styling and set bytes buffer as output
func (co *ConfigOptions) setOutput(writer io.Writer, disableStyling bool) {
co.writer = writer
co.disableStyling = disableStyling
co.initPrinter()
} }
// NewConfigOptions creates an instance of ConfigOptions. // NewConfigOptions creates an instance of ConfigOptions.
func NewConfigOptions() (*ConfigOptions, error) { func NewConfigOptions() *ConfigOptions {
o := &ConfigOptions{ o := &ConfigOptions{}
writer: os.Stdout,
logLevel: output.NewLogLevel(),
disableStyling: false,
}
o.initPrinter()
if err := defaults.Set(o); err != nil { if err := defaults.Set(o); err != nil {
// Return ConfigOptions anyway because we need the logger slog.With("err", err.Error(), "options", "ConfigOptions").Error("error setting driverkit options defaults")
return o, err os.Exit(1)
} }
return o, nil return o
} }
// Validate validates the ConfigOptions fields. // Validate validates the ConfigOptions fields.
func (co *ConfigOptions) validate() []error { func (co *ConfigOptions) Validate() []error {
if err := validate.V.Struct(co); err != nil { if err := validate.V.Struct(co); err != nil {
var errs validator.ValidationErrors errors := err.(validator.ValidationErrors)
errors.As(err, &errs) errArr := []error{}
var errArr []error for _, e := range errors {
for _, e := range errs {
// Translate each error one at a time // Translate each error one at a time
errArr = append(errArr, errors.New(e.Translate(validate.T))) errArr = append(errArr, fmt.Errorf(e.Translate(validate.T)))
} }
co.configErrors = true
return errArr return errArr
} }
return nil return nil
} }
// AddFlags registers the common flags.
func (co *ConfigOptions) AddFlags(flags *pflag.FlagSet) {
flags.StringVarP(&co.configFile, "config", "c", co.configFile, "config file path (default $HOME/.driverkit.yaml if exists)")
flags.VarP(co.logLevel, "loglevel", "l", "set level for logs "+co.logLevel.Allowed())
flags.IntVar(&co.Timeout, "timeout", co.Timeout, "timeout in seconds")
flags.StringVar(&co.ProxyURL, "proxy", co.ProxyURL, "the proxy to use to download data")
flags.BoolVar(&co.dryRun, "dryrun", co.dryRun, "do not actually perform the action")
}
// Init reads in config file and ENV variables if set.
func (co *ConfigOptions) Init() bool {
configErr := false
if errs := co.validate(); errs != nil {
for _, err := range errs {
co.Printer.Logger.Error("error validating config options",
co.Printer.Logger.Args("err", err.Error()))
}
configErr = true
}
if co.configFile != "" {
viper.SetConfigFile(co.configFile)
} else {
// Find home directory.
home, err := homedir.Dir()
if err != nil {
co.Printer.Logger.Error("error getting the home directory",
co.Printer.Logger.Args("err", err.Error()))
// not setting configErr = true because we fallback to `$HOME/.driverkit.yaml` and try with it
}
viper.AddConfigPath(home)
viper.SetConfigName(".driverkit")
}
viper.AutomaticEnv()
viper.SetEnvPrefix("driverkit")
viper.SetEnvKeyReplacer(strings.NewReplacer("-", "_"))
// If a config file is found, read it in.
err := viper.ReadInConfig()
// Init printer with either read or existent one,
// so that we can further log considering log level set.
co.initPrinter()
if err == nil {
co.Printer.Logger.Info("using config file",
co.Printer.Logger.Args("file", viper.ConfigFileUsed()))
} else {
var configFileNotFoundError viper.ConfigFileNotFoundError
if errors.As(err, &configFileNotFoundError) {
// Config file not found, ignore ...
co.Printer.Logger.Debug("running without a configuration file")
}
}
return configErr
}

View File

@ -15,42 +15,32 @@ limitations under the License.
package cmd package cmd
import ( import (
"bytes" "log/slog"
"os"
"github.com/falcosecurity/driverkit/pkg/driverbuilder" "github.com/falcosecurity/driverkit/pkg/driverbuilder"
"github.com/falcosecurity/driverkit/pkg/driverbuilder/builder"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/pflag" "github.com/spf13/pflag"
"github.com/spf13/viper"
) )
// NewDockerCmd creates the `driverkit docker` command. // NewDockerCmd creates the `driverkit docker` command.
func NewDockerCmd(configOpts *ConfigOptions, rootOpts *RootOptions, rootFlags *pflag.FlagSet) *cobra.Command { func NewDockerCmd(rootOpts *RootOptions, rootFlags *pflag.FlagSet) *cobra.Command {
dockerCmd := &cobra.Command{ dockerCmd := &cobra.Command{
Use: "docker", Use: "docker",
Short: "Build Falco kernel modules and eBPF probes against a docker daemon.", Short: "Build Falco kernel modules and eBPF probes against a docker daemon.",
RunE: func(c *cobra.Command, args []string) error { Run: func(c *cobra.Command, args []string) {
configOpts.Printer.Logger.Info("starting build", slog.With("processor", c.Name()).Info("driver building, it will take a few seconds")
configOpts.Printer.Logger.Args("processor", c.Name())) if !configOptions.DryRun {
if !configOpts.dryRun { b := rootOpts.ToBuild()
if !rootOpts.Output.HasOutputs() { if !b.HasOutputs() {
configOpts.Printer.Logger.Info("no output specified") return
return nil
} }
// Since we use a spinner, cache log data to a bytesbuffer; if err := driverbuilder.NewDockerBuildProcessor(viper.GetInt("timeout"), viper.GetString("proxy")).Start(b); err != nil {
// we will later print it once we stop the spinner. slog.With("err", err.Error()).Error("exiting")
var b *builder.Build os.Exit(1)
if configOpts.disableStyling {
b = rootOpts.ToBuild(configOpts.Printer)
} else {
var buf bytes.Buffer
b = rootOpts.ToBuild(configOpts.Printer.WithWriter(&buf))
configOpts.Printer.Spinner, _ = configOpts.Printer.Spinner.Start("driver building, it will take a few seconds")
defer func() {
configOpts.Printer.DefaultText.Print(buf.String())
}()
} }
return driverbuilder.NewDockerBuildProcessor(configOpts.Timeout, configOpts.ProxyURL).Start(b)
} }
return nil
}, },
} }
// Add root flags // Add root flags

View File

@ -15,8 +15,7 @@ limitations under the License.
package cmd package cmd
import ( import (
"bytes" "log/slog"
"github.com/falcosecurity/driverkit/pkg/driverbuilder/builder"
"os" "os"
"github.com/olekukonko/tablewriter" "github.com/olekukonko/tablewriter"
@ -25,30 +24,14 @@ import (
) )
// NewImagesCmd creates the `driverkit images` command. // NewImagesCmd creates the `driverkit images` command.
func NewImagesCmd(configOpts *ConfigOptions, rootOpts *RootOptions, rootFlags *pflag.FlagSet) *cobra.Command { func NewImagesCmd(rootOpts *RootOptions, rootFlags *pflag.FlagSet) *cobra.Command {
imagesCmd := &cobra.Command{ imagesCmd := &cobra.Command{
Use: "images", Use: "images",
Short: "List builder images", Short: "List builder images",
RunE: func(c *cobra.Command, args []string) error { Run: func(c *cobra.Command, args []string) {
configOpts.Printer.Logger.Info("starting loading images", slog.With("processor", c.Name()).Info("listing images")
configOpts.Printer.Logger.Args("processor", c.Name())) b := rootOpts.ToBuild()
// Since we use a spinner, cache log data to a bytesbuffer;
// we will later print it once we stop the spinner.
var (
buf bytes.Buffer
b *builder.Build
)
if configOpts.disableStyling {
b = rootOpts.ToBuild(configOpts.Printer)
} else {
b = rootOpts.ToBuild(configOpts.Printer.WithWriter(&buf))
configOpts.Printer.Spinner, _ = configOpts.Printer.Spinner.Start("listing images, it will take a few seconds")
}
b.LoadImages() b.LoadImages()
if !configOpts.disableStyling {
_ = configOpts.Printer.Spinner.Stop()
configOpts.Printer.DefaultText.Print(buf.String())
}
table := tablewriter.NewWriter(os.Stdout) table := tablewriter.NewWriter(os.Stdout)
table.SetHeader([]string{"Image", "Target", "Arch", "GCC"}) table.SetHeader([]string{"Image", "Target", "Arch", "GCC"})
@ -64,7 +47,6 @@ func NewImagesCmd(configOpts *ConfigOptions, rootOpts *RootOptions, rootFlags *p
table.Append(data) table.Append(data)
} }
table.Render() // Send output table.Render() // Send output
return nil
}, },
} }
// Add root flags // Add root flags

View File

@ -15,8 +15,8 @@ limitations under the License.
package cmd package cmd
import ( import (
"bytes" "log/slog"
"github.com/falcosecurity/driverkit/pkg/driverbuilder/builder" "os"
"regexp" "regexp"
"strings" "strings"
@ -24,11 +24,12 @@ import (
"github.com/falcosecurity/driverkit/pkg/kubernetes/factory" "github.com/falcosecurity/driverkit/pkg/kubernetes/factory"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/pflag" "github.com/spf13/pflag"
"github.com/spf13/viper"
"k8s.io/cli-runtime/pkg/genericclioptions" "k8s.io/cli-runtime/pkg/genericclioptions"
) )
// NewKubernetesCmd creates the `driverkit kubernetes` command. // NewKubernetesCmd creates the `driverkit kubernetes` command.
func NewKubernetesCmd(configOpts *ConfigOptions, rootOpts *RootOptions, rootFlags *pflag.FlagSet) *cobra.Command { func NewKubernetesCmd(rootOpts *RootOptions, rootFlags *pflag.FlagSet) *cobra.Command {
kubernetesCmd := &cobra.Command{ kubernetesCmd := &cobra.Command{
Use: "kubernetes", Use: "kubernetes",
Short: "Build Falco kernel modules and eBPF probes against a Kubernetes cluster.", Short: "Build Falco kernel modules and eBPF probes against a Kubernetes cluster.",
@ -57,39 +58,34 @@ func NewKubernetesCmd(configOpts *ConfigOptions, rootOpts *RootOptions, rootFlag
kubefactory := factory.NewFactory(configFlags) kubefactory := factory.NewFactory(configFlags)
kubernetesCmd.RunE = func(c *cobra.Command, args []string) error { kubernetesCmd.Run = func(cmd *cobra.Command, args []string) {
configOpts.Printer.Logger.Info("starting build", slog.With("processor", cmd.Name()).Info("driver building, it will take a few seconds")
configOpts.Printer.Logger.Args("processor", c.Name())) if !configOptions.DryRun {
if !configOpts.dryRun { if err := kubernetesRun(cmd, args, kubefactory, rootOpts); err != nil {
if !rootOpts.Output.HasOutputs() { slog.With("err", err.Error()).Error("exiting")
configOpts.Printer.Logger.Info("no output specified") os.Exit(1)
return nil
} }
// Since we use a spinner, cache log data to a bytesbuffer;
// we will later print it once we stop the spinner.
var b *builder.Build
if configOpts.disableStyling {
b = rootOpts.ToBuild(configOpts.Printer)
} else {
var buf bytes.Buffer
b = rootOpts.ToBuild(configOpts.Printer.WithWriter(&buf))
configOpts.Printer.Spinner, _ = configOpts.Printer.Spinner.Start("driver building, it will take a few seconds")
defer func() {
configOpts.Printer.DefaultText.Print(buf.String())
}()
}
return kubernetesRun(kubefactory, b, configOpts)
} }
return nil
} }
return kubernetesCmd return kubernetesCmd
} }
func kubernetesRun(kubefactory factory.Factory, func kubernetesRun(cmd *cobra.Command, args []string, kubefactory factory.Factory, rootOpts *RootOptions) error {
b *builder.Build, f := cmd.Flags()
configOpts *ConfigOptions, b := rootOpts.ToBuild()
) error { if !b.HasOutputs() {
return nil
}
namespaceStr, err := f.GetString("namespace")
if err != nil {
return err
}
if len(namespaceStr) == 0 {
namespaceStr = "default"
}
kc, err := kubefactory.KubernetesClientSet() kc, err := kubefactory.KubernetesClientSet()
if err != nil { if err != nil {
return err return err
@ -102,12 +98,6 @@ func kubernetesRun(kubefactory factory.Factory,
return err return err
} }
buildProcessor := driverbuilder.NewKubernetesBuildProcessor(kc.CoreV1(), buildProcessor := driverbuilder.NewKubernetesBuildProcessor(kc.CoreV1(), clientConfig, kubernetesOptions.RunAsUser, kubernetesOptions.Namespace, kubernetesOptions.ImagePullSecret, viper.GetInt("timeout"), viper.GetString("proxy"))
clientConfig,
kubernetesOptions.RunAsUser,
kubernetesOptions.Namespace,
kubernetesOptions.ImagePullSecret,
configOpts.Timeout,
configOpts.ProxyURL)
return buildProcessor.Start(b) return buildProcessor.Start(b)
} }

View File

@ -15,18 +15,20 @@ limitations under the License.
package cmd package cmd
import ( import (
"bytes" "log/slog"
"os"
"github.com/falcosecurity/driverkit/pkg/driverbuilder" "github.com/falcosecurity/driverkit/pkg/driverbuilder"
"github.com/falcosecurity/driverkit/pkg/driverbuilder/builder"
"github.com/falcosecurity/driverkit/pkg/kubernetes/factory" "github.com/falcosecurity/driverkit/pkg/kubernetes/factory"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/pflag" "github.com/spf13/pflag"
"github.com/spf13/viper"
"k8s.io/client-go/kubernetes" "k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest" "k8s.io/client-go/rest"
) )
// NewKubernetesInClusterCmd creates the `driverkit kubernetes` command. // NewKubernetesInClusterCmd creates the `driverkit kubernetes` command.
func NewKubernetesInClusterCmd(configOpts *ConfigOptions, rootOpts *RootOptions, rootFlags *pflag.FlagSet) *cobra.Command { func NewKubernetesInClusterCmd(rootOpts *RootOptions, rootFlags *pflag.FlagSet) *cobra.Command {
kubernetesInClusterCmd := &cobra.Command{ kubernetesInClusterCmd := &cobra.Command{
Use: "kubernetes-in-cluster", Use: "kubernetes-in-cluster",
Short: "Build Falco kernel modules and eBPF probes against a Kubernetes cluster inside a Kubernetes cluster.", Short: "Build Falco kernel modules and eBPF probes against a Kubernetes cluster inside a Kubernetes cluster.",
@ -40,42 +42,32 @@ func NewKubernetesInClusterCmd(configOpts *ConfigOptions, rootOpts *RootOptions,
// Add root flags // Add root flags
kubernetesInClusterCmd.PersistentFlags().AddFlagSet(rootFlags) kubernetesInClusterCmd.PersistentFlags().AddFlagSet(rootFlags)
kubernetesInClusterCmd.RunE = func(c *cobra.Command, args []string) error { kubernetesInClusterCmd.Run = func(cmd *cobra.Command, args []string) {
configOpts.Printer.Logger.Info("starting build", slog.With("processor", cmd.Name()).Info("driver building, it will take a few seconds")
configOpts.Printer.Logger.Args("processor", c.Name())) if !configOptions.DryRun {
if !configOpts.dryRun { config, err := rest.InClusterConfig()
if !rootOpts.Output.HasOutputs() { if err != nil {
configOpts.Printer.Logger.Info("no output specified") slog.With("err", err.Error()).Error("exiting")
return nil os.Exit(1)
} }
// Since we use a spinner, cache log data to a bytesbuffer; if err = factory.SetKubernetesDefaults(config); err != nil {
// we will later print it once we stop the spinner. slog.With("err", err.Error()).Error("exiting")
var b *builder.Build os.Exit(1)
if configOpts.disableStyling { }
b = rootOpts.ToBuild(configOpts.Printer) if err = kubernetesInClusterRun(cmd, args, config, rootOpts); err != nil {
} else { slog.With("err", err.Error()).Error("exiting")
var buf bytes.Buffer os.Exit(1)
b = rootOpts.ToBuild(configOpts.Printer.WithWriter(&buf))
configOpts.Printer.Spinner, _ = configOpts.Printer.Spinner.Start("driver building, it will take a few seconds")
defer func() {
configOpts.Printer.DefaultText.Print(buf.String())
}()
} }
return kubernetesInClusterRun(b, configOpts)
} }
return nil
} }
return kubernetesInClusterCmd return kubernetesInClusterCmd
} }
func kubernetesInClusterRun(b *builder.Build, configOpts *ConfigOptions) error { func kubernetesInClusterRun(_ *cobra.Command, _ []string, kubeConfig *rest.Config, rootOpts *RootOptions) error {
kubeConfig, err := rest.InClusterConfig() b := rootOpts.ToBuild()
if err != nil { if !b.HasOutputs() {
return err return nil
}
if err = factory.SetKubernetesDefaults(kubeConfig); err != nil {
return err
} }
kc, err := kubernetes.NewForConfig(kubeConfig) kc, err := kubernetes.NewForConfig(kubeConfig)
@ -83,12 +75,7 @@ func kubernetesInClusterRun(b *builder.Build, configOpts *ConfigOptions) error {
return err return err
} }
buildProcessor := driverbuilder.NewKubernetesBuildProcessor(kc.CoreV1(), buildProcessor := driverbuilder.NewKubernetesBuildProcessor(kc.CoreV1(), kubeConfig, kubernetesOptions.RunAsUser, kubernetesOptions.Namespace, kubernetesOptions.ImagePullSecret, viper.GetInt("timeout"), viper.GetString("proxy"))
kubeConfig,
kubernetesOptions.RunAsUser,
kubernetesOptions.Namespace,
kubernetesOptions.ImagePullSecret,
configOpts.Timeout,
configOpts.ProxyURL)
return buildProcessor.Start(b) return buildProcessor.Start(b)
} }

View File

@ -1,11 +1,12 @@
package cmd package cmd
import ( import (
"bytes"
"github.com/falcosecurity/driverkit/pkg/driverbuilder" "github.com/falcosecurity/driverkit/pkg/driverbuilder"
"github.com/falcosecurity/driverkit/pkg/driverbuilder/builder"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/pflag" "github.com/spf13/pflag"
"github.com/spf13/viper"
"log/slog"
"os"
) )
type localCmdOptions struct { type localCmdOptions struct {
@ -16,40 +17,27 @@ type localCmdOptions struct {
} }
// NewLocalCmd creates the `driverkit local` command. // NewLocalCmd creates the `driverkit local` command.
func NewLocalCmd(configOpts *ConfigOptions, rootOpts *RootOptions, rootFlags *pflag.FlagSet) *cobra.Command { func NewLocalCmd(rootOpts *RootOptions, rootFlags *pflag.FlagSet) *cobra.Command {
opts := localCmdOptions{} opts := localCmdOptions{}
localCmd := &cobra.Command{ localCmd := &cobra.Command{
Use: "local", Use: "local",
Short: "Build Falco kernel modules and eBPF probes in local env with local kernel sources and gcc/clang.", Short: "Build Falco kernel modules and eBPF probes in local env with local kernel sources and gcc/clang.",
RunE: func(c *cobra.Command, args []string) error { Run: func(c *cobra.Command, args []string) {
configOpts.Printer.Logger.Info("starting build", slog.With("processor", c.Name()).Info("driver building, it will take a few seconds")
configOpts.Printer.Logger.Args("processor", c.Name())) if !configOptions.DryRun {
if !configOpts.dryRun { b := rootOpts.ToBuild()
if !rootOpts.Output.HasOutputs() { if !b.HasOutputs() {
configOpts.Printer.Logger.Info("no output specified") return
return nil
} }
// Since we use a spinner, cache log data to a bytesbuffer; if err := driverbuilder.NewLocalBuildProcessor(viper.GetInt("timeout"),
// we will later print it once we stop the spinner. opts.useDKMS,
var b *builder.Build
if configOpts.disableStyling {
b = rootOpts.ToBuild(configOpts.Printer)
} else {
var buf bytes.Buffer
b = rootOpts.ToBuild(configOpts.Printer.WithWriter(&buf))
configOpts.Printer.Spinner, _ = configOpts.Printer.Spinner.Start("driver building, it will take a few seconds")
defer func() {
configOpts.Printer.DefaultText.Print(buf.String())
}()
}
return driverbuilder.NewLocalBuildProcessor(opts.useDKMS,
opts.downloadHeaders, opts.downloadHeaders,
false,
opts.srcDir, opts.srcDir,
opts.envMap, opts.envMap).Start(b); err != nil {
configOpts.Timeout).Start(b) slog.With("err", err.Error()).Error("exiting")
os.Exit(1)
}
} }
return nil
}, },
} }
// Add root flags, but not the ones unneeded // Add root flags, but not the ones unneeded

View File

@ -15,29 +15,32 @@ limitations under the License.
package cmd package cmd
import ( import (
"errors"
"fmt" "fmt"
"io" "io"
"log/slog"
"os" "os"
"runtime"
"sort" "sort"
"strings" "strings"
"github.com/falcosecurity/driverkit/pkg/driverbuilder/builder"
"github.com/falcosecurity/driverkit/pkg/kernelrelease" "github.com/falcosecurity/driverkit/pkg/kernelrelease"
"github.com/falcosecurity/driverkit/validate"
"github.com/falcosecurity/driverkit/pkg/driverbuilder/builder"
"github.com/falcosecurity/driverkit/pkg/version" "github.com/falcosecurity/driverkit/pkg/version"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/pflag" "github.com/spf13/pflag"
homedir "github.com/mitchellh/go-homedir"
"github.com/spf13/viper" "github.com/spf13/viper"
) )
func persistentValidateFunc(rootCommand *RootCmd, configOpts *ConfigOptions, rootOpts *RootOptions) func(c *cobra.Command, args []string) error { func persistentValidateFunc(rootCommand *RootCmd, rootOpts *RootOptions) func(c *cobra.Command, args []string) error {
return func(c *cobra.Command, args []string) error { return func(c *cobra.Command, args []string) error {
var validationError = errors.New("exiting for validation errors") initConfig()
configErr := configOpts.Init()
// Early exit if detect some error into config flags // Early exit if detect some error into config flags
if configErr { if configOptions.configErrors {
return validationError return fmt.Errorf("exiting for validation errors")
} }
// Merge environment variables or config file values into the RootOptions instance // Merge environment variables or config file values into the RootOptions instance
skip := map[string]bool{ // do not merge these skip := map[string]bool{ // do not merge these
@ -58,13 +61,13 @@ func persistentValidateFunc(rootCommand *RootCmd, configOpts *ConfigOptions, roo
// rather than replace, it appends. Since viper will already have the cli options set // rather than replace, it appends. Since viper will already have the cli options set
// if supplied, we only need this step if rootCommand doesn't already have them e.g. // if supplied, we only need this step if rootCommand doesn't already have them e.g.
// not set on CLI so read from config. // not set on CLI so read from config.
if cliURLs, err := rootCommand.c.Flags().GetStringSlice(name); err == nil && len(cliURLs) != 0 { if cli_urls, err := rootCommand.c.Flags().GetStringSlice(name); err == nil && len(cli_urls) != 0 {
return return
} }
value := viper.GetStringSlice(name) value := viper.GetStringSlice(name)
if len(value) != 0 { if len(value) != 0 {
strValue := strings.Join(value, ",") strValue := strings.Join(value, ",")
_ = rootCommand.c.Flags().Set(name, strValue) rootCommand.c.Flags().Set(name, strValue)
} }
} else { } else {
value := viper.GetString(name) value := viper.GetString(name)
@ -76,7 +79,7 @@ func persistentValidateFunc(rootCommand *RootCmd, configOpts *ConfigOptions, roo
} }
// set the value, if any, otherwise let the default // set the value, if any, otherwise let the default
if value != "" { if value != "" {
_ = rootCommand.c.Flags().Set(name, value) rootCommand.c.Flags().Set(name, value)
} }
} }
} }
@ -89,12 +92,11 @@ func persistentValidateFunc(rootCommand *RootCmd, configOpts *ConfigOptions, roo
if c.Root() != c && c.Name() != "help" && c.Name() != "__complete" && c.Name() != "__completeNoDesc" && c.Name() != "completion" { if c.Root() != c && c.Name() != "help" && c.Name() != "__complete" && c.Name() != "__completeNoDesc" && c.Name() != "completion" {
if errs := rootOpts.Validate(); errs != nil { if errs := rootOpts.Validate(); errs != nil {
for _, err := range errs { for _, err := range errs {
configOpts.Printer.Logger.Error("error validating build options", slog.With("err", err.Error()).Error("error validating build options")
configOpts.Printer.Logger.Args("err", err.Error()))
} }
return validationError return fmt.Errorf("exiting for validation errors")
} }
rootOpts.Log(configOpts.Printer) rootOpts.Log()
} }
return nil return nil
} }
@ -106,7 +108,9 @@ type RootCmd struct {
} }
// NewRootCmd instantiates the root command. // NewRootCmd instantiates the root command.
func NewRootCmd(configOpts *ConfigOptions, rootOpts *RootOptions) *RootCmd { func NewRootCmd() *RootCmd {
configOptions = NewConfigOptions()
rootOpts := NewRootOptions()
rootCmd := &cobra.Command{ rootCmd := &cobra.Command{
Use: "driverkit", Use: "driverkit",
Short: "A command line tool to build Falco kernel modules and eBPF probes.", Short: "A command line tool to build Falco kernel modules and eBPF probes.",
@ -115,51 +119,74 @@ func NewRootCmd(configOpts *ConfigOptions, rootOpts *RootOptions) *RootCmd {
Args: cobra.OnlyValidArgs, Args: cobra.OnlyValidArgs,
DisableFlagsInUseLine: true, DisableFlagsInUseLine: true,
DisableAutoGenTag: true, DisableAutoGenTag: true,
SilenceErrors: true,
SilenceUsage: true,
Version: version.String(), Version: version.String(),
RunE: func(c *cobra.Command, args []string) error { Run: func(c *cobra.Command, args []string) {
if len(args) == 0 { if len(args) == 0 {
configOpts.Printer.Logger.Info("specify a valid processor", configOpts.Printer.Logger.Args("processors", validProcessors)) slog.With("processors", validProcessors).Info("specify a valid processor")
} }
// Fallback to help // Fallback to help
return c.Help() c.Help()
}, },
} }
ret := &RootCmd{ ret := &RootCmd{
c: rootCmd, c: rootCmd,
} }
rootCmd.PersistentPreRunE = persistentValidateFunc(ret, configOpts, rootOpts) rootCmd.PersistentPreRunE = persistentValidateFunc(ret, rootOpts)
flags := rootCmd.Flags() flags := rootCmd.Flags()
targets := builder.Targets() targets := builder.Targets()
sort.Strings(targets) sort.Strings(targets)
configOpts.AddFlags(flags) flags.StringVarP(&configOptions.ConfigFile, "config", "c", configOptions.ConfigFile, "config file path (default $HOME/.driverkit.yaml if exists)")
rootOpts.AddFlags(flags, targets) flags.StringVarP(&configOptions.LogLevel, "loglevel", "l", configOptions.LogLevel, "log level")
flags.IntVar(&configOptions.Timeout, "timeout", configOptions.Timeout, "timeout in seconds")
flags.BoolVar(&configOptions.DryRun, "dryrun", configOptions.DryRun, "do not actually perform the action")
flags.StringVar(&configOptions.ProxyURL, "proxy", configOptions.ProxyURL, "the proxy to use to download data")
if err := viper.BindPFlags(flags); err != nil { flags.StringVar(&rootOpts.Output.Module, "output-module", rootOpts.Output.Module, "filepath where to save the resulting kernel module")
panic(err) flags.StringVar(&rootOpts.Output.Probe, "output-probe", rootOpts.Output.Probe, "filepath where to save the resulting eBPF probe")
} flags.StringVar(&rootOpts.Architecture, "architecture", runtime.GOARCH, "target architecture for the built driver, one of "+kernelrelease.SupportedArchs.String())
flags.StringVar(&rootOpts.DriverVersion, "driverversion", rootOpts.DriverVersion, "driver version as a git commit hash or as a git tag")
flags.StringVar(&rootOpts.KernelVersion, "kernelversion", rootOpts.KernelVersion, "kernel version to build the module for, it's the numeric value after the hash when you execute 'uname -v'")
flags.StringVar(&rootOpts.KernelRelease, "kernelrelease", rootOpts.KernelRelease, "kernel release to build the module for, it can be found by executing 'uname -v'")
flags.StringVarP(&rootOpts.Target, "target", "t", rootOpts.Target, "the system to target the build for, one of ["+strings.Join(targets, ",")+"]")
flags.StringVar(&rootOpts.KernelConfigData, "kernelconfigdata", rootOpts.KernelConfigData, "base64 encoded kernel config data: in some systems it can be found under the /boot directory, in other it is gzip compressed under /proc")
flags.StringVar(&rootOpts.ModuleDeviceName, "moduledevicename", rootOpts.ModuleDeviceName, "kernel module device name (the default is falco, so the device will be under /dev/falco*)")
flags.StringVar(&rootOpts.ModuleDriverName, "moduledrivername", rootOpts.ModuleDriverName, "kernel module driver name, i.e. the name you see when you check installed modules via lsmod")
flags.StringVar(&rootOpts.BuilderImage, "builderimage", rootOpts.BuilderImage, "docker image to be used to build the kernel module and eBPF probe. If not provided, an automatically selected image will be used.")
flags.StringSliceVar(&rootOpts.BuilderRepos, "builderrepo", rootOpts.BuilderRepos, "list of docker repositories or yaml file (absolute path) containing builder images index with the format 'images: [ { target:<target>, name:<image-name>, arch: <arch>, tag: <imagetag>, gcc_versions: [ <gcc-tag> ] },...]', in descending priority order. Used to search for builder images. eg: --builderrepo myorg/driverkit-builder --builderrepo falcosecurity/driverkit-builder --builderrepo '/path/to/my/index.yaml'.")
flags.StringVar(&rootOpts.GCCVersion, "gccversion", rootOpts.GCCVersion, "enforce a specific gcc version for the build")
flags.StringSliceVar(&rootOpts.KernelUrls, "kernelurls", nil, "list of kernel header urls (e.g. --kernelurls <URL1> --kernelurls <URL2> --kernelurls \"<URL3>,<URL4>\")")
flags.StringVar(&rootOpts.Repo.Org, "repo-org", rootOpts.Repo.Org, "repository github organization")
flags.StringVar(&rootOpts.Repo.Name, "repo-name", rootOpts.Repo.Name, "repository github name")
flags.StringVar(&rootOpts.Registry.Name, "registry-name", rootOpts.Registry.Name, "registry name to which authenticate")
flags.StringVar(&rootOpts.Registry.Username, "registry-user", rootOpts.Registry.Username, "registry username")
flags.StringVar(&rootOpts.Registry.Password, "registry-password", rootOpts.Registry.Password, "registry password")
flags.BoolVar(&rootOpts.Registry.PlainHTTP, "registry-plain-http", rootOpts.Registry.PlainHTTP, "allows interacting with remote registry via plain http requests")
viper.BindPFlags(flags)
// Flag annotations and custom completions // Flag annotations and custom completions
_ = rootCmd.MarkFlagFilename("config", viper.SupportedExts...) rootCmd.MarkFlagFilename("config", viper.SupportedExts...)
_ = rootCmd.RegisterFlagCompletionFunc("target", func(c *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { rootCmd.RegisterFlagCompletionFunc("target", func(c *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
return targets, cobra.ShellCompDirectiveDefault return targets, cobra.ShellCompDirectiveDefault
}) })
_ = rootCmd.RegisterFlagCompletionFunc("architecture", func(c *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { rootCmd.RegisterFlagCompletionFunc("architecture", func(c *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
return kernelrelease.SupportedArchs.Strings(), cobra.ShellCompDirectiveDefault return kernelrelease.SupportedArchs.Strings(), cobra.ShellCompDirectiveDefault
}) })
// Subcommands // Subcommands
rootCmd.AddCommand(NewKubernetesCmd(configOpts, rootOpts, flags)) rootCmd.AddCommand(NewKubernetesCmd(rootOpts, flags))
rootCmd.AddCommand(NewKubernetesInClusterCmd(configOpts, rootOpts, flags)) rootCmd.AddCommand(NewKubernetesInClusterCmd(rootOpts, flags))
rootCmd.AddCommand(NewDockerCmd(configOpts, rootOpts, flags)) rootCmd.AddCommand(NewDockerCmd(rootOpts, flags))
rootCmd.AddCommand(NewLocalCmd(configOpts, rootOpts, flags)) rootCmd.AddCommand(NewLocalCmd(rootOpts, flags))
rootCmd.AddCommand(NewImagesCmd(configOpts, rootOpts, flags)) rootCmd.AddCommand(NewImagesCmd(rootOpts, flags))
rootCmd.AddCommand(NewCompletionCmd(configOpts, rootOpts, flags)) rootCmd.AddCommand(NewCompletionCmd())
ret.StripSensitive() ret.StripSensitive()
@ -188,15 +215,32 @@ func (r *RootCmd) Command() *cobra.Command {
return r.c return r.c
} }
// SetArgs proxies the arguments to the underlying cobra.Command. func createDefaultLogger(w io.Writer) {
func (r *RootCmd) SetArgs(args []string) { h := slog.NewTextHandler(w, &slog.HandlerOptions{
r.c.SetArgs(args) Level: validate.ProgramLevel,
ReplaceAttr: func(groups []string, a slog.Attr) slog.Attr {
if a.Key == slog.TimeKey {
return slog.Attr{}
}
return a
}})
slog.SetDefault(slog.New(h))
} }
// SetOutput sets the main command output writer. // SetOutput sets the main command output writer.
func (r *RootCmd) SetOutput(w io.Writer) { func (r *RootCmd) SetOutput(w io.Writer) {
r.c.SetOut(w) r.c.SetOut(w)
r.c.SetErr(w) r.c.SetErr(w)
createDefaultLogger(w)
}
func init() {
createDefaultLogger(os.Stdout)
}
// SetArgs proxies the arguments to the underlying cobra.Command.
func (r *RootCmd) SetArgs(args []string) {
r.c.SetArgs(args)
} }
// Execute proxies the cobra.Command execution. // Execute proxies the cobra.Command execution.
@ -206,30 +250,50 @@ func (r *RootCmd) Execute() error {
// Start creates the root command and runs it. // Start creates the root command and runs it.
func Start() { func Start() {
configOpts, err := NewConfigOptions() root := NewRootCmd()
if err != nil { if err := root.Execute(); err != nil {
// configOpts will never be nil here slog.With("err", err.Error()).Error("error executing driverkit")
if configOpts != nil { os.Exit(1)
configOpts.Printer.Logger.Fatal("error setting driverkit config options defaults", }
configOpts.Printer.Logger.Args("err", err.Error())) }
} else {
os.Exit(1) // initConfig reads in config file and ENV variables if set.
} func initConfig() {
} if errs := configOptions.Validate(); errs != nil {
rootOpts, err := NewRootOptions() for _, err := range errs {
if err != nil { slog.With("err", err.Error()).Error("error validating config options")
configOpts.Printer.Logger.Fatal("error setting driverkit root options defaults", }
configOpts.Printer.Logger.Args("err", err.Error())) // configOptions.configErrors should be true here
} }
if configOptions.ConfigFile != "" {
// Cleanup spinner upon leaving if any viper.SetConfigFile(configOptions.ConfigFile)
defer func() { } else {
if configOpts.Printer.Spinner != nil { // Find home directory.
_ = configOpts.Printer.Spinner.Stop() home, err := homedir.Dir()
} if err != nil {
}() slog.With("err", err.Error()).Debug("error getting the home directory")
root := NewRootCmd(configOpts, rootOpts) // not setting configOptions.configErrors = true because we fallback to `$HOME/.driverkit.yaml` and try with it
if err = root.Execute(); err != nil { }
configOpts.Printer.Logger.Fatal("error executing driverkit", configOpts.Printer.Logger.Args("err", err.Error()))
viper.AddConfigPath(home)
viper.SetConfigName(".driverkit")
}
viper.AutomaticEnv()
viper.SetEnvPrefix("driverkit")
viper.SetEnvKeyReplacer(strings.NewReplacer("-", "_"))
// If a config file is found, read it in.
if err := viper.ReadInConfig(); err == nil {
slog.With("file", viper.ConfigFileUsed()).Info("using config file")
} else {
if _, ok := err.(viper.ConfigFileNotFoundError); ok {
// Config file not found, ignore ...
slog.Debug("running without a configuration file")
} else {
// Config file was found but another error was produced
slog.With("file", viper.ConfigFileUsed(), "err", err.Error()).Debug("error running with config file")
configOptions.configErrors = true
}
} }
} }

View File

@ -15,12 +15,9 @@ limitations under the License.
package cmd package cmd
import ( import (
"errors" "fmt"
"github.com/falcosecurity/falcoctl/pkg/output" "log/slog"
"github.com/spf13/pflag"
"os" "os"
"runtime"
"strings"
"github.com/creasty/defaults" "github.com/creasty/defaults"
"github.com/falcosecurity/driverkit/pkg/driverbuilder/builder" "github.com/falcosecurity/driverkit/pkg/driverbuilder/builder"
@ -35,10 +32,6 @@ type OutputOptions struct {
Probe string `validate:"required_without=Module,filepath,omitempty,endswith=.o" name:"output probe path"` Probe string `validate:"required_without=Module,filepath,omitempty,endswith=.o" name:"output probe path"`
} }
func (oo *OutputOptions) HasOutputs() bool {
return oo.Module != "" || oo.Probe != ""
}
type RepoOptions struct { type RepoOptions struct {
Org string `default:"falcosecurity" name:"organization name"` Org string `default:"falcosecurity" name:"organization name"`
Name string `default:"libs" name:"repo name"` Name string `default:"libs" name:"repo name"`
@ -75,23 +68,23 @@ func init() {
} }
// NewRootOptions ... // NewRootOptions ...
func NewRootOptions() (*RootOptions, error) { func NewRootOptions() *RootOptions {
rootOpts := &RootOptions{} rootOpts := &RootOptions{}
if err := defaults.Set(rootOpts); err != nil { if err := defaults.Set(rootOpts); err != nil {
return nil, err slog.With("err", err.Error(), "options", "RootOptions").Error("error setting driverkit options defaults")
os.Exit(1)
} }
return rootOpts, nil return rootOpts
} }
// Validate validates the RootOptions fields. // Validate validates the RootOptions fields.
func (ro *RootOptions) Validate() []error { func (ro *RootOptions) Validate() []error {
if err := validate.V.Struct(ro); err != nil { if err := validate.V.Struct(ro); err != nil {
var errs validator.ValidationErrors errors := err.(validator.ValidationErrors)
errors.As(err, &errs)
errArr := []error{} errArr := []error{}
for _, e := range errs { for _, e := range errors {
// Translate each error one at a time // Translate each error one at a time
errArr = append(errArr, errors.New(e.Translate(validate.T))) errArr = append(errArr, fmt.Errorf(e.Translate(validate.T)))
} }
return errArr return errArr
} }
@ -100,58 +93,31 @@ func (ro *RootOptions) Validate() []error {
kr := kernelrelease.FromString(ro.KernelRelease) kr := kernelrelease.FromString(ro.KernelRelease)
kr.Architecture = kernelrelease.Architecture(ro.Architecture) kr.Architecture = kernelrelease.Architecture(ro.Architecture)
if !kr.SupportsModule() && !kr.SupportsProbe() { if !kr.SupportsModule() && !kr.SupportsProbe() {
return []error{errors.New("both module and probe are not supported by given options")} return []error{fmt.Errorf("both module and probe are not supported by given options")}
} }
return nil return nil
} }
func (ro *RootOptions) AddFlags(flags *pflag.FlagSet, targets []string) {
flags.StringVar(&ro.Output.Module, "output-module", ro.Output.Module, "filepath where to save the resulting kernel module")
flags.StringVar(&ro.Output.Probe, "output-probe", ro.Output.Probe, "filepath where to save the resulting eBPF probe")
flags.StringVar(&ro.Architecture, "architecture", runtime.GOARCH, "target architecture for the built driver, one of "+kernelrelease.SupportedArchs.String())
flags.StringVar(&ro.DriverVersion, "driverversion", ro.DriverVersion, "driver version as a git commit hash or as a git tag")
flags.StringVar(&ro.KernelVersion, "kernelversion", ro.KernelVersion, "kernel version to build the module for, it's the numeric value after the hash when you execute 'uname -v'")
flags.StringVar(&ro.KernelRelease, "kernelrelease", ro.KernelRelease, "kernel release to build the module for, it can be found by executing 'uname -v'")
flags.StringVarP(&ro.Target, "target", "t", ro.Target, "the system to target the build for, one of ["+strings.Join(targets, ",")+"]")
flags.StringVar(&ro.KernelConfigData, "kernelconfigdata", ro.KernelConfigData, "base64 encoded kernel config data: in some systems it can be found under the /boot directory, in other it is gzip compressed under /proc")
flags.StringVar(&ro.ModuleDeviceName, "moduledevicename", ro.ModuleDeviceName, "kernel module device name (the default is falco, so the device will be under /dev/falco*)")
flags.StringVar(&ro.ModuleDriverName, "moduledrivername", ro.ModuleDriverName, "kernel module driver name, i.e. the name you see when you check installed modules via lsmod")
flags.StringVar(&ro.BuilderImage, "builderimage", ro.BuilderImage, "docker image to be used to build the kernel module and eBPF probe. If not provided, an automatically selected image will be used.")
flags.StringSliceVar(&ro.BuilderRepos, "builderrepo", ro.BuilderRepos, "list of docker repositories or yaml file (absolute path) containing builder images index with the format 'images: [ { target:<target>, name:<image-name>, arch: <arch>, tag: <imagetag>, gcc_versions: [ <gcc-tag> ] },...]', in descending priority order. Used to search for builder images. eg: --builderrepo myorg/driverkit-builder --builderrepo falcosecurity/driverkit-builder --builderrepo '/path/to/my/index.yaml'.")
flags.StringVar(&ro.GCCVersion, "gccversion", ro.GCCVersion, "enforce a specific gcc version for the build")
flags.StringSliceVar(&ro.KernelUrls, "kernelurls", nil, "list of kernel header urls (e.g. --kernelurls <URL1> --kernelurls <URL2> --kernelurls \"<URL3>,<URL4>\")")
flags.StringVar(&ro.Repo.Org, "repo-org", ro.Repo.Org, "repository github organization")
flags.StringVar(&ro.Repo.Name, "repo-name", ro.Repo.Name, "repository github name")
flags.StringVar(&ro.Registry.Name, "registry-name", ro.Registry.Name, "registry name to which authenticate")
flags.StringVar(&ro.Registry.Username, "registry-user", ro.Registry.Username, "registry username")
flags.StringVar(&ro.Registry.Password, "registry-password", ro.Registry.Password, "registry password")
flags.BoolVar(&ro.Registry.PlainHTTP, "registry-plain-http", ro.Registry.PlainHTTP, "allows interacting with remote registry via plain http requests")
}
// Log emits a log line containing the receiving RootOptions for debugging purposes. // Log emits a log line containing the receiving RootOptions for debugging purposes.
// //
// Call it only after validation. // Call it only after validation.
func (ro *RootOptions) Log(printer *output.Printer) { func (ro *RootOptions) Log() {
printer.Logger.Debug("running with options", slog.Debug("running with options",
printer.Logger.Args( "output-module", ro.Output.Module,
"output-module", ro.Output.Module, "output-probe", ro.Output.Probe,
"output-probe", ro.Output.Probe, "driverversion", ro.DriverVersion,
"driverversion", ro.DriverVersion, "kernelrelease", ro.KernelRelease,
"kernelrelease", ro.KernelRelease, "kernelversion", ro.KernelVersion,
"kernelversion", ro.KernelVersion, "target", ro.Target,
"target", ro.Target, "arch", ro.Architecture,
"arch", ro.Architecture, "kernelurls", ro.KernelUrls,
"kernelurls", ro.KernelUrls, "repo-org", ro.Repo.Org,
"repo-org", ro.Repo.Org, "repo-name", ro.Repo.Name,
"repo-name", ro.Repo.Name, )
))
} }
func (ro *RootOptions) ToBuild(printer *output.Printer) *builder.Build { func (ro *RootOptions) ToBuild() *builder.Build {
kernelConfigData := ro.KernelConfigData kernelConfigData := ro.KernelConfigData
if len(kernelConfigData) == 0 { if len(kernelConfigData) == 0 {
kernelConfigData = "bm8tZGF0YQ==" // no-data kernelConfigData = "bm8tZGF0YQ==" // no-data
@ -179,7 +145,6 @@ func (ro *RootOptions) ToBuild(printer *output.Printer) *builder.Build {
RegistryUser: ro.Registry.Username, RegistryUser: ro.Registry.Username,
RegistryPassword: ro.Registry.Password, RegistryPassword: ro.Registry.Password,
RegistryPlainHTTP: ro.Registry.PlainHTTP, RegistryPlainHTTP: ro.Registry.PlainHTTP,
Printer: printer,
} }
// loop over BuilderRepos to build the list ImagesListers based on the value of the builderRepo: // loop over BuilderRepos to build the list ImagesListers based on the value of the builderRepo:
@ -195,8 +160,7 @@ func (ro *RootOptions) ToBuild(printer *output.Printer) *builder.Build {
imageLister, err = builder.NewRepoImagesLister(builderRepo, build) imageLister, err = builder.NewRepoImagesLister(builderRepo, build)
} }
if err != nil { if err != nil {
printer.Logger.Warn("skipping repo", slog.With("err", err.Error()).Warn("Skipping repo", "repo", builderRepo)
printer.Logger.Args("repo", builderRepo, "err", err.Error()))
} else { } else {
build.ImagesListers = append(build.ImagesListers, imageLister) build.ImagesListers = append(build.ImagesListers, imageLister)
} }
@ -206,13 +170,11 @@ func (ro *RootOptions) ToBuild(printer *output.Printer) *builder.Build {
kr := build.KernelReleaseFromBuildConfig() kr := build.KernelReleaseFromBuildConfig()
if len(build.ModuleFilePath) > 0 && !kr.SupportsModule() { if len(build.ModuleFilePath) > 0 && !kr.SupportsModule() {
build.ModuleFilePath = "" build.ModuleFilePath = ""
printer.Logger.Warn("skipping build attempt of module for unsupported kernel release", slog.Warn("Skipping build attempt of module for unsupported kernel release", "kernelrelease", kr.String())
printer.Logger.Args("kernelrelease", kr.String()))
} }
if len(build.ProbeFilePath) > 0 && !kr.SupportsProbe() { if len(build.ProbeFilePath) > 0 && !kr.SupportsProbe() {
build.ProbeFilePath = "" build.ProbeFilePath = ""
printer.Logger.Warn("skipping build attempt of probe for unsupported kernel release", slog.Warn("Skipping build attempt of probe for unsupported kernel release", "kernelrelease", kr.String())
printer.Logger.Args("kernelrelease", kr.String()))
} }
return build return build
} }

View File

@ -1,5 +1,4 @@
INFO specify a valid processor level=INFO msg="specify a valid processor" processors="[docker kubernetes kubernetes-in-cluster local]"
└ processors: [docker kubernetes kubernetes-in-cluster local]
{{ .Desc }} {{ .Desc }}
{{ .Usage }} {{ .Usage }}

View File

@ -3,5 +3,4 @@ kernelversion: 59
target: ubuntu-aws target: ubuntu-aws
output: output:
module: /tmp/falco-ubuntu-aws.ko module: /tmp/falco-ubuntu-aws.ko
probe: /tmp/falco-ubuntu-aws.o
driverversion: master driverversion: master

View File

@ -7,5 +7,4 @@ kernelurls: [
target: ubuntu-aws target: ubuntu-aws
output: output:
module: /tmp/falco-ubuntu-aws.ko module: /tmp/falco-ubuntu-aws.ko
probe: /tmp/falco-ubuntu-aws.o
driverversion: master driverversion: master

View File

@ -1,13 +1,3 @@
INFO using config file file: testdata/configs/1.yaml level=INFO msg="using config file" file=testdata/configs/1.yaml
DEBUG running with options level=DEBUG msg="running with options" output-module=/tmp/falco-ubuntu-aws.ko output-probe="" driverversion=master kernelrelease=4.15.0-1057-aws kernelversion=59 target=ubuntu-aws arch={{ .CurrentArch }} kernelurls=[] repo-org=falcosecurity repo-name=libs
├ output-module: /tmp/falco-ubuntu-aws.ko level=INFO msg="driver building, it will take a few seconds" processor=docker
├ output-probe: /tmp/falco-ubuntu-aws.o
├ driverversion: master
├ kernelrelease: 4.15.0-1057-aws
├ kernelversion: 59
├ target: ubuntu-aws
├ arch: {{ .CurrentArch }}
├ kernelurls: []
├ repo-org: falcosecurity
└ repo-name: libs
INFO starting build processor: docker

View File

@ -1,13 +1,3 @@
INFO using config file file: testdata/configs/1.yaml level=INFO msg="using config file" file=testdata/configs/1.yaml
DEBUG running with options level=DEBUG msg="running with options" output-module=/tmp/override.ko output-probe="" driverversion=master kernelrelease=4.15.0-1057-aws kernelversion=229 target=ubuntu-aws arch={{ .CurrentArch }} kernelurls=[] repo-org=falcosecurity repo-name=libs
├ output-module: /tmp/override.ko level=INFO msg="driver building, it will take a few seconds" processor=docker
├ output-probe: /tmp/falco-ubuntu-aws.o
├ driverversion: master
├ kernelrelease: 4.15.0-1057-aws
├ kernelversion: 229
├ target: ubuntu-aws
├ arch: {{ .CurrentArch }}
├ kernelurls: []
├ repo-org: falcosecurity
└ repo-name: libs
INFO starting build processor: docker

View File

@ -1,13 +1,3 @@
INFO using config file file: testdata/configs/2.yaml level=INFO msg="using config file" file=testdata/configs/2.yaml
DEBUG running with options level=DEBUG msg="running with options" output-module=/tmp/falco-ubuntu-aws.ko output-probe="" driverversion=master kernelrelease=4.15.0-1057-aws kernelversion=59 target=ubuntu-aws arch={{ .CurrentArch }} kernelurls="[https://mirrors.edge.kernel.org/ubuntu/pool/main/l/linux-aws/linux-aws-headers-4.15.0-1057_4.15.0-1057.59_all.deb https://mirrors.edge.kernel.org/ubuntu/pool/main/l/linux-aws/linux-headers-4.15.0-1057-aws_4.15.0-1057.59_amd64.deb]" repo-org=falcosecurity repo-name=libs
├ output-module: /tmp/falco-ubuntu-aws.ko level=INFO msg="driver building, it will take a few seconds" processor=docker
├ output-probe: /tmp/falco-ubuntu-aws.o
├ driverversion: master
├ kernelrelease: 4.15.0-1057-aws
├ kernelversion: 59
├ target: ubuntu-aws
├ arch: {{ .CurrentArch }}
├ kernelurls: [https://mirrors.edge.kernel.org/ubuntu/pool/main/l/linux-aws/linux-aws-headers-4.15.0-1057_4.15.0-1057.59_all.deb https://mirrors.edge.kernel.org/ubuntu/pool/main/l/linux-aws/linux-headers-4.15.0-1057-aws_4.15.0-1057.59_amd64.deb]
├ repo-org: falcosecurity
└ repo-name: libs
INFO starting build processor: docker

View File

@ -1,13 +1,3 @@
DEBUG running without a configuration file level=DEBUG msg="running without a configuration file"
DEBUG running with options level=DEBUG msg="running with options" output-module=/tmp/falco-ubuntu-azure.ko output-probe="" driverversion=master kernelrelease=4.15.0-1057-azure kernelversion=62 target=ubuntu-azure arch={{ .CurrentArch }} kernelurls="[http://mirrors.edge.kernel.org/ubuntu/pool/main/l/linux-azure/linux-azure-headers-4.15.0-1057_4.15.0-1057.62_all.deb http://mirrors.edge.kernel.org/ubuntu/pool/main/l/linux-azure/linux-headers-4.15.0-1057-azure_4.15.0-1057.62_amd64.deb]" repo-org=falcosecurity repo-name=libs
├ output-module: /tmp/falco-ubuntu-azure.ko level=INFO msg="driver building, it will take a few seconds" processor=docker
├ output-probe: /tmp/falco-ubuntu-aws.o
├ driverversion: master
├ kernelrelease: 4.15.0-1057-azure
├ kernelversion: 62
├ target: ubuntu-azure
├ arch: {{ .CurrentArch }}
├ kernelurls: [http://mirrors.edge.kernel.org/ubuntu/pool/main/l/linux-azure/linux-azure-headers-4.15.0-1057_4.15.0-1057.62_all.deb http://mirrors.edge.kernel.org/ubuntu/pool/main/l/linux-azure/linux-headers-4.15.0-1057-azure_4.15.0-1057.62_amd64.deb]
├ repo-org: falcosecurity
└ repo-name: libs
INFO starting build processor: docker

View File

@ -1,4 +1,8 @@
DEBUG running without a configuration file level=DEBUG msg="running without a configuration file"
ERROR error validating build options level=ERROR msg="error validating build options" err="builder image is a required field when target is redhat"
└ err: builder image is a required field when target is redhat Error: exiting for validation errors
ERROR error executing driverkit err: exiting for validation errors Usage:
driverkit docker [flags]
{{ .Flags }}

View File

@ -1,13 +1,3 @@
DEBUG running without a configuration file level=DEBUG msg="running without a configuration file"
DEBUG running with options level=DEBUG msg="running with options" output-module=/tmp/falco-ubuntu-aws.ko output-probe="" driverversion=master kernelrelease=4.15.0-1057-aws kernelversion=59 target=ubuntu-aws arch={{ .CurrentArch }} kernelurls="[https://mirrors.edge.kernel.org/ubuntu/pool/main/l/linux-aws/linux-aws-headers-4.15.0-1057_4.15.0-1057.59_all.deb https://mirrors.edge.kernel.org/ubuntu/pool/main/l/linux-aws/linux-headers-4.15.0-1057-aws_4.15.0-1057.59_amd64.deb]" repo-org=falcosecurity repo-name=libs
├ output-module: /tmp/falco-ubuntu-aws.ko level=INFO msg="driver building, it will take a few seconds" processor=docker
├ output-probe: /tmp/falco-ubuntu-aws.o
├ driverversion: master
├ kernelrelease: 4.15.0-1057-aws
├ kernelversion: 59
├ target: ubuntu-aws
├ arch: {{ .CurrentArch }}
├ kernelurls: [https://mirrors.edge.kernel.org/ubuntu/pool/main/l/linux-aws/linux-aws-headers-4.15.0-1057_4.15.0-1057.59_all.deb https://mirrors.edge.kernel.org/ubuntu/pool/main/l/linux-aws/linux-headers-4.15.0-1057-aws_4.15.0-1057.59_amd64.deb]
├ repo-org: falcosecurity
└ repo-name: libs
INFO starting build processor: docker

View File

@ -1 +1 @@
INFO starting build processor: docker level=INFO msg="driver building, it will take a few seconds" processor=docker

View File

@ -1,7 +1,10 @@
ERROR error validating build options err: kernel release is a required field level=ERROR msg="error validating build options" err="kernel release is a required field"
ERROR error validating build options err: target is a required field level=ERROR msg="error validating build options" err="target is a required field"
ERROR error validating build options level=ERROR msg="error validating build options" err="output module path is required when probe is missing"
└ err: output module path is required when probe is missing level=ERROR msg="error validating build options" err="output probe path is required when module is missing"
ERROR error validating build options Error: exiting for validation errors
└ err: output probe path is required when module is missing Usage:
ERROR error executing driverkit err: exiting for validation errors driverkit docker [flags]
{{ .Flags }}

View File

@ -1,3 +1,11 @@
ERROR error validating config options level=ERROR msg="error validating config options" err="proxy url must start with http:// or https:// or socks5:// prefix"
└ err: proxy url must start with http:// or https:// or socks5:// prefix Error: exiting for validation errors
ERROR error executing driverkit err: exiting for validation errors {{ .Usage }}
{{ .Commands }}
{{ .Flags }}
-v, --version version for driverkit
{{ .Info }}

View File

@ -1 +1,10 @@
ERROR error executing driverkit err: invalid argument "abc" for "driverkit" Error: invalid argument "abc" for "driverkit"
{{ .Usage }}
{{ .Commands }}
{{ .Flags }}
-v, --version version for driverkit
{{ .Info }}

View File

@ -11,7 +11,7 @@ Flags:
--kernelrelease string kernel release to build the module for, it can be found by executing 'uname -v' --kernelrelease string kernel release to build the module for, it can be found by executing 'uname -v'
--kernelurls strings list of kernel header urls (e.g. --kernelurls <URL1> --kernelurls <URL2> --kernelurls "<URL3>,<URL4>") --kernelurls strings list of kernel header urls (e.g. --kernelurls <URL1> --kernelurls <URL2> --kernelurls "<URL3>,<URL4>")
--kernelversion string kernel version to build the module for, it's the numeric value after the hash when you execute 'uname -v' (default "1") --kernelversion string kernel version to build the module for, it's the numeric value after the hash when you execute 'uname -v' (default "1")
-l, --loglevel string set level for logs (info, warn, debug, trace) (default "info") -l, --loglevel string log level (default "INFO")
--moduledevicename string kernel module device name (the default is falco, so the device will be under /dev/falco*) (default "falco") --moduledevicename string kernel module device name (the default is falco, so the device will be under /dev/falco*) (default "falco")
--moduledrivername string kernel module driver name, i.e. the name you see when you check installed modules via lsmod (default "falco") --moduledrivername string kernel module driver name, i.e. the name you see when you check installed modules via lsmod (default "falco")
--output-module string filepath where to save the resulting kernel module --output-module string filepath where to save the resulting kernel module

View File

@ -18,6 +18,8 @@ import (
"bytes" "bytes"
"flag" "flag"
"fmt" "fmt"
"io/ioutil"
"log/slog"
"os" "os"
"path" "path"
"strings" "strings"
@ -59,22 +61,7 @@ func main() {
flag.Parse() flag.Parse()
// Get root command // Get root command
configOpts, err := cmd.NewConfigOptions() driverkit := cmd.NewRootCmd()
if err != nil {
// configOpts will never be nil here
if configOpts != nil {
configOpts.Printer.Logger.Fatal("error setting driverkit config options defaults",
configOpts.Printer.Logger.Args("err", err.Error()))
} else {
os.Exit(1)
}
}
rootOpts, err := cmd.NewRootOptions()
if err != nil {
configOpts.Printer.Logger.Fatal("error setting driverkit root options defaults",
configOpts.Printer.Logger.Args("err", err.Error()))
}
driverkit := cmd.NewRootCmd(configOpts, rootOpts)
root := driverkit.Command() root := driverkit.Command()
num := len(root.Commands()) + 1 num := len(root.Commands()) + 1
@ -97,20 +84,23 @@ func main() {
} }
// Generate markdown docs // Generate markdown docs
err = doc.GenMarkdownTreeCustom(root, outputDir, prepender(num), linker) err := doc.GenMarkdownTreeCustom(root, outputDir, prepender(num), linker)
if err != nil { if err != nil {
configOpts.Printer.Logger.Fatal("markdown generation", configOpts.Printer.Logger.Args("err", err.Error())) slog.With("err", err.Error()).Error("markdown generation")
os.Exit(1)
} }
if targetWebsite { if targetWebsite {
err = os.Rename(path.Join(outputDir, "driverkit.md"), path.Join(outputDir, "_index.md")) err = os.Rename(path.Join(outputDir, "driverkit.md"), path.Join(outputDir, "_index.md"))
if err != nil { if err != nil {
configOpts.Printer.Logger.Fatal("renaming main docs page", configOpts.Printer.Logger.Args("err", err.Error())) slog.With("err", err.Error()).Error("renaming main docs page")
os.Exit(1)
} }
} }
if err = stripSensitive(); err != nil { if err = stripSensitive(); err != nil {
configOpts.Printer.Logger.Fatal("error replacing sensitive data", configOpts.Printer.Logger.Args("err", err.Error())) slog.With("err", err.Error()).Error("error replacing sensitive data")
os.Exit(1)
} }
} }
@ -127,7 +117,7 @@ func stripSensitive() error {
for _, file := range files { for _, file := range files {
filePath := path.Join(outputDir, file.Name()) filePath := path.Join(outputDir, file.Name())
file, err := os.ReadFile(filePath) file, err := ioutil.ReadFile(filePath)
if err != nil { if err != nil {
return err return err
} }
@ -137,7 +127,7 @@ func stripSensitive() error {
target := []byte(os.Getenv(s)) target := []byte(os.Getenv(s))
file = bytes.ReplaceAll(file, target, append(envMark, []byte(s)...)) file = bytes.ReplaceAll(file, target, append(envMark, []byte(s)...))
} }
if err = os.WriteFile(filePath, file, 0666); err != nil { if err = ioutil.WriteFile(filePath, file, 0666); err != nil {
return err return err
} }
} }

View File

@ -1,32 +0,0 @@
FROM amazonlinux:2.0.20240529.0
LABEL maintainer="cncf-falco-dev@lists.cncf.io"
RUN yum -y install gcc10 \
clang \
llvm \
bash-completion \
bc \
ca-certificates \
curl \
gnupg2 \
libc6-dev \
elfutils-libelf-devel \
xz \
cpio \
flex \
bison \
openssl \
openssl-devel \
wget \
binutils \
which \
make \
cmake3 \
tar \
zstd \
git
# Properly create soft links
RUN ln -s /usr/bin/gcc10-cc /usr/bin/gcc-10.0.0
RUN ln -s /usr/bin/cmake3 /usr/bin/cmake

View File

@ -1 +0,0 @@
builder-any-x86_64_gcc14.0.0.Dockerfile

View File

@ -1,40 +0,0 @@
FROM fedora:41
LABEL maintainer="cncf-falco-dev@lists.cncf.io"
ARG TARGETARCH
RUN dnf install -y \
bash-completion \
bc \
clang \
llvm \
ca-certificates \
curl \
dkms \
dwarves \
gnupg2 \
gcc \
jq \
glibc-devel \
elfutils-libelf-devel \
netcat \
xz \
cpio \
flex \
bison \
openssl \
openssl-devel \
ncurses-devel \
systemd-devel \
pciutils-devel \
binutils-devel \
lsb-release \
wget \
gpg \
zstd \
cmake \
git
# Properly create soft links
RUN ln -s /usr/bin/gcc /usr/bin/gcc-14.0.0

View File

@ -1,4 +1,4 @@
FROM debian:buster FROM debian:buster-backports
LABEL maintainer="cncf-falco-dev@lists.cncf.io" LABEL maintainer="cncf-falco-dev@lists.cncf.io"
@ -6,23 +6,16 @@ ARG TARGETARCH
RUN cp /etc/skel/.bashrc /root && cp /etc/skel/.profile /root RUN cp /etc/skel/.bashrc /root && cp /etc/skel/.profile /root
# Use 20250630T203427Z debian apt snapshot as it still contains support for buster.
RUN cat <<EOF > /etc/apt/sources.list
deb http://snapshot.debian.org/archive/debian/20250630T203427Z buster main
deb http://snapshot.debian.org/archive/debian-security/20250630T203427Z buster/updates main
deb http://snapshot.debian.org/archive/debian/20250630T203427Z buster-updates main
EOF
RUN apt-get update \ RUN apt-get update \
&& apt-get install -y --no-install-recommends \ && apt-get install -y --no-install-recommends \
bash-completion \ bash-completion \
bc \ bc \
clang \ clang \
llvm \ llvm \
ca-certificates \ ca-certificates \
curl \ curl \
dkms \ dkms \
dwarves \ dwarves/buster-backports \
gnupg2 \ gnupg2 \
gcc \ gcc \
jq \ jq \
@ -47,6 +40,7 @@ RUN apt-get update \
zstd \ zstd \
gawk \ gawk \
mawk \ mawk \
cmake \
git \ git \
&& rm -rf /var/lib/apt/lists/* && rm -rf /var/lib/apt/lists/*
@ -131,13 +125,6 @@ RUN curl -L -o binutils_2.30-22_${TARGETARCH}.deb https://download.falco.org/dep
&& dpkg -i *binutils*.deb \ && dpkg -i *binutils*.deb \
&& rm -f *binutils*.deb && rm -f *binutils*.deb
# Install a recent version of cmake (debian buster has at most 3.13)
RUN curl -L -o /tmp/cmake.tar.gz https://github.com/Kitware/CMake/releases/download/v3.22.5/cmake-3.22.5-linux-$(uname -m).tar.gz; \
gzip -d /tmp/cmake.tar.gz; \
tar -xpf /tmp/cmake.tar --directory=/tmp; \
cp -R /tmp/cmake-3.22.5-linux-$(uname -m)/* /usr; \
rm -rf /tmp/cmake-3.22.5-linux-$(uname -m)/
# Properly create soft link # Properly create soft link
RUN ln -s /usr/bin/gcc-4.8 /usr/bin/gcc-4.8.0 RUN ln -s /usr/bin/gcc-4.8 /usr/bin/gcc-4.8.0
RUN if [ "$TARGETARCH" = "amd64" ] ; then ln -s /usr/bin/gcc-4.9 /usr/bin/gcc-4.9.0; fi; RUN if [ "$TARGETARCH" = "amd64" ] ; then ln -s /usr/bin/gcc-4.9 /usr/bin/gcc-4.9.0; fi;

View File

@ -2,19 +2,8 @@ FROM centos:7
LABEL maintainer="cncf-falco-dev@lists.cncf.io" LABEL maintainer="cncf-falco-dev@lists.cncf.io"
# Fix broken mirrors - centos:7 eol RUN yum -y install centos-release-scl && \
RUN sed -i s/mirror.centos.org/vault.centos.org/g /etc/yum.repos.d/*.repo; \ yum -y install gcc \
sed -i s/^#.*baseurl=http/baseurl=https/g /etc/yum.repos.d/*.repo; \
sed -i s/^mirrorlist=http/#mirrorlist=https/g /etc/yum.repos.d/*.repo
RUN yum -y install centos-release-scl
# fix broken mirrors (again)
RUN sed -i s/mirror.centos.org/vault.centos.org/g /etc/yum.repos.d/*.repo; \
sed -i s/^#.*baseurl=http/baseurl=https/g /etc/yum.repos.d/*.repo; \
sed -i s/^mirrorlist=http/#mirrorlist=https/g /etc/yum.repos.d/*.repo
RUN yum -y install gcc \
llvm-toolset-7.0 \ llvm-toolset-7.0 \
bash-completion \ bash-completion \
bc \ bc \

View File

@ -13,8 +13,7 @@ If that distribution is not yet supported by driverkit, the Falco Drivers Build
Adding support for a new distro is a multiple-step work: Adding support for a new distro is a multiple-step work:
* first of all, a new builder on driverkit must be created * first of all, a new builder on driverkit must be created
* secondly, [kernel-crawler](https://github.com/falcosecurity/kernel-crawler) must also be updated to support the new distro; see [below](#5-kernel-crawler) section * secondly, [kernel-crawler](https://github.com/falcosecurity/kernel-crawler) must also be updated to support the new distro; see [below](#5-kernel-crawler) section
* third, [dbg-go](https://github.com/falcosecurity/dbg-go) must [bump driverkit](https://github.com/falcosecurity/dbg-go?tab=readme-ov-file#bumping-driverkit) and enable support to generate configs for the new distro: https://github.com/falcosecurity/dbg-go/blob/main/pkg/root/distro.go#L30. * lastly, [test-infra](https://github.com/falcosecurity/test-infra) must be updated to add the new [prow config](https://github.com/falcosecurity/test-infra/tree/master/config/jobs/build-drivers) for new distro related jobs
* lastly, [test-infra](https://github.com/falcosecurity/test-infra) must be updated to add the new [prow config](https://github.com/falcosecurity/test-infra/tree/master/config/jobs/build-drivers) for new distro related jobs and `dbg-go` images must be bumped, see https://github.com/falcosecurity/test-infra/tree/master/images/build-drivers and https://github.com/falcosecurity/test-infra/tree/master/images/update-dbg.
Here, we will only focus about driverkit part. Here, we will only focus about driverkit part.
@ -38,7 +37,7 @@ Your builder will need a constant for the target it implements. Usually that con
can just be the ID of the distribution you are implementing, as taken reading `/etc/os-release` file. can just be the ID of the distribution you are implementing, as taken reading `/etc/os-release` file.
A builder can implement more than one target at time. For example, the minikube builder is just a vanilla one. A builder can implement more than one target at time. For example, the minikube builder is just a vanilla one.
Once you have the constant, you will need to add it to the [byTarget](https://github.com/falcosecurity/driverkit/blob/master/pkg/driverbuilder/builder/target.go) map. Once you have the constant, you will need to add it to the `BuilderByTarget` map.
Open your file and you will need to add something like this: Open your file and you will need to add something like this:
```go ```go
@ -49,7 +48,7 @@ type archLinux struct {
} }
func init() { func init() {
byTarget[TargetTypeArchLinux] = &archLinux{} BuilderByTarget[TargetTypeArchLinux] = &archLinux{}
} }
``` ```
@ -59,19 +58,15 @@ you just registered.
Here's a very minimalistic example: Here's a very minimalistic example:
```go ```go
func (c *archlinux) Name() string { func (c archlinux) Name() string {
return TargetTypeArchlinux.String() return TargetTypeArchlinux.String()
} }
func (c *archlinux) TemplateKernelUrlsScript() string { func (c archlinux) TemplateScript() string {
return archlinuxKernelTemplate return archlinuxTemplate
} }
func (c *archlinux) TemplateScript() string { func (c archlinux) URLs(cfg Config, kr kernelrelease.KernelRelease) ([]string, error) {
return archlinuxTemplate
}
func (c archlinux) URLs(kr kernelrelease.KernelRelease) ([]string, error) {
urls := []string{} urls := []string{}
if kr.Architecture == kernelrelease.ArchitectureAmd64 { if kr.Architecture == kernelrelease.ArchitectureAmd64 {
urls = append(urls, fmt.Sprintf("https://archive.archlinux.org/packages/l/linux-headers/linux-headers-%s.%s-%d-%s.pkg.tar.xz", urls = append(urls, fmt.Sprintf("https://archive.archlinux.org/packages/l/linux-headers/linux-headers-%s.%s-%d-%s.pkg.tar.xz",
@ -80,7 +75,7 @@ func (c archlinux) URLs(kr kernelrelease.KernelRelease) ([]string, error) {
cfg.KernelVersion, cfg.KernelVersion,
kr.Architecture.ToNonDeb())) kr.Architecture.ToNonDeb()))
} else { } else {
urls = append(urls, fmt.Sprintf("https://alaa.ad24.cz/packages/l/linux-%s-headers/linux-%s-headers-%s-%d-%s.pkg.tar.xz", urls = append(urls, fmt.Sprintf("http://tardis.tiny-vps.com/aarm/packages/l/linux-%s-headers/linux-%s-headers-%s-%d-%s.pkg.tar.xz",
kr.Architecture.ToNonDeb(), kr.Architecture.ToNonDeb(),
kr.Architecture.ToNonDeb(), kr.Architecture.ToNonDeb(),
kr.Fullversion, kr.Fullversion,
@ -90,17 +85,17 @@ func (c archlinux) URLs(kr kernelrelease.KernelRelease) ([]string, error) {
return urls, nil return urls, nil
} }
func (c *archlinux) KernelTemplateData(_ kernelrelease.KernelRelease, urls []string) interface{} { func (c archlinux) TemplateData(cfg Config, kr kernelrelease.KernelRelease, urls []string) interface{} {
return archlinuxTemplateData{ return archlinuxTemplateData{
KernelDownloadURL: urls[0], commonTemplateData: cfg.toTemplateData(),
KernelDownloadURL: urls[0],
} }
} }
``` ```
Essentially, the various methods that you are implementing are needed to: Essentially, the various methods that you are implementing are needed to:
* fill the kernel download/extract script template, a `bash` script responsible to fetch and extract the kernel headers for the distro * fill the script template (see below), that is a `bash` script that will be executed by driverkit at build time
* fill the build script template (see below), that is a `bash` script that will be executed by driverkit at build time * fetch kernel headers urls that will later be downloaded inside the builder container, and used for the driver build
* return a list of possible kernel headers urls that will later be downloaded by the kernel download script, and then used for the driver build
Under `pkg/driverbuilder/builder/templates` folder, you can find all the template scripts for the supported builders. Under `pkg/driverbuilder/builder/templates` folder, you can find all the template scripts for the supported builders.
Adding a new template there and using `go:embed` to include it in your builder, allows leaner code Adding a new template there and using `go:embed` to include it in your builder, allows leaner code
@ -108,57 +103,14 @@ without mixing up templates and builder logic.
For example: For example:
```go ```go
//go:embed templates/archlinux_kernel.sh
var archlinuxKernelTemplate string
//go:embed templates/archlinux.sh //go:embed templates/archlinux.sh
var archlinuxTemplate string var archlinuxTemplate string
``` ```
Depending on how the distro works, the "kernel" template script will fetch the kernel headers for it at the specific kernel version specified Depending on how the distro works, the script will need to fetch the kernel headers for it at the specific kernel version specified
in the `Config` struct at `c.Build.KernelVersion`, and then extracting them. in the `Config` struct at `c.Build.KernelVersion`.
Finally, the script will also `export` the `KERNELDIR` variable to be consumed by the actual build script.
Example kernel download template for archlinux:
```bash
set -xeuo pipefail
# Fetch the kernel
mkdir /tmp/kernel-download
cd /tmp/kernel-download
curl --silent -o kernel-devel.pkg.tar.xz -SL {{ .KernelDownloadURL }}
tar -xf kernel-devel.pkg.tar.xz
rm -Rf /tmp/kernel
mkdir -p /tmp/kernel
mv usr/lib/modules/*/build/* /tmp/kernel
# exit value
export KERNELDIR=/tmp/kernel
```
Once you have those, based on what that kernel can do and based on what was configured Once you have those, based on what that kernel can do and based on what was configured
by the user, the build script will build the kernel module driver and/or the eBPF probe driver. by the user you will need to build the kernel module driver and/or the eBPF probe driver.
Example build template for archlinux:
```bash
set -xeuo pipefail
cd {{ .DriverBuildDir }}
mkdir -p build && cd build
{{ .CmakeCmd }}
{{ if .BuildModule }}
# Build the module
make CC=/usr/bin/gcc-{{ .GCCVersion }} driver
strip -g {{ .ModuleFullPath }}
# Print results
modinfo {{ .ModuleFullPath }}
{{ end }}
{{ if .BuildProbe }}
# Build the eBPF probe
make bpf
ls -l driver/bpf/probe.o
{{ end }}
```
How does this work? How does this work?
@ -193,4 +145,4 @@ can also support collecting the new builders kernel versions and header package
for the new builder are automatically built by [test-infra](https://github.com/falcosecurity/test-infra). If required, add a feature request for the new builder are automatically built by [test-infra](https://github.com/falcosecurity/test-infra). If required, add a feature request
for support for the new builder on the kernel-crawler repository. for support for the new builder on the kernel-crawler repository.
> **NOTE**: be sure that the crawler you are going to add is interesting for the community as a whole. > **NOTE**: be sure that the crawler you are going to add is interesting for the community as a whole.

View File

@ -21,7 +21,7 @@ driverkit
--kernelrelease string kernel release to build the module for, it can be found by executing 'uname -v' --kernelrelease string kernel release to build the module for, it can be found by executing 'uname -v'
--kernelurls strings list of kernel header urls (e.g. --kernelurls <URL1> --kernelurls <URL2> --kernelurls "<URL3>,<URL4>") --kernelurls strings list of kernel header urls (e.g. --kernelurls <URL1> --kernelurls <URL2> --kernelurls "<URL3>,<URL4>")
--kernelversion string kernel version to build the module for, it's the numeric value after the hash when you execute 'uname -v' (default "1") --kernelversion string kernel version to build the module for, it's the numeric value after the hash when you execute 'uname -v' (default "1")
-l, --loglevel string set level for logs (info, warn, debug, trace) (default "info") -l, --loglevel string log level (default "INFO")
--moduledevicename string kernel module device name (the default is falco, so the device will be under /dev/falco*) (default "falco") --moduledevicename string kernel module device name (the default is falco, so the device will be under /dev/falco*) (default "falco")
--moduledrivername string kernel module driver name, i.e. the name you see when you check installed modules via lsmod (default "falco") --moduledrivername string kernel module driver name, i.e. the name you see when you check installed modules via lsmod (default "falco")
--output-module string filepath where to save the resulting kernel module --output-module string filepath where to save the resulting kernel module
@ -33,7 +33,7 @@ driverkit
--registry-user string registry username --registry-user string registry username
--repo-name string repository github name (default "libs") --repo-name string repository github name (default "libs")
--repo-org string repository github organization (default "falcosecurity") --repo-org string repository github organization (default "falcosecurity")
-t, --target string the system to target the build for, one of [alinux,almalinux,amazonlinux,amazonlinux2,amazonlinux2022,amazonlinux2023,arch,bottlerocket,centos,debian,fedora,flatcar,minikube,ol,opensuse,photon,redhat,rocky,sles,talos,ubuntu,vanilla] -t, --target string the system to target the build for, one of [alinux,almalinux,amazonlinux,amazonlinux2,amazonlinux2022,amazonlinux2023,arch,bottlerocket,centos,debian,fedora,flatcar,minikube,ol,opensuse,photon,redhat,rocky,talos,ubuntu,vanilla]
--timeout int timeout in seconds (default 120) --timeout int timeout in seconds (default 120)
``` ```
@ -44,5 +44,4 @@ driverkit
* [driverkit images](driverkit_images.md) - List builder images * [driverkit images](driverkit_images.md) - List builder images
* [driverkit kubernetes](driverkit_kubernetes.md) - Build Falco kernel modules and eBPF probes against a Kubernetes cluster. * [driverkit kubernetes](driverkit_kubernetes.md) - Build Falco kernel modules and eBPF probes against a Kubernetes cluster.
* [driverkit kubernetes-in-cluster](driverkit_kubernetes-in-cluster.md) - Build Falco kernel modules and eBPF probes against a Kubernetes cluster inside a Kubernetes cluster. * [driverkit kubernetes-in-cluster](driverkit_kubernetes-in-cluster.md) - Build Falco kernel modules and eBPF probes against a Kubernetes cluster inside a Kubernetes cluster.
* [driverkit local](driverkit_local.md) - Build Falco kernel modules and eBPF probes in local env with local kernel sources and gcc/clang.

View File

@ -21,7 +21,7 @@ driverkit docker [flags]
--kernelrelease string kernel release to build the module for, it can be found by executing 'uname -v' --kernelrelease string kernel release to build the module for, it can be found by executing 'uname -v'
--kernelurls strings list of kernel header urls (e.g. --kernelurls <URL1> --kernelurls <URL2> --kernelurls "<URL3>,<URL4>") --kernelurls strings list of kernel header urls (e.g. --kernelurls <URL1> --kernelurls <URL2> --kernelurls "<URL3>,<URL4>")
--kernelversion string kernel version to build the module for, it's the numeric value after the hash when you execute 'uname -v' (default "1") --kernelversion string kernel version to build the module for, it's the numeric value after the hash when you execute 'uname -v' (default "1")
-l, --loglevel string set level for logs (info, warn, debug, trace) (default "info") -l, --loglevel string log level (default "INFO")
--moduledevicename string kernel module device name (the default is falco, so the device will be under /dev/falco*) (default "falco") --moduledevicename string kernel module device name (the default is falco, so the device will be under /dev/falco*) (default "falco")
--moduledrivername string kernel module driver name, i.e. the name you see when you check installed modules via lsmod (default "falco") --moduledrivername string kernel module driver name, i.e. the name you see when you check installed modules via lsmod (default "falco")
--output-module string filepath where to save the resulting kernel module --output-module string filepath where to save the resulting kernel module
@ -33,7 +33,7 @@ driverkit docker [flags]
--registry-user string registry username --registry-user string registry username
--repo-name string repository github name (default "libs") --repo-name string repository github name (default "libs")
--repo-org string repository github organization (default "falcosecurity") --repo-org string repository github organization (default "falcosecurity")
-t, --target string the system to target the build for, one of [alinux,almalinux,amazonlinux,amazonlinux2,amazonlinux2022,amazonlinux2023,arch,bottlerocket,centos,debian,fedora,flatcar,minikube,ol,opensuse,photon,redhat,rocky,sles,talos,ubuntu,vanilla] -t, --target string the system to target the build for, one of [alinux,almalinux,amazonlinux,amazonlinux2,amazonlinux2022,amazonlinux2023,arch,bottlerocket,centos,debian,fedora,flatcar,minikube,ol,opensuse,photon,redhat,rocky,talos,ubuntu,vanilla]
--timeout int timeout in seconds (default 120) --timeout int timeout in seconds (default 120)
``` ```

View File

@ -21,7 +21,7 @@ driverkit images [flags]
--kernelrelease string kernel release to build the module for, it can be found by executing 'uname -v' --kernelrelease string kernel release to build the module for, it can be found by executing 'uname -v'
--kernelurls strings list of kernel header urls (e.g. --kernelurls <URL1> --kernelurls <URL2> --kernelurls "<URL3>,<URL4>") --kernelurls strings list of kernel header urls (e.g. --kernelurls <URL1> --kernelurls <URL2> --kernelurls "<URL3>,<URL4>")
--kernelversion string kernel version to build the module for, it's the numeric value after the hash when you execute 'uname -v' (default "1") --kernelversion string kernel version to build the module for, it's the numeric value after the hash when you execute 'uname -v' (default "1")
-l, --loglevel string set level for logs (info, warn, debug, trace) (default "info") -l, --loglevel string log level (default "INFO")
--moduledevicename string kernel module device name (the default is falco, so the device will be under /dev/falco*) (default "falco") --moduledevicename string kernel module device name (the default is falco, so the device will be under /dev/falco*) (default "falco")
--moduledrivername string kernel module driver name, i.e. the name you see when you check installed modules via lsmod (default "falco") --moduledrivername string kernel module driver name, i.e. the name you see when you check installed modules via lsmod (default "falco")
--output-module string filepath where to save the resulting kernel module --output-module string filepath where to save the resulting kernel module
@ -33,7 +33,7 @@ driverkit images [flags]
--registry-user string registry username --registry-user string registry username
--repo-name string repository github name (default "libs") --repo-name string repository github name (default "libs")
--repo-org string repository github organization (default "falcosecurity") --repo-org string repository github organization (default "falcosecurity")
-t, --target string the system to target the build for, one of [alinux,almalinux,amazonlinux,amazonlinux2,amazonlinux2022,amazonlinux2023,arch,bottlerocket,centos,debian,fedora,flatcar,minikube,ol,opensuse,photon,redhat,rocky,sles,talos,ubuntu,vanilla] -t, --target string the system to target the build for, one of [alinux,almalinux,amazonlinux,amazonlinux2,amazonlinux2022,amazonlinux2023,arch,bottlerocket,centos,debian,fedora,flatcar,minikube,ol,opensuse,photon,redhat,rocky,talos,ubuntu,vanilla]
--timeout int timeout in seconds (default 120) --timeout int timeout in seconds (default 120)
``` ```

View File

@ -22,7 +22,7 @@ driverkit kubernetes-in-cluster [flags]
--kernelrelease string kernel release to build the module for, it can be found by executing 'uname -v' --kernelrelease string kernel release to build the module for, it can be found by executing 'uname -v'
--kernelurls strings list of kernel header urls (e.g. --kernelurls <URL1> --kernelurls <URL2> --kernelurls "<URL3>,<URL4>") --kernelurls strings list of kernel header urls (e.g. --kernelurls <URL1> --kernelurls <URL2> --kernelurls "<URL3>,<URL4>")
--kernelversion string kernel version to build the module for, it's the numeric value after the hash when you execute 'uname -v' (default "1") --kernelversion string kernel version to build the module for, it's the numeric value after the hash when you execute 'uname -v' (default "1")
-l, --loglevel string set level for logs (info, warn, debug, trace) (default "info") -l, --loglevel string log level (default "INFO")
--moduledevicename string kernel module device name (the default is falco, so the device will be under /dev/falco*) (default "falco") --moduledevicename string kernel module device name (the default is falco, so the device will be under /dev/falco*) (default "falco")
--moduledrivername string kernel module driver name, i.e. the name you see when you check installed modules via lsmod (default "falco") --moduledrivername string kernel module driver name, i.e. the name you see when you check installed modules via lsmod (default "falco")
-n, --namespace string If present, the namespace scope for the pods and its config (default "default") -n, --namespace string If present, the namespace scope for the pods and its config (default "default")
@ -36,7 +36,7 @@ driverkit kubernetes-in-cluster [flags]
--repo-name string repository github name (default "libs") --repo-name string repository github name (default "libs")
--repo-org string repository github organization (default "falcosecurity") --repo-org string repository github organization (default "falcosecurity")
--run-as-user int Pods runner user --run-as-user int Pods runner user
-t, --target string the system to target the build for, one of [alinux,almalinux,amazonlinux,amazonlinux2,amazonlinux2022,amazonlinux2023,arch,bottlerocket,centos,debian,fedora,flatcar,minikube,ol,opensuse,photon,redhat,rocky,sles,talos,ubuntu,vanilla] -t, --target string the system to target the build for, one of [alinux,almalinux,amazonlinux,amazonlinux2,amazonlinux2022,amazonlinux2023,arch,bottlerocket,centos,debian,fedora,flatcar,minikube,ol,opensuse,photon,redhat,rocky,talos,ubuntu,vanilla]
--timeout int timeout in seconds (default 120) --timeout int timeout in seconds (default 120)
``` ```

View File

@ -22,7 +22,6 @@ driverkit kubernetes [flags]
--cluster string the name of the kubeconfig cluster to use --cluster string the name of the kubeconfig cluster to use
-c, --config string config file path (default $HOME/.driverkit.yaml if exists) -c, --config string config file path (default $HOME/.driverkit.yaml if exists)
--context string the name of the kubeconfig context to use --context string the name of the kubeconfig context to use
--disable-compression if true, opt-out of response compression for all requests to the server
--driverversion string driver version as a git commit hash or as a git tag (default "master") --driverversion string driver version as a git commit hash or as a git tag (default "master")
--dryrun do not actually perform the action --dryrun do not actually perform the action
--gccversion string enforce a specific gcc version for the build --gccversion string enforce a specific gcc version for the build
@ -34,7 +33,7 @@ driverkit kubernetes [flags]
--kernelurls strings list of kernel header urls (e.g. --kernelurls <URL1> --kernelurls <URL2> --kernelurls "<URL3>,<URL4>") --kernelurls strings list of kernel header urls (e.g. --kernelurls <URL1> --kernelurls <URL2> --kernelurls "<URL3>,<URL4>")
--kernelversion string kernel version to build the module for, it's the numeric value after the hash when you execute 'uname -v' (default "1") --kernelversion string kernel version to build the module for, it's the numeric value after the hash when you execute 'uname -v' (default "1")
--kubeconfig string path to the kubeconfig file to use for CLI requests --kubeconfig string path to the kubeconfig file to use for CLI requests
-l, --loglevel string set level for logs (info, warn, debug, trace) (default "info") -l, --loglevel string log level (default "info")
--moduledevicename string kernel module device name (the default is falco, so the device will be under /dev/falco*) (default "falco") --moduledevicename string kernel module device name (the default is falco, so the device will be under /dev/falco*) (default "falco")
--moduledrivername string kernel module driver name, i.e. the name you see when you check installed modules via lsmod (default "falco") --moduledrivername string kernel module driver name, i.e. the name you see when you check installed modules via lsmod (default "falco")
-n, --namespace string If present, the namespace scope for the pods and its config (default "default") -n, --namespace string If present, the namespace scope for the pods and its config (default "default")
@ -50,7 +49,7 @@ driverkit kubernetes [flags]
--request-timeout string the length of time to wait before giving up on a single server request, non-zero values should contain a corresponding time unit (e.g, 1s, 2m, 3h), a value of zero means don't timeout requests (default "0") --request-timeout string the length of time to wait before giving up on a single server request, non-zero values should contain a corresponding time unit (e.g, 1s, 2m, 3h), a value of zero means don't timeout requests (default "0")
--run-as-user int Pods runner user --run-as-user int Pods runner user
-s, --server string the address and port of the Kubernetes API server -s, --server string the address and port of the Kubernetes API server
-t, --target string the system to target the build for, one of [alinux,almalinux,amazonlinux,amazonlinux2,amazonlinux2022,amazonlinux2023,arch,bottlerocket,centos,debian,fedora,flatcar,minikube,ol,opensuse,photon,redhat,rocky,sles,talos,ubuntu,vanilla] -t, --target string the system to target the build for, one of [alinux,almalinux,amazonlinux,amazonlinux2,amazonlinux2022,amazonlinux2023,arch,bottlerocket,centos,debian,fedora,flatcar,minikube,ol,opensuse,photon,redhat,rocky,talos,ubuntu,vanilla]
--timeout int timeout in seconds (default 120) --timeout int timeout in seconds (default 120)
--tls-server-name string server name to use for server certificate validation, if it is not provided, the hostname used to contact the server is used --tls-server-name string server name to use for server certificate validation, if it is not provided, the hostname used to contact the server is used
--token string bearer token for authentication to the API server --token string bearer token for authentication to the API server

View File

@ -1,36 +0,0 @@
## driverkit local
Build Falco kernel modules and eBPF probes in local env with local kernel sources and gcc/clang.
```
driverkit local [flags]
```
### Options
```
-c, --config string config file path (default $HOME/.driverkit.yaml if exists)
--dkms Enforce usage of DKMS to build the kernel module.
--download-headers Try to automatically download kernel headers.
--driverversion string driver version as a git commit hash or as a git tag (default "master")
--dryrun do not actually perform the action
--env stringToString Env variables to be enforced during the driver build. (default [])
-h, --help help for local
--kernelrelease string kernel release to build the module for, it can be found by executing 'uname -v'
--kernelversion string kernel version to build the module for, it's the numeric value after the hash when you execute 'uname -v' (default "1")
-l, --loglevel string set level for logs (info, warn, debug, trace) (default "info")
--moduledevicename string kernel module device name (the default is falco, so the device will be under /dev/falco*) (default "falco")
--moduledrivername string kernel module driver name, i.e. the name you see when you check installed modules via lsmod (default "falco")
--output-module string filepath where to save the resulting kernel module
--output-probe string filepath where to save the resulting eBPF probe
--repo-name string repository github name (default "libs")
--repo-org string repository github organization (default "falcosecurity")
--src-dir string Enforce usage of local source dir to build drivers.
-t, --target string the system to target the build for, one of [alinux,almalinux,amazonlinux,amazonlinux2,amazonlinux2022,amazonlinux2023,arch,bottlerocket,centos,debian,fedora,flatcar,minikube,ol,opensuse,photon,redhat,rocky,sles,talos,ubuntu,vanilla]
--timeout int timeout in seconds (default 120)
```
### SEE ALSO
* [driverkit](driverkit.md) - A command line tool to build Falco kernel modules and eBPF probes.

164
go.mod
View File

@ -1,51 +1,46 @@
module github.com/falcosecurity/driverkit module github.com/falcosecurity/driverkit
go 1.24.1 go 1.21
toolchain go1.24.2
require ( require (
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d
github.com/blang/semver/v4 v4.0.0 github.com/blang/semver v3.5.1+incompatible
github.com/containerd/containerd v1.7.14 // indirect
github.com/creasty/defaults v1.7.0 github.com/creasty/defaults v1.7.0
github.com/docker/docker v28.3.3+incompatible github.com/docker/docker v26.0.0+incompatible
github.com/falcosecurity/falcoctl v0.11.1
github.com/go-playground/locales v0.14.1 github.com/go-playground/locales v0.14.1
github.com/go-playground/universal-translator v0.18.1 github.com/go-playground/universal-translator v0.18.1
github.com/go-playground/validator/v10 v10.24.0 github.com/go-playground/validator/v10 v10.19.0
github.com/mitchellh/go-homedir v1.1.0 github.com/mitchellh/go-homedir v1.1.0
github.com/olekukonko/tablewriter v0.0.5 github.com/opencontainers/image-spec v1.1.0
github.com/opencontainers/image-spec v1.1.1 github.com/sirupsen/logrus v1.9.3 // indirect
github.com/pterm/pterm v0.12.80 github.com/spf13/cobra v1.8.0
github.com/spf13/cobra v1.9.1 github.com/spf13/pflag v1.0.5
github.com/spf13/pflag v1.0.6 github.com/spf13/viper v1.18.2
github.com/spf13/viper v1.20.0
gopkg.in/yaml.v3 v3.0.1
gotest.tools v2.2.0+incompatible gotest.tools v2.2.0+incompatible
k8s.io/api v0.32.3 k8s.io/api v0.29.3
k8s.io/apimachinery v0.32.3 k8s.io/apimachinery v0.29.3
k8s.io/cli-runtime v0.30.0 k8s.io/cli-runtime v0.29.3
k8s.io/client-go v0.32.3 k8s.io/client-go v0.29.3
k8s.io/kubectl v0.30.0 k8s.io/kubectl v0.29.3
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 k8s.io/utils v0.0.0-20240310230437-4693a0247e57
modernc.org/sqlite v1.29.9 modernc.org/sqlite v1.29.5
)
require (
github.com/falcosecurity/falcoctl v0.7.3
github.com/olekukonko/tablewriter v0.0.5
gopkg.in/yaml.v3 v3.0.1
oras.land/oras-go/v2 v2.5.0 oras.land/oras-go/v2 v2.5.0
) )
require ( require (
atomicgo.dev/cursor v0.2.0 // indirect github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect
atomicgo.dev/keyboard v0.2.9 // indirect
atomicgo.dev/schedule v0.1.0 // indirect
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect
github.com/MakeNowJust/heredoc v1.0.0 // indirect github.com/MakeNowJust/heredoc v1.0.0 // indirect
github.com/Microsoft/go-winio v0.6.2 // indirect github.com/Microsoft/go-winio v0.6.1 // indirect
github.com/chai2010/gettext-go v1.0.3 // indirect github.com/chai2010/gettext-go v1.0.2 // indirect
github.com/containerd/console v1.0.4 // indirect
github.com/containerd/errdefs v1.0.0 // indirect
github.com/containerd/errdefs/pkg v0.3.0 // indirect
github.com/containerd/log v0.1.0 // indirect github.com/containerd/log v0.1.0 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.6 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.3 // indirect
github.com/creack/pty v1.1.21 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/distribution/reference v0.6.0 // indirect github.com/distribution/reference v0.6.0 // indirect
github.com/docker/go-connections v0.5.0 // indirect github.com/docker/go-connections v0.5.0 // indirect
@ -56,49 +51,46 @@ require (
github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f // indirect github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f // indirect
github.com/fatih/camelcase v1.0.0 // indirect github.com/fatih/camelcase v1.0.0 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/fsnotify/fsnotify v1.8.0 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/fvbommel/sortorder v1.1.0 // indirect github.com/fvbommel/sortorder v1.1.0 // indirect
github.com/fxamacker/cbor/v2 v2.7.0 // indirect github.com/gabriel-vasile/mimetype v1.4.3 // indirect
github.com/gabriel-vasile/mimetype v1.4.8 // indirect
github.com/go-errors/errors v1.5.1 // indirect github.com/go-errors/errors v1.5.1 // indirect
github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/logr v1.4.1 // indirect
github.com/go-logr/stdr v1.2.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-openapi/jsonpointer v0.21.0 // indirect github.com/go-openapi/jsonpointer v0.21.0 // indirect
github.com/go-openapi/jsonreference v0.21.0 // indirect github.com/go-openapi/jsonreference v0.21.0 // indirect
github.com/go-openapi/swag v0.23.0 // indirect github.com/go-openapi/swag v0.23.0 // indirect
github.com/go-viper/mapstructure/v2 v2.3.0 // indirect
github.com/gogo/protobuf v1.3.2 // indirect github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/protobuf v1.5.4 // indirect github.com/golang/protobuf v1.5.4 // indirect
github.com/google/btree v1.1.3 // indirect github.com/google/btree v1.1.2 // indirect
github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49 // indirect github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49 // indirect
github.com/google/go-cmp v0.7.0 // indirect github.com/google/go-cmp v0.6.0 // indirect
github.com/google/gofuzz v1.2.0 // indirect github.com/google/gofuzz v1.2.0 // indirect
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
github.com/google/uuid v1.6.0 // indirect github.com/google/uuid v1.6.0 // indirect
github.com/gookit/color v1.5.4 // indirect
github.com/gorilla/websocket v1.5.1 // indirect github.com/gorilla/websocket v1.5.1 // indirect
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
github.com/hashicorp/hcl v1.0.1-vault-5 // indirect
github.com/imdario/mergo v0.3.16 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/josharian/intern v1.0.0 // indirect github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/compress v1.18.0 // indirect github.com/klauspost/compress v1.17.7 // indirect
github.com/leodido/go-urn v1.4.0 // indirect github.com/leodido/go-urn v1.4.0 // indirect
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect
github.com/lithammer/fuzzysearch v1.1.8 // indirect github.com/magiconair/properties v1.8.7 // indirect
github.com/mailru/easyjson v0.7.7 // indirect github.com/mailru/easyjson v0.7.7 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-runewidth v0.0.16 // indirect github.com/mattn/go-runewidth v0.0.15 // indirect
github.com/mitchellh/go-wordwrap v1.0.1 // indirect github.com/mitchellh/go-wordwrap v1.0.1 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/moby/docker-image-spec v1.3.1 // indirect github.com/moby/docker-image-spec v1.3.1 // indirect
github.com/moby/go-archive v0.1.0 // indirect
github.com/moby/patternmatcher v0.6.0 // indirect github.com/moby/patternmatcher v0.6.0 // indirect
github.com/moby/spdystream v0.5.0 // indirect github.com/moby/spdystream v0.2.0 // indirect
github.com/moby/sys/atomicwriter v0.1.0 // indirect github.com/moby/sys/sequential v0.5.0 // indirect
github.com/moby/sys/sequential v0.6.0 // indirect github.com/moby/sys/user v0.1.0 // indirect
github.com/moby/sys/user v0.4.0 // indirect github.com/moby/term v0.5.0 // indirect
github.com/moby/sys/userns v0.1.0 // indirect
github.com/moby/term v0.5.2 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect
@ -107,56 +99,56 @@ require (
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect
github.com/ncruces/go-strftime v0.1.9 // indirect github.com/ncruces/go-strftime v0.1.9 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/pelletier/go-toml/v2 v2.2.3 // indirect github.com/pelletier/go-toml/v2 v2.2.0 // indirect
github.com/peterbourgon/diskv v2.0.1+incompatible // indirect github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
github.com/pkg/errors v0.9.1 // indirect github.com/pkg/errors v0.9.1 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/rivo/uniseg v0.4.7 // indirect github.com/rivo/uniseg v0.4.7 // indirect
github.com/rogpeppe/go-internal v1.13.2-0.20241226121412-a5dc8ff20d0a // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/sagikazarmark/locafero v0.7.0 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect
github.com/sergi/go-diff v1.3.1 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect github.com/sergi/go-diff v1.2.0 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect github.com/sourcegraph/conc v0.3.0 // indirect
github.com/spf13/afero v1.12.0 // indirect github.com/spf13/afero v1.11.0 // indirect
github.com/spf13/cast v1.7.1 // indirect github.com/spf13/cast v1.6.0 // indirect
github.com/subosito/gotenv v1.6.0 // indirect github.com/subosito/gotenv v1.6.0 // indirect
github.com/x448/float16 v0.8.4 // indirect
github.com/xlab/treeprint v1.2.0 // indirect github.com/xlab/treeprint v1.2.0 // indirect
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect
go.opentelemetry.io/auto/sdk v1.1.0 // indirect go.opentelemetry.io/otel v1.24.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 // indirect go.opentelemetry.io/otel/metric v1.24.0 // indirect
go.opentelemetry.io/otel v1.34.0 // indirect go.opentelemetry.io/otel/trace v1.24.0 // indirect
go.opentelemetry.io/otel/metric v1.34.0 // indirect go.starlark.net v0.0.0-20240314022150-ee8ed142361c // indirect
go.opentelemetry.io/otel/trace v1.34.0 // indirect
go.starlark.net v0.0.0-20240507195648-35fe9f26b4bc // indirect
go.uber.org/multierr v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect
golang.org/x/crypto v0.36.0 // indirect golang.org/x/crypto v0.21.0 // indirect
golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f // indirect golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8 // indirect
golang.org/x/net v0.38.0 // indirect golang.org/x/mod v0.16.0 // indirect
golang.org/x/oauth2 v0.28.0 // indirect golang.org/x/net v0.22.0 // indirect
golang.org/x/sync v0.12.0 // indirect golang.org/x/oauth2 v0.18.0 // indirect
golang.org/x/sys v0.31.0 // indirect golang.org/x/sync v0.6.0 // indirect
golang.org/x/term v0.30.0 // indirect golang.org/x/sys v0.18.0 // indirect
golang.org/x/text v0.23.0 // indirect golang.org/x/term v0.18.0 // indirect
golang.org/x/time v0.11.0 // indirect golang.org/x/text v0.14.0 // indirect
google.golang.org/protobuf v1.36.5 // indirect golang.org/x/time v0.5.0 // indirect
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect golang.org/x/tools v0.19.0 // indirect
google.golang.org/appengine v1.6.8 // indirect
google.golang.org/protobuf v1.33.0 // indirect
gopkg.in/evanphx/json-patch.v5 v5.9.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect
gotest.tools/v3 v3.5.2 // indirect gotest.tools/v3 v3.4.0 // indirect
k8s.io/component-base v0.30.0 // indirect k8s.io/component-base v0.29.3 // indirect
k8s.io/klog/v2 v2.130.1 // indirect k8s.io/klog/v2 v2.120.1 // indirect
k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f // indirect k8s.io/kube-openapi v0.0.0-20240322212309-b815d8309940 // indirect
modernc.org/gc/v3 v3.0.0-20240304020402-f0dba7c97c2b // indirect modernc.org/gc/v3 v3.0.0-20240304020402-f0dba7c97c2b // indirect
modernc.org/libc v1.50.5 // indirect modernc.org/libc v1.49.0 // indirect
modernc.org/mathutil v1.6.0 // indirect modernc.org/mathutil v1.6.0 // indirect
modernc.org/memory v1.8.0 // indirect modernc.org/memory v1.7.2 // indirect
modernc.org/strutil v1.2.0 // indirect modernc.org/strutil v1.2.0 // indirect
modernc.org/token v1.1.0 // indirect modernc.org/token v1.1.0 // indirect
sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
sigs.k8s.io/kustomize/api v0.17.1 // indirect sigs.k8s.io/kustomize/api v0.16.0 // indirect
sigs.k8s.io/kustomize/kyaml v0.17.0 // indirect sigs.k8s.io/kustomize/kyaml v0.16.0 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.4.2 // indirect sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect
sigs.k8s.io/yaml v1.4.0 // indirect sigs.k8s.io/yaml v1.4.0 // indirect
) )

444
go.sum
View File

@ -1,52 +1,31 @@
atomicgo.dev/assert v0.0.2 h1:FiKeMiZSgRrZsPo9qn/7vmr7mCsh5SZyXY4YGYiYwrg= github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU=
atomicgo.dev/assert v0.0.2/go.mod h1:ut4NcI3QDdJtlmAxQULOmA13Gz6e2DWbSAS8RUOmNYQ= github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8=
atomicgo.dev/cursor v0.2.0 h1:H6XN5alUJ52FZZUkI7AlJbUc1aW38GWZalpYRPpoPOw= github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0=
atomicgo.dev/cursor v0.2.0/go.mod h1:Lr4ZJB3U7DfPPOkbH7/6TOtJ4vFGHlgj1nc+n900IpU= github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
atomicgo.dev/keyboard v0.2.9 h1:tOsIid3nlPLZ3lwgG8KZMp/SFmr7P0ssEN5JUsm78K8=
atomicgo.dev/keyboard v0.2.9/go.mod h1:BC4w9g00XkxH/f1HXhW2sXmJFOCWbKn9xrOunSFtExQ=
atomicgo.dev/schedule v0.1.0 h1:nTthAbhZS5YZmgYbb2+DH8uQIZcTlIrd4eYr3UQxEjs=
atomicgo.dev/schedule v0.1.0/go.mod h1:xeUa3oAkiuHYh8bKiQBRojqAMq3PXXbJujjb0hw8pEU=
github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 h1:He8afgbRMd7mFxO99hRNu+6tazq8nFF9lIwo9JFroBk=
github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8=
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c h1:udKWzYgxTojEKWjV8V+WSxDXJ4NFATAsZjh8iIbsQIg=
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ= github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ=
github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE= github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE=
github.com/MarvinJWendt/testza v0.1.0/go.mod h1:7AxNvlfeHP7Z/hDQ5JtE3OKYT3XFUeLCDE2DQninSqs= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=
github.com/MarvinJWendt/testza v0.2.1/go.mod h1:God7bhG8n6uQxwdScay+gjm9/LnO4D3kkcZX4hv9Rp8= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
github.com/MarvinJWendt/testza v0.2.8/go.mod h1:nwIcjmr0Zz+Rcwfh3/4UhBp7ePKVhuBExvZqnKYWlII= github.com/Microsoft/hcsshim v0.11.4 h1:68vKo2VN8DE9AdN4tnkWnmdhqdbpUFM8OF3Airm7fz8=
github.com/MarvinJWendt/testza v0.2.10/go.mod h1:pd+VWsoGUiFtq+hRKSU1Bktnn+DMCSrDrXDpX2bG66k= github.com/Microsoft/hcsshim v0.11.4/go.mod h1:smjE4dvqPX9Zldna+t5FG3rnoHhaB7QYxPRqGcpAD9w=
github.com/MarvinJWendt/testza v0.2.12/go.mod h1:JOIegYyV7rX+7VZ9r77L/eH6CfJHHzXjB69adAhzZkI=
github.com/MarvinJWendt/testza v0.3.0/go.mod h1:eFcL4I0idjtIx8P9C6KkAuLgATNKpX4/2oUqKc6bF2c=
github.com/MarvinJWendt/testza v0.4.2/go.mod h1:mSdhXiKH8sg/gQehJ63bINcCKp7RtYewEjXsvsVUPbE=
github.com/MarvinJWendt/testza v0.5.2 h1:53KDo64C1z/h/d/stCYCPY69bt/OSwjq5KpFNwi+zB4=
github.com/MarvinJWendt/testza v0.5.2/go.mod h1:xu53QFE5sCdjtMCKk8YMQ2MnymimEctc4n3EjyIYvEY=
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d h1:licZJFw2RwpHMqeKTCYkitsPqHNxTmd4SNR5r94FGM8= github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d h1:licZJFw2RwpHMqeKTCYkitsPqHNxTmd4SNR5r94FGM8=
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d/go.mod h1:asat636LX7Bqt5lYEZ27JNDcqxfjdBQuJ/MM4CN/Lzo= github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d/go.mod h1:asat636LX7Bqt5lYEZ27JNDcqxfjdBQuJ/MM4CN/Lzo=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
github.com/atomicgo/cursor v0.0.1/go.mod h1:cBON2QmmrysudxNBFthvMtN32r3jxVRIvzkUiF/RuIk= github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ=
github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM=
github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/chai2010/gettext-go v1.0.2 h1:1Lwwip6Q2QGsAdl/ZKPCwTe9fe0CjlUbqj5bFNSjIRk=
github.com/chai2010/gettext-go v1.0.3 h1:9liNh8t+u26xl5ddmWLmsOsdNLwkdRTg5AG+JnTiM80= github.com/chai2010/gettext-go v1.0.2/go.mod h1:y+wnP2cHYaVj19NZhYKAwEMH2CI1gNHeQQ+5AjwawxA=
github.com/chai2010/gettext-go v1.0.3/go.mod h1:y+wnP2cHYaVj19NZhYKAwEMH2CI1gNHeQQ+5AjwawxA= github.com/containerd/containerd v1.7.14 h1:H/XLzbnGuenZEGK+v0RkwTdv2u1QFAruMe5N0GNPJwA=
github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= github.com/containerd/containerd v1.7.14/go.mod h1:YMC9Qt5yzNqXx/fO4j/5yYVIHXSRrlB3H7sxkUTvspg=
github.com/containerd/console v1.0.4 h1:F2g4+oChYvBTsASRTz8NP6iIAi97J3TtSAsLbIFn4ro=
github.com/containerd/console v1.0.4/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk=
github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI=
github.com/containerd/errdefs v1.0.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M=
github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE=
github.com/containerd/errdefs/pkg v0.3.0/go.mod h1:NJw6s9HwNuRhnjJhM7pylWwMyAkmCQvQ4GpJHEqRLVk=
github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=
github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo=
github.com/cpuguy83/go-md2man/v2 v2.0.6 h1:XJtiaUW6dEEqVuZiMTn1ldk455QWwEIsMIJlo5vtkx0= github.com/cpuguy83/go-md2man/v2 v2.0.3 h1:qMCsGGgs+MAzDFyp9LpAe1Lqy/fY/qCovCm0qnXZOBM=
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/creack/pty v1.1.21 h1:1/QdRyBaHHJP61QkWMXlOIBfsgdDeeKfK8SYVUWJKf0= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=
github.com/creack/pty v1.1.21/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
github.com/creasty/defaults v1.7.0 h1:eNdqZvc5B509z18lD8yc212CAqJNvfT1Jq6L8WowdBA= github.com/creasty/defaults v1.7.0 h1:eNdqZvc5B509z18lD8yc212CAqJNvfT1Jq6L8WowdBA=
github.com/creasty/defaults v1.7.0/go.mod h1:iGzKe6pbEHnpMPtfDXZEr0NVxWnPTjb1bbDy08fPzYM= github.com/creasty/defaults v1.7.0/go.mod h1:iGzKe6pbEHnpMPtfDXZEr0NVxWnPTjb1bbDy08fPzYM=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@ -55,8 +34,8 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
github.com/docker/docker v28.3.3+incompatible h1:Dypm25kh4rmk49v1eiVbsAtpAsYURjYkaKubwuBdxEI= github.com/docker/docker v26.0.0+incompatible h1:Ng2qi+gdKADUa/VM+6b6YaY2nlZhk/lVJiKR/2bMudU=
github.com/docker/docker v28.3.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v26.0.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c=
github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc=
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
@ -69,27 +48,25 @@ github.com/evanphx/json-patch v5.9.0+incompatible h1:fBXyNpNMuTTDdquAq/uisOr2lSh
github.com/evanphx/json-patch v5.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch v5.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f h1:Wl78ApPPB2Wvf/TIe2xdyJxTlb6obmF18d8QdkxNDu4= github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f h1:Wl78ApPPB2Wvf/TIe2xdyJxTlb6obmF18d8QdkxNDu4=
github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f/go.mod h1:OSYXu++VVOHnXeitef/D8n/6y4QV8uLHSFXX4NeXMGc= github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f/go.mod h1:OSYXu++VVOHnXeitef/D8n/6y4QV8uLHSFXX4NeXMGc=
github.com/falcosecurity/falcoctl v0.11.1 h1:slBPwAPs5n5CO2Lro1w7ugemu8WuCOoKnfnL45IHhmQ= github.com/falcosecurity/falcoctl v0.7.3 h1:Xhd7DoGKvHgLEAjglxx6SSvXvcaPY+krbA3ouOBqVm0=
github.com/falcosecurity/falcoctl v0.11.1/go.mod h1:sD9ghf9R/uFeY8X9fimecMwtvqLbrMn5+jcpwQfPeJQ= github.com/falcosecurity/falcoctl v0.7.3/go.mod h1:oTe3WFuLjoE5Oka2JspMA3X7mR6aOuIck32ArEM0YlU=
github.com/fatih/camelcase v1.0.0 h1:hxNvNX/xYBp0ovncs8WyWZrOrpBNub/JfaMvbURyft8= github.com/fatih/camelcase v1.0.0 h1:hxNvNX/xYBp0ovncs8WyWZrOrpBNub/JfaMvbURyft8=
github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc= github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc=
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
github.com/fvbommel/sortorder v1.1.0 h1:fUmoe+HLsBTctBDoaBwpQo5N+nrCp8g/BjKb/6ZQmYw= github.com/fvbommel/sortorder v1.1.0 h1:fUmoe+HLsBTctBDoaBwpQo5N+nrCp8g/BjKb/6ZQmYw=
github.com/fvbommel/sortorder v1.1.0/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0= github.com/fvbommel/sortorder v1.1.0/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0=
github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM=
github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8=
github.com/go-errors/errors v1.5.1 h1:ZwEMSLRCapFLflTpT7NKaAc7ukJ8ZPEjzlxt8rPN8bk= github.com/go-errors/errors v1.5.1 h1:ZwEMSLRCapFLflTpT7NKaAc7ukJ8ZPEjzlxt8rPN8bk=
github.com/go-errors/errors v1.5.1/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= github.com/go-errors/errors v1.5.1/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og=
github.com/go-logr/logr v1.2.2/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.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= 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-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ= github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ=
@ -104,45 +81,46 @@ github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/o
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
github.com/go-playground/validator/v10 v10.24.0 h1:KHQckvo8G6hlWnrPX4NJJ+aBfWNAE/HH+qdL2cBpCmg= github.com/go-playground/validator/v10 v10.19.0 h1:ol+5Fu+cSq9JD7SoSqe04GMI92cbn0+wvQ3bZ8b/AU4=
github.com/go-playground/validator/v10 v10.24.0/go.mod h1:GGzBIJMuE98Ic/kJsBXbz1x/7cByt++cQ+YOuDM5wus= github.com/go-playground/validator/v10 v10.19.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
github.com/go-viper/mapstructure/v2 v2.3.0 h1:27XbWsHIqhbdR5TIC911OfYvgSaW93HM+dX7970Q7jk=
github.com/go-viper/mapstructure/v2 v2.3.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg= github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU=
github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49 h1:0VpGH+cDhbDtdcweoyCVsF3fhN8kejK6rFe/2FFX2nU= github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49 h1:0VpGH+cDhbDtdcweoyCVsF3fhN8kejK6rFe/2FFX2nU=
github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49/go.mod h1:BkkQ4L1KS1xMt2aWSPStnn55ChGC0DPOn2FQYj+f25M= github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49/go.mod h1:BkkQ4L1KS1xMt2aWSPStnn55ChGC0DPOn2FQYj+f25M=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad h1:a6HEuzUHeKH6hwfN/ZoQgRgVIWFJljSWa/zetS2WTvg= github.com/google/pprof v0.0.0-20231023181126-ff6d637d2a7b h1:RMpPgZTSApbPf7xaVel+QkoGPRLFLrwFO89uDUHEGf0=
github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= github.com/google/pprof v0.0.0-20231023181126-ff6d637d2a7b/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gookit/color v1.4.2/go.mod h1:fqRyamkC1W8uxl+lxCQxOT09l/vYfZ+QeiX3rKQHCoQ= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gookit/color v1.5.0/go.mod h1:43aQb+Zerm/BWh2GnrgOQm7ffz7tvQXEKV6BFMl7wAo=
github.com/gookit/color v1.5.4 h1:FZmqs7XOyGgCAxmWyPslpiok1k05wmY3SJTytgvYFs0=
github.com/gookit/color v1.5.4/go.mod h1:pZJOeOS8DM43rXbp4AZo1n9zCU2qjpcRko0b6/QJi9w=
github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY=
github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY=
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 h1:+ngKgrYPPJrOjhax5N+uePQ0Fh1Z7PheYoUI/0nzkPA= github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 h1:+ngKgrYPPJrOjhax5N+uePQ0Fh1Z7PheYoUI/0nzkPA=
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1 h1:VNqngBF40hVlDloBruUehVYC3ArSgIyScOAyMRqBxRg= github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 h1:YBftPWNWd4WwGqtY2yeZL2ef8rHAxPBD8KFhJpmcqms=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1/go.mod h1:RBRO7fro65R6tjKzYgLAFo0t1QEXY1Dp+i/bvpRiqiQ= github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg=
github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
github.com/hashicorp/hcl v1.0.1-vault-5 h1:kI3hhbbyzr4dldA8UdTb7ZlVVlI2DACdCfz31RPDgJM=
github.com/hashicorp/hcl v1.0.1-vault-5/go.mod h1:XYhtn6ijBSAj6n4YqAaf7RBPS4I06AItNorpy+MoQNM=
github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4=
github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
@ -151,13 +129,8 @@ github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnr
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg=
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.0.10/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c=
github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c=
github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM=
github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
@ -169,38 +142,35 @@ github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0= github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0=
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE= github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE=
github.com/lithammer/fuzzysearch v1.1.8 h1:/HIuJnjHuXS8bKaiTMeeDlW2/AyIWk2brx1V8LFgLN4= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
github.com/lithammer/fuzzysearch v1.1.8/go.mod h1:IdqeyBClc3FFqSzYq/MXESsS4S0FsZ5ajtkr5xPLts4= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0=
github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
github.com/moby/go-archive v0.1.0 h1:Kk/5rdW/g+H8NHdJW2gsXyZ7UnzvJNOy6VKJqueWdcQ=
github.com/moby/go-archive v0.1.0/go.mod h1:G9B+YoujNohJmrIYFBpSd54GTUB4lt9S+xVQvsJyFuo=
github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk= github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk=
github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc= github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc=
github.com/moby/spdystream v0.5.0 h1:7r0J1Si3QO/kjRitvSLVVFUjxMEb/YLj6S9FF62JBCU= github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8=
github.com/moby/spdystream v0.5.0/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVOwrfMgdI= github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c=
github.com/moby/sys/atomicwriter v0.1.0 h1:kw5D/EqkBwsBFi0ss9v1VG3wIkVhzGvLklJ+w3A14Sw= github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc=
github.com/moby/sys/atomicwriter v0.1.0/go.mod h1:Ul8oqv2ZMNHOceF643P6FKPXeCmYtlQMvpizfsSoaWs= github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo=
github.com/moby/sys/sequential v0.6.0 h1:qrx7XFUd/5DxtqcoH1h438hF5TmOvzC/lspjy7zgvCU= github.com/moby/sys/user v0.1.0 h1:WmZ93f5Ux6het5iituh9x2zAG7NFY9Aqi49jjE1PaQg=
github.com/moby/sys/sequential v0.6.0/go.mod h1:uyv8EUTrca5PnDsdMGXhZe6CCe8U/UiTWd+lL+7b/Ko= github.com/moby/sys/user v0.1.0/go.mod h1:fKJhFOnsCN6xZ5gSfbM6zaHGgDJMrqt9/reuj4T7MmU=
github.com/moby/sys/user v0.4.0 h1:jhcMKit7SA80hivmFJcbB1vqmw//wU61Zdui2eQXuMs= github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0=
github.com/moby/sys/user v0.4.0/go.mod h1:bG+tYYYJgaMtRKgEmuueC0hJEAZWwtIbZTB+85uoHjs= github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y=
github.com/moby/sys/userns v0.1.0 h1:tVLXkFOxVu9A64/yh59slHVv9ahO9UIev4JZusOLG/g=
github.com/moby/sys/userns v0.1.0/go.mod h1:IHUYgu/kao6N8YZlp9Cf444ySSvCmDlmzUcYfDHOl28=
github.com/moby/term v0.5.2 h1:6qk3FJAFDs6i/q3W/pQ97SX192qKfZgGjCQqfCJkgzQ=
github.com/moby/term v0.5.2/go.mod h1:d3djjFCrjnB+fl8NJux+EJzu0msscUP+f8it8hPkFLc=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
@ -218,16 +188,16 @@ github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdh
github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls= github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
github.com/onsi/ginkgo/v2 v2.23.3 h1:edHxnszytJ4lD9D5Jjc4tiDkPBZ3siDeJJkUZJJVkp0= github.com/onsi/ginkgo/v2 v2.13.0 h1:0jY9lJquiL8fcf3M4LAXN5aMlS/b2BV86HFFPCPMgE4=
github.com/onsi/ginkgo/v2 v2.23.3/go.mod h1:zXTP6xIp3U8aVuXN8ENK9IXRaTjFnpVB9mGmaSRvxnM= github.com/onsi/ginkgo/v2 v2.13.0/go.mod h1:TE309ZR8s5FsKKpuB1YAQYBzCaAfUgatB/xlT/ETL/o=
github.com/onsi/gomega v1.36.3 h1:hID7cr8t3Wp26+cYnfcjR6HpJ00fdogN6dqZ1t6IylU= github.com/onsi/gomega v1.29.0 h1:KIA/t2t5UBzoirT4H9tsML45GEbo3ouUnBHsCfD2tVg=
github.com/onsi/gomega v1.36.3/go.mod h1:8D9+Txp43QWKhM24yyOBEdpkzN8FvJyAwecBgsU4KU0= github.com/onsi/gomega v1.29.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ=
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040= github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug=
github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M= github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM=
github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M= github.com/pelletier/go-toml/v2 v2.2.0 h1:QLgLl2yMN7N+ruc31VynXs1vhMZa7CeHHejIeBAsoHo=
github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc= github.com/pelletier/go-toml/v2 v2.2.0/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI= github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI=
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
@ -235,84 +205,74 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pterm/pterm v0.12.27/go.mod h1:PhQ89w4i95rhgE+xedAoqous6K9X+r6aSOI2eFF7DZI=
github.com/pterm/pterm v0.12.29/go.mod h1:WI3qxgvoQFFGKGjGnJR849gU0TsEOvKn5Q8LlY1U7lg=
github.com/pterm/pterm v0.12.30/go.mod h1:MOqLIyMOgmTDz9yorcYbcw+HsgoZo3BQfg2wtl3HEFE=
github.com/pterm/pterm v0.12.31/go.mod h1:32ZAWZVXD7ZfG0s8qqHXePte42kdz8ECtRyEejaWgXU=
github.com/pterm/pterm v0.12.33/go.mod h1:x+h2uL+n7CP/rel9+bImHD5lF3nM9vJj80k9ybiiTTE=
github.com/pterm/pterm v0.12.36/go.mod h1:NjiL09hFhT/vWjQHSj1athJpx6H8cjpHXNAK5bUw8T8=
github.com/pterm/pterm v0.12.40/go.mod h1:ffwPLwlbXxP+rxT0GsgDTzS3y3rmpAO1NMjUkGTYf8s=
github.com/pterm/pterm v0.12.80 h1:mM55B+GnKUnLMUSqhdINe4s6tOuVQIetQ3my8JGyAIg=
github.com/pterm/pterm v0.12.80/go.mod h1:c6DeF9bSnOSeFPZlfs4ZRAFcf5SCoTwvwQ5xaKGQlHo=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/rogpeppe/go-internal v1.13.2-0.20241226121412-a5dc8ff20d0a h1:w3tdWGKbLGBPtR/8/oO74W6hmz0qE5q0z9aqSAewaaM= github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
github.com/rogpeppe/go-internal v1.13.2-0.20241226121412-a5dc8ff20d0a/go.mod h1:S8kfXMp+yh77OxPD4fdM6YUknrZpQxLhvxzS4gDHENY= github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sagikazarmark/locafero v0.7.0 h1:5MqpDsTGNDhY8sGp0Aowyf0qKsPrhewaLSsFaodPcyo= github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ=
github.com/sagikazarmark/locafero v0.7.0/go.mod h1:2za3Cg5rMaTMoG/2Ulr9AwtFaIppKXTRYnozin4aB5k= github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4=
github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE=
github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ=
github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ=
github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8=
github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
github.com/spf13/afero v1.12.0 h1:UcOPyRBYczmFn6yvphxkn9ZEOY65cpwGKb5mL36mrqs= github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8=
github.com/spf13/afero v1.12.0/go.mod h1:ZTlWwG4/ahT8W7T0WQ5uYmjI9duaLQGy3Q2OAl4sk/4= github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY=
github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y= github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0=
github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo= github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0=
github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0= github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho=
github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.20.0 h1:zrxIyR3RQIOsarIrgL8+sAvALXul9jeEPa06Y0Ph6vY= github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ=
github.com/spf13/viper v1.20.0/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqjJvu4= github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
github.com/xlab/treeprint v1.2.0 h1:HzHnuAF1plUN2zGlAFHbSQP2qJ0ZAD3XF5XD7OesXRQ= github.com/xlab/treeprint v1.2.0 h1:HzHnuAF1plUN2zGlAFHbSQP2qJ0ZAD3XF5XD7OesXRQ=
github.com/xlab/treeprint v1.2.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0= github.com/xlab/treeprint v1.2.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0=
github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778/go.mod h1:2MuV+tbUrU1zIOPMxZ5EncGwgmMJsa+9ucAQZXxsObs=
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no=
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 h1:jq9TW8u3so/bN+JPT166wjOI6/vQPF6Xe7nMNIltagk=
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 h1:CV7UdSGJt/Ao6Gp4CXckLxVRRsRgDHoI8XjbL3PDl8s= go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0/go.mod h1:FRmFuRJfag1IZ2dPkHnEoSFVgTVPUd2qf5Vi69hLb8I= go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo=
go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0 h1:Mne5On7VWdx7omSrSSZvM4Kw7cS7NQkOOmLcgscI51U=
go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0/go.mod h1:IPtUMKL4O3tH5y+iXVyAXqpAwMuzC1IrxVS81rummfE=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0 h1:OeNbIYk/2C15ckl7glBlOBp5+WlYsOElzTNmiPW/x60= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0 h1:IeMeyr1aBvBiPVYihXIaeIZba6b8E1bYp7lbdxK8CQg=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0/go.mod h1:7Bept48yIeqxP2OZ9/AqIpYS94h2or0aB4FypJTc8ZM= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0/go.mod h1:oVdCUtjq9MK9BlS7TtucsQwUcXcymNiEDjgDD2jMtZU=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.33.0 h1:wpMfgF8E1rkrT1Z6meFh1NDtownE9Ii3n3X2GJYjsaU= go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.33.0/go.mod h1:wAy0T/dUbs468uOlkT31xjvqQgEVXv58BRFWEgn5v/0= go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco=
go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ= go.opentelemetry.io/otel/sdk v1.19.0 h1:6USY6zH+L8uMH8L3t1enZPR3WFEmSTADlqldyHtJi3o=
go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE= go.opentelemetry.io/otel/sdk v1.19.0/go.mod h1:NedEbbS4w3C6zElbLdPJKOpJQOrGUJ+GfzpjUvI0v1A=
go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A= go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI=
go.opentelemetry.io/otel/sdk v1.34.0/go.mod h1:0e/pNiaMAqaykJGKbi+tSjWfNNHMTxoC9qANsCzbyxU= go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU=
go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k= go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I=
go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE= go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM=
go.opentelemetry.io/proto/otlp v1.5.0 h1:xJvq7gMzB31/d406fB8U5CBdyQGw4P399D1aQWU/3i4= go.starlark.net v0.0.0-20240314022150-ee8ed142361c h1:roAjH18hZcwI4hHStHbkXjF5b7UUyZ/0SG3hXNN1SjA=
go.opentelemetry.io/proto/otlp v1.5.0/go.mod h1:keN8WnHxOy8PG0rQZjJJ5A2ebUoafqWp0eVQ4yIXvJ4= go.starlark.net v0.0.0-20240314022150-ee8ed142361c/go.mod h1:YKMCv9b1WrfWmeqdV5MAuEHWsu5iC+fe6kYl2sQjdI8=
go.starlark.net v0.0.0-20240507195648-35fe9f26b4bc h1:WMJEq47tB89BoJ5HUfoMZVtN+0u6f32LgIfQlu3mMF8=
go.starlark.net v0.0.0-20240507195648-35fe9f26b4bc/go.mod h1:YKMCv9b1WrfWmeqdV5MAuEHWsu5iC+fe6kYl2sQjdI8=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
@ -321,162 +281,156 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34= golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc= golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f h1:XdNn9LlyWAhLVp6P/i8QYBW+hlyhrhei9uErw2B5GJo= golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8 h1:aAcj0Da7eBAtrTp03QXWvm88pSyOt+UgdZw2BFZ+lEw=
golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f/go.mod h1:D5SMRVC3C2/4+F/DB1wZsLRnSNimn2Sp/NPsCrsv8ak= golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8/go.mod h1:CQ1k9gNrJ50XIzaKCRR2hssIjF07kZFEiieALBM/ARQ=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.16.0 h1:QX4fJ0Rr5cPQCF7O9lh9Se4pmwfwskqZfq5moyldzic=
golang.org/x/mod v0.23.0 h1:Zb7khfcRGKk+kqfxFaP5tZqCnDZMjC5VtUBs87Hr6QM= golang.org/x/mod v0.16.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.23.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc=
golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8= golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= golang.org/x/oauth2 v0.18.0 h1:09qnuIAgzdx1XplqJvW6CQqMCtGZykZWcXzPMPUusvI=
golang.org/x/oauth2 v0.28.0 h1:CrgCKl8PPAVtLnU3c+EDw6x11699EWlsDeWNWKdIOkc= golang.org/x/oauth2 v0.18.0/go.mod h1:Wf7knwG0MPoWIMMBgFlEaSUDaKskp0dCfrlJRJXbBi8=
golang.org/x/oauth2 v0.28.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw= golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211013075003-97ac67df715c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8=
golang.org/x/term v0.30.0 h1:PQ39fJZ+mfadBm0y5WlL4vlM7Sx1Hgf13sMIY2+QS9Y= golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
golang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0= golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.19.0 h1:tfGCXNR1OsFG+sVdLAitlpjAvD/I6dHDKnYrpEZUHkw=
golang.org/x/tools v0.30.0 h1:BgcpHewrV5AUp2G9MebG4XPFI1E2W41zU1SaqVA9vJY= golang.org/x/tools v0.19.0/go.mod h1:qoJWxmGSIBmAeriMx19ogtrEPrGtDbPK634QFIcLAhc=
golang.org/x/tools v0.30.0/go.mod h1:c347cR/OJfw5TI+GfX7RUPNMdDRRbjvYTS0jPyvsVtY=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/genproto v0.0.0-20250303144028-a0af3efb3deb h1:ITgPrl429bc6+2ZraNSzMDk3I95nmQln2fuPstKwFDE= google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM=
google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb h1:p31xT4yrYrSM/G4Sn2+TNUkVhFCbG9y8itM2S6Th950= google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds=
google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb/go.mod h1:jbe3Bkdp+Dh2IrslsFCklNhweNTBgSYanP1UXhJDhKg= google.golang.org/genproto v0.0.0-20231106174013-bbf56f31fb17 h1:wpZ8pe2x1Q3f2KyT5f8oP/fa9rHAKgFPr/HZdNuS+PQ=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250313205543-e70fdf4c4cb4 h1:iK2jbkWL86DXjEx0qiHcRE9dE4/Ahua5k6V8OWFb//c= google.golang.org/genproto/googleapis/api v0.0.0-20231106174013-bbf56f31fb17 h1:JpwMPBpFN3uKhdaekDpiNlImDdkUAyiJ6ez/uxGaUSo=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250313205543-e70fdf4c4cb4/go.mod h1:LuRYeWDFV6WOn90g357N17oMCaxpgCnbi/44qJvDn2I= google.golang.org/genproto/googleapis/api v0.0.0-20231106174013-bbf56f31fb17/go.mod h1:0xJLfVdJqpAPl8tDg1ujOCGzx6LFLttXT5NhllGOXY4=
google.golang.org/grpc v1.71.0 h1:kF77BGdPTQ4/JZWMlb9VpJ5pa25aqvVqogsxNHHdeBg= google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f h1:ultW7fxlIvee4HYrtnaRPon9HpEgFk5zYpmfMgtKB5I=
google.golang.org/grpc v1.71.0/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec= google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f/go.mod h1:L9KNLi232K1/xB6f7AlSX692koaRnKaWSR0stBki0Yc=
google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM= google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk=
google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4= gopkg.in/evanphx/json-patch.v5 v5.9.0 h1:hx1VU2SGj4F8r9b8GUwJLdc8DNO8sy79ZGui0G05GLo=
gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M= gopkg.in/evanphx/json-patch.v5 v5.9.0/go.mod h1:/kvTRh1TVm5wuM6OkHxqXtE/1nUZZpihg29RtuIyfvk=
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q= gotest.tools/v3 v3.4.0 h1:ZazjZUfuVeZGLAmlKKuyv3IKP5orXcwtOwDQH6YVr6o=
gotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA= gotest.tools/v3 v3.4.0/go.mod h1:CtbdzLSsqVhDgMtKsx03ird5YTGB3ar27v0u/yKBW5g=
k8s.io/api v0.32.3 h1:Hw7KqxRusq+6QSplE3NYG4MBxZw1BZnq4aP4cJVINls= k8s.io/api v0.29.3 h1:2ORfZ7+bGC3YJqGpV0KSDDEVf8hdGQ6A03/50vj8pmw=
k8s.io/api v0.32.3/go.mod h1:2wEDTXADtm/HA7CCMD8D8bK4yuBUptzaRhYcYEEYA3k= k8s.io/api v0.29.3/go.mod h1:y2yg2NTyHUUkIoTC+phinTnEa3KFM6RZ3szxt014a80=
k8s.io/apimachinery v0.32.3 h1:JmDuDarhDmA/Li7j3aPrwhpNBA94Nvk5zLeOge9HH1U= k8s.io/apimachinery v0.29.3 h1:2tbx+5L7RNvqJjn7RIuIKu9XTsIZ9Z5wX2G22XAa5EU=
k8s.io/apimachinery v0.32.3/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE= k8s.io/apimachinery v0.29.3/go.mod h1:hx/S4V2PNW4OMg3WizRrHutyB5la0iCUbZym+W0EQIU=
k8s.io/cli-runtime v0.30.0 h1:0vn6/XhOvn1RJ2KJOC6IRR2CGqrpT6QQF4+8pYpWQ48= k8s.io/cli-runtime v0.29.3 h1:r68rephmmytoywkw2MyJ+CxjpasJDQY7AGc3XY2iv1k=
k8s.io/cli-runtime v0.30.0/go.mod h1:vATpDMATVTMA79sZ0YUCzlMelf6rUjoBzlp+RnoM+cg= k8s.io/cli-runtime v0.29.3/go.mod h1:aqVUsk86/RhaGJwDhHXH0jcdqBrgdF3bZWk4Z9D4mkM=
k8s.io/client-go v0.32.3 h1:RKPVltzopkSgHS7aS98QdscAgtgah/+zmpAogooIqVU= k8s.io/client-go v0.29.3 h1:R/zaZbEAxqComZ9FHeQwOh3Y1ZUs7FaHKZdQtIc2WZg=
k8s.io/client-go v0.32.3/go.mod h1:3v0+3k4IcT9bXTc4V2rt+d2ZPPG700Xy6Oi0Gdl2PaY= k8s.io/client-go v0.29.3/go.mod h1:tkDisCvgPfiRpxGnOORfkljmS+UrW+WtXAy2fTvXJB0=
k8s.io/component-base v0.30.0 h1:cj6bp38g0ainlfYtaOQuRELh5KSYjhKxM+io7AUIk4o= k8s.io/component-base v0.29.3 h1:Oq9/nddUxlnrCuuR2K/jp6aflVvc0uDvxMzAWxnGzAo=
k8s.io/component-base v0.30.0/go.mod h1:V9x/0ePFNaKeKYA3bOvIbrNoluTSG+fSJKjLdjOoeXQ= k8s.io/component-base v0.29.3/go.mod h1:Yuj33XXjuOk2BAaHsIGHhCKZQAgYKhqIxIjIr2UXYio=
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= k8s.io/klog/v2 v2.120.1 h1:QXU6cPEOIslTGvZaXvFWiP9VKyeet3sawzTOvdXb4Vw=
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= k8s.io/klog/v2 v2.120.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f h1:GA7//TjRY9yWGy1poLzYYJJ4JRdzg3+O6e8I+e+8T5Y= k8s.io/kube-openapi v0.0.0-20240322212309-b815d8309940 h1:qVoMaQV5t62UUvHe16Q3eb2c5HPzLHYzsi0Tu/xLndo=
k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f/go.mod h1:R/HEjbvWI0qdfb8viZUeVZm0X6IZnxAydC7YU42CMw4= k8s.io/kube-openapi v0.0.0-20240322212309-b815d8309940/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98=
k8s.io/kubectl v0.30.0 h1:xbPvzagbJ6RNYVMVuiHArC1grrV5vSmmIcSZuCdzRyk= k8s.io/kubectl v0.29.3 h1:RuwyyIU42MAISRIePaa8Q7A3U74Q9P4MoJbDFz9o3us=
k8s.io/kubectl v0.30.0/go.mod h1:zgolRw2MQXLPwmic2l/+iHs239L49fhSeICuMhQQXTI= k8s.io/kubectl v0.29.3/go.mod h1:yCxfY1dbwgVdEt2zkJ6d5NNLOhhWgTyrqACIoFhpdd4=
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 h1:M3sRQVHv7vB20Xc2ybTt7ODCeFj6JSWYFzOFnYeS6Ro= k8s.io/utils v0.0.0-20240310230437-4693a0247e57 h1:gbqbevonBh57eILzModw6mrkbwM0gQBEuevE/AaBsHY=
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= k8s.io/utils v0.0.0-20240310230437-4693a0247e57/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
modernc.org/cc/v4 v4.21.0 h1:D/gLKtcztomvWbsbvBKo3leKQv+86f+DdqEZBBXhnag= modernc.org/cc/v4 v4.19.5 h1:QlsZyQ1zf78DGeqnQ9ILi9hXyMdoC5e1qoGNUyBjHQw=
modernc.org/cc/v4 v4.21.0/go.mod h1:HM7VJTZbUCR3rV8EYBi9wxnJ0ZBRiGE5OeGXNA0IsLQ= modernc.org/cc/v4 v4.19.5/go.mod h1:HM7VJTZbUCR3rV8EYBi9wxnJ0ZBRiGE5OeGXNA0IsLQ=
modernc.org/ccgo/v4 v4.17.3 h1:t2CQci84jnxKw3GGnHvjGKjiNZeZqyQx/023spkk4hU= modernc.org/ccgo/v4 v4.13.1 h1:qBttaSxEHNze36VBivw1/vkHuyjMDN3RY5wQX+p1Oxg=
modernc.org/ccgo/v4 v4.17.3/go.mod h1:1FCbAtWYJoKuc+AviS+dH+vGNtYmFJqBeRWjmnDWsIg= modernc.org/ccgo/v4 v4.13.1/go.mod h1:Td6RI9W9G2ZpKHaJ7UeGEiB2aIpoDqLBnm4wtkbJTbQ=
modernc.org/fileutil v1.3.0 h1:gQ5SIzK3H9kdfai/5x41oQiKValumqNTDXMvKo62HvE= modernc.org/fileutil v1.3.0 h1:gQ5SIzK3H9kdfai/5x41oQiKValumqNTDXMvKo62HvE=
modernc.org/fileutil v1.3.0/go.mod h1:XatxS8fZi3pS8/hKG2GH/ArUogfxjpEKs3Ku3aK4JyQ= modernc.org/fileutil v1.3.0/go.mod h1:XatxS8fZi3pS8/hKG2GH/ArUogfxjpEKs3Ku3aK4JyQ=
modernc.org/gc/v2 v2.4.1 h1:9cNzOqPyMJBvrUipmynX0ZohMhcxPtMccYgGOJdOiBw= modernc.org/gc/v2 v2.4.1 h1:9cNzOqPyMJBvrUipmynX0ZohMhcxPtMccYgGOJdOiBw=
modernc.org/gc/v2 v2.4.1/go.mod h1:wzN5dK1AzVGoH6XOzc3YZ+ey/jPgYHLuVckd62P0GYU= modernc.org/gc/v2 v2.4.1/go.mod h1:wzN5dK1AzVGoH6XOzc3YZ+ey/jPgYHLuVckd62P0GYU=
modernc.org/gc/v3 v3.0.0-20240304020402-f0dba7c97c2b h1:BnN1t+pb1cy61zbvSUV7SeI0PwosMhlAEi/vBY4qxp8= modernc.org/gc/v3 v3.0.0-20240304020402-f0dba7c97c2b h1:BnN1t+pb1cy61zbvSUV7SeI0PwosMhlAEi/vBY4qxp8=
modernc.org/gc/v3 v3.0.0-20240304020402-f0dba7c97c2b/go.mod h1:Qz0X07sNOR1jWYCrJMEnbW/X55x206Q7Vt4mz6/wHp4= modernc.org/gc/v3 v3.0.0-20240304020402-f0dba7c97c2b/go.mod h1:Qz0X07sNOR1jWYCrJMEnbW/X55x206Q7Vt4mz6/wHp4=
modernc.org/libc v1.50.5 h1:ZzeUd0dIc/sUtoPTCYIrgypkuzoGzNu6kbEWj2VuEmk= modernc.org/libc v1.49.0 h1:/kkNBuCXvlTbOGwrQdgR67eK1Y9+kR+fhdBd89C64VM=
modernc.org/libc v1.50.5/go.mod h1:rhzrUx5oePTSTIzBgM0mTftwWHK8tiT9aNFUt1mldl0= modernc.org/libc v1.49.0/go.mod h1:DNz0lgQgT6FPIPm8rHtjFj0FL5/YOr/NYFXWYBcSxMw=
modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4= modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4=
modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo= modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo=
modernc.org/memory v1.8.0 h1:IqGTL6eFMaDZZhEWwcREgeMXYwmW83LYW8cROZYkg+E= modernc.org/memory v1.7.2 h1:Klh90S215mmH8c9gO98QxQFsY+W451E8AnzjoE2ee1E=
modernc.org/memory v1.8.0/go.mod h1:XPZ936zp5OMKGWPqbD3JShgd/ZoQ7899TUuQqxY+peU= modernc.org/memory v1.7.2/go.mod h1:NO4NVCQy0N7ln+T9ngWqOQfi7ley4vpwvARR+Hjw95E=
modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4= modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4=
modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
modernc.org/sortutil v1.2.0 h1:jQiD3PfS2REGJNzNCMMaLSp/wdMNieTbKX920Cqdgqc= modernc.org/sortutil v1.2.0 h1:jQiD3PfS2REGJNzNCMMaLSp/wdMNieTbKX920Cqdgqc=
modernc.org/sortutil v1.2.0/go.mod h1:TKU2s7kJMf1AE84OoiGppNHJwvB753OYfNl2WRb++Ss= modernc.org/sortutil v1.2.0/go.mod h1:TKU2s7kJMf1AE84OoiGppNHJwvB753OYfNl2WRb++Ss=
modernc.org/sqlite v1.29.9 h1:9RhNMklxJs+1596GNuAX+O/6040bvOwacTxuFcRuQow= modernc.org/sqlite v1.29.5 h1:8l/SQKAjDtZFo9lkJLdk8g9JEOeYRG4/ghStDCCTiTE=
modernc.org/sqlite v1.29.9/go.mod h1:ItX2a1OVGgNsFh6Dv60JQvGfJfTPHPVpV6DF59akYOA= modernc.org/sqlite v1.29.5/go.mod h1:S02dvcmm7TnTRvGhv8IGYyLnIt7AS2KPaB1F/71p75U=
modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA= modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA=
modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0= modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0=
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y= modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
oras.land/oras-go/v2 v2.5.0 h1:o8Me9kLY74Vp5uw07QXPiitjsw7qNXi8Twd+19Zf02c= oras.land/oras-go/v2 v2.5.0 h1:o8Me9kLY74Vp5uw07QXPiitjsw7qNXi8Twd+19Zf02c=
oras.land/oras-go/v2 v2.5.0/go.mod h1:z4eisnLP530vwIOUOJeBIj0aGI0L1C3d53atvCBqZHg= oras.land/oras-go/v2 v2.5.0/go.mod h1:z4eisnLP530vwIOUOJeBIj0aGI0L1C3d53atvCBqZHg=
sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 h1:/Rv+M11QRah1itp8VhT6HoVx1Ray9eB4DBr+K+/sCJ8= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo=
sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3/go.mod h1:18nIHnGi6636UCz6m8i4DhaJ65T6EruyzmoQqI2BVDo= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
sigs.k8s.io/kustomize/api v0.17.1 h1:MYJBOP/yQ3/5tp4/sf6HiiMfNNyO97LmtnirH9SLNr4= sigs.k8s.io/kustomize/api v0.16.0 h1:/zAR4FOQDCkgSDmVzV2uiFbuy9bhu3jEzthrHCuvm1g=
sigs.k8s.io/kustomize/api v0.17.1/go.mod h1:ffn5491s2EiNrJSmgqcWGzQUVhc/pB0OKNI0HsT/0tA= sigs.k8s.io/kustomize/api v0.16.0/go.mod h1:MnFZ7IP2YqVyVwMWoRxPtgl/5hpA+eCCrQR/866cm5c=
sigs.k8s.io/kustomize/kyaml v0.17.0 h1:G2bWs03V9Ur2PinHLzTUJ8Ded+30SzXZKiO92SRDs3c= sigs.k8s.io/kustomize/kyaml v0.16.0 h1:6J33uKSoATlKZH16unr2XOhDI+otoe2sR3M8PDzW3K0=
sigs.k8s.io/kustomize/kyaml v0.17.0/go.mod h1:6lxkYF1Cv9Ic8g/N7I86cvxNc5iinUo/P2vKsHNmpyE= sigs.k8s.io/kustomize/kyaml v0.16.0/go.mod h1:xOK/7i+vmE14N2FdFyugIshB8eF6ALpy7jI87Q2nRh4=
sigs.k8s.io/structured-merge-diff/v4 v4.4.2 h1:MdmvkGuXi/8io6ixD5wud3vOLwc1rj0aNqRlpuvjmwA= sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4=
sigs.k8s.io/structured-merge-diff/v4 v4.4.2/go.mod h1:N8f93tFZh9U6vpxwRArLiikrE5/2tiu1w1AGfACIGE4= sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08=
sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=

View File

@ -22,9 +22,10 @@ import (
"database/sql" "database/sql"
_ "embed" _ "embed"
"fmt" "fmt"
"github.com/blang/semver/v4"
"io" "io"
"io/ioutil"
"log" "log"
"log/slog"
"net/http" "net/http"
"os" "os"
"strings" "strings"
@ -164,7 +165,7 @@ func (a *amazonlinux2023) repos() []string {
} }
func (a *amazonlinux2023) baseUrl() string { func (a *amazonlinux2023) baseUrl() string {
return "https://cdn.amazonlinux.com/al2023/core/mirrors" return "https://cdn.amazonlinux.com/al2023/core/mirrors/"
} }
func (a *amazonlinux2023) ext() string { func (a *amazonlinux2023) ext() string {
@ -179,14 +180,6 @@ func (a *amazonlinux2) URLs(kr kernelrelease.KernelRelease) ([]string, error) {
return fetchAmazonLinuxPackagesURLs(a, kr) return fetchAmazonLinuxPackagesURLs(a, kr)
} }
func (a *amazonlinux2) GCCVersion(kr kernelrelease.KernelRelease) semver.Version {
// 5.10 amazonlinux2 kernels need gcc 10
if kr.Major == 5 && kr.Minor == 10 {
return semver.Version{Major: 10}
}
return semver.Version{}
}
func (a *amazonlinux2) repos() []string { func (a *amazonlinux2) repos() []string {
return []string{ return []string{
"core/2.0", "core/2.0",
@ -210,13 +203,16 @@ func buildMirror(a amazonBuilder, r string, kv kernelrelease.KernelRelease) (str
switch a.(type) { switch a.(type) {
case *amazonlinux: case *amazonlinux:
baseURL = fmt.Sprintf("%s/%s", a.baseUrl(), r) baseURL = fmt.Sprintf("%s/%s", a.baseUrl(), r)
case *amazonlinux2, *amazonlinux2022, *amazonlinux2023: case *amazonlinux2:
baseURL = fmt.Sprintf("%s/%s/%s", a.baseUrl(), r, kv.Architecture.ToNonDeb())
case *amazonlinux2022:
baseURL = fmt.Sprintf("%s/%s/%s", a.baseUrl(), r, kv.Architecture.ToNonDeb()) baseURL = fmt.Sprintf("%s/%s/%s", a.baseUrl(), r, kv.Architecture.ToNonDeb())
default: default:
return "", fmt.Errorf("unsupported target") return "", fmt.Errorf("unsupported target")
} }
mirror := fmt.Sprintf("%s/%s", baseURL, "mirror.list") mirror := fmt.Sprintf("%s/%s", baseURL, "mirror.list")
slog.With("url", mirror, "version", r).Debug("looking for repo...")
return mirror, nil return mirror, nil
} }
@ -237,92 +233,92 @@ func fetchAmazonLinuxPackagesURLs(a amazonBuilder, kv kernelrelease.KernelReleas
visited := make(map[string]struct{}) visited := make(map[string]struct{})
for _, v := range a.repos() { for _, v := range a.repos() {
err := func() error { mirror, err := buildMirror(a, v, kv)
mirror, err := buildMirror(a, v, kv)
if err != nil {
return err
}
// Obtain the repo URL by getting mirror URL content
mirrorRes, err := http.Get(mirror)
if err != nil {
return err
}
defer mirrorRes.Body.Close()
var repo string
scanner := bufio.NewScanner(mirrorRes.Body)
if scanner.Scan() {
repo = scanner.Text()
}
if repo == "" {
return fmt.Errorf("repository not found")
}
repo = strings.ReplaceAll(strings.TrimSuffix(repo, "\n"), "$basearch", kv.Architecture.ToNonDeb())
repo = strings.TrimSuffix(repo, "/")
repoDatabaseURL := fmt.Sprintf("%s/repodata/primary.sqlite.%s", repo, a.ext())
if _, ok := visited[repoDatabaseURL]; ok {
return nil
}
// Download the repo database
repoRes, err := http.Get(repoDatabaseURL)
if err != nil {
return err
}
defer repoRes.Body.Close()
visited[repoDatabaseURL] = struct{}{}
unzip, err := unzipFuncFromBuilder(a)
if err != nil {
return err
}
dbBytes, err := unzip(repoRes.Body)
if err != nil {
return err
}
// Create the temporary database file
dbFile, err := os.CreateTemp(os.TempDir(), fmt.Sprintf("%s-*.sqlite", a.Name()))
if err != nil {
return err
}
defer os.Remove(dbFile.Name())
if _, err := dbFile.Write(dbBytes); err != nil {
return err
}
// Open the database
db, err := sql.Open("sqlite", dbFile.Name())
if err != nil {
return err
}
defer db.Close()
// Query the database
rel := strings.TrimPrefix(strings.TrimSuffix(kv.FullExtraversion, fmt.Sprintf(".%s", kv.Architecture.ToNonDeb())), "-")
q := fmt.Sprintf("SELECT location_href FROM packages WHERE name LIKE 'kernel-devel%%' AND version='%s' AND release='%s'", kv.Fullversion, rel)
stmt, err := db.Prepare(q)
if err != nil {
return err
}
defer stmt.Close()
rows, err := stmt.Query()
if err != nil {
return err
}
defer rows.Close()
for rows.Next() {
var href string
err = rows.Scan(&href)
if err != nil {
log.Fatal(err)
}
urls = append(urls, fmt.Sprintf("%s/%s", repo, href))
}
return dbFile.Close()
}()
if err != nil { if err != nil {
return nil, err return nil, err
} }
// Obtain the repo URL by getting mirror URL content
mirrorRes, err := http.Get(mirror)
if err != nil {
return nil, err
}
defer mirrorRes.Body.Close()
var repo string
scanner := bufio.NewScanner(mirrorRes.Body)
if scanner.Scan() {
repo = scanner.Text()
}
if repo == "" {
return nil, fmt.Errorf("repository not found")
}
repo = strings.ReplaceAll(strings.TrimSuffix(repo, "\n"), "$basearch", kv.Architecture.ToNonDeb())
repo = strings.TrimSuffix(repo, "/")
repoDatabaseURL := fmt.Sprintf("%s/repodata/primary.sqlite.%s", repo, a.ext())
if _, ok := visited[repoDatabaseURL]; ok {
continue
}
// Download the repo database
repoRes, err := http.Get(repoDatabaseURL)
slog.With("url", repoDatabaseURL).Debug("downloading...")
if err != nil {
return nil, err
}
defer repoRes.Body.Close()
visited[repoDatabaseURL] = struct{}{}
unzip, err := unzipFuncFromBuilder(a)
if err != nil {
return nil, err
}
dbBytes, err := unzip(repoRes.Body)
if err != nil {
return nil, err
}
// Create the temporary database file
dbFile, err := ioutil.TempFile(os.TempDir(), fmt.Sprintf("%s-*.sqlite", a.Name()))
if err != nil {
return nil, err
}
defer os.Remove(dbFile.Name())
if _, err := dbFile.Write(dbBytes); err != nil {
return nil, err
}
// Open the database
db, err := sql.Open("sqlite", dbFile.Name())
if err != nil {
return nil, err
}
defer db.Close()
slog.With("db", dbFile.Name()).Debug("connecting to database...")
// Query the database
rel := strings.TrimPrefix(strings.TrimSuffix(kv.FullExtraversion, fmt.Sprintf(".%s", kv.Architecture.ToNonDeb())), "-")
q := fmt.Sprintf("SELECT location_href FROM packages WHERE name LIKE 'kernel-devel%%' AND version='%s' AND release='%s'", kv.Fullversion, rel)
stmt, err := db.Prepare(q)
if err != nil {
return nil, err
}
defer stmt.Close()
rows, err := stmt.Query()
if err != nil {
return nil, err
}
defer rows.Close()
for rows.Next() {
var href string
err = rows.Scan(&href)
if err != nil {
log.Fatal(err)
}
urls = append(urls, fmt.Sprintf("%s/%s", repo, href))
}
if err := dbFile.Close(); err != nil {
return nil, err
}
// Found, do not continue // Found, do not continue
if len(urls) > 0 { if len(urls) > 0 {
break break

View File

@ -75,10 +75,10 @@ func (c *archlinux) URLs(kr kernelrelease.KernelRelease) ([]string, error) {
urls = append( urls = append(
urls, urls,
fmt.Sprintf( fmt.Sprintf(
"%s/linux-headers-%s-%s-%s.pkg.tar.%s", "%s/linux-headers-%s%s-%s.pkg.tar.%s",
baseURL, baseURL,
kr.String(), kr.Fullversion,
kr.KernelVersion, kr.FullExtraversion,
kr.Architecture.ToNonDeb(), kr.Architecture.ToNonDeb(),
compressionAlgo, compressionAlgo,
), ),
@ -90,10 +90,10 @@ func (c *archlinux) URLs(kr kernelrelease.KernelRelease) ([]string, error) {
urls = append( urls = append(
urls, urls,
fmt.Sprintf( fmt.Sprintf(
"%s/linux-hardened-headers-%s-%s-%s.pkg.tar.%s", "%s/linux-hardened-headers-%s%s-%s.pkg.tar.%s",
baseURL, baseURL,
kr.String(), kr.Fullversion,
kr.KernelVersion, kr.FullExtraversion,
kr.Architecture.ToNonDeb(), kr.Architecture.ToNonDeb(),
compressionAlgo, compressionAlgo,
), ),
@ -105,10 +105,10 @@ func (c *archlinux) URLs(kr kernelrelease.KernelRelease) ([]string, error) {
urls = append( urls = append(
urls, urls,
fmt.Sprintf( fmt.Sprintf(
"%s/linux-zen-headers-%s-%s-%s.pkg.tar.%s", "%s/linux-zen-headers-%s%s-%s.pkg.tar.%s",
baseURL, baseURL,
kr.String(), kr.Fullversion,
kr.KernelVersion, kr.FullExtraversion,
kr.Architecture.ToNonDeb(), kr.Architecture.ToNonDeb(),
compressionAlgo, compressionAlgo,
), ),
@ -120,10 +120,10 @@ func (c *archlinux) URLs(kr kernelrelease.KernelRelease) ([]string, error) {
urls = append( urls = append(
urls, urls,
fmt.Sprintf( fmt.Sprintf(
"%s/linux-lts-headers-%s-%s-%s.pkg.tar.%s", "%s/linux-lts-headers-%s%s-%s.pkg.tar.%s",
baseURL, baseURL,
kr.String(), kr.Fullversion,
kr.KernelVersion, kr.FullExtraversion,
kr.Architecture.ToNonDeb(), kr.Architecture.ToNonDeb(),
compressionAlgo, compressionAlgo,
), ),
@ -131,15 +131,15 @@ func (c *archlinux) URLs(kr kernelrelease.KernelRelease) ([]string, error) {
} }
} }
} else if kr.Architecture.ToNonDeb() == "aarch64" { } else if kr.Architecture.ToNonDeb() == "aarch64" {
baseURL := "https://alaa.ad24.cz/packages/l/linux-aarch64-headers/" baseURL := "http://tardis.tiny-vps.com/aarm/packages/l/linux-aarch64-headers/"
for _, compressionAlgo := range possibleCompressionSuffixes { for _, compressionAlgo := range possibleCompressionSuffixes {
urls = append( urls = append(
urls, urls,
fmt.Sprintf( fmt.Sprintf(
"%s/linux-aarch64-headers-%s-%s-%s.pkg.tar.%s", "%s/linux-aarch64-headers-%s%s-%s.pkg.tar.%s",
baseURL, baseURL,
kr.String(), kr.Fullversion,
kr.KernelVersion, kr.FullExtraversion,
kr.Architecture.ToNonDeb(), kr.Architecture.ToNonDeb(),
compressionAlgo, compressionAlgo,
), ),

View File

@ -17,7 +17,6 @@ package builder
import ( import (
"context" "context"
"fmt" "fmt"
"github.com/falcosecurity/falcoctl/pkg/output"
"strings" "strings"
"github.com/falcosecurity/driverkit/pkg/kernelrelease" "github.com/falcosecurity/driverkit/pkg/kernelrelease"
@ -50,8 +49,6 @@ type Build struct {
RegistryUser string RegistryUser string
RegistryPassword string RegistryPassword string
RegistryPlainHTTP bool RegistryPlainHTTP bool
*output.Printer
} }
func (b *Build) KernelReleaseFromBuildConfig() kernelrelease.KernelRelease { func (b *Build) KernelReleaseFromBuildConfig() kernelrelease.KernelRelease {
@ -111,3 +108,7 @@ func (b *Build) ClientForRegistry(registry string) *auth.Client {
return client return client
} }
func (b *Build) HasOutputs() bool {
return b.ModuleFilePath != "" || b.ProbeFilePath != ""
}

View File

@ -19,14 +19,15 @@ import (
_ "embed" _ "embed"
"errors" "errors"
"fmt" "fmt"
"github.com/falcosecurity/falcoctl/pkg/output" "log/slog"
"net/http" "net/http"
"net/url" "net/url"
"os"
"path" "path"
"strings" "strings"
"text/template" "text/template"
"github.com/blang/semver/v4" "github.com/blang/semver"
"github.com/falcosecurity/driverkit/pkg/kernelrelease" "github.com/falcosecurity/driverkit/pkg/kernelrelease"
) )
@ -131,11 +132,7 @@ func LibsDownloadScript(c Config) (string, error) {
} }
// KernelDownloadScript returns the script that will download and extract kernel headers // KernelDownloadScript returns the script that will download and extract kernel headers
func KernelDownloadScript(b Builder, func KernelDownloadScript(b Builder, kernelurls []string, kr kernelrelease.KernelRelease) (string, error) {
kernelurls []string,
kr kernelrelease.KernelRelease,
printer *output.Printer,
) (string, error) {
t := template.New("download-kernel") t := template.New("download-kernel")
parsed, err := t.Parse(b.TemplateKernelUrlsScript()) parsed, err := t.Parse(b.TemplateKernelUrlsScript())
if err != nil { if err != nil {
@ -170,9 +167,6 @@ func KernelDownloadScript(b Builder,
return "", fmt.Errorf("not enough headers packages found; expected %d, found %d", minimumURLs, len(urls)) return "", fmt.Errorf("not enough headers packages found; expected %d, found %d", minimumURLs, len(urls))
} }
printer.Logger.Debug("kernel headers found",
printer.Logger.Args("urls", urls))
td := b.KernelTemplateData(kr, urls) td := b.KernelTemplateData(kr, urls)
if tdErr, ok := td.(error); ok { if tdErr, ok := td.(error); ok {
return "", tdErr return "", tdErr
@ -220,9 +214,6 @@ type GCCVersionRequestor interface {
func defaultGCC(kr kernelrelease.KernelRelease) semver.Version { func defaultGCC(kr kernelrelease.KernelRelease) semver.Version {
switch kr.Major { switch kr.Major {
case 6: case 6:
if kr.Minor >= 9 {
return semver.Version{Major: 14}
}
if kr.Minor >= 5 { if kr.Minor >= 5 {
return semver.Version{Major: 13} return semver.Version{Major: 13}
} }
@ -242,7 +233,7 @@ func defaultGCC(kr kernelrelease.KernelRelease) semver.Version {
case 2: case 2:
return semver.Version{Major: 4, Minor: 8} return semver.Version{Major: 4, Minor: 8}
default: default:
return semver.Version{Major: 14} return semver.Version{Major: 13}
} }
} }
@ -306,10 +297,8 @@ func (b *Build) setGCCVersion(builder Builder, kr kernelrelease.KernelRelease) {
proposedGCCs := make([]semver.Version, 0) proposedGCCs := make([]semver.Version, 0)
for _, img := range b.Images { for _, img := range b.Images {
proposedGCCs = append(proposedGCCs, img.GCCVersion) proposedGCCs = append(proposedGCCs, img.GCCVersion)
b.Logger.Debug("proposed GCC", slog.With("image", img.Name, "targetGCC", targetGCC.String()).
b.Logger.Args("image", img.Name, Debug("proposedGCC", "version", img.GCCVersion.String())
"targetGCC", targetGCC.String(),
"proposedGCC", img.GCCVersion.String()))
} }
// Now, sort versions and fetch // Now, sort versions and fetch
@ -324,8 +313,8 @@ func (b *Build) setGCCVersion(builder Builder, kr kernelrelease.KernelRelease) {
} }
b.GCCVersion = lastGCC.String() b.GCCVersion = lastGCC.String()
} }
b.Logger.Debug("found GCC", slog.With("targetGCC", targetGCC.String()).
b.Logger.Args("targetGCC", targetGCC.String(), "version", b.GCCVersion)) Debug("foundGCC", "version", b.GCCVersion)
} }
type BuilderImageNetworkMode interface { type BuilderImageNetworkMode interface {
@ -400,11 +389,13 @@ func (c Config) toTemplateData(b Builder, kr kernelrelease.KernelRelease) common
func resolveURLReference(u string) string { func resolveURLReference(u string) string {
uu, err := url.Parse(u) uu, err := url.Parse(u)
if err != nil { if err != nil {
panic(err) slog.Error(err.Error())
os.Exit(1)
} }
base, err := url.Parse(uu.Host) base, err := url.Parse(uu.Host)
if err != nil { if err != nil {
panic(err) slog.Error(err.Error())
os.Exit(1)
} }
return base.ResolveReference(uu).String() return base.ResolveReference(uu).String()
} }
@ -424,6 +415,7 @@ func GetResolvingURLs(urls []string) ([]string, error) {
} }
if res.StatusCode == http.StatusOK { if res.StatusCode == http.StatusOK {
results = append(results, u) results = append(results, u)
slog.With("url", u).Debug("kernel header url found")
} }
} }
if len(results) == 0 { if len(results) == 0 {

View File

@ -17,7 +17,7 @@ package builder
import ( import (
"testing" "testing"
"github.com/blang/semver/v4" "github.com/blang/semver"
"github.com/falcosecurity/driverkit/pkg/kernelrelease" "github.com/falcosecurity/driverkit/pkg/kernelrelease"
) )

View File

@ -18,7 +18,7 @@ import (
_ "embed" _ "embed"
"fmt" "fmt"
"github.com/blang/semver/v4" "github.com/blang/semver"
"github.com/falcosecurity/driverkit/pkg/kernelrelease" "github.com/falcosecurity/driverkit/pkg/kernelrelease"
) )

View File

@ -85,13 +85,6 @@ func (c *fedora) URLs(kr kernelrelease.KernelRelease) ([]string, error) {
kr.Fullversion, kr.Fullversion,
kr.FullExtraversion, kr.FullExtraversion,
), ),
fmt.Sprintf( // updates-archive
"https://fedoraproject-updates-archive.fedoraproject.org/fedora/%s/%s/kernel-devel-%s%s.rpm",
version,
kr.Architecture.ToNonDeb(),
kr.Fullversion,
kr.FullExtraversion,
),
} }
// return out all possible urls // return out all possible urls

View File

@ -21,7 +21,7 @@ import (
"net/http" "net/http"
"strings" "strings"
"github.com/blang/semver/v4" "github.com/blang/semver"
"github.com/falcosecurity/driverkit/pkg/kernelrelease" "github.com/falcosecurity/driverkit/pkg/kernelrelease"
) )

View File

@ -17,12 +17,12 @@ package builder
import ( import (
"context" "context"
"fmt" "fmt"
"github.com/falcosecurity/falcoctl/pkg/output" "log/slog"
"os" "os"
"regexp" "regexp"
"strings" "strings"
"github.com/blang/semver/v4" "github.com/blang/semver"
"github.com/falcosecurity/driverkit/pkg/kernelrelease" "github.com/falcosecurity/driverkit/pkg/kernelrelease"
"github.com/falcosecurity/falcoctl/pkg/oci/repository" "github.com/falcosecurity/falcoctl/pkg/oci/repository"
"gopkg.in/yaml.v3" "gopkg.in/yaml.v3"
@ -47,7 +47,7 @@ type Image struct {
} }
type ImagesLister interface { type ImagesLister interface {
LoadImages(printer *output.Printer) []Image LoadImages() []Image
} }
type FileImagesLister struct { type FileImagesLister struct {
@ -98,7 +98,7 @@ func NewFileImagesLister(filePath string, build *Build) (*FileImagesLister, erro
}, nil }, nil
} }
func (f *FileImagesLister) LoadImages(printer *output.Printer) []Image { func (f *FileImagesLister) LoadImages() []Image {
var ( var (
res []Image res []Image
imageList YAMLImagesList imageList YAMLImagesList
@ -107,43 +107,37 @@ func (f *FileImagesLister) LoadImages(printer *output.Printer) []Image {
// loop over lines in file to print them // loop over lines in file to print them
fileData, err := os.ReadFile(f.FilePath) fileData, err := os.ReadFile(f.FilePath)
if err != nil { if err != nil {
printer.Logger.Warn("error opening builder repo file", slog.With("err", err.Error(), "FilePath", f.FilePath).Warn("Error opening builder repo file")
printer.Logger.Args("err", err.Error(), "filepath", f.FilePath))
return res return res
} }
err = yaml.Unmarshal(fileData, &imageList) err = yaml.Unmarshal(fileData, &imageList)
if err != nil { if err != nil {
printer.Logger.Warn("error unmarshalling builder repo file", slog.With("err", err.Error(), "FilePath", f.FilePath).Warn("Error unmarshalling builder repo file")
printer.Logger.Args("err", err.Error(), "filepath", f.FilePath))
return res return res
} }
for _, image := range imageList.Images { for _, image := range imageList.Images {
logger := slog.With("FilePath", f.FilePath, "image", image)
// Values checks // Values checks
if image.Arch != f.Arch { if image.Arch != f.Arch {
printer.Logger.Debug("skipping wrong-arch image", logger.Debug("Skipping wrong-arch image")
printer.Logger.Args("filepath", f.FilePath, "image", image))
continue continue
} }
if image.Tag != f.Tag { if image.Tag != f.Tag {
printer.Logger.Debug("skipping wrong-tag image", logger.Debug("Skipping wrong-tag image")
printer.Logger.Args("filepath", f.FilePath, "image", image))
continue continue
} }
if image.Target != "any" && image.Target != f.Target { if image.Target != "any" && image.Target != f.Target {
printer.Logger.Debug("skipping wrong-target image", logger.Debug("Skipping wrong-target image")
printer.Logger.Args("filepath", f.FilePath, "image", image))
continue continue
} }
if image.Name == "" { if image.Name == "" {
printer.Logger.Debug("skipping empty name image", logger.Debug("Skipping empty name image")
printer.Logger.Args("filepath", f.FilePath, "image", image))
continue continue
} }
if len(image.GCCVersions) == 0 { if len(image.GCCVersions) == 0 {
printer.Logger.Debug("expected at least 1 gcc version", logger.Debug("Expected at least 1 gcc version")
printer.Logger.Args("filepath", f.FilePath, "image", image))
continue continue
} }
@ -184,11 +178,10 @@ func NewRepoImagesLister(repo string, build *Build) (*RepoImagesLister, error) {
return &RepoImagesLister{repoOCI}, nil return &RepoImagesLister{repoOCI}, nil
} }
func (repo *RepoImagesLister) LoadImages(printer *output.Printer) []Image { func (repo *RepoImagesLister) LoadImages() []Image {
tags, err := repo.Tags(context.Background()) tags, err := repo.Tags(context.Background())
if err != nil { if err != nil {
printer.Logger.Warn("skipping repo", slog.With("Repo", repo.Reference, "err", err.Error()).Warn("Skipping repo")
printer.Logger.Args("repo", repo.Reference, "err", err.Error()))
return nil return nil
} }
@ -236,7 +229,7 @@ func (repo *RepoImagesLister) LoadImages(printer *output.Printer) []Image {
func (b *Build) LoadImages() { func (b *Build) LoadImages() {
for _, imagesLister := range b.ImagesListers { for _, imagesLister := range b.ImagesListers {
for _, image := range imagesLister.LoadImages(b.Printer) { for _, image := range imagesLister.LoadImages() {
// User forced a gcc version? Only load images matching the requested gcc version. // User forced a gcc version? Only load images matching the requested gcc version.
if b.GCCVersion != "" && b.GCCVersion != image.GCCVersion.String() { if b.GCCVersion != "" && b.GCCVersion != image.GCCVersion.String() {
continue continue
@ -248,7 +241,8 @@ func (b *Build) LoadImages() {
} }
} }
if len(b.Images) == 0 { if len(b.Images) == 0 {
b.Printer.Logger.Fatal("Could not load any builder image. Leaving.") slog.Error("Could not load any builder image. Leaving.")
os.Exit(1)
} }
} }

View File

@ -15,14 +15,12 @@ limitations under the License.
package builder package builder
import ( import (
"github.com/falcosecurity/falcoctl/pkg/output"
"github.com/pterm/pterm"
"io" "io"
"net/http" "net/http"
"os" "os"
"testing" "testing"
"github.com/blang/semver/v4" "github.com/blang/semver"
"github.com/docker/docker/testutil/registry" "github.com/docker/docker/testutil/registry"
"gotest.tools/assert" "gotest.tools/assert"
) )
@ -238,8 +236,6 @@ images:
} }
func TestFileImagesLister(t *testing.T) { func TestFileImagesLister(t *testing.T) {
printer := output.NewPrinter(pterm.LogLevelInfo, pterm.LogFormatterColorful, os.Stdout)
// setup images file // setup images file
f, err := os.CreateTemp(t.TempDir(), "imagetest") f, err := os.CreateTemp(t.TempDir(), "imagetest")
if err != nil { if err != nil {
@ -273,13 +269,11 @@ func TestFileImagesLister(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
assert.DeepEqual(t, test.expected, lister.LoadImages(printer)) assert.DeepEqual(t, test.expected, lister.LoadImages())
} }
} }
func TestRepoImagesLister(t *testing.T) { func TestRepoImagesLister(t *testing.T) {
printer := output.NewPrinter(pterm.LogLevelInfo, pterm.LogFormatterColorful, os.Stdout)
mock, err := registry.NewMock(t) mock, err := registry.NewMock(t)
assert.NilError(t, err) assert.NilError(t, err)
defer mock.Close() defer mock.Close()
@ -306,6 +300,6 @@ func TestRepoImagesLister(t *testing.T) {
mock.RegisterHandler("/v2/foo/test/tags/list", func(w http.ResponseWriter, r *http.Request) { mock.RegisterHandler("/v2/foo/test/tags/list", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(test.jsonData)) w.Write([]byte(test.jsonData))
}) })
assert.DeepEqual(t, test.expected, lister.LoadImages(printer)) assert.DeepEqual(t, test.expected, lister.LoadImages())
} }
} }

View File

@ -15,7 +15,7 @@ limitations under the License.
package builder package builder
import ( import (
"github.com/blang/semver/v4" "github.com/blang/semver"
"github.com/falcosecurity/driverkit/pkg/kernelrelease" "github.com/falcosecurity/driverkit/pkg/kernelrelease"
) )

View File

@ -31,6 +31,7 @@ mkdir -p build && cd build
{{ end }} {{ end }}
{{ end }} {{ end }}
{{ if .BuildModule }} {{ if .BuildModule }}
{{ if .UseDKMS }} {{ if .UseDKMS }}
echo "* Building kmod with DKMS" echo "* Building kmod with DKMS"

View File

@ -18,7 +18,7 @@ import (
"fmt" "fmt"
"testing" "testing"
"github.com/blang/semver/v4" "github.com/blang/semver"
"github.com/falcosecurity/driverkit/pkg/kernelrelease" "github.com/falcosecurity/driverkit/pkg/kernelrelease"
) )
@ -160,16 +160,16 @@ var tests = []struct {
}, },
{ {
config: kernelrelease.KernelRelease{ config: kernelrelease.KernelRelease{
Fullversion: "6.8.0", Fullversion: "6.5.0",
Version: semver.Version{ Version: semver.Version{
Major: 6, Major: 6,
Minor: 8, Minor: 5,
Patch: 0, Patch: 0,
}, },
Extraversion: "48", Extraversion: "9",
FullExtraversion: "-48", FullExtraversion: "-9",
Architecture: kernelrelease.ArchitectureAmd64, Architecture: kernelrelease.ArchitectureAmd64,
KernelVersion: "48", KernelVersion: "9",
}, },
expected: struct { expected: struct {
headersURLs []string headersURLs []string
@ -180,31 +180,31 @@ var tests = []struct {
err error err error
}{ }{
headersURLs: []string{ headersURLs: []string{
"https://mirrors.edge.kernel.org/ubuntu/pool/main/l/linux/linux-headers-6.8.0-48-generic_6.8.0-48.48_amd64.deb", "https://mirrors.edge.kernel.org/ubuntu/pool/main/l/linux/linux-headers-6.5.0-9-generic_6.5.0-9.9_amd64.deb",
"https://mirrors.edge.kernel.org/ubuntu/pool/main/l/linux/linux-headers-6.8.0-48_6.8.0-48.48_all.deb", "https://mirrors.edge.kernel.org/ubuntu/pool/main/l/linux/linux-headers-6.5.0-9_6.5.0-9.9_all.deb",
}, },
urls: []string{ urls: []string{
"https://mirrors.edge.kernel.org/ubuntu/pool/main/l/linux/linux-headers-6.8.0-48_6.8.0-48.48_amd64_all.deb", "https://mirrors.edge.kernel.org/ubuntu/pool/main/l/linux/linux-headers-6.5.0-9_6.5.0-9.9_amd64_all.deb",
"https://mirrors.edge.kernel.org/ubuntu/pool/main/l/linux/linux-headers-6.8.0-48-generic_6.8.0-48.48_amd64.deb", "https://mirrors.edge.kernel.org/ubuntu/pool/main/l/linux/linux-headers-6.5.0-9-generic_6.5.0-9.9_amd64.deb",
"https://mirrors.edge.kernel.org/ubuntu/pool/main/l/linux/linux-generic-headers-6.8.0-48_6.8.0-48.48_all.deb", "https://mirrors.edge.kernel.org/ubuntu/pool/main/l/linux/linux-generic-headers-6.5.0-9_6.5.0-9.9_all.deb",
"https://mirrors.edge.kernel.org/ubuntu/pool/main/l/linux/linux-headers-6.8.0-48_6.8.0-48.48_amd64.deb", "https://mirrors.edge.kernel.org/ubuntu/pool/main/l/linux/linux-headers-6.5.0-9_6.5.0-9.9_amd64.deb",
"https://mirrors.edge.kernel.org/ubuntu/pool/main/l/linux/linux-headers-6.8.0-48_6.8.0-48.48_all.deb", "https://mirrors.edge.kernel.org/ubuntu/pool/main/l/linux/linux-headers-6.5.0-9_6.5.0-9.9_all.deb",
"https://mirrors.edge.kernel.org/ubuntu/pool/main/l/linux-generic/linux-headers-6.8.0-48_6.8.0-48.48_amd64_all.deb", "https://mirrors.edge.kernel.org/ubuntu/pool/main/l/linux-generic/linux-headers-6.5.0-9_6.5.0-9.9_amd64_all.deb",
"https://mirrors.edge.kernel.org/ubuntu/pool/main/l/linux-generic/linux-headers-6.8.0-48-generic_6.8.0-48.48_amd64.deb", "https://mirrors.edge.kernel.org/ubuntu/pool/main/l/linux-generic/linux-headers-6.5.0-9-generic_6.5.0-9.9_amd64.deb",
"https://mirrors.edge.kernel.org/ubuntu/pool/main/l/linux-generic/linux-generic-headers-6.8.0-48_6.8.0-48.48_all.deb", "https://mirrors.edge.kernel.org/ubuntu/pool/main/l/linux-generic/linux-generic-headers-6.5.0-9_6.5.0-9.9_all.deb",
"https://mirrors.edge.kernel.org/ubuntu/pool/main/l/linux-generic/linux-headers-6.8.0-48_6.8.0-48.48_amd64.deb", "https://mirrors.edge.kernel.org/ubuntu/pool/main/l/linux-generic/linux-headers-6.5.0-9_6.5.0-9.9_amd64.deb",
"https://mirrors.edge.kernel.org/ubuntu/pool/main/l/linux-generic/linux-headers-6.8.0-48_6.8.0-48.48_all.deb", "https://mirrors.edge.kernel.org/ubuntu/pool/main/l/linux-generic/linux-headers-6.5.0-9_6.5.0-9.9_all.deb",
"https://mirrors.edge.kernel.org/ubuntu/pool/main/l/linux-generic-6.8/linux-headers-6.8.0-48_6.8.0-48.48_amd64_all.deb", "https://mirrors.edge.kernel.org/ubuntu/pool/main/l/linux-generic-6.5/linux-headers-6.5.0-9_6.5.0-9.9_amd64_all.deb",
"https://mirrors.edge.kernel.org/ubuntu/pool/main/l/linux-generic-6.8/linux-headers-6.8.0-48-generic_6.8.0-48.48_amd64.deb", "https://mirrors.edge.kernel.org/ubuntu/pool/main/l/linux-generic-6.5/linux-headers-6.5.0-9-generic_6.5.0-9.9_amd64.deb",
"https://mirrors.edge.kernel.org/ubuntu/pool/main/l/linux-generic-6.8/linux-generic-headers-6.8.0-48_6.8.0-48.48_all.deb", "https://mirrors.edge.kernel.org/ubuntu/pool/main/l/linux-generic-6.5/linux-generic-headers-6.5.0-9_6.5.0-9.9_all.deb",
"https://mirrors.edge.kernel.org/ubuntu/pool/main/l/linux-generic-6.8/linux-headers-6.8.0-48_6.8.0-48.48_amd64.deb", "https://mirrors.edge.kernel.org/ubuntu/pool/main/l/linux-generic-6.5/linux-headers-6.5.0-9_6.5.0-9.9_amd64.deb",
"https://mirrors.edge.kernel.org/ubuntu/pool/main/l/linux-generic-6.8/linux-headers-6.8.0-48_6.8.0-48.48_all.deb", "https://mirrors.edge.kernel.org/ubuntu/pool/main/l/linux-generic-6.5/linux-headers-6.5.0-9_6.5.0-9.9_all.deb",
}, },
gccVersion: semver.Version{ gccVersion: semver.Version{
Major: 6, Major: 6,
Minor: 3, Minor: 3,
}, },
firstExtra: "48", firstExtra: "9",
flavor: "generic", flavor: "generic",
err: nil, err: nil,
}, },

View File

@ -23,24 +23,23 @@ import (
"encoding/binary" "encoding/binary"
"fmt" "fmt"
"io" "io"
"io/ioutil"
"log" "log"
"log/slog"
"os"
"runtime" "runtime"
"strconv" "strconv"
"strings" "strings"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/image"
"github.com/docker/docker/client" "github.com/docker/docker/client"
"github.com/docker/docker/pkg/archive" "github.com/docker/docker/pkg/archive"
v1 "github.com/opencontainers/image-spec/specs-go/v1"
"k8s.io/apimachinery/pkg/util/uuid"
"github.com/falcosecurity/falcoctl/pkg/output"
"github.com/falcosecurity/driverkit/pkg/driverbuilder/builder" "github.com/falcosecurity/driverkit/pkg/driverbuilder/builder"
"github.com/falcosecurity/driverkit/pkg/kernelrelease" "github.com/falcosecurity/driverkit/pkg/kernelrelease"
"github.com/falcosecurity/driverkit/pkg/signals" "github.com/falcosecurity/driverkit/pkg/signals"
v1 "github.com/opencontainers/image-spec/specs-go/v1"
"k8s.io/apimachinery/pkg/util/uuid"
) )
// DockerBuildProcessorName is a constant containing the docker name. // DockerBuildProcessorName is a constant containing the docker name.
@ -50,7 +49,6 @@ type DockerBuildProcessor struct {
clean bool clean bool
timeout int timeout int
proxy string proxy string
*output.Printer
} }
// NewDockerBuildProcessor ... // NewDockerBuildProcessor ...
@ -65,7 +63,7 @@ func (bp *DockerBuildProcessor) String() string {
return DockerBuildProcessorName return DockerBuildProcessorName
} }
func (bp *DockerBuildProcessor) mustCheckArchUseQemu(ctx context.Context, b *builder.Build, cli *client.Client) { func mustCheckArchUseQemu(ctx context.Context, b *builder.Build, cli *client.Client) {
var err error var err error
if b.Architecture == runtime.GOARCH { if b.Architecture == runtime.GOARCH {
// Nothing to do // Nothing to do
@ -73,19 +71,18 @@ func (bp *DockerBuildProcessor) mustCheckArchUseQemu(ctx context.Context, b *bui
} }
if runtime.GOARCH != kernelrelease.ArchitectureAmd64 { if runtime.GOARCH != kernelrelease.ArchitectureAmd64 {
bp.Logger.Fatal("qemu-user-static image is only available for x86_64 hosts: https://github.com/multiarch/qemu-user-static#supported-host-architectures") log.Fatal("qemu-user-static image is only available for x86_64 hosts: https://github.com/multiarch/qemu-user-static#supported-host-architectures")
} }
bp.Logger.Debug("using qemu for cross build") slog.Debug("using qemu for cross build")
if _, _, err = cli.ImageInspectWithRaw(ctx, "multiarch/qemu-user-static"); client.IsErrNotFound(err) { if _, _, err = cli.ImageInspectWithRaw(ctx, "multiarch/qemu-user-static"); client.IsErrNotFound(err) {
bp.Logger.Debug("pulling qemu static image", slog.With("image", "multiarch/qemu-user-static").Debug("pulling qemu static image")
bp.Logger.Args("image", "multiarch/qemu-user-static")) pullRes, err := cli.ImagePull(ctx, "multiarch/qemu-user-static", types.ImagePullOptions{})
pullRes, err := cli.ImagePull(ctx, "multiarch/qemu-user-static", image.PullOptions{})
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
defer pullRes.Close() defer pullRes.Close()
_, err = io.Copy(io.Discard, pullRes) _, err = io.Copy(ioutil.Discard, pullRes)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
@ -101,8 +98,8 @@ func (bp *DockerBuildProcessor) mustCheckArchUseQemu(ctx context.Context, b *bui
Privileged: true, Privileged: true,
}, nil, nil, "") }, nil, nil, "")
if err != nil { if err != nil {
bp.Logger.Fatal("failed to create qemu container", slog.Error(err.Error())
bp.Logger.Args("err", err.Error())) os.Exit(1)
} }
if err = cli.ContainerStart(ctx, qemuImage.ID, container.StartOptions{}); err != nil { if err = cli.ContainerStart(ctx, qemuImage.ID, container.StartOptions{}); err != nil {
@ -120,15 +117,14 @@ func (bp *DockerBuildProcessor) mustCheckArchUseQemu(ctx context.Context, b *bui
err = cli.ContainerStop(ctx, qemuImage.ID, container.StopOptions{}) err = cli.ContainerStop(ctx, qemuImage.ID, container.StopOptions{})
if err != nil && !client.IsErrNotFound(err) { if err != nil && !client.IsErrNotFound(err) {
bp.Logger.Fatal("failed to stop qemu container", slog.Error(err.Error())
bp.Logger.Args("err", err.Error())) os.Exit(1)
} }
} }
// Start the docker processor // Start the docker processor
func (bp *DockerBuildProcessor) Start(b *builder.Build) error { func (bp *DockerBuildProcessor) Start(b *builder.Build) error {
bp.Printer = b.Printer slog.Debug("doing a new docker build")
cli, err := client.NewClientWithOpts(client.FromEnv) cli, err := client.NewClientWithOpts(client.FromEnv)
if err != nil { if err != nil {
return err return err
@ -149,7 +145,7 @@ func (bp *DockerBuildProcessor) Start(b *builder.Build) error {
return err return err
} }
kernelDownloadScript, err := builder.KernelDownloadScript(v, c.KernelUrls, kr, b.Printer) kernelDownloadScript, err := builder.KernelDownloadScript(v, c.KernelUrls, kr)
if err != nil { if err != nil {
return err return err
} }
@ -171,27 +167,30 @@ func (bp *DockerBuildProcessor) Start(b *builder.Build) error {
ctx := context.Background() ctx := context.Background()
ctx = signals.WithStandardSignals(ctx) ctx = signals.WithStandardSignals(ctx)
bp.mustCheckArchUseQemu(ctx, b, cli) mustCheckArchUseQemu(ctx, b, cli)
var inspect types.ImageInspect var inspect types.ImageInspect
if inspect, _, err = cli.ImageInspectWithRaw(ctx, builderImage); client.IsErrNotFound(err) || if inspect, _, err = cli.ImageInspectWithRaw(ctx, builderImage); client.IsErrNotFound(err) ||
inspect.Architecture != b.Architecture { inspect.Architecture != b.Architecture {
bp.Logger.Debug("pulling builder image", slog.
bp.Logger.Args("image", builderImage, "arch", b.Architecture)) With("image", builderImage, "arch", b.Architecture).
Debug("pulling builder image")
pullRes, err := cli.ImagePull(ctx, builderImage, image.PullOptions{Platform: b.Architecture}) pullRes, err := cli.ImagePull(ctx, builderImage, types.ImagePullOptions{Platform: b.Architecture})
if err != nil { if err != nil {
return err return err
} }
defer pullRes.Close() defer pullRes.Close()
_, err = io.Copy(io.Discard, pullRes) _, err = io.Copy(ioutil.Discard, pullRes)
if err != nil { if err != nil {
return err return err
} }
} }
bp.Logger.Debug("starting container", bp.Logger.Args("image", builderImage)) slog.
With("image", builderImage).
Debug("starting container")
containerCfg := &container.Config{ containerCfg := &container.Config{
Tty: true, Tty: true,
@ -200,7 +199,7 @@ func (bp *DockerBuildProcessor) Start(b *builder.Build) error {
} }
// check for any overridden builder image network modes by the builder // check for any overridden builder image network modes by the builder
builderImageNetMode := container.NetworkMode("default") var builderImageNetMode = container.NetworkMode("default")
if vv, ok := v.(builder.BuilderImageNetworkMode); ok { if vv, ok := v.(builder.BuilderImageNetworkMode); ok {
builderImageNetMode = container.NetworkMode(vv.BuilderImageNetMode()) builderImageNetMode = container.NetworkMode(vv.BuilderImageNetMode())
} }
@ -241,7 +240,8 @@ func (bp *DockerBuildProcessor) Start(b *builder.Build) error {
// * each download-headers script will export KERNELDIR variable internally // * each download-headers script will export KERNELDIR variable internally
// * we source download-headers.sh so that KERNELDIR is then visible to driverkit.sh // * we source download-headers.sh so that KERNELDIR is then visible to driverkit.sh
// * we finally make the actual build of the drivers // * we finally make the actual build of the drivers
runCmd := ` runCmd :=
`
#!/bin/bash #!/bin/bash
chmod +x /driverkit/download-libs.sh chmod +x /driverkit/download-libs.sh
@ -267,7 +267,7 @@ chmod +x /driverkit/driverkit.sh
return err return err
} }
// Copy the needed files to the container // Copy the needed files to the container
err = cli.CopyToContainer(ctx, cdata.ID, "/", &buf, container.CopyToContainerOptions{}) err = cli.CopyToContainer(ctx, cdata.ID, "/", &buf, types.CopyToContainerOptions{})
if err != nil { if err != nil {
return err return err
} }
@ -282,7 +282,7 @@ chmod +x /driverkit/driverkit.sh
) )
} }
edata, err := cli.ContainerExecCreate(ctx, cdata.ID, container.ExecOptions{ edata, err := cli.ContainerExecCreate(ctx, cdata.ID, types.ExecConfig{
Privileged: false, Privileged: false,
Tty: false, Tty: false,
AttachStdin: false, AttachStdin: false,
@ -296,11 +296,12 @@ chmod +x /driverkit/driverkit.sh
"/driverkit/cmd.sh", "/driverkit/cmd.sh",
}, },
}) })
if err != nil { if err != nil {
return err return err
} }
hr, err := cli.ContainerExecAttach(ctx, edata.ID, container.ExecAttachOptions{}) hr, err := cli.ContainerExecAttach(ctx, edata.ID, types.ExecStartCheck{})
if err != nil { if err != nil {
return err return err
} }
@ -311,23 +312,23 @@ chmod +x /driverkit/driverkit.sh
isMultiplexed = val == "application/vnd.docker.multiplexed-stream" isMultiplexed = val == "application/vnd.docker.multiplexed-stream"
} }
if isMultiplexed { if isMultiplexed {
bp.multiplexedForwardLogs(hr.Reader) multiplexedForwardLogs(hr.Reader)
} else { } else {
bp.forwardLogs(hr.Reader) forwardLogs(hr.Reader)
} }
if len(b.ModuleFilePath) > 0 { if len(b.ModuleFilePath) > 0 {
if err := copyFromContainer(ctx, cli, cdata.ID, c.ToDriverFullPath(), b.ModuleFilePath); err != nil { if err := copyFromContainer(ctx, cli, cdata.ID, c.ToDriverFullPath(), b.ModuleFilePath); err != nil {
return err return err
} }
bp.Logger.Info("kernel module available", bp.Logger.Args("path", b.ModuleFilePath)) slog.With("path", b.ModuleFilePath).Info("kernel module available")
} }
if len(b.ProbeFilePath) > 0 { if len(b.ProbeFilePath) > 0 {
if err := copyFromContainer(ctx, cli, cdata.ID, c.ToProbeFullPath(), b.ProbeFilePath); err != nil { if err := copyFromContainer(ctx, cli, cdata.ID, c.ToProbeFullPath(), b.ProbeFilePath); err != nil {
return err return err
} }
bp.Logger.Info("eBPF probe available", bp.Logger.Args("path", b.ProbeFilePath)) slog.With("path", b.ProbeFilePath).Info("eBPF probe available")
} }
return nil return nil
@ -352,11 +353,10 @@ func copyFromContainer(ctx context.Context, cli *client.Client, ID, from, to str
func (bp *DockerBuildProcessor) cleanup(cli *client.Client, ID string) { func (bp *DockerBuildProcessor) cleanup(cli *client.Client, ID string) {
if !bp.clean { if !bp.clean {
bp.clean = true bp.clean = true
bp.Logger.Debug("context canceled") slog.Debug("context canceled")
duration := 1 duration := 1
if err := cli.ContainerStop(context.Background(), ID, container.StopOptions{Timeout: &duration}); err != nil && !client.IsErrNotFound(err) { if err := cli.ContainerStop(context.Background(), ID, container.StopOptions{Timeout: &duration}); err != nil && !client.IsErrNotFound(err) {
bp.Logger.Error("error stopping container", slog.With("err", err.Error(), "container_id", ID).Error("error stopping container")
bp.Logger.Args("err", err.Error()))
} }
} }
} }
@ -385,21 +385,21 @@ func tarWriterFiles(buf io.Writer, files []dockerCopyFile) error {
return nil return nil
} }
func (bp *DockerBuildProcessor) forwardLogs(logPipe io.Reader) { func forwardLogs(logPipe io.Reader) {
lineReader := bufio.NewReader(logPipe) lineReader := bufio.NewReader(logPipe)
for { for {
line, err := lineReader.ReadBytes('\n') line, err := lineReader.ReadBytes('\n')
if len(line) > 0 { if len(line) > 0 {
bp.Logger.Debug(string(line)) slog.Debug(string(line))
} }
if err == io.EOF { if err == io.EOF {
break break
} }
if err != nil { if err != nil {
bp.Logger.Error("log pipe error", bp.Logger.Args("err", err.Error())) slog.With("err", err.Error()).Error("log pipe error")
} }
} }
bp.Logger.Debug("log pipe close") slog.Debug("log pipe close")
} }
// When docker container attach is called on a non-tty terminal, // When docker container attach is called on a non-tty terminal,
@ -408,7 +408,7 @@ func (bp *DockerBuildProcessor) forwardLogs(logPipe io.Reader) {
// > The format of the multiplexed stream is as follows: // > The format of the multiplexed stream is as follows:
// > [8]byte{STREAM_TYPE, 0, 0, 0, SIZE1, SIZE2, SIZE3, SIZE4}[]byte{OUTPUT} // > [8]byte{STREAM_TYPE, 0, 0, 0, SIZE1, SIZE2, SIZE3, SIZE4}[]byte{OUTPUT}
// see cli.ContainerAttach() method for more info. // see cli.ContainerAttach() method for more info.
func (bp *DockerBuildProcessor) multiplexedForwardLogs(logPipe io.Reader) { func multiplexedForwardLogs(logPipe io.Reader) {
hdr := make([]byte, 8) hdr := make([]byte, 8)
for { for {
// Load size of message // Load size of message
@ -417,7 +417,7 @@ func (bp *DockerBuildProcessor) multiplexedForwardLogs(logPipe io.Reader) {
break break
} }
if err != nil { if err != nil {
bp.Logger.Error("log pipe error", bp.Logger.Args("err", err.Error())) slog.With("err", err.Error()).Error("log pipe error")
return return
} }
count := binary.BigEndian.Uint32(hdr[4:]) count := binary.BigEndian.Uint32(hdr[4:])
@ -432,11 +432,11 @@ func (bp *DockerBuildProcessor) multiplexedForwardLogs(logPipe io.Reader) {
if uint32(readCnt) == count { if uint32(readCnt) == count {
break break
} }
bp.Logger.Error("log pipe error", bp.Logger.Args("err", io.EOF.Error())) slog.With("err", err.Error()).Error("log pipe error")
return return
} }
if err != nil { if err != nil {
bp.Logger.Error("log pipe error", bp.Logger.Args("err", err.Error())) slog.With("err", err.Error()).Error("log pipe error")
return return
} }
} }
@ -445,9 +445,9 @@ func (bp *DockerBuildProcessor) multiplexedForwardLogs(logPipe io.Reader) {
lines := strings.Split(string(dat), "\n") lines := strings.Split(string(dat), "\n")
for _, line := range lines { for _, line := range lines {
if line != "" { if line != "" {
bp.Logger.Debug(line) slog.Debug(line)
} }
} }
} }
bp.Logger.Debug("log pipe close") slog.Debug("log pipe close")
} }

View File

@ -20,8 +20,7 @@ import (
"encoding/base64" "encoding/base64"
"errors" "errors"
"fmt" "fmt"
"github.com/falcosecurity/falcoctl/pkg/output" "log/slog"
"k8s.io/cli-runtime/pkg/genericiooptions"
"os" "os"
"time" "time"
@ -51,21 +50,13 @@ type KubernetesBuildProcessor struct {
imagePullSecret string imagePullSecret string
timeout int timeout int
proxy string proxy string
*output.Printer
} }
// NewKubernetesBuildProcessor constructs a KubernetesBuildProcessor // NewKubernetesBuildProcessor constructs a KubernetesBuildProcessor
// starting from a kubernetes.Clientset. bufferSize represents the length of the // starting from a kubernetes.Clientset. bufferSize represents the length of the
// channel we use to do the builds. A bigger bufferSize will mean that we can save more Builds // channel we use to do the builds. A bigger bufferSize will mean that we can save more Builds
// for processing, however setting this to a big value will have impacts // for processing, however setting this to a big value will have impacts
func NewKubernetesBuildProcessor(corev1Client v1.CoreV1Interface, func NewKubernetesBuildProcessor(corev1Client v1.CoreV1Interface, clientConfig *restclient.Config, runAsUser int64, namespace string, imagePullSecret string, timeout int, proxy string) *KubernetesBuildProcessor {
clientConfig *restclient.Config,
runAsUser int64,
namespace string,
imagePullSecret string,
timeout int,
proxy string,
) *KubernetesBuildProcessor {
return &KubernetesBuildProcessor{ return &KubernetesBuildProcessor{
coreV1Client: corev1Client, coreV1Client: corev1Client,
clientConfig: clientConfig, clientConfig: clientConfig,
@ -82,8 +73,11 @@ func (bp *KubernetesBuildProcessor) String() string {
} }
func (bp *KubernetesBuildProcessor) Start(b *builder.Build) error { func (bp *KubernetesBuildProcessor) Start(b *builder.Build) error {
bp.Printer = b.Printer slog.Debug("doing a new kubernetes build")
return bp.buildModule(b)
}
func (bp *KubernetesBuildProcessor) buildModule(b *builder.Build) error {
deadline := int64(bp.timeout) deadline := int64(bp.timeout)
namespace := bp.namespace namespace := bp.namespace
uid := uuid.NewUUID() uid := uuid.NewUUID()
@ -107,7 +101,7 @@ func (bp *KubernetesBuildProcessor) Start(b *builder.Build) error {
return err return err
} }
kernelDownloadScript, err := builder.KernelDownloadScript(v, c.KernelUrls, kr, bp.Printer) kernelDownloadScript, err := builder.KernelDownloadScript(v, c.KernelUrls, kr)
if err != nil { if err != nil {
return err return err
} }
@ -243,8 +237,9 @@ func (bp *KubernetesBuildProcessor) Start(b *builder.Build) error {
}, },
} }
bp.Logger.Debug("starting pod", slog.
bp.Logger.Args("name", pod.Name, "spec", pod.Spec.String())) With("name", pod.Name, "spec", pod.Spec.String()).
Debug("starting pod")
ctx := context.Background() ctx := context.Background()
ctx = signals.WithStandardSignals(ctx) ctx = signals.WithStandardSignals(ctx)
@ -281,35 +276,33 @@ func (bp *KubernetesBuildProcessor) copyModuleAndProbeFromPodWithUID(ctx context
event := <-watch.ResultChan() event := <-watch.ResultChan()
p, ok := event.Object.(*corev1.Pod) p, ok := event.Object.(*corev1.Pod)
if !ok { if !ok {
bp.Logger.Error("unexpected type when watching pods") slog.Error("unexpected type when watching pods")
continue continue
} }
if p.Status.Phase == corev1.PodPending { if p.Status.Phase == corev1.PodPending {
continue continue
} }
if p.Status.Phase == corev1.PodRunning { if p.Status.Phase == corev1.PodRunning {
bp.Logger.Info("start downloading module and probe from pod", slog.With(falcoBuilderUIDLabel, falcoBuilderUID).Info("start downloading module and probe from pod")
bp.Logger.Args(falcoBuilderUIDLabel, falcoBuilderUID))
if c.ModuleFilePath != "" { if c.ModuleFilePath != "" {
err = copySingleFileFromPod(c.ModuleFilePath, bp.coreV1Client, bp.clientConfig, p.Namespace, p.Name, c.ToDriverFullPath(), moduleLockFile) err = copySingleFileFromPod(c.ModuleFilePath, bp.coreV1Client, bp.clientConfig, p.Namespace, p.Name, c.ToDriverFullPath(), moduleLockFile)
if err != nil { if err != nil {
return err return err
} }
bp.Logger.Info("Kernel Module extraction successful") slog.Info("Kernel Module extraction successful")
} }
if c.ProbeFilePath != "" { if c.ProbeFilePath != "" {
err = copySingleFileFromPod(c.ProbeFilePath, bp.coreV1Client, bp.clientConfig, p.Namespace, p.Name, c.ToProbeFullPath(), probeLockFile) err = copySingleFileFromPod(c.ProbeFilePath, bp.coreV1Client, bp.clientConfig, p.Namespace, p.Name, c.ToProbeFullPath(), probeLockFile)
if err != nil { if err != nil {
return err return err
} }
bp.Logger.Info("Probe Module extraction successful") slog.Info("Probe Module extraction successful")
} }
err = unlockPod(bp.coreV1Client, bp.clientConfig, p) err = unlockPod(bp.coreV1Client, bp.clientConfig, p)
if err != nil { if err != nil {
return err return err
} }
bp.Logger.Info("completed downloading from pod", slog.With(falcoBuilderUIDLabel, falcoBuilderUID).Info("completed downloading from pod")
bp.Logger.Args(falcoBuilderUIDLabel, falcoBuilderUID))
} }
return nil return nil
} }
@ -321,7 +314,7 @@ func unlockPod(podClient v1.PodsGetter, clientConfig *restclient.Config, pod *co
PodClient: podClient, PodClient: podClient,
Config: clientConfig, Config: clientConfig,
StreamOptions: exec.StreamOptions{ StreamOptions: exec.StreamOptions{
IOStreams: genericiooptions.IOStreams{ IOStreams: genericclioptions.IOStreams{
Out: bytes.NewBuffer([]byte{}), Out: bytes.NewBuffer([]byte{}),
ErrOut: bytes.NewBuffer([]byte{}), ErrOut: bytes.NewBuffer([]byte{}),
}, },

View File

@ -8,8 +8,8 @@ import (
"errors" "errors"
"fmt" "fmt"
"github.com/falcosecurity/driverkit/pkg/driverbuilder/builder" "github.com/falcosecurity/driverkit/pkg/driverbuilder/builder"
"github.com/falcosecurity/falcoctl/pkg/output"
"io" "io"
"log/slog"
"os" "os"
"os/exec" "os/exec"
"os/user" "os/user"
@ -23,31 +23,20 @@ const (
) )
type LocalBuildProcessor struct { type LocalBuildProcessor struct {
timeout int
useDKMS bool useDKMS bool
downloadHeaders bool downloadHeaders bool
// Whether to only print cmd output on error srcDir string
printOnError bool envMap map[string]string
srcDir string
envMap map[string]string
timeout int
*output.Printer
} }
func NewLocalBuildProcessor(useDKMS, downloadHeaders, printOnError bool, func NewLocalBuildProcessor(timeout int, useDKMS, downloadHeaders bool, srcDir string, envMap map[string]string) *LocalBuildProcessor {
srcDir string,
envMap map[string]string,
timeout int,
) *LocalBuildProcessor {
if envMap == nil {
envMap = make(map[string]string)
}
return &LocalBuildProcessor{ return &LocalBuildProcessor{
timeout: timeout,
useDKMS: useDKMS, useDKMS: useDKMS,
srcDir: srcDir, srcDir: srcDir,
printOnError: printOnError,
envMap: envMap, envMap: envMap,
downloadHeaders: downloadHeaders, downloadHeaders: downloadHeaders,
timeout: timeout,
} }
} }
@ -56,7 +45,8 @@ func (lbp *LocalBuildProcessor) String() string {
} }
func (lbp *LocalBuildProcessor) Start(b *builder.Build) error { func (lbp *LocalBuildProcessor) Start(b *builder.Build) error {
lbp.Printer = b.Printer slog.Debug("doing a new local build")
if lbp.useDKMS { if lbp.useDKMS {
currentUser, err := user.Current() currentUser, err := user.Current()
if err != nil { if err != nil {
@ -77,8 +67,8 @@ func (lbp *LocalBuildProcessor) Start(b *builder.Build) error {
// if an unsupported target is passed. // if an unsupported target is passed.
// Go on skipping automatic kernel headers download. // Go on skipping automatic kernel headers download.
if err == nil { if err == nil {
lbp.Logger.Info("Trying automatic kernel headers download.") slog.Info("Trying automatic kernel headers download")
kernelDownloadScript, err := builder.KernelDownloadScript(realBuilder, nil, kr, lbp.Printer) kernelDownloadScript, err := builder.KernelDownloadScript(realBuilder, nil, kr)
// Patch kernel download script to echo KERNELDIR. // Patch kernel download script to echo KERNELDIR.
// We need to capture KERNELDIR to later pass it as env variable to the build. // We need to capture KERNELDIR to later pass it as env variable to the build.
kernelDownloadScript += "\necho $KERNELDIR" kernelDownloadScript += "\necho $KERNELDIR"
@ -93,7 +83,7 @@ func (lbp *LocalBuildProcessor) Start(b *builder.Build) error {
for scanner.Scan() { for scanner.Scan() {
path = scanner.Text() path = scanner.Text()
} }
lbp.Logger.Info("Setting KERNELDIR env var.", lbp.Logger.Args("path", path)) slog.Info("Setting KERNELDIR env var", "path", path)
// add the kerneldir path to env // add the kerneldir path to env
lbp.envMap[kernelDirEnv] = path lbp.envMap[kernelDirEnv] = path
defer func() { defer func() {
@ -101,13 +91,11 @@ func (lbp *LocalBuildProcessor) Start(b *builder.Build) error {
_ = os.RemoveAll(path) _ = os.RemoveAll(path)
}() }()
} else { } else {
lbp.Logger.Warn("Failed to download headers.", lbp.Logger.Args("err", err)) slog.Warn("Failed to download headers", "err", err)
} }
} else {
lbp.Logger.Warn("Failed to generate script.", lbp.Logger.Args("err", err))
} }
} else { } else {
lbp.Logger.Info("Skipping kernel headers automatic download.", lbp.Logger.Args("err", err)) slog.Info("Skipping kernel headers automatic download", "err", err)
} }
} }
@ -125,7 +113,7 @@ func (lbp *LocalBuildProcessor) Start(b *builder.Build) error {
// Load gcc versions from system // Load gcc versions from system
var gccs []string var gccs []string
if len(c.ModuleFilePath) > 0 { if len(b.ModuleFilePath) > 0 {
out, err := exec.Command("which", "gcc").Output() out, err := exec.Command("which", "gcc").Output()
if err != nil { if err != nil {
return err return err
@ -160,7 +148,7 @@ func (lbp *LocalBuildProcessor) Start(b *builder.Build) error {
srcProbePath := vv.GetProbeFullPath(c) srcProbePath := vv.GetProbeFullPath(c)
if len(lbp.srcDir) == 0 { if len(lbp.srcDir) == 0 {
lbp.Logger.Info("Downloading driver sources") slog.Info("Downloading driver sources")
// Download src! // Download src!
libsDownloadScript, err := builder.LibsDownloadScript(c) libsDownloadScript, err := builder.LibsDownloadScript(c)
if err != nil { if err != nil {
@ -174,12 +162,6 @@ func (lbp *LocalBuildProcessor) Start(b *builder.Build) error {
for _, gcc := range gccs { for _, gcc := range gccs {
vv.GccPath = gcc vv.GccPath = gcc
if c.ModuleFilePath != "" {
lbp.Logger.Info("Trying to dkms install module.", lbp.Logger.Args("gcc", gcc))
}
if c.ProbeFilePath != "" {
lbp.Logger.Info("Trying to build eBPF probe.")
}
// Generate the build script from the builder // Generate the build script from the builder
driverkitScript, err := builder.Script(v, c, kr) driverkitScript, err := builder.Script(v, c, kr)
@ -195,58 +177,59 @@ func (lbp *LocalBuildProcessor) Start(b *builder.Build) error {
cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%s", key, val)) cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%s", key, val))
} }
out, err := cmd.CombinedOutput() stdout, err := cmd.StdoutPipe()
if !lbp.printOnError || err != nil { if err != nil {
// Only print on error slog.Warn("Failed to pipe stdout", "err", err)
lbp.DefaultText.Print(string(out)) _, err = cmd.CombinedOutput()
} else {
cmd.Stderr = cmd.Stdout // redirect stderr to stdout so that we catch it
defer stdout.Close()
err = cmd.Start()
if err != nil {
slog.Warn("Failed to execute command", "err", err)
} else {
// print the output of the subprocess line by line
scanner := bufio.NewScanner(stdout)
for scanner.Scan() {
m := scanner.Text()
fmt.Println(m)
}
err = cmd.Wait()
}
} }
// If we built the probe, disable its build for subsequent attempts (with other available gccs) // If we built the probe, disable its build for subsequent attempts (with other available gccs)
if c.ProbeFilePath != "" { if c.ProbeFilePath != "" {
if _, err = os.Stat(srcProbePath); !os.IsNotExist(err) { if _, err = os.Stat(srcProbePath); !os.IsNotExist(err) {
if err = copyDataToLocalPath(srcProbePath, c.ProbeFilePath); err != nil { if err = copyDataToLocalPath(srcProbePath, b.ProbeFilePath); err != nil {
return err return err
} }
lbp.Logger.Info("eBPF probe available.", lbp.Logger.Args("path", c.ProbeFilePath)) slog.With("path", b.ProbeFilePath).Info("eBPF probe available")
c.ProbeFilePath = "" c.ProbeFilePath = ""
} }
} }
// If we received an error, perhaps we just need to try another build for the kmod. // If we received an error, perhaps we just need to try another build for the kmod.
// Check if we were able to build anything. // Check if we were able to build anything.
if c.ModuleFilePath != "" { koFiles, err := filepath.Glob(srcModulePath)
koFiles, err := filepath.Glob(srcModulePath) if err == nil && len(koFiles) > 0 {
if err == nil && len(koFiles) > 0 { // Since only kmod might need to get rebuilt
// Since only kmod might need to get rebuilt // with another gcc, break here if we actually built the kmod.
// with another gcc, break here if we actually built the kmod, break
// since we already checked ebpf build status.
if err = copyDataToLocalPath(koFiles[0], c.ModuleFilePath); err != nil {
return err
}
lbp.Logger.Info("kernel module available.", lbp.Logger.Args("path", b.ModuleFilePath))
c.ModuleFilePath = ""
break
} else {
// print dkms build log
dkmsLogFile := fmt.Sprintf("/var/lib/dkms/%s/%s/build/make.log", c.DriverName, c.DriverVersion)
logs, err := os.ReadFile(filepath.Clean(dkmsLogFile))
if err != nil {
lbp.Logger.Warn("Running dkms build failed, couldn't find dkms log.", lbp.Logger.Args("file", dkmsLogFile))
} else {
lbp.Logger.Warn("Running dkms build failed. Dumping dkms log.", lbp.Logger.Args("file", dkmsLogFile))
logBuf := bytes.NewBuffer(logs)
scanner := bufio.NewScanner(logBuf)
for scanner.Scan() {
m := scanner.Text()
lbp.DefaultText.Println(m)
}
}
}
} }
} }
if c.ModuleFilePath != "" || c.ProbeFilePath != "" { if len(b.ModuleFilePath) > 0 {
return errors.New("failed to build all requested drivers") // If we received an error, perhaps we must just rebuilt the kmod.
// Check if we were able to build anything.
koFiles, err := filepath.Glob(srcModulePath)
if err != nil || len(koFiles) == 0 {
return fmt.Errorf("failed to find kernel module .ko file: %s", srcModulePath)
}
if err = copyDataToLocalPath(koFiles[0], b.ModuleFilePath); err != nil {
return err
}
slog.With("path", b.ModuleFilePath).Info("kernel module available")
} }
return nil return nil
} }

View File

@ -21,11 +21,11 @@ import (
"strconv" "strconv"
"strings" "strings"
"github.com/blang/semver/v4" "github.com/blang/semver"
) )
var ( var (
kernelVersionPattern = regexp.MustCompile(`(?P<fullversion>^(?P<version>0|[1-9]\d*)\.(?P<patchlevel>0|[1-9]\d*)[.+]?(?P<sublevel>0|[1-9]\d*)?)(?P<fullextraversion>[-.+](?P<extraversion>\d+|\d*[a-zA-Z-][0-9a-zA-Z-]*)?([\.+~](\d+|\d*[a-zA-Z-][0-9a-zA-Z-_]*))*)?(\+[0-9a-zA-Z-]+(\.[0-9a-zA-Z-]+)*)?$`) kernelVersionPattern = regexp.MustCompile(`(?P<fullversion>^(?P<version>0|[1-9]\d*)\.(?P<patchlevel>0|[1-9]\d*)[.+]?(?P<sublevel>0|[1-9]\d*)?)(?P<fullextraversion>[-.+](?P<extraversion>0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)([\.+~](0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-_]*))*)?(\+[0-9a-zA-Z-]+(\.[0-9a-zA-Z-]+)*)?$`)
) )
const ( const (

View File

@ -17,7 +17,7 @@ package kernelrelease
import ( import (
"testing" "testing"
"github.com/blang/semver/v4" "github.com/blang/semver"
"gotest.tools/assert" "gotest.tools/assert"
) )
@ -234,40 +234,11 @@ func TestFromString(t *testing.T) {
FullExtraversion: "+deb10u4~bpo9+1", FullExtraversion: "+deb10u4~bpo9+1",
}, },
}, },
// See https://github.com/falcosecurity/falco/issues/3172
"strange tencentos version": {
kernelVersionStr: "5.4.119-19.0009.28",
want: KernelRelease{
Fullversion: "5.4.119",
Version: semver.Version{
Major: 5,
Minor: 4,
Patch: 119,
},
Extraversion: "19",
FullExtraversion: "-19.0009.28",
},
},
// See https://github.com/falcosecurity/falco/issues/3278
"strange cos version": {
kernelVersionStr: "5.15.146+",
want: KernelRelease{
Fullversion: "5.15.146",
Version: semver.Version{
Major: 5,
Minor: 15,
Patch: 146,
},
Extraversion: "",
FullExtraversion: "+",
},
},
} }
for name, tt := range tests { for name, tt := range tests {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
got := FromString(tt.kernelVersionStr) got := FromString(tt.kernelVersionStr)
assert.DeepEqual(t, tt.want, got) assert.DeepEqual(t, tt.want, got)
assert.Equal(t, got.String(), tt.kernelVersionStr)
}) })
} }
} }

32
validate/isloglevel.go Normal file
View File

@ -0,0 +1,32 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright (C) 2023 The Falco Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package validate
import (
"log/slog"
"github.com/go-playground/validator/v10"
)
var ProgramLevel = new(slog.LevelVar)
func isLogLevel(fl validator.FieldLevel) bool {
level := fl.Field().String()
err := ProgramLevel.UnmarshalText([]byte(level))
if err != nil {
return false
}
return true
}

View File

@ -18,7 +18,7 @@ import (
"fmt" "fmt"
"reflect" "reflect"
"github.com/blang/semver/v4" "github.com/blang/semver"
"github.com/go-playground/validator/v10" "github.com/go-playground/validator/v10"
) )

View File

@ -48,6 +48,7 @@ func init() {
return name return name
}) })
V.RegisterValidation("loglevel", isLogLevel)
V.RegisterValidation("filepath", isFilePath) V.RegisterValidation("filepath", isFilePath)
V.RegisterValidation("sha1", isSHA1) V.RegisterValidation("sha1", isSHA1)
V.RegisterValidation("target", isTargetSupported) V.RegisterValidation("target", isTargetSupported)
@ -153,6 +154,19 @@ func init() {
}, },
) )
V.RegisterTranslation(
"loglevel",
T,
func(ut ut.Translator) error {
return ut.Add("loglevel", "{0} must be a valid slog level", true)
},
func(ut ut.Translator, fe validator.FieldError) string {
t, _ := ut.T("loglevel", fe.Field())
return t
},
)
V.RegisterTranslation( V.RegisterTranslation(
"eq=dev|sha1|semver", "eq=dev|sha1|semver",
T, T,