├── configs └── fpga-operator │ ├── VERSION │ ├── Dockerfile │ ├── .env │ └── docker-compose.yml ├── internal ├── config.go ├── error.go ├── host.go └── cmd │ ├── ps.go │ ├── config.go │ ├── up.go │ ├── run.go │ ├── down.go │ ├── logs.go │ └── exec.go ├── NOTICE ├── README.md ├── .goreleaser.yml ├── .github └── workflows │ ├── release.yml │ └── dockerhub.yml ├── pkg ├── xdg │ └── xdg.go ├── grep │ └── grep.go └── system │ └── system.go ├── go.mod ├── cmd └── main.go ├── LICENSE └── go.sum /configs/fpga-operator/VERSION: -------------------------------------------------------------------------------- 1 | 2.3.1 2 | -------------------------------------------------------------------------------- /internal/config.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | const Config = "fpga-operator" 4 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | inaccel/docker 2 | Copyright © 2018-2023 InAccel 3 | 4 | This product includes software developed at 5 | InAccel (https://inaccel.com). 6 | -------------------------------------------------------------------------------- /configs/fpga-operator/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM docker/compose:1.29.2 2 | ENV COMPOSE_IGNORE_ORPHANS=true 3 | COPY docker-compose.yml . 4 | COPY .env . 5 | ENTRYPOINT ["docker-compose"] 6 | -------------------------------------------------------------------------------- /internal/error.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | import ( 4 | "os/exec" 5 | 6 | "github.com/docker/cli/cli" 7 | ) 8 | 9 | func ExitToStatus(err error) error { 10 | if exitErr, ok := err.(*exec.ExitError); ok { 11 | err = cli.StatusError{ 12 | StatusCode: exitErr.ExitCode(), 13 | } 14 | } 15 | return err 16 | } 17 | -------------------------------------------------------------------------------- /internal/host.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | import ( 4 | "net/url" 5 | "os" 6 | "syscall" 7 | ) 8 | 9 | var Host *url.URL 10 | 11 | func Rootless() (bool, error) { 12 | info, err := os.Stat(Host.Path) 13 | if err != nil { 14 | return false, err 15 | } 16 | return info.Sys().(*syscall.Stat_t).Uid != 0, nil 17 | } 18 | -------------------------------------------------------------------------------- /configs/fpga-operator/.env: -------------------------------------------------------------------------------- 1 | coral_fpgas=all 2 | coral_httpsProxy= 3 | coral_image=inaccel/coral 4 | coral_logLevel=info 5 | coral_port= 6 | coral_tag=2.1 7 | driver_image=inaccel/driver 8 | driver_tag=latest 9 | license= 10 | mkrt_image=inaccel/mkrt 11 | mkrt_tag=latest 12 | monitor_image=inaccel/monitor 13 | monitor_port= 14 | monitor_tag=2.1 15 | tests_vadd_image=inaccel/vadd 16 | tests_vadd_platform= 17 | tests_vadd_tag=latest 18 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## docker inaccel 2 | 3 | **Simplifying FPGA management in Docker** 4 | 5 | [![Go Reference](https://pkg.go.dev/badge/github.com/inaccel/docker.svg)](https://pkg.go.dev/github.com/inaccel/docker) 6 | [![Go Report Card](https://goreportcard.com/badge/github.com/inaccel/docker)](https://goreportcard.com/report/github.com/inaccel/docker) 7 | [![Latest Release](https://img.shields.io/github/release/inaccel/docker.svg)](https://github.com/inaccel/docker/releases/latest) 8 | -------------------------------------------------------------------------------- /.goreleaser.yml: -------------------------------------------------------------------------------- 1 | project_name: inaccel-docker 2 | 3 | before: 4 | hooks: 5 | - go mod download 6 | builds: 7 | - binary: docker-inaccel 8 | env: 9 | - CGO_ENABLED=0 10 | goarch: 11 | - amd64 12 | goos: 13 | - linux 14 | main: ./cmd 15 | 16 | archives: 17 | - files: 18 | - none* 19 | id: archive 20 | name_template: "{{ .Os }}-{{ .Arch }}" 21 | changelog: 22 | filters: 23 | exclude: 24 | - '\[APP\]' 25 | checksum: 26 | name_template: checksums.txt 27 | nfpms: 28 | - bindir: /usr/libexec/docker/cli-plugins 29 | description: Simplifying FPGA management in Docker 30 | file_name_template: "{{ .ConventionalFileName }}" 31 | formats: 32 | - deb 33 | - rpm 34 | homepage: https://inaccel.com 35 | license: Apache-2.0 36 | maintainer: InAccel 37 | vendor: InAccel 38 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | on: 3 | push: 4 | tags: 5 | - v*.*.* 6 | jobs: 7 | pipeline: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - name: Checkout 11 | uses: actions/checkout@v4 12 | with: 13 | fetch-depth: 0 14 | - name: Set up Go 15 | uses: actions/setup-go@v4 16 | with: 17 | go-version: 1.21 18 | - name: Release binaries 19 | uses: goreleaser/goreleaser-action@v5 20 | with: 21 | args: release 22 | env: 23 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 24 | - name: Push Debian 25 | uses: cloudsmith-io/action@master 26 | with: 27 | api-key: ${{ secrets.CLOUDSMITH_API_KEY }} 28 | command: push 29 | format: deb 30 | owner: inaccel 31 | repo: stable 32 | distro: any-distro 33 | release: any-version 34 | file: dist/*.deb 35 | - name: Push RPM 36 | uses: cloudsmith-io/action@master 37 | with: 38 | api-key: ${{ secrets.CLOUDSMITH_API_KEY }} 39 | command: push 40 | format: rpm 41 | owner: inaccel 42 | repo: stable 43 | distro: any-distro 44 | release: any-version 45 | file: dist/*.rpm 46 | -------------------------------------------------------------------------------- /pkg/xdg/xdg.go: -------------------------------------------------------------------------------- 1 | package xdg 2 | 3 | import ( 4 | "os" 5 | "path/filepath" 6 | "strconv" 7 | ) 8 | 9 | var ( 10 | CacheHome string 11 | ConfigDirs []string 12 | ConfigHome string 13 | DataDirs []string 14 | DataHome string 15 | RuntimeDir string 16 | StateHome string 17 | ) 18 | 19 | func init() { 20 | if value := os.Getenv("XDG_CACHE_HOME"); value != "" { 21 | CacheHome = value 22 | } else { 23 | CacheHome = filepath.Join(os.Getenv("HOME"), ".cache") 24 | } 25 | 26 | if value := os.Getenv("XDG_CONFIG_DIRS"); value != "" { 27 | ConfigDirs = filepath.SplitList(value) 28 | } else { 29 | ConfigDirs = []string{ 30 | filepath.Join("/", "etc", "xdg"), 31 | } 32 | } 33 | 34 | if value := os.Getenv("XDG_CONFIG_HOME"); value != "" { 35 | ConfigHome = value 36 | } else { 37 | ConfigHome = filepath.Join(os.Getenv("HOME"), ".config") 38 | } 39 | 40 | if value := os.Getenv("XDG_DATA_DIRS"); value != "" { 41 | DataDirs = filepath.SplitList(value) 42 | } else { 43 | DataDirs = []string{ 44 | filepath.Join("/", "usr", "local", "share"), 45 | filepath.Join("/", "usr", "share"), 46 | } 47 | } 48 | 49 | if value := os.Getenv("XDG_DATA_HOME"); value != "" { 50 | DataHome = value 51 | } else { 52 | DataHome = filepath.Join(os.Getenv("HOME"), ".local", "share") 53 | } 54 | 55 | if value := os.Getenv("XDG_RUNTIME_DIR"); value != "" { 56 | RuntimeDir = value 57 | } else { 58 | RuntimeDir = filepath.Join("/", "run", "user", strconv.Itoa(os.Getuid())) 59 | } 60 | 61 | if value := os.Getenv("XDG_STATE_HOME"); value != "" { 62 | StateHome = value 63 | } else { 64 | StateHome = filepath.Join(os.Getenv("HOME"), ".local", "state") 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /internal/cmd/ps.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "regexp" 7 | "strings" 8 | 9 | "github.com/inaccel/docker/internal" 10 | "github.com/inaccel/docker/pkg/system" 11 | "github.com/spf13/cobra" 12 | "github.com/spf13/viper" 13 | ) 14 | 15 | var ( 16 | ps = viper.New() 17 | 18 | // Ps : docker inaccel ps 19 | Ps = &cobra.Command{ 20 | Use: "ps [OPTIONS]", 21 | Short: "List containers", 22 | Args: cobra.NoArgs, 23 | RunE: func(_ *cobra.Command, _ []string) error { 24 | var cmd *system.Cmd 25 | 26 | cmd = system.Command("docker") 27 | cmd.Flag("host", internal.Host) 28 | cmd.Flag("log-level", viper.GetString("log-level")) 29 | cmd.Arg("ps") 30 | cmd.Flag("all", true) 31 | cmd.Flag("filter", "label=com.docker.compose.oneoff=False") 32 | cmd.Flag("filter", fmt.Sprintf("label=com.docker.compose.project=%s", regexp.MustCompile("[^-0-9_a-z]").ReplaceAllString(strings.ToLower(viper.GetString("project-name")), "_"))) 33 | if !ps.GetBool("quiet") { 34 | cmd.Flag("format", `table {{ .ID }}\t{{ .Image }}\t{{ .RunningFor }}\t{{ .Status }}\t{{ if eq ( .Label "com.docker.compose.service" ) "service" }}SERVICE{{ else }}{{ .Label "com.docker.compose.service" }}{{ end }}\t{{ if eq ( .Label "com.docker.compose.container-number" ) "container number" }}INDEX{{ else }}{{ .Label "com.docker.compose.container-number" }}{{ end }}`) 35 | } 36 | cmd.Flag("no-trunc", ps.GetBool("no-trunc")) 37 | cmd.Flag("quiet", ps.GetBool("quiet")) 38 | cmd.Std(nil, os.Stdout, os.Stderr) 39 | 40 | if err := cmd.Run(viper.GetBool("debug")); err != nil { 41 | return internal.ExitToStatus(err) 42 | } 43 | 44 | return nil 45 | }, 46 | } 47 | ) 48 | 49 | func init() { 50 | Ps.Flags().Bool("no-trunc", false, "Don't truncate output") 51 | ps.BindPFlag("no-trunc", Ps.Flags().Lookup("no-trunc")) 52 | 53 | Ps.Flags().BoolP("quiet", "q", false, "Only display container IDs") 54 | ps.BindPFlag("quiet", Ps.Flags().Lookup("quiet")) 55 | } 56 | -------------------------------------------------------------------------------- /configs/fpga-operator/docker-compose.yml: -------------------------------------------------------------------------------- 1 | services: 2 | coral: 3 | depends_on: 4 | mkrt: 5 | condition: service_completed_successfully 6 | environment: 7 | FPGAS: ${coral_fpgas} 8 | HTTPS_PROXY: ${coral_httpsProxy} 9 | LICENSE: ${license} 10 | LOG_LEVEL: ${coral_logLevel} 11 | image: ${coral_image}:${coral_tag} 12 | labels: 13 | com.inaccel.docker.default-exec-command: console 14 | com.inaccel.docker.default-exec-service: True 15 | com.inaccel.docker.default-logs-service: True 16 | ports: 17 | - ${coral_port:-0}:55677 18 | privileged: true 19 | restart: always 20 | volumes: 21 | - /etc/localtime:/etc/localtime:ro 22 | - ${XDG_STATE_HOME:-/var/lib}/inaccel:/var/lib/inaccel:rslave 23 | - runtimes:/var/opt/inaccel/runtimes:ro 24 | driver: 25 | environment: 26 | DRIVER_SYSROOT_DIR: /host 27 | image: ${driver_image}:${driver_tag} 28 | network_mode: host 29 | pid: host 30 | privileged: true 31 | profiles: 32 | - disabled 33 | restart: on-failure 34 | volumes: 35 | - /:/host 36 | mkrt: 37 | environment: 38 | MKRT_CONFIG_PATH: ${XDG_CONFIG_HOME:-/etc}/inaccel/runtimes 39 | MKRT_SYSROOT_DIR: /host 40 | image: ${mkrt_image}:${mkrt_tag} 41 | restart: on-failure 42 | volumes: 43 | - /:/host:ro 44 | - runtimes:/var/opt/inaccel/runtimes 45 | monitor: 46 | image: ${monitor_image}:${monitor_tag} 47 | ports: 48 | - ${monitor_port:-0}:19999 49 | restart: always 50 | tests_vadd-init: 51 | command: 52 | - bitstream 53 | - install 54 | - https://store.inaccel.com/artifactory/bitstreams/${tests_vadd_platform}/vector/1/1addition 55 | image: inaccel/cli 56 | profiles: 57 | - tests 58 | volumes: 59 | - volume:/var/lib/inaccel 60 | tests_vadd: 61 | depends_on: 62 | tests_vadd-init: 63 | condition: service_completed_successfully 64 | image: ${tests_vadd_image}:${tests_vadd_tag} 65 | profiles: 66 | - tests 67 | volumes: 68 | - volume:/var/lib/inaccel 69 | volumes: 70 | runtimes: 71 | volume: 72 | driver: inaccel 73 | -------------------------------------------------------------------------------- /pkg/grep/grep.go: -------------------------------------------------------------------------------- 1 | package grep 2 | 3 | import ( 4 | "bytes" 5 | "io" 6 | "os" 7 | "regexp" 8 | ) 9 | 10 | var ( 11 | color = []byte("\033[01;31m") 12 | reset = []byte("\033[00m") 13 | ) 14 | 15 | func init() { 16 | if env, ok := os.LookupEnv("GREP_COLOR"); ok { 17 | color = []byte("\033[" + env + "m") 18 | } 19 | } 20 | 21 | type Grep struct { 22 | ere *regexp.Regexp 23 | } 24 | 25 | type internal struct { 26 | *Grep 27 | 28 | writer io.Writer 29 | color bool 30 | invertMatch bool 31 | 32 | buffer []byte 33 | } 34 | 35 | func Compile(pattern string) (*Grep, error) { 36 | ere, err := regexp.CompilePOSIX(pattern) 37 | if err != nil { 38 | return nil, err 39 | } 40 | 41 | return &Grep{ 42 | ere: ere, 43 | }, nil 44 | } 45 | 46 | func MustCompile(pattern string) *Grep { 47 | ere := regexp.MustCompilePOSIX(pattern) 48 | 49 | return &Grep{ 50 | ere: ere, 51 | } 52 | } 53 | 54 | func (grep *Grep) WriteCloser(writer io.Writer, color, invertMatch bool) io.WriteCloser { 55 | return &internal{ 56 | Grep: grep, 57 | writer: writer, 58 | color: color, 59 | invertMatch: invertMatch, 60 | } 61 | } 62 | 63 | func (grep *internal) flush(line []byte, ln bool) error { 64 | if (grep.invertMatch && !grep.ere.Match(line)) || (!grep.invertMatch && grep.ere.Match(line)) { 65 | if grep.color { 66 | line = grep.ere.ReplaceAllFunc(line, func(match []byte) []byte { 67 | return append(append(color, match...), reset...) 68 | }) 69 | } 70 | 71 | if _, err := grep.writer.Write(line); err != nil { 72 | return err 73 | } 74 | if ln { 75 | if _, err := grep.writer.Write([]byte{'\n'}); err != nil { 76 | return err 77 | } 78 | } 79 | } 80 | 81 | return nil 82 | } 83 | 84 | func (grep *internal) Close() error { 85 | return grep.flush(grep.buffer, false) 86 | } 87 | 88 | func (grep *internal) Write(p []byte) (int, error) { 89 | var offset int 90 | for { 91 | index := bytes.IndexByte(p[offset:], '\n') 92 | if index < 0 { 93 | grep.buffer = append(grep.buffer, p[offset:]...) 94 | 95 | return len(p), nil 96 | } 97 | 98 | var line []byte 99 | if len(grep.buffer) > 0 { 100 | line = append(grep.buffer, p[offset:offset+index]...) 101 | 102 | grep.buffer = nil 103 | } else { 104 | line = p[offset : offset+index] 105 | } 106 | 107 | offset += index + 1 108 | 109 | if err := grep.flush(line, true); err != nil { 110 | return -1, err 111 | } 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /.github/workflows/dockerhub.yml: -------------------------------------------------------------------------------- 1 | name: dockerhub 2 | on: 3 | push: 4 | paths: 5 | - configs/*/VERSION 6 | jobs: 7 | configs: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - name: Checkout 11 | uses: actions/checkout@v3 12 | with: 13 | fetch-depth: 2 14 | - name: Get changed VERSION files 15 | id: changed-files 16 | uses: tj-actions/changed-files@v34 17 | with: 18 | separator: ',' 19 | files: configs/*/VERSION 20 | - name: List all modified configs 21 | id: matrix 22 | run: | 23 | ALL_MODIFIED_FILES=${{ steps.changed-files.outputs.all_modified_files }} 24 | for VERSION in ${ALL_MODIFIED_FILES//,/ }; do 25 | CONFIG="${CONFIG:+${CONFIG}, }\"$(basename $(dirname ${VERSION}))\"" 26 | done 27 | echo "config=[${CONFIG}]" >> ${GITHUB_OUTPUT} 28 | outputs: 29 | matrix: ${{ steps.matrix.outputs.config }} 30 | pipeline: 31 | runs-on: ubuntu-latest 32 | needs: configs 33 | if: ${{ !contains(needs.configs.outputs.matrix, '[]') }} 34 | strategy: 35 | matrix: 36 | config: ${{ fromJson(needs.configs.outputs.matrix) }} 37 | steps: 38 | - name: Checkout 39 | uses: actions/checkout@v3 40 | - name: Read ${{ matrix.config }} VERSION file 41 | run: echo VERSION=$(cat configs/${{ matrix.config }}/VERSION) >> ${GITHUB_ENV} 42 | - name: Set up Docker Buildx 43 | uses: docker/setup-buildx-action@v2 44 | - name: Login to DockerHub 45 | uses: docker/login-action@v2 46 | with: 47 | username: ${{ secrets.DOCKERHUB_USERNAME }} 48 | password: ${{ secrets.DOCKERHUB_TOKEN }} 49 | - name: Docker Metadata 50 | id: meta 51 | uses: docker/metadata-action@v4 52 | with: 53 | flavor: latest=true 54 | images: inaccel/${{ matrix.config }} 55 | labels: | 56 | org.opencontainers.image.authors=InAccel 57 | org.opencontainers.image.title=${{ matrix.config }} 58 | org.opencontainers.image.url=https://inaccel.com 59 | org.opencontainers.image.vendor=InAccel 60 | tags: ${{ env.VERSION }} 61 | - name: Build and push 62 | uses: docker/build-push-action@v3 63 | with: 64 | context: configs/${{ matrix.config }} 65 | labels: ${{ steps.meta.outputs.labels }} 66 | push: true 67 | tags: ${{ steps.meta.outputs.tags }} 68 | - name: Release 69 | uses: softprops/action-gh-release@v1 70 | with: 71 | body: | 72 | ## Docker images 73 | 74 | - `docker pull ${{ fromJSON(steps.meta.outputs.json).tags[0] }}` 75 | tag_name: ${{ matrix.config }}-${{ steps.meta.outputs.version }} 76 | -------------------------------------------------------------------------------- /pkg/system/system.go: -------------------------------------------------------------------------------- 1 | package system 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "io" 7 | "os/exec" 8 | "reflect" 9 | "strings" 10 | "unicode" 11 | ) 12 | 13 | type Cmd struct { 14 | arg []string 15 | env []string 16 | name string 17 | stderr io.Writer 18 | stdin io.Reader 19 | stdout io.Writer 20 | } 21 | 22 | func Command(name string) *Cmd { 23 | return &Cmd{ 24 | name: name, 25 | } 26 | } 27 | 28 | func (cmd *Cmd) debug() { 29 | args := append([]string{cmd.name}, cmd.arg...) 30 | 31 | for index, arg := range args { 32 | for _, r := range arg { 33 | if unicode.IsSpace(r) { 34 | args[index] = fmt.Sprintf("'%s'", arg) 35 | 36 | break 37 | } 38 | } 39 | } 40 | 41 | fmt.Println("$", strings.Join(args, " ")) 42 | } 43 | 44 | func (cmd *Cmd) Arg(arg ...string) { 45 | cmd.arg = append(cmd.arg, arg...) 46 | } 47 | 48 | func (cmd *Cmd) Env(env ...string) { 49 | cmd.env = append(cmd.env, env...) 50 | } 51 | 52 | func (cmd *Cmd) Err(debug bool) (string, error) { 53 | var stderr bytes.Buffer 54 | 55 | command := exec.Command(cmd.name, cmd.arg...) 56 | 57 | command.Env = cmd.env 58 | 59 | command.Stdin = cmd.stdin 60 | command.Stdout = cmd.stdout 61 | if cmd.stderr != nil { 62 | command.Stderr = io.MultiWriter(cmd.stderr, &stderr) 63 | } else { 64 | command.Stderr = &stderr 65 | } 66 | 67 | if debug { 68 | cmd.debug() 69 | } 70 | 71 | err := command.Run() 72 | 73 | return stderr.String(), err 74 | } 75 | 76 | func (cmd *Cmd) Flag(key string, value interface{}) { 77 | if !reflect.ValueOf(value).IsZero() { 78 | switch len(key) { 79 | case 1: 80 | key = fmt.Sprintf("-%s", key) 81 | default: 82 | key = fmt.Sprintf("--%s", key) 83 | } 84 | 85 | switch reflect.TypeOf(value).Kind() { 86 | case reflect.Bool: 87 | if reflect.ValueOf(value).Bool() { 88 | cmd.arg = append(cmd.arg, key) 89 | } 90 | case reflect.Slice: 91 | slice := reflect.ValueOf(value) 92 | for index := 0; index < slice.Len(); index++ { 93 | cmd.arg = append(cmd.arg, key, fmt.Sprintf("%v", slice.Index(index))) 94 | } 95 | default: 96 | cmd.arg = append(cmd.arg, key, fmt.Sprintf("%v", value)) 97 | } 98 | } 99 | } 100 | 101 | func (cmd *Cmd) Out(debug bool) (string, error) { 102 | var stdout bytes.Buffer 103 | 104 | command := exec.Command(cmd.name, cmd.arg...) 105 | 106 | command.Env = cmd.env 107 | 108 | command.Stdin = cmd.stdin 109 | if cmd.stdout != nil { 110 | command.Stdout = io.MultiWriter(cmd.stdout, &stdout) 111 | } else { 112 | command.Stdout = &stdout 113 | } 114 | command.Stderr = cmd.stderr 115 | 116 | if debug { 117 | cmd.debug() 118 | } 119 | 120 | err := command.Run() 121 | 122 | return stdout.String(), err 123 | } 124 | 125 | func (cmd *Cmd) Run(debug bool) error { 126 | command := exec.Command(cmd.name, cmd.arg...) 127 | 128 | command.Env = cmd.env 129 | 130 | command.Stdin = cmd.stdin 131 | command.Stdout = cmd.stdout 132 | command.Stderr = cmd.stderr 133 | 134 | if debug { 135 | cmd.debug() 136 | } 137 | 138 | return command.Run() 139 | } 140 | 141 | func (cmd *Cmd) Std(in io.Reader, out, err io.Writer) { 142 | cmd.stdin = in 143 | cmd.stdout = out 144 | cmd.stderr = err 145 | } 146 | -------------------------------------------------------------------------------- /internal/cmd/config.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "strings" 7 | 8 | "github.com/inaccel/docker/internal" 9 | "github.com/inaccel/docker/pkg/system" 10 | "github.com/inaccel/docker/pkg/xdg" 11 | "github.com/mattn/go-isatty" 12 | "github.com/spf13/cobra" 13 | "github.com/spf13/viper" 14 | ) 15 | 16 | var ( 17 | config = viper.New() 18 | 19 | // Config : docker inaccel config 20 | Config = &cobra.Command{ 21 | Use: "config [OPTIONS]", 22 | Short: "Validate and view the config file", 23 | Args: cobra.NoArgs, 24 | RunE: func(_ *cobra.Command, _ []string) error { 25 | rootless, err := internal.Rootless() 26 | if err != nil { 27 | return err 28 | } 29 | 30 | var cmd *system.Cmd 31 | 32 | if viper.GetBool("pull") { 33 | cmd = system.Command("docker") 34 | cmd.Flag("host", internal.Host) 35 | cmd.Flag("log-level", viper.GetString("log-level")) 36 | cmd.Arg("pull") 37 | cmd.Arg(fmt.Sprintf("%s:%s", viper.GetString("project-name"), viper.GetString("tag"))) 38 | cmd.Std(nil, os.Stdout, os.Stderr) 39 | 40 | if err := cmd.Run(viper.GetBool("debug")); err != nil { 41 | return internal.ExitToStatus(err) 42 | } 43 | } 44 | 45 | cmd = system.Command("docker") 46 | cmd.Flag("host", internal.Host) 47 | cmd.Flag("log-level", viper.GetString("log-level")) 48 | cmd.Arg("run") 49 | cmd.Flag("env", fmt.Sprintf("%s=%s", "DOCKER_HOST_PATH", internal.Host.Path)) 50 | cmd.Flag("env", fmt.Sprintf("%s=%s", "DOCKER_HOST_SCHEME", internal.Host.Scheme)) 51 | if rootless { 52 | cmd.Flag("env", fmt.Sprintf("%s=%s", "XDG_CACHE_HOME", xdg.CacheHome)) 53 | cmd.Flag("env", fmt.Sprintf("%s=%s", "XDG_CONFIG_DIRS", strings.Join(xdg.ConfigDirs, ":"))) 54 | cmd.Flag("env", fmt.Sprintf("%s=%s", "XDG_CONFIG_HOME", xdg.ConfigHome)) 55 | cmd.Flag("env", fmt.Sprintf("%s=%s", "XDG_DATA_DIRS", strings.Join(xdg.DataDirs, ":"))) 56 | cmd.Flag("env", fmt.Sprintf("%s=%s", "XDG_DATA_HOME", xdg.DataHome)) 57 | cmd.Flag("env", fmt.Sprintf("%s=%s", "XDG_RUNTIME_DIR", xdg.RuntimeDir)) 58 | cmd.Flag("env", fmt.Sprintf("%s=%s", "XDG_STATE_HOME", xdg.StateHome)) 59 | } 60 | cmd.Flag("env", viper.GetStringSlice("env")) 61 | if len(viper.GetString("env-file")) > 0 { 62 | cmd.Flag("env-file", viper.GetString("env-file")) 63 | } else if _, err := os.Stat(".env"); err == nil { 64 | cmd.Flag("env-file", ".env") 65 | } 66 | cmd.Flag("interactive", true) 67 | cmd.Flag("rm", true) 68 | cmd.Flag("volume", fmt.Sprintf("%s:%s", internal.Host.Path, "/var/run/docker.sock")) 69 | cmd.Arg(fmt.Sprintf("%s:%s", viper.GetString("project-name"), viper.GetString("tag"))) 70 | if isatty.IsTerminal(os.Stdout.Fd()) && isatty.IsTerminal(os.Stderr.Fd()) { 71 | cmd.Flag("ansi", "always") 72 | } else { 73 | cmd.Flag("ansi", "never") 74 | } 75 | cmd.Arg("config") 76 | cmd.Flag("profiles", config.GetBool("profiles")) 77 | cmd.Flag("quiet", config.GetBool("quiet")) 78 | cmd.Flag("resolve-image-digests", config.GetBool("resolve-image-digests")) 79 | cmd.Flag("services", config.GetBool("services")) 80 | cmd.Std(nil, os.Stdout, os.Stderr) 81 | 82 | if err := cmd.Run(viper.GetBool("debug")); err != nil { 83 | return internal.ExitToStatus(err) 84 | } 85 | 86 | return nil 87 | }, 88 | } 89 | ) 90 | 91 | func init() { 92 | Config.Flags().Bool("profiles", false, "Print the profile names, one per line") 93 | config.BindPFlag("profiles", Config.Flags().Lookup("profiles")) 94 | 95 | Config.Flags().BoolP("quiet", "q", false, "Only validate the configuration, don't print anything") 96 | config.BindPFlag("quiet", Config.Flags().Lookup("quiet")) 97 | 98 | Config.Flags().Bool("resolve-image-digests", false, "Pin image tags to digests") 99 | config.BindPFlag("resolve-image-digests", Config.Flags().Lookup("resolve-image-digests")) 100 | 101 | Config.Flags().Bool("services", false, "Print the service names, one per line") 102 | config.BindPFlag("services", Config.Flags().Lookup("services")) 103 | } 104 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/inaccel/docker 2 | 3 | go 1.21 4 | 5 | require ( 6 | github.com/c-bata/go-prompt v0.2.5 7 | github.com/docker/cli v25.0.2+incompatible 8 | github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 9 | github.com/mattn/go-isatty v0.0.17 10 | github.com/spf13/cobra v1.8.0 11 | github.com/spf13/viper v1.18.2 12 | ) 13 | 14 | require ( 15 | github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect 16 | github.com/Microsoft/go-winio v0.4.14 // indirect 17 | github.com/beorn7/perks v0.0.0-20150223135152-b965b613227f // indirect 18 | github.com/containerd/log v0.1.0 // indirect 19 | github.com/distribution/reference v0.5.0 // indirect 20 | github.com/docker/distribution v2.8.3+incompatible // indirect 21 | github.com/docker/docker v25.0.2+incompatible // indirect 22 | github.com/docker/docker-credential-helpers v0.8.1 // indirect 23 | github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c // indirect 24 | github.com/docker/go-connections v0.5.0 // indirect 25 | github.com/docker/go-metrics v0.0.0-20180209012529-399ea8c73916 // indirect 26 | github.com/docker/go-units v0.5.0 // indirect 27 | github.com/felixge/httpsnoop v1.0.4 // indirect 28 | github.com/fsnotify/fsnotify v1.7.0 // indirect 29 | github.com/fvbommel/sortorder v1.1.0 // indirect 30 | github.com/go-logr/logr v1.4.1 // indirect 31 | github.com/go-logr/stdr v1.2.2 // indirect 32 | github.com/gogo/protobuf v1.3.2 // indirect 33 | github.com/golang/protobuf v1.5.3 // indirect 34 | github.com/gorilla/mux v1.7.0 // indirect 35 | github.com/hashicorp/hcl v1.0.0 // indirect 36 | github.com/inconshreveable/mousetrap v1.1.0 // indirect 37 | github.com/magiconair/properties v1.8.7 // indirect 38 | github.com/mattn/go-colorable v0.1.13 // indirect 39 | github.com/mattn/go-runewidth v0.0.9 // indirect 40 | github.com/mattn/go-tty v0.0.3 // indirect 41 | github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect 42 | github.com/miekg/pkcs11 v1.0.2 // indirect 43 | github.com/mitchellh/mapstructure v1.5.0 // indirect 44 | github.com/moby/sys/sequential v0.5.0 // indirect 45 | github.com/moby/term v0.5.0 // indirect 46 | github.com/morikuni/aec v1.0.0 // indirect 47 | github.com/opencontainers/go-digest v1.0.0 // indirect 48 | github.com/opencontainers/image-spec v1.0.2 // indirect 49 | github.com/pelletier/go-toml/v2 v2.1.0 // indirect 50 | github.com/pkg/errors v0.9.1 // indirect 51 | github.com/pkg/term v1.1.0 // indirect 52 | github.com/prometheus/client_golang v0.9.0-pre1.0.20180209125602-c332b6f63c06 // indirect 53 | github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5 // indirect 54 | github.com/prometheus/common v0.0.0-20180110214958-89604d197083 // indirect 55 | github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7 // indirect 56 | github.com/sagikazarmark/locafero v0.4.0 // indirect 57 | github.com/sagikazarmark/slog-shim v0.1.0 // indirect 58 | github.com/sirupsen/logrus v1.9.3 // indirect 59 | github.com/sourcegraph/conc v0.3.0 // indirect 60 | github.com/spf13/afero v1.11.0 // indirect 61 | github.com/spf13/cast v1.6.0 // indirect 62 | github.com/spf13/pflag v1.0.5 // indirect 63 | github.com/subosito/gotenv v1.6.0 // indirect 64 | github.com/theupdateframework/notary v0.7.0 // indirect 65 | go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.47.0 // indirect 66 | go.opentelemetry.io/otel v1.22.0 // indirect 67 | go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.22.0 // indirect 68 | go.opentelemetry.io/otel/metric v1.22.0 // indirect 69 | go.opentelemetry.io/otel/sdk v1.22.0 // indirect 70 | go.opentelemetry.io/otel/trace v1.22.0 // indirect 71 | go.uber.org/atomic v1.9.0 // indirect 72 | go.uber.org/multierr v1.9.0 // indirect 73 | golang.org/x/crypto v0.16.0 // indirect 74 | golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect 75 | golang.org/x/sync v0.5.0 // indirect 76 | golang.org/x/sys v0.16.0 // indirect 77 | golang.org/x/term v0.15.0 // indirect 78 | golang.org/x/text v0.14.0 // indirect 79 | google.golang.org/protobuf v1.32.0 // indirect 80 | gopkg.in/ini.v1 v1.67.0 // indirect 81 | gopkg.in/yaml.v3 v3.0.1 // indirect 82 | gotest.tools/v3 v3.5.1 // indirect 83 | ) 84 | -------------------------------------------------------------------------------- /internal/cmd/up.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "regexp" 7 | "strings" 8 | 9 | "github.com/inaccel/docker/internal" 10 | "github.com/inaccel/docker/pkg/system" 11 | "github.com/inaccel/docker/pkg/xdg" 12 | "github.com/mattn/go-isatty" 13 | "github.com/spf13/cobra" 14 | "github.com/spf13/viper" 15 | ) 16 | 17 | var ( 18 | up = viper.New() 19 | 20 | // Up : docker inaccel up 21 | Up = &cobra.Command{ 22 | Use: "up [OPTIONS] [SERVICE]", 23 | Short: "Create and start containers", 24 | Args: cobra.MaximumNArgs(1), 25 | RunE: func(_ *cobra.Command, args []string) error { 26 | rootless, err := internal.Rootless() 27 | if err != nil { 28 | return err 29 | } 30 | 31 | var cmd *system.Cmd 32 | 33 | if viper.GetBool("pull") { 34 | cmd = system.Command("docker") 35 | cmd.Flag("host", internal.Host) 36 | cmd.Flag("log-level", viper.GetString("log-level")) 37 | cmd.Arg("pull") 38 | cmd.Arg(fmt.Sprintf("%s:%s", viper.GetString("project-name"), viper.GetString("tag"))) 39 | cmd.Std(nil, os.Stdout, os.Stderr) 40 | 41 | if err := cmd.Run(viper.GetBool("debug")); err != nil { 42 | return internal.ExitToStatus(err) 43 | } 44 | } 45 | 46 | cmd = system.Command("docker") 47 | cmd.Flag("host", internal.Host) 48 | cmd.Flag("log-level", viper.GetString("log-level")) 49 | cmd.Arg("run") 50 | cmd.Flag("env", fmt.Sprintf("%s=%s", "DOCKER_HOST_PATH", internal.Host.Path)) 51 | cmd.Flag("env", fmt.Sprintf("%s=%s", "DOCKER_HOST_SCHEME", internal.Host.Scheme)) 52 | if rootless { 53 | cmd.Flag("env", fmt.Sprintf("%s=%s", "XDG_CACHE_HOME", xdg.CacheHome)) 54 | cmd.Flag("env", fmt.Sprintf("%s=%s", "XDG_CONFIG_DIRS", strings.Join(xdg.ConfigDirs, ":"))) 55 | cmd.Flag("env", fmt.Sprintf("%s=%s", "XDG_CONFIG_HOME", xdg.ConfigHome)) 56 | cmd.Flag("env", fmt.Sprintf("%s=%s", "XDG_DATA_DIRS", strings.Join(xdg.DataDirs, ":"))) 57 | cmd.Flag("env", fmt.Sprintf("%s=%s", "XDG_DATA_HOME", xdg.DataHome)) 58 | cmd.Flag("env", fmt.Sprintf("%s=%s", "XDG_RUNTIME_DIR", xdg.RuntimeDir)) 59 | cmd.Flag("env", fmt.Sprintf("%s=%s", "XDG_STATE_HOME", xdg.StateHome)) 60 | } 61 | cmd.Flag("env", viper.GetStringSlice("env")) 62 | if len(viper.GetString("env-file")) > 0 { 63 | cmd.Flag("env-file", viper.GetString("env-file")) 64 | } else if _, err := os.Stat(".env"); err == nil { 65 | cmd.Flag("env-file", ".env") 66 | } 67 | cmd.Flag("interactive", true) 68 | cmd.Flag("rm", true) 69 | cmd.Flag("volume", fmt.Sprintf("%s:%s", internal.Host.Path, "/var/run/docker.sock")) 70 | cmd.Arg(fmt.Sprintf("%s:%s", viper.GetString("project-name"), viper.GetString("tag"))) 71 | if isatty.IsTerminal(os.Stdout.Fd()) && isatty.IsTerminal(os.Stderr.Fd()) { 72 | cmd.Flag("ansi", "always") 73 | } else { 74 | cmd.Flag("ansi", "never") 75 | } 76 | cmd.Flag("profile", viper.GetStringSlice("profile")) 77 | cmd.Flag("project-name", regexp.MustCompile("[^-0-9_a-z]").ReplaceAllString(strings.ToLower(viper.GetString("project-name")), "_")) 78 | cmd.Arg("up") 79 | cmd.Flag("always-recreate-deps", up.GetBool("always-recreate-deps")) 80 | cmd.Flag("detach", true) 81 | cmd.Flag("force-recreate", up.GetBool("force-recreate")) 82 | cmd.Flag("no-deps", up.GetBool("no-deps")) 83 | cmd.Flag("no-recreate", up.GetBool("no-recreate")) 84 | if len(args) > 0 { 85 | cmd.Arg(args[0]) 86 | } 87 | cmd.Std(nil, os.Stdout, os.Stderr) 88 | 89 | if err := cmd.Run(viper.GetBool("debug")); err != nil { 90 | return internal.ExitToStatus(err) 91 | } 92 | 93 | return nil 94 | }, 95 | } 96 | ) 97 | 98 | func init() { 99 | Up.Flags().Bool("always-recreate-deps", false, "Recreate dependent containers") 100 | up.BindPFlag("always-recreate-deps", Up.Flags().Lookup("always-recreate-deps")) 101 | 102 | Up.Flags().Bool("force-recreate", false, "Recreate containers even if their configuration and image haven't changed") 103 | up.BindPFlag("force-recreate", Up.Flags().Lookup("force-recreate")) 104 | 105 | Up.Flags().Bool("no-deps", false, "Don't start linked services") 106 | up.BindPFlag("no-deps", Up.Flags().Lookup("no-deps")) 107 | 108 | Up.Flags().Bool("no-recreate", false, "If containers already exist, don't recreate them") 109 | up.BindPFlag("no-recreate", Up.Flags().Lookup("no-recreate")) 110 | } 111 | -------------------------------------------------------------------------------- /internal/cmd/run.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "regexp" 7 | "strings" 8 | 9 | "github.com/inaccel/docker/internal" 10 | "github.com/inaccel/docker/pkg/system" 11 | "github.com/inaccel/docker/pkg/xdg" 12 | "github.com/mattn/go-isatty" 13 | "github.com/spf13/cobra" 14 | "github.com/spf13/viper" 15 | ) 16 | 17 | var ( 18 | run = viper.New() 19 | 20 | // Run : docker inaccel run 21 | Run = &cobra.Command{ 22 | Use: "run [OPTIONS] SERVICE [COMMAND] [ARG...]", 23 | Short: "Run a one-off command", 24 | Args: cobra.MinimumNArgs(1), 25 | RunE: func(_ *cobra.Command, args []string) error { 26 | rootless, err := internal.Rootless() 27 | if err != nil { 28 | return err 29 | } 30 | 31 | var cmd *system.Cmd 32 | 33 | if viper.GetBool("pull") { 34 | cmd = system.Command("docker") 35 | cmd.Flag("host", internal.Host) 36 | cmd.Flag("log-level", viper.GetString("log-level")) 37 | cmd.Arg("pull") 38 | cmd.Arg(fmt.Sprintf("%s:%s", viper.GetString("project-name"), viper.GetString("tag"))) 39 | cmd.Std(nil, os.Stdout, os.Stderr) 40 | 41 | if err := cmd.Run(viper.GetBool("debug")); err != nil { 42 | return internal.ExitToStatus(err) 43 | } 44 | } 45 | 46 | cmd = system.Command("docker") 47 | cmd.Flag("host", internal.Host) 48 | cmd.Flag("log-level", viper.GetString("log-level")) 49 | cmd.Arg("run") 50 | cmd.Flag("env", fmt.Sprintf("%s=%s", "DOCKER_HOST_PATH", internal.Host.Path)) 51 | cmd.Flag("env", fmt.Sprintf("%s=%s", "DOCKER_HOST_SCHEME", internal.Host.Scheme)) 52 | if rootless { 53 | cmd.Flag("env", fmt.Sprintf("%s=%s", "XDG_CACHE_HOME", xdg.CacheHome)) 54 | cmd.Flag("env", fmt.Sprintf("%s=%s", "XDG_CONFIG_DIRS", strings.Join(xdg.ConfigDirs, ":"))) 55 | cmd.Flag("env", fmt.Sprintf("%s=%s", "XDG_CONFIG_HOME", xdg.ConfigHome)) 56 | cmd.Flag("env", fmt.Sprintf("%s=%s", "XDG_DATA_DIRS", strings.Join(xdg.DataDirs, ":"))) 57 | cmd.Flag("env", fmt.Sprintf("%s=%s", "XDG_DATA_HOME", xdg.DataHome)) 58 | cmd.Flag("env", fmt.Sprintf("%s=%s", "XDG_RUNTIME_DIR", xdg.RuntimeDir)) 59 | cmd.Flag("env", fmt.Sprintf("%s=%s", "XDG_STATE_HOME", xdg.StateHome)) 60 | } 61 | cmd.Flag("env", viper.GetStringSlice("env")) 62 | if len(viper.GetString("env-file")) > 0 { 63 | cmd.Flag("env-file", viper.GetString("env-file")) 64 | } else if _, err := os.Stat(".env"); err == nil { 65 | cmd.Flag("env-file", ".env") 66 | } 67 | cmd.Flag("interactive", true) 68 | cmd.Flag("rm", true) 69 | cmd.Flag("tty", !run.GetBool("no-tty") && isatty.IsTerminal(os.Stdin.Fd()) && isatty.IsTerminal(os.Stdout.Fd()) && isatty.IsTerminal(os.Stderr.Fd())) 70 | cmd.Flag("volume", fmt.Sprintf("%s:%s", internal.Host.Path, "/var/run/docker.sock")) 71 | cmd.Arg(fmt.Sprintf("%s:%s", viper.GetString("project-name"), viper.GetString("tag"))) 72 | if !run.GetBool("no-tty") && isatty.IsTerminal(os.Stdin.Fd()) && isatty.IsTerminal(os.Stdout.Fd()) && isatty.IsTerminal(os.Stderr.Fd()) { 73 | cmd.Flag("ansi", "always") 74 | } else { 75 | cmd.Flag("ansi", "never") 76 | } 77 | cmd.Flag("project-name", regexp.MustCompile("[^-0-9_a-z]").ReplaceAllString(strings.ToLower(viper.GetString("project-name")), "_")) 78 | cmd.Arg("run") 79 | cmd.Flag("entrypoint", run.GetString("entrypoint")) 80 | cmd.Flag("e", run.GetStringSlice("env")) 81 | cmd.Flag("no-deps", run.GetBool("no-deps")) 82 | cmd.Flag("publish", run.GetStringSlice("publish")) 83 | cmd.Flag("rm", true) 84 | cmd.Flag("service-ports", true) 85 | cmd.Flag("user", run.GetString("user")) 86 | cmd.Flag("volume", run.GetStringSlice("volume")) 87 | cmd.Flag("workdir", run.GetString("workdir")) 88 | cmd.Arg(args...) 89 | cmd.Std(os.Stdin, os.Stdout, os.Stderr) 90 | 91 | if err := cmd.Run(viper.GetBool("debug")); err != nil { 92 | return internal.ExitToStatus(err) 93 | } 94 | 95 | return nil 96 | }, 97 | } 98 | ) 99 | 100 | func init() { 101 | Run.Flags().String("entrypoint", "", "Override the entrypoint of the container") 102 | run.BindPFlag("entrypoint", Run.Flags().Lookup("entrypoint")) 103 | 104 | Run.Flags().StringSliceP("env", "e", []string{}, "Set environment variables") 105 | run.BindPFlag("env", Run.Flags().Lookup("env")) 106 | 107 | Run.Flags().Bool("no-deps", false, "Don't start linked services") 108 | run.BindPFlag("no-deps", Run.Flags().Lookup("no-deps")) 109 | 110 | Run.Flags().BoolP("no-tty", "T", false, "Disable pseudo-TTY allocation") 111 | run.BindPFlag("no-tty", Run.Flags().Lookup("no-tty")) 112 | 113 | Run.Flags().StringSliceP("publish", "p", []string{}, "Publish a container's port(s) to the host") 114 | run.BindPFlag("publish", Run.Flags().Lookup("publish")) 115 | 116 | Run.Flags().StringP("user", "u", "", "Username or UID (format: [:])") 117 | run.BindPFlag("user", Run.Flags().Lookup("user")) 118 | 119 | Run.Flags().StringSliceP("volume", "v", []string{}, "Bind mount a volume") 120 | run.BindPFlag("volume", Run.Flags().Lookup("volume")) 121 | 122 | Run.Flags().StringP("workdir", "w", "", "Working directory inside the container") 123 | run.BindPFlag("workdir", Run.Flags().Lookup("workdir")) 124 | } 125 | -------------------------------------------------------------------------------- /internal/cmd/down.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "regexp" 7 | "strings" 8 | 9 | "github.com/inaccel/docker/internal" 10 | "github.com/inaccel/docker/pkg/grep" 11 | "github.com/inaccel/docker/pkg/system" 12 | "github.com/spf13/cobra" 13 | "github.com/spf13/viper" 14 | ) 15 | 16 | var ( 17 | down = viper.New() 18 | 19 | // Down : docker inaccel down 20 | Down = &cobra.Command{ 21 | Use: "down [OPTIONS] [SERVICE]", 22 | Short: "Stop and remove containers and networks", 23 | ValidArgsFunction: func(_ *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { 24 | var cmd *system.Cmd 25 | 26 | cmd = system.Command("docker") 27 | cmd.Flag("host", internal.Host) 28 | cmd.Arg("ps") 29 | cmd.Flag("filter", "label=com.docker.compose.oneoff=False") 30 | cmd.Flag("filter", fmt.Sprintf("label=com.docker.compose.project=%s", regexp.MustCompile("[^-0-9_a-z]").ReplaceAllString(strings.ToLower(viper.GetString("project-name")), "_"))) 31 | cmd.Flag("format", `{{ .Label "com.docker.compose.service" }}`) 32 | 33 | out, err := cmd.Out(false) 34 | if err != nil { 35 | return nil, cobra.ShellCompDirectiveDefault 36 | } 37 | 38 | var completions []string 39 | for _, completion := range strings.Fields(out) { 40 | if strings.HasPrefix(completion, toComplete) { 41 | completions = append(completions, completion) 42 | } 43 | } 44 | return completions, cobra.ShellCompDirectiveNoFileComp 45 | }, 46 | Args: cobra.MaximumNArgs(1), 47 | PreRunE: func(_ *cobra.Command, args []string) error { 48 | var cmd *system.Cmd 49 | 50 | cmd = system.Command("docker") 51 | cmd.Flag("host", internal.Host) 52 | cmd.Flag("log-level", viper.GetString("log-level")) 53 | cmd.Arg("ps") 54 | cmd.Flag("filter", "label=com.docker.compose.oneoff=False") 55 | cmd.Flag("filter", fmt.Sprintf("label=com.docker.compose.project=%s", regexp.MustCompile("[^-0-9_a-z]").ReplaceAllString(strings.ToLower(viper.GetString("project-name")), "_"))) 56 | if len(args) > 0 { 57 | cmd.Flag("filter", fmt.Sprintf("label=com.docker.compose.service=%s", args[0])) 58 | } 59 | cmd.Flag("format", `{{ .ID }}`) 60 | cmd.Std(nil, nil, os.Stderr) 61 | 62 | out, err := cmd.Out(viper.GetBool("debug")) 63 | if err != nil { 64 | return internal.ExitToStatus(err) 65 | } 66 | 67 | ids := strings.Fields(out) 68 | 69 | if len(ids) > 0 { 70 | cmd = system.Command("docker") 71 | cmd.Flag("host", internal.Host) 72 | cmd.Flag("log-level", viper.GetString("log-level")) 73 | cmd.Arg("stop") 74 | cmd.Arg(ids...) 75 | cmd.Std(nil, nil, os.Stderr) 76 | 77 | if err := cmd.Run(viper.GetBool("debug")); err != nil { 78 | return internal.ExitToStatus(err) 79 | } 80 | } 81 | 82 | return nil 83 | }, 84 | RunE: func(_ *cobra.Command, args []string) error { 85 | var cmd *system.Cmd 86 | 87 | cmd = system.Command("docker") 88 | cmd.Flag("host", internal.Host) 89 | cmd.Flag("log-level", viper.GetString("log-level")) 90 | cmd.Arg("container", "prune") 91 | cmd.Flag("filter", fmt.Sprintf("label=com.docker.compose.project=%s", regexp.MustCompile("[^-0-9_a-z]").ReplaceAllString(strings.ToLower(viper.GetString("project-name")), "_"))) 92 | cmd.Flag("force", true) 93 | cmd.Std(nil, grep.MustCompile("^$|Total reclaimed space").WriteCloser(os.Stdout, false, true), os.Stderr) 94 | 95 | if err := cmd.Run(viper.GetBool("debug")); err != nil { 96 | return internal.ExitToStatus(err) 97 | } 98 | 99 | cmd = system.Command("docker") 100 | cmd.Flag("host", internal.Host) 101 | cmd.Flag("log-level", viper.GetString("log-level")) 102 | cmd.Arg("network", "prune") 103 | cmd.Flag("filter", fmt.Sprintf("label=com.docker.compose.project=%s", regexp.MustCompile("[^-0-9_a-z]").ReplaceAllString(strings.ToLower(viper.GetString("project-name")), "_"))) 104 | cmd.Flag("force", true) 105 | cmd.Std(nil, grep.MustCompile("^$|Total reclaimed space").WriteCloser(os.Stdout, false, true), os.Stderr) 106 | 107 | if err := cmd.Run(viper.GetBool("debug")); err != nil { 108 | return internal.ExitToStatus(err) 109 | } 110 | 111 | if down.GetBool("volumes") { 112 | cmd = system.Command("docker") 113 | cmd.Flag("host", internal.Host) 114 | cmd.Flag("log-level", viper.GetString("log-level")) 115 | cmd.Arg("volume", "ls") 116 | cmd.Flag("filter", "dangling=true") 117 | cmd.Flag("filter", fmt.Sprintf("label=com.docker.compose.project=%s", regexp.MustCompile("[^-0-9_a-z]").ReplaceAllString(strings.ToLower(viper.GetString("project-name")), "_"))) 118 | cmd.Flag("format", `{{ .Name }}`) 119 | cmd.Std(nil, nil, os.Stderr) 120 | 121 | out, err := cmd.Out(viper.GetBool("debug")) 122 | if err != nil { 123 | return internal.ExitToStatus(err) 124 | } 125 | 126 | names := strings.Fields(out) 127 | 128 | if len(names) > 0 { 129 | cmd = system.Command("docker") 130 | cmd.Flag("host", internal.Host) 131 | cmd.Flag("log-level", viper.GetString("log-level")) 132 | cmd.Arg("volume", "rm") 133 | cmd.Arg(names...) 134 | cmd.Std(nil, nil, os.Stderr) 135 | 136 | if err := cmd.Run(viper.GetBool("debug")); err != nil { 137 | return internal.ExitToStatus(err) 138 | } 139 | 140 | fmt.Fprintln(os.Stdout, "Deleted Volumes:") 141 | fmt.Fprint(os.Stdout, out) 142 | } 143 | } 144 | 145 | return nil 146 | }, 147 | } 148 | ) 149 | 150 | func init() { 151 | Down.Flags().BoolP("volumes", "v", false, "Remove volumes attached to containers") 152 | down.BindPFlag("volumes", Down.Flags().Lookup("volumes")) 153 | } 154 | -------------------------------------------------------------------------------- /cmd/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "net" 6 | "net/url" 7 | "os" 8 | "strings" 9 | 10 | "github.com/c-bata/go-prompt" 11 | "github.com/docker/cli/cli-plugins/manager" 12 | "github.com/docker/cli/cli-plugins/plugin" 13 | "github.com/docker/cli/cli/command" 14 | "github.com/google/shlex" 15 | "github.com/inaccel/docker/internal" 16 | "github.com/inaccel/docker/internal/cmd" 17 | "github.com/inaccel/docker/pkg/system" 18 | "github.com/spf13/cobra" 19 | "github.com/spf13/viper" 20 | ) 21 | 22 | var version string 23 | 24 | func main() { 25 | plugin.Run(func(cli command.Cli) *cobra.Command { 26 | inaccel := &cobra.Command{ 27 | Use: "inaccel", 28 | Short: "Simplifying FPGA management in Docker", 29 | Args: cobra.NoArgs, 30 | Version: version, 31 | PersistentPreRunE: func(cmd *cobra.Command, args []string) error { 32 | if err := plugin.PersistentPreRunE(cmd, args); err != nil { 33 | return err 34 | } 35 | 36 | viper.BindPFlag("debug", cmd.Root().Flags().Lookup("debug")) 37 | viper.BindPFlag("log-level", cmd.Root().Flags().Lookup("log-level")) 38 | 39 | endpoint := cli.DockerEndpoint() 40 | internal.Host, _ = url.Parse(endpoint.Host) 41 | 42 | switch internal.Host.Scheme { 43 | case "unix": 44 | return nil 45 | default: 46 | return net.UnknownNetworkError(internal.Host.Scheme) 47 | } 48 | }, 49 | Run: func(cmd *cobra.Command, _ []string) { 50 | executor := func(input string) { 51 | args, err := shlex.Split(input) 52 | if err != nil { 53 | fmt.Fprintln(os.Stderr, err) 54 | return 55 | } 56 | 57 | if len(args) == 0 { 58 | return 59 | } 60 | 61 | inaccel := system.Command(os.Args[0]) 62 | inaccel.Arg(os.Args[1:]...) 63 | inaccel.Arg(args...) 64 | inaccel.Env(os.Environ()...) 65 | inaccel.Std(os.Stdin, os.Stdout, os.Stderr) 66 | 67 | if err := inaccel.Run(false); err != nil { 68 | fmt.Fprintln(os.Stderr, err) 69 | return 70 | } 71 | } 72 | 73 | completer := func(document prompt.Document) []prompt.Suggest { 74 | if document.GetCharRelativeToCursor(1) > 0 && document.GetCharRelativeToCursor(1) != ' ' && document.GetCharRelativeToCursor(1) != '=' { 75 | return nil 76 | } 77 | input := document.CurrentLineBeforeCursor() 78 | 79 | args, err := shlex.Split(input) 80 | if err != nil { 81 | return nil 82 | } 83 | 84 | if len(args) == 0 || strings.HasSuffix(input, " ") { 85 | args = append(args, "") 86 | } 87 | 88 | inaccel := system.Command(os.Args[0]) 89 | inaccel.Arg(cobra.ShellCompRequestCmd) 90 | inaccel.Arg(os.Args[1:]...) 91 | inaccel.Arg(args...) 92 | inaccel.Env(os.Environ()...) 93 | 94 | out, err := inaccel.Out(false) 95 | if err != nil { 96 | return nil 97 | } 98 | 99 | var suggestions []prompt.Suggest 100 | for _, line := range strings.Split(out, "\n") { 101 | if len(line) > 0 && !strings.HasPrefix(line, ":") { 102 | suggestion := strings.SplitN(line, "\t", 2) 103 | switch len(suggestion) { 104 | case 1: 105 | suggestions = append(suggestions, prompt.Suggest{ 106 | Text: suggestion[0], 107 | }) 108 | case 2: 109 | suggestions = append(suggestions, prompt.Suggest{ 110 | Text: suggestion[0], 111 | Description: suggestion[1], 112 | }) 113 | } 114 | } 115 | } 116 | return suggestions 117 | } 118 | 119 | fmt.Fprintln(os.Stdout, "Use Ctrl-D (i.e. EOF) to quit") 120 | 121 | ps1, ok := os.LookupEnv("INACCEL_PS1") 122 | if !ok { 123 | args := make([]string, len(os.Args)) 124 | args[0] = cmd.Root().Name() 125 | copy(args[1:], os.Args[1:]) 126 | ps1 = fmt.Sprintf("$ %s ", strings.Join(args, " ")) 127 | } 128 | 129 | prompt.New( 130 | executor, 131 | completer, 132 | prompt.OptionCompletionOnDown(), 133 | prompt.OptionCompletionWordSeparator(" ="), 134 | prompt.OptionDescriptionBGColor(prompt.DefaultColor), 135 | prompt.OptionDescriptionTextColor(prompt.Blue), 136 | prompt.OptionInputBGColor(prompt.DefaultColor), 137 | prompt.OptionInputTextColor(prompt.DefaultColor), 138 | prompt.OptionPrefix(ps1), 139 | prompt.OptionPrefixBackgroundColor(prompt.DefaultColor), 140 | prompt.OptionPrefixTextColor(prompt.DarkBlue), 141 | prompt.OptionPreviewSuggestionBGColor(prompt.DefaultColor), 142 | prompt.OptionPreviewSuggestionTextColor(prompt.Blue), 143 | prompt.OptionScrollbarBGColor(prompt.DefaultColor), 144 | prompt.OptionScrollbarThumbColor(prompt.DarkGray), 145 | prompt.OptionSelectedDescriptionBGColor(prompt.DarkBlue), 146 | prompt.OptionSelectedDescriptionTextColor(prompt.White), 147 | prompt.OptionSelectedSuggestionBGColor(prompt.LightGray), 148 | prompt.OptionSelectedSuggestionTextColor(prompt.Black), 149 | prompt.OptionShowCompletionAtStart(), 150 | prompt.OptionSuggestionBGColor(prompt.DefaultColor), 151 | prompt.OptionSuggestionTextColor(prompt.DefaultColor), 152 | ).Run() 153 | }, 154 | } 155 | 156 | inaccel.Flags().StringSliceP("env", "e", []string{}, "Set environment variables") 157 | viper.BindPFlag("env", inaccel.Flags().Lookup("env")) 158 | 159 | inaccel.Flags().String("env-file", "", "Specify an alternate environment file") 160 | inaccel.MarkFlagFilename("env-file") 161 | viper.BindPFlag("env-file", inaccel.Flags().Lookup("env-file")) 162 | 163 | inaccel.Flags().StringSlice("profile", []string{}, "Specify a profile to enable") 164 | viper.BindPFlag("profile", inaccel.Flags().Lookup("profile")) 165 | viper.BindEnv("profile", "INACCEL_PROFILES") 166 | 167 | inaccel.Flags().StringP("project-name", "p", fmt.Sprintf("inaccel/%s", internal.Config), "Specify an alternate project name") 168 | viper.BindPFlag("project-name", inaccel.Flags().Lookup("project-name")) 169 | viper.BindEnv("project-name", "INACCEL_PROJECT_NAME") 170 | 171 | inaccel.Flags().Bool("pull", false, "Always attempt to pull a newer version of the project") 172 | viper.BindPFlag("pull", inaccel.Flags().Lookup("pull")) 173 | 174 | inaccel.Flags().StringP("tag", "t", "latest", "Specify the project tag to use") 175 | viper.BindPFlag("tag", inaccel.Flags().Lookup("tag")) 176 | 177 | inaccel.Flags().BoolP("version", "v", false, "Print version information and quit") 178 | viper.BindPFlag("version", inaccel.Flags().Lookup("version")) 179 | 180 | inaccel.AddCommand(cmd.Config, cmd.Down, cmd.Exec, cmd.Logs, cmd.Ps, cmd.Run, cmd.Up) 181 | 182 | return inaccel 183 | }, manager.Metadata{ 184 | SchemaVersion: "0.1.0", 185 | Vendor: "InAccel ", 186 | Version: version, 187 | URL: "https://inaccel.com", 188 | }) 189 | } 190 | -------------------------------------------------------------------------------- /internal/cmd/logs.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "regexp" 7 | "strings" 8 | 9 | "github.com/inaccel/docker/internal" 10 | "github.com/inaccel/docker/pkg/grep" 11 | "github.com/inaccel/docker/pkg/system" 12 | "github.com/spf13/cobra" 13 | "github.com/spf13/viper" 14 | ) 15 | 16 | var ( 17 | logs = viper.New() 18 | 19 | // Logs : docker inaccel logs 20 | Logs = &cobra.Command{ 21 | Use: "logs [OPTIONS] [PATTERN]", 22 | Short: "View output from containers", 23 | Args: cobra.MaximumNArgs(1), 24 | PreRunE: func(_ *cobra.Command, args []string) error { 25 | var cmd *system.Cmd 26 | 27 | if len(logs.GetString("service")) == 0 { 28 | cmd = system.Command("docker") 29 | cmd.Flag("host", internal.Host) 30 | cmd.Flag("log-level", viper.GetString("log-level")) 31 | cmd.Arg("ps") 32 | cmd.Flag("all", true) 33 | cmd.Flag("filter", fmt.Sprintf("label=com.docker.compose.container-number=%d", logs.GetInt("index"))) 34 | cmd.Flag("filter", "label=com.docker.compose.oneoff=False") 35 | cmd.Flag("filter", fmt.Sprintf("label=com.docker.compose.project=%s", regexp.MustCompile("[^-0-9_a-z]").ReplaceAllString(strings.ToLower(viper.GetString("project-name")), "_"))) 36 | cmd.Flag("filter", "label=com.inaccel.docker.default-logs-service=True") 37 | cmd.Flag("format", `{{ .Label "com.docker.compose.service" }}`) 38 | cmd.Std(nil, nil, os.Stderr) 39 | 40 | out, err := cmd.Out(viper.GetBool("debug")) 41 | if err != nil { 42 | return internal.ExitToStatus(err) 43 | } 44 | 45 | services := strings.Fields(out) 46 | 47 | if len(services) > 0 { 48 | logs.Set("service", services[0]) 49 | } else { 50 | cmd = system.Command("docker") 51 | cmd.Flag("host", internal.Host) 52 | cmd.Flag("log-level", viper.GetString("log-level")) 53 | cmd.Arg("ps") 54 | cmd.Flag("all", true) 55 | cmd.Flag("filter", fmt.Sprintf("label=com.docker.compose.container-number=%d", logs.GetInt("index"))) 56 | cmd.Flag("filter", "label=com.docker.compose.oneoff=False") 57 | cmd.Flag("filter", fmt.Sprintf("label=com.docker.compose.project=%s", regexp.MustCompile("[^-0-9_a-z]").ReplaceAllString(strings.ToLower(viper.GetString("project-name")), "_"))) 58 | cmd.Flag("format", `{{ .Label "com.docker.compose.service" }}`) 59 | cmd.Std(nil, nil, os.Stderr) 60 | 61 | out, err := cmd.Out(viper.GetBool("debug")) 62 | if err != nil { 63 | return internal.ExitToStatus(err) 64 | } 65 | 66 | services := strings.Fields(out) 67 | 68 | if len(services) == 0 { 69 | return fmt.Errorf("Error: No service (%d) found for %s", logs.GetInt("index"), viper.GetString("project-name")) 70 | } else if len(services) == 1 { 71 | logs.Set("service", services[0]) 72 | } else { 73 | return fmt.Errorf("Error: A service (%d) must be specified for %s, choose one of: [%s]", logs.GetInt("index"), viper.GetString("project-name"), strings.Join(services, " ")) 74 | } 75 | } 76 | } 77 | 78 | return nil 79 | }, 80 | RunE: func(_ *cobra.Command, args []string) error { 81 | var cmd *system.Cmd 82 | 83 | cmd = system.Command("docker") 84 | cmd.Flag("host", internal.Host) 85 | cmd.Flag("log-level", viper.GetString("log-level")) 86 | cmd.Arg("logs") 87 | cmd.Flag("follow", logs.GetBool("follow")) 88 | cmd.Flag("tail", logs.GetString("tail")) 89 | cmd.Flag("timestamps", logs.GetBool("timestamps")) 90 | cmd.Arg(fmt.Sprintf("%s_%s_%d", regexp.MustCompile("[^-0-9_a-z]").ReplaceAllString(strings.ToLower(viper.GetString("project-name")), "_"), logs.GetString("service"), logs.GetInt("index"))) 91 | switch len(args) { 92 | case 0: 93 | cmd.Std(nil, os.Stdout, os.Stderr) 94 | case 1: 95 | pattern, err := grep.Compile(args[0]) 96 | if err != nil { 97 | return err 98 | } 99 | 100 | stdout := pattern.WriteCloser(os.Stdout, !logs.GetBool("no-color"), false) 101 | defer stdout.Close() 102 | 103 | cmd.Std(nil, stdout, os.Stderr) 104 | } 105 | 106 | if err := cmd.Run(viper.GetBool("debug")); err != nil { 107 | return internal.ExitToStatus(err) 108 | } 109 | 110 | return nil 111 | }, 112 | } 113 | ) 114 | 115 | func init() { 116 | Logs.Flags().BoolP("follow", "f", false, "Follow log output") 117 | logs.BindPFlag("follow", Logs.Flags().Lookup("follow")) 118 | 119 | Logs.Flags().Int("index", 1, "Index of the container if there are multiple instances of a service") 120 | logs.BindPFlag("index", Logs.Flags().Lookup("index")) 121 | Logs.RegisterFlagCompletionFunc("index", func(_ *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { 122 | var cmd *system.Cmd 123 | 124 | if len(logs.GetString("service")) > 0 { 125 | cmd = system.Command("docker") 126 | cmd.Flag("host", internal.Host) 127 | cmd.Arg("ps") 128 | cmd.Flag("all", true) 129 | cmd.Flag("filter", "label=com.docker.compose.oneoff=False") 130 | cmd.Flag("filter", fmt.Sprintf("label=com.docker.compose.project=%s", regexp.MustCompile("[^-0-9_a-z]").ReplaceAllString(strings.ToLower(viper.GetString("project-name")), "_"))) 131 | cmd.Flag("filter", fmt.Sprintf("label=com.docker.compose.service=%s", logs.GetString("service"))) 132 | cmd.Flag("format", `{{ .Label "com.docker.compose.container-number" }}`) 133 | 134 | out, err := cmd.Out(false) 135 | if err != nil { 136 | return nil, cobra.ShellCompDirectiveDefault 137 | } 138 | 139 | var completions []string 140 | for _, completion := range strings.Fields(out) { 141 | if strings.HasPrefix(completion, toComplete) { 142 | completions = append(completions, completion) 143 | } 144 | } 145 | return completions, cobra.ShellCompDirectiveNoFileComp 146 | } 147 | 148 | return nil, cobra.ShellCompDirectiveDefault 149 | }) 150 | 151 | Logs.Flags().Bool("no-color", false, "Produce monochrome output") 152 | logs.BindPFlag("no-color", Logs.Flags().Lookup("no-color")) 153 | 154 | Logs.Flags().StringP("service", "s", "", "Service name") 155 | logs.BindPFlag("service", Logs.Flags().Lookup("service")) 156 | Logs.RegisterFlagCompletionFunc("service", func(_ *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { 157 | var cmd *system.Cmd 158 | 159 | cmd = system.Command("docker") 160 | cmd.Flag("host", internal.Host) 161 | cmd.Arg("ps") 162 | cmd.Flag("all", true) 163 | cmd.Flag("filter", "label=com.docker.compose.oneoff=False") 164 | cmd.Flag("filter", fmt.Sprintf("label=com.docker.compose.project=%s", regexp.MustCompile("[^-0-9_a-z]").ReplaceAllString(strings.ToLower(viper.GetString("project-name")), "_"))) 165 | cmd.Flag("format", `{{ .Label "com.docker.compose.service" }}`) 166 | 167 | out, err := cmd.Out(false) 168 | if err != nil { 169 | return nil, cobra.ShellCompDirectiveDefault 170 | } 171 | 172 | var completions []string 173 | for _, completion := range strings.Fields(out) { 174 | if strings.HasPrefix(completion, toComplete) { 175 | completions = append(completions, completion) 176 | } 177 | } 178 | return completions, cobra.ShellCompDirectiveNoFileComp 179 | }) 180 | 181 | Logs.Flags().StringP("tail", "n", "10", "Number of lines to show from the end of the logs") 182 | logs.BindPFlag("tail", Logs.Flags().Lookup("tail")) 183 | Logs.RegisterFlagCompletionFunc("tail", func(_ *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { 184 | var completions []string 185 | for _, completion := range []string{"all"} { 186 | if strings.HasPrefix(completion, toComplete) { 187 | completions = append(completions, completion) 188 | } 189 | } 190 | return completions, cobra.ShellCompDirectiveNoFileComp 191 | }) 192 | 193 | Logs.Flags().BoolP("timestamps", "t", false, "Show timestamps") 194 | logs.BindPFlag("timestamps", Logs.Flags().Lookup("timestamps")) 195 | } 196 | -------------------------------------------------------------------------------- /internal/cmd/exec.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "regexp" 7 | "strings" 8 | 9 | "github.com/inaccel/docker/internal" 10 | "github.com/inaccel/docker/pkg/system" 11 | "github.com/mattn/go-isatty" 12 | "github.com/spf13/cobra" 13 | "github.com/spf13/viper" 14 | ) 15 | 16 | var ( 17 | exec = viper.New() 18 | 19 | // Exec : docker inaccel exec 20 | Exec = &cobra.Command{ 21 | Use: "exec [OPTIONS] COMMAND [ARG...]", 22 | Short: "Execute a command in a running container", 23 | Args: cobra.ArbitraryArgs, 24 | PreRunE: func(_ *cobra.Command, args []string) error { 25 | var cmd *system.Cmd 26 | 27 | if len(exec.GetString("service")) == 0 { 28 | cmd = system.Command("docker") 29 | cmd.Flag("host", internal.Host) 30 | cmd.Flag("log-level", viper.GetString("log-level")) 31 | cmd.Arg("ps") 32 | cmd.Flag("all", true) 33 | cmd.Flag("filter", fmt.Sprintf("label=com.docker.compose.container-number=%d", exec.GetInt("index"))) 34 | cmd.Flag("filter", "label=com.docker.compose.oneoff=False") 35 | cmd.Flag("filter", fmt.Sprintf("label=com.docker.compose.project=%s", regexp.MustCompile("[^-0-9_a-z]").ReplaceAllString(strings.ToLower(viper.GetString("project-name")), "_"))) 36 | cmd.Flag("filter", "label=com.inaccel.docker.default-exec-service=True") 37 | cmd.Flag("format", `{{ .Label "com.docker.compose.service" }}`) 38 | cmd.Std(nil, nil, os.Stderr) 39 | 40 | out, err := cmd.Out(viper.GetBool("debug")) 41 | if err != nil { 42 | return internal.ExitToStatus(err) 43 | } 44 | 45 | services := strings.Fields(out) 46 | 47 | if len(services) > 0 { 48 | exec.Set("service", services[0]) 49 | } else { 50 | cmd = system.Command("docker") 51 | cmd.Flag("host", internal.Host) 52 | cmd.Flag("log-level", viper.GetString("log-level")) 53 | cmd.Arg("ps") 54 | cmd.Flag("all", true) 55 | cmd.Flag("filter", fmt.Sprintf("label=com.docker.compose.container-number=%d", exec.GetInt("index"))) 56 | cmd.Flag("filter", "label=com.docker.compose.oneoff=False") 57 | cmd.Flag("filter", fmt.Sprintf("label=com.docker.compose.project=%s", regexp.MustCompile("[^-0-9_a-z]").ReplaceAllString(strings.ToLower(viper.GetString("project-name")), "_"))) 58 | cmd.Flag("format", `{{ .Label "com.docker.compose.service" }}`) 59 | cmd.Std(nil, nil, os.Stderr) 60 | 61 | out, err := cmd.Out(viper.GetBool("debug")) 62 | if err != nil { 63 | return internal.ExitToStatus(err) 64 | } 65 | 66 | services := strings.Fields(out) 67 | 68 | if len(services) == 0 { 69 | return fmt.Errorf("Error: No service (%d) found for %s", exec.GetInt("index"), viper.GetString("project-name")) 70 | } else if len(services) == 1 { 71 | exec.Set("service", services[0]) 72 | } else { 73 | return fmt.Errorf("Error: A service (%d) must be specified for %s, choose one of: [%s]", exec.GetInt("index"), viper.GetString("project-name"), strings.Join(services, " ")) 74 | } 75 | } 76 | } 77 | 78 | return nil 79 | }, 80 | RunE: func(_ *cobra.Command, args []string) error { 81 | var cmd *system.Cmd 82 | 83 | if err := cobra.MinimumNArgs(1)(nil, args); err != nil { 84 | cmd = system.Command("docker") 85 | cmd.Flag("host", internal.Host) 86 | cmd.Flag("log-level", viper.GetString("log-level")) 87 | cmd.Arg("inspect") 88 | cmd.Flag("format", `{{ index .Config.Labels "com.inaccel.docker.default-exec-command" }}`) 89 | cmd.Arg(fmt.Sprintf("%s_%s_%d", regexp.MustCompile("[^-0-9_a-z]").ReplaceAllString(strings.ToLower(viper.GetString("project-name")), "_"), exec.GetString("service"), exec.GetInt("index"))) 90 | cmd.Std(nil, nil, os.Stderr) 91 | 92 | out, err := cmd.Out(viper.GetBool("debug")) 93 | if err != nil { 94 | return internal.ExitToStatus(err) 95 | } 96 | 97 | args = strings.Fields(out) 98 | 99 | if err := cobra.MinimumNArgs(1)(nil, args); err != nil { 100 | return err 101 | } 102 | } 103 | 104 | cmd = system.Command("docker") 105 | cmd.Flag("host", internal.Host) 106 | cmd.Flag("log-level", viper.GetString("log-level")) 107 | cmd.Arg("exec") 108 | cmd.Flag("env", exec.GetStringSlice("env")) 109 | cmd.Flag("interactive", true) 110 | cmd.Flag("tty", !exec.GetBool("no-tty") && isatty.IsTerminal(os.Stdin.Fd()) && isatty.IsTerminal(os.Stdout.Fd()) && isatty.IsTerminal(os.Stderr.Fd())) 111 | cmd.Flag("user", exec.GetString("user")) 112 | cmd.Flag("workdir", exec.GetString("workdir")) 113 | cmd.Arg(fmt.Sprintf("%s_%s_%d", regexp.MustCompile("[^-0-9_a-z]").ReplaceAllString(strings.ToLower(viper.GetString("project-name")), "_"), exec.GetString("service"), exec.GetInt("index"))) 114 | cmd.Arg(args...) 115 | cmd.Std(os.Stdin, os.Stdout, os.Stderr) 116 | 117 | if err := cmd.Run(viper.GetBool("debug")); err != nil { 118 | return internal.ExitToStatus(err) 119 | } 120 | 121 | return nil 122 | }, 123 | } 124 | ) 125 | 126 | func init() { 127 | Exec.Flags().StringSliceP("env", "e", []string{}, "Set environment variables") 128 | exec.BindPFlag("env", Exec.Flags().Lookup("env")) 129 | 130 | Exec.Flags().Int("index", 1, "Index of the container if there are multiple instances of a service") 131 | exec.BindPFlag("index", Exec.Flags().Lookup("index")) 132 | Exec.RegisterFlagCompletionFunc("index", func(_ *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { 133 | var cmd *system.Cmd 134 | 135 | if len(exec.GetString("service")) > 0 { 136 | cmd = system.Command("docker") 137 | cmd.Flag("host", internal.Host) 138 | cmd.Arg("ps") 139 | cmd.Flag("filter", "label=com.docker.compose.oneoff=False") 140 | cmd.Flag("filter", fmt.Sprintf("label=com.docker.compose.project=%s", regexp.MustCompile("[^-0-9_a-z]").ReplaceAllString(strings.ToLower(viper.GetString("project-name")), "_"))) 141 | cmd.Flag("filter", fmt.Sprintf("label=com.docker.compose.service=%s", exec.GetString("service"))) 142 | cmd.Flag("format", `{{ .Label "com.docker.compose.container-number" }}`) 143 | 144 | out, err := cmd.Out(false) 145 | if err != nil { 146 | return nil, cobra.ShellCompDirectiveDefault 147 | } 148 | 149 | var completions []string 150 | for _, completion := range strings.Fields(out) { 151 | if strings.HasPrefix(completion, toComplete) { 152 | completions = append(completions, completion) 153 | } 154 | } 155 | return completions, cobra.ShellCompDirectiveNoFileComp 156 | } 157 | 158 | return nil, cobra.ShellCompDirectiveDefault 159 | }) 160 | 161 | Exec.Flags().BoolP("no-tty", "T", false, "Disable pseudo-TTY allocation") 162 | exec.BindPFlag("no-tty", Exec.Flags().Lookup("no-tty")) 163 | 164 | Exec.Flags().StringP("service", "s", "", "Service name") 165 | exec.BindPFlag("service", Exec.Flags().Lookup("service")) 166 | Exec.RegisterFlagCompletionFunc("service", func(_ *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { 167 | var cmd *system.Cmd 168 | 169 | cmd = system.Command("docker") 170 | cmd.Flag("host", internal.Host) 171 | cmd.Arg("ps") 172 | cmd.Flag("filter", "label=com.docker.compose.oneoff=False") 173 | cmd.Flag("filter", fmt.Sprintf("label=com.docker.compose.project=%s", regexp.MustCompile("[^-0-9_a-z]").ReplaceAllString(strings.ToLower(viper.GetString("project-name")), "_"))) 174 | cmd.Flag("format", `{{ .Label "com.docker.compose.service" }}`) 175 | 176 | out, err := cmd.Out(false) 177 | if err != nil { 178 | return nil, cobra.ShellCompDirectiveDefault 179 | } 180 | 181 | var completions []string 182 | for _, completion := range strings.Fields(out) { 183 | if strings.HasPrefix(completion, toComplete) { 184 | completions = append(completions, completion) 185 | } 186 | } 187 | return completions, cobra.ShellCompDirectiveNoFileComp 188 | }) 189 | 190 | Exec.Flags().StringP("user", "u", "", "Username or UID (format: [:])") 191 | exec.BindPFlag("user", Exec.Flags().Lookup("user")) 192 | 193 | Exec.Flags().StringP("workdir", "w", "", "Working directory inside the container") 194 | exec.BindPFlag("workdir", Exec.Flags().Lookup("workdir")) 195 | } 196 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= 2 | github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= 3 | github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= 4 | github.com/Microsoft/go-winio v0.4.14 h1:+hMXMk01us9KgxGb7ftKQt2Xpf5hH/yky+TDA+qxleU= 5 | github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= 6 | github.com/Shopify/logrus-bugsnag v0.0.0-20170309145241-6dbc35f2c30d h1:hi6J4K6DKrR4/ljxn6SF6nURyu785wKMuQcjt7H3VCQ= 7 | github.com/Shopify/logrus-bugsnag v0.0.0-20170309145241-6dbc35f2c30d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ= 8 | github.com/beorn7/perks v0.0.0-20150223135152-b965b613227f h1:L/FlB1krOjojJSmUaiAiOMiIdRWylhc9QcHg0vHBuzA= 9 | github.com/beorn7/perks v0.0.0-20150223135152-b965b613227f/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= 10 | github.com/bitly/go-hostpool v0.1.0/go.mod h1:4gOCgp6+NZnVqlKyZ/iBZFTAJKembaVENUpMkpg42fw= 11 | github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA= 12 | github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= 13 | github.com/bugsnag/bugsnag-go v1.0.5-0.20150529004307-13fd6b8acda0 h1:s7+5BfS4WFJoVF9pnB8kBk03S7pZXRdKamnV0FOl5Sc= 14 | github.com/bugsnag/bugsnag-go v1.0.5-0.20150529004307-13fd6b8acda0/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8= 15 | github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b h1:otBG+dV+YK+Soembjv71DPz3uX/V/6MMlSyD9JBQ6kQ= 16 | github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50= 17 | github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0 h1:nvj0OLI3YqYXer/kZD8Ri1aaunCxIEsOst1BVJswV0o= 18 | github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE= 19 | github.com/c-bata/go-prompt v0.2.5 h1:3zg6PecEywxNn0xiqcXHD96fkbxghD+gdB2tbsYfl+Y= 20 | github.com/c-bata/go-prompt v0.2.5/go.mod h1:vFnjEGDIIA/Lib7giyE4E9c50Lvl8j0S+7FVlAwDAVw= 21 | github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= 22 | github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= 23 | github.com/cloudflare/cfssl v0.0.0-20180223231731-4e2dcbde5004 h1:lkAMpLVBDaj17e85keuznYcH5rqI438v41pKcBl4ZxQ= 24 | github.com/cloudflare/cfssl v0.0.0-20180223231731-4e2dcbde5004/go.mod h1:yMWuSON2oQp+43nFtAV/uvKQIFpSPerB57DCt9t8sSA= 25 | github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= 26 | github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= 27 | github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= 28 | github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= 29 | github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= 30 | github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= 31 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 32 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 33 | github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= 34 | github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 35 | github.com/denisenkom/go-mssqldb v0.0.0-20191128021309-1d7a30a10f73/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= 36 | github.com/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK2OFGvA0= 37 | github.com/distribution/reference v0.5.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= 38 | github.com/docker/cli v25.0.2+incompatible h1:6GEdvxwEA451/+Y3GtqIGn/MNjujQazUlxC6uGu8Tog= 39 | github.com/docker/cli v25.0.2+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= 40 | github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= 41 | github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk= 42 | github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= 43 | github.com/docker/docker v25.0.2+incompatible h1:/OaKeauroa10K4Nqavw4zlhcDq/WBcPMc5DbjOGgozY= 44 | github.com/docker/docker v25.0.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= 45 | github.com/docker/docker-credential-helpers v0.8.1 h1:j/eKUktUltBtMzKqmfLB0PAgqYyMHOp5vfsD1807oKo= 46 | github.com/docker/docker-credential-helpers v0.8.1/go.mod h1:P3ci7E3lwkZg6XiHdRKft1KckHiO9a2rNtyFbZ/ry9M= 47 | github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c h1:lzqkGL9b3znc+ZUgi7FlLnqjQhcXxkNM/quxIjBVMD0= 48 | github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c/go.mod h1:CADgU4DSXK5QUlFslkQu2yW2TKzFZcXq/leZfM0UH5Q= 49 | github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= 50 | github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= 51 | github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= 52 | github.com/docker/go-metrics v0.0.0-20180209012529-399ea8c73916 h1:yWHOI+vFjEsAakUTSrtqc/SAHrhSkmn48pqjidZX3QA= 53 | github.com/docker/go-metrics v0.0.0-20180209012529-399ea8c73916/go.mod h1:/u0gXw0Gay3ceNrsHubL3BtdOL2fHf93USgMTe0W5dI= 54 | github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= 55 | github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= 56 | github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7 h1:UhxFibDNY/bfvqU5CAUmr9zpesgbU6SWc8/B4mflAE4= 57 | github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE= 58 | github.com/dvsekhvalnov/jose2go v0.0.0-20170216131308-f21a8cedbbae/go.mod h1:7BvyPhdbLxMXIYTFPLsyJRFMsKmOZnQmzh6Gb+uquuM= 59 | github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0= 60 | github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= 61 | github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= 62 | github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= 63 | github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= 64 | github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= 65 | github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= 66 | github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= 67 | github.com/fvbommel/sortorder v1.1.0 h1:fUmoe+HLsBTctBDoaBwpQo5N+nrCp8g/BjKb/6ZQmYw= 68 | github.com/fvbommel/sortorder v1.1.0/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0= 69 | github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= 70 | github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= 71 | github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= 72 | github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= 73 | github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= 74 | github.com/go-sql-driver/mysql v1.3.0 h1:pgwjLi/dvffoP9aabwkT3AKpXQM93QARkjFhDDqC1UE= 75 | github.com/go-sql-driver/mysql v1.3.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= 76 | github.com/gogo/protobuf v1.0.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= 77 | github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= 78 | github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= 79 | github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= 80 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 81 | github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= 82 | github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= 83 | github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= 84 | github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= 85 | github.com/google/certificate-transparency-go v1.0.10-0.20180222191210-5ab67e519c93 h1:jc2UWq7CbdszqeH6qu1ougXMIUBfSy8Pbh/anURYbGI= 86 | github.com/google/certificate-transparency-go v1.0.10-0.20180222191210-5ab67e519c93/go.mod h1:QeJfpSbVSfYc7RgB3gJFj9cbuQMMchQxrWXz8Ruopmg= 87 | github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 88 | github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= 89 | github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 90 | github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= 91 | github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= 92 | github.com/gorilla/mux v1.7.0 h1:tOSd0UKHQd6urX6ApfOn4XdBMY6Sh1MfxV3kmaazO+U= 93 | github.com/gorilla/mux v1.7.0/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= 94 | github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 h1:YBftPWNWd4WwGqtY2yeZL2ef8rHAxPBD8KFhJpmcqms= 95 | github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg= 96 | github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed h1:5upAirOpQc1Q53c0bnx2ufif5kANL7bfZWcc6VJWJd8= 97 | github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4= 98 | github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= 99 | github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= 100 | github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= 101 | github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= 102 | github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= 103 | github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= 104 | github.com/jinzhu/gorm v0.0.0-20170222002820-5409931a1bb8 h1:CZkYfurY6KGhVtlalI4QwQ6T0Cu6iuY3e0x5RLu96WE= 105 | github.com/jinzhu/gorm v0.0.0-20170222002820-5409931a1bb8/go.mod h1:Vla75njaFJ8clLU1W44h34PjIkijhjHIYnZxMqCdxqo= 106 | github.com/jinzhu/inflection v0.0.0-20170102125226-1c35d901db3d h1:jRQLvyVGL+iVtDElaEIDdKwpPqUIZJfzkNLV34htpEc= 107 | github.com/jinzhu/inflection v0.0.0-20170102125226-1c35d901db3d/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= 108 | github.com/jinzhu/now v1.1.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= 109 | github.com/juju/loggo v0.0.0-20190526231331-6e530bcce5d8/go.mod h1:vgyd7OREkbtVEN/8IXZe5Ooef3LQePvuBm9UWj6ZL8U= 110 | github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= 111 | github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= 112 | github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= 113 | github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= 114 | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= 115 | github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= 116 | github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= 117 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 118 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 119 | github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= 120 | github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= 121 | github.com/lib/pq v0.0.0-20150723085316-0dad96c0b94f/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= 122 | github.com/magiconair/properties v1.5.3/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= 123 | github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= 124 | github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= 125 | github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= 126 | github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= 127 | github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= 128 | github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= 129 | github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= 130 | github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= 131 | github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= 132 | github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= 133 | github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= 134 | github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= 135 | github.com/mattn/go-runewidth v0.0.6/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= 136 | github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= 137 | github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= 138 | github.com/mattn/go-sqlite3 v1.6.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= 139 | github.com/mattn/go-tty v0.0.3 h1:5OfyWorkyO7xP52Mq7tB36ajHDG5OHrmBGIS/DtakQI= 140 | github.com/mattn/go-tty v0.0.3/go.mod h1:ihxohKRERHTVzN+aSVRwACLCeqIoZAWpoICkkvrWyR0= 141 | github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= 142 | github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= 143 | github.com/miekg/pkcs11 v1.0.2 h1:CIBkOawOtzJNE0B+EpRiUBzuVW7JEQAwdwhSS6YhIeg= 144 | github.com/miekg/pkcs11 v1.0.2/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= 145 | github.com/mitchellh/mapstructure v0.0.0-20150613213606-2caf8efc9366/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= 146 | github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= 147 | github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= 148 | github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc= 149 | github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo= 150 | github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= 151 | github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= 152 | github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= 153 | github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= 154 | github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= 155 | github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= 156 | github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= 157 | github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg= 158 | github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= 159 | github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= 160 | github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= 161 | github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= 162 | github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= 163 | github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= 164 | github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM= 165 | github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= 166 | github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU= 167 | github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= 168 | github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= 169 | github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= 170 | github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 171 | github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= 172 | github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 173 | github.com/pkg/term v1.1.0 h1:xIAAdCMh3QIAy+5FrE8Ad8XoDhEU4ufwbaSozViP9kk= 174 | github.com/pkg/term v1.1.0/go.mod h1:E25nymQcrSllhX42Ok8MRm1+hyBdHY0dCeiKZ9jpNGw= 175 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 176 | github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= 177 | github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 178 | github.com/prometheus/client_golang v0.9.0-pre1.0.20180209125602-c332b6f63c06 h1:HfhRu7DulhCtYuCwmHYHdZ0pR/qYrCde5uhuemqD8rI= 179 | github.com/prometheus/client_golang v0.9.0-pre1.0.20180209125602-c332b6f63c06/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= 180 | github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5 h1:cLL6NowurKLMfCeQy4tIeph12XNQWgANCNvdyrOYKV4= 181 | github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= 182 | github.com/prometheus/common v0.0.0-20180110214958-89604d197083 h1:BVsJT8+ZbyuL3hypz/HmEiM8h2P6hBQGig4el9/MdjA= 183 | github.com/prometheus/common v0.0.0-20180110214958-89604d197083/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= 184 | github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7 h1:hhvfGDVThBnd4kYisSFmYuHYeUhglxcwag7FhVPH9zM= 185 | github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= 186 | github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= 187 | github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= 188 | github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= 189 | github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= 190 | github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= 191 | github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= 192 | github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= 193 | github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= 194 | github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= 195 | github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= 196 | github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= 197 | github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= 198 | github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= 199 | github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= 200 | github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= 201 | github.com/spf13/cast v0.0.0-20150508191742-4d07383ffe94/go.mod h1:r2rcYCSwa1IExKTDiTfzaxqT2FNHs8hODu4LnUfgKEg= 202 | github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= 203 | github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= 204 | github.com/spf13/cobra v0.0.1/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= 205 | github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= 206 | github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= 207 | github.com/spf13/jwalterweatherman v0.0.0-20141219030609-3d60171a6431/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= 208 | github.com/spf13/pflag v1.0.0/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= 209 | github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= 210 | github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= 211 | github.com/spf13/viper v0.0.0-20150530192845-be5ff3e4840c/go.mod h1:A8kyI5cUJhb8N+3pkfONlcEcZbueH6nhAm0Fq7SrnBM= 212 | github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ= 213 | github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk= 214 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 215 | github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 216 | github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= 217 | github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= 218 | github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= 219 | github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 220 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 221 | github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= 222 | github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= 223 | github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 224 | github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 225 | github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= 226 | github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= 227 | github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= 228 | github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= 229 | github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= 230 | github.com/theupdateframework/notary v0.7.0 h1:QyagRZ7wlSpjT5N2qQAh/pN+DVqgekv4DzbAiAiEL3c= 231 | github.com/theupdateframework/notary v0.7.0/go.mod h1:c9DRxcmhHmVLDay4/2fUYdISnHqbFDGRSlXPO0AhYWw= 232 | github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 233 | github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 234 | go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.47.0 h1:sv9kVfal0MK0wBMCOGr+HeJm9v803BkJxGrk2au7j08= 235 | go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.47.0/go.mod h1:SK2UL73Zy1quvRPonmOmRDiWk1KBV3LyIeeIxcEApWw= 236 | go.opentelemetry.io/otel v1.22.0 h1:xS7Ku+7yTFvDfDraDIJVpw7XPyuHlB9MCiqqX5mcJ6Y= 237 | go.opentelemetry.io/otel v1.22.0/go.mod h1:eoV4iAi3Ea8LkAEI9+GFT44O6T/D0GWAVFyZVCC6pMI= 238 | go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.22.0 h1:9M3+rhx7kZCIQQhQRYaZCdNu1V73tm4TvXs2ntl98C4= 239 | go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.22.0/go.mod h1:noq80iT8rrHP1SfybmPiRGc9dc5M8RPmGvtwo7Oo7tc= 240 | go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.22.0 h1:FyjCyI9jVEfqhUh2MoSkmolPjfh5fp2hnV0b0irxH4Q= 241 | go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.22.0/go.mod h1:hYwym2nDEeZfG/motx0p7L7J1N1vyzIThemQsb4g2qY= 242 | go.opentelemetry.io/otel/metric v1.22.0 h1:lypMQnGyJYeuYPhOM/bgjbFM6WE44W1/T45er4d8Hhg= 243 | go.opentelemetry.io/otel/metric v1.22.0/go.mod h1:evJGjVpZv0mQ5QBRJoBF64yMuOf4xCWdXjK8pzFvliY= 244 | go.opentelemetry.io/otel/sdk v1.22.0 h1:6coWHw9xw7EfClIC/+O31R8IY3/+EiRFHevmHafB2Gw= 245 | go.opentelemetry.io/otel/sdk v1.22.0/go.mod h1:iu7luyVGYovrRpe2fmj3CVKouQNdTOkxtLzPvPz1DOc= 246 | go.opentelemetry.io/otel/trace v1.22.0 h1:Hg6pPujv0XG9QaVbGOBVHunyuLcCC3jN7WEhPx83XD0= 247 | go.opentelemetry.io/otel/trace v1.22.0/go.mod h1:RbbHXVqKES9QhzZq/fE5UnOSILqRt40a21sPw2He1xo= 248 | go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= 249 | go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= 250 | go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= 251 | go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= 252 | go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI= 253 | go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ= 254 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 255 | golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 256 | golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 257 | golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 258 | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 259 | golang.org/x/crypto v0.0.0-20201117144127-c1f2f97bffc9/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= 260 | golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY= 261 | golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= 262 | golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g= 263 | golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= 264 | golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 265 | golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 266 | golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 267 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 268 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 269 | golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 270 | golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= 271 | golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= 272 | golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= 273 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 274 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 275 | golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 276 | golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 277 | golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= 278 | golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= 279 | golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 280 | golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 281 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 282 | golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 283 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 284 | golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 285 | golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 286 | golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 287 | golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 288 | golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 289 | golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 290 | golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 291 | golang.org/x/sys v0.0.0-20200918174421-af09f7315aff/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 292 | golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 293 | golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 294 | golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 295 | golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 296 | golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= 297 | golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 298 | golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= 299 | golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4= 300 | golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= 301 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 302 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 303 | golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= 304 | golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= 305 | golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= 306 | golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= 307 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 308 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 309 | golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= 310 | golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= 311 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 312 | golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 313 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 314 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 315 | google.golang.org/genproto v0.0.0-20231106174013-bbf56f31fb17 h1:wpZ8pe2x1Q3f2KyT5f8oP/fa9rHAKgFPr/HZdNuS+PQ= 316 | google.golang.org/genproto/googleapis/api v0.0.0-20231106174013-bbf56f31fb17 h1:JpwMPBpFN3uKhdaekDpiNlImDdkUAyiJ6ez/uxGaUSo= 317 | google.golang.org/genproto/googleapis/api v0.0.0-20231106174013-bbf56f31fb17/go.mod h1:0xJLfVdJqpAPl8tDg1ujOCGzx6LFLttXT5NhllGOXY4= 318 | google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f h1:ultW7fxlIvee4HYrtnaRPon9HpEgFk5zYpmfMgtKB5I= 319 | google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f/go.mod h1:L9KNLi232K1/xB6f7AlSX692koaRnKaWSR0stBki0Yc= 320 | google.golang.org/grpc v1.0.5/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= 321 | google.golang.org/grpc v1.60.1 h1:26+wFr+cNqSGFcOXcabYC0lUVJVRa2Sb2ortSK7VrEU= 322 | google.golang.org/grpc v1.60.1/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM= 323 | google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= 324 | google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= 325 | google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= 326 | google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= 327 | gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= 328 | gopkg.in/cenkalti/backoff.v2 v2.2.1 h1:eJ9UAg01/HIHG987TwxvnzK2MgxXq97YY6rYDpY9aII= 329 | gopkg.in/cenkalti/backoff.v2 v2.2.1/go.mod h1:S0QdOvT2AlerfSBkp0O+dk+bbIMaNbEmVk876gPCthU= 330 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 331 | gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= 332 | gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 333 | gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= 334 | gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo= 335 | gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= 336 | gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= 337 | gopkg.in/rethinkdb/rethinkdb-go.v6 v6.2.1 h1:d4KQkxAaAiRY2h5Zqis161Pv91A37uZyJOx73duwUwM= 338 | gopkg.in/rethinkdb/rethinkdb-go.v6 v6.2.1/go.mod h1:WbjuEoo1oadwzQ4apSDU+JTvmllEHtsNHS6y7vFc7iw= 339 | gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= 340 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 341 | gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 342 | gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 343 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 344 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 345 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 346 | gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU= 347 | gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= 348 | --------------------------------------------------------------------------------