diff --git a/.github/workflows/test_ci.yaml b/.github/workflows/test_ci.yaml index 4cc4f26..59c4105 100644 --- a/.github/workflows/test_ci.yaml +++ b/.github/workflows/test_ci.yaml @@ -1,6 +1,8 @@ name: Golang Test on: push: + branches: + - main pull_request: jobs: @@ -13,8 +15,7 @@ jobs: - name: Run golangci-lint uses: golangci/golangci-lint-action@3a919529898de77ec3da873e3063ca4b10e7f5cc # v3 with: - # Hard-coding version due to this bug: https://github.com/golangci/golangci-lint-action/issues/535 - version: v1.52.2 + version: v1.55.2 test: name: go test runs-on: ubuntu-latest @@ -24,12 +25,12 @@ jobs: - name: Checkout uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 - name: Set up Go - uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4 + uses: actions/setup-go@v5 with: - go-version: 1.18 + go-version: 1.21.6 - name: Set up gotestfmt uses: GoTestTools/gotestfmt-action@v2 - - uses: actions/cache@e12d46a63a90f2fae62d114769bbf2a179198b5c # v3 + - uses: actions/cache@v4 with: path: | ~/go/pkg/mod diff --git a/.golangci.yaml b/.golangci.yaml new file mode 100644 index 0000000..6f41ec7 --- /dev/null +++ b/.golangci.yaml @@ -0,0 +1,100 @@ +run: + timeout: 5m +linters: + enable: + # region General + + # Add depguard to prevent adding additional dependencies. This is a client library, we really don't want + # additional dependencies. + - depguard + # Prevent improper directives in go.mod. + - gomoddirectives + # Prevent improper nolint directives. + - nolintlint + + # endregion + + + # region Code Quality and Comments + + # Inspect source code for potential security problems. This check has a fairly high false positive rate, + # comment with // nolint:gosec where not relevant. + - gosec + # Replace golint. +# - revive + # Complain about deeply nested if cases. + - nestif + # Prevent naked returns in long functions. + - nakedret + # Make Go code more readable. + - gocritic + # Check if comments end in a period. This helps prevent incomplete comment lines, such as half-written sentences. +# - godot + # Complain about comments as these indicate incomplete code. + - godox + # Keep the cyclomatic complexity of functions to a reasonable level. + - gocyclo + # Complain about cognitive complexity of functions. + - gocognit + # Find repeated strings that could be converted into constants. + - goconst + # Complain about unnecessary type conversions. + - unconvert + # Complain about unused parameters. These should be replaced with underscores. + - unparam + # Check for non-ASCII identifiers. + - asciicheck + # Check for HTTP response body being closed. Sometimes, you may need to disable this using // nolint:bodyclose. + - bodyclose + # Check for duplicate code. You may want to disable this with // nolint:dupl if the source code is the same, but + # legitimately exists for different reasons. + - dupl + # Check for pointers in loops. This is a typical bug source. + - exportloopref + # Enforce a reasonable function length of 60 lines or 40 instructions. In very rare cases you may want to disable + # this with // nolint:funlen if there is absolutely no way to split the function in question. + - funlen + # Prevent dogsledding (mass-ignoring return values). This typically indicates missing error handling. + - dogsled + # Enforce consistent import aliases across all files. + - importas + # Make code properly formatted. + - gofmt + # Prevent faulty error checks. + - nilerr + # Prevent direct error checks that won't work with wrapped errors. + - errorlint + # Find slice usage that could potentially be preallocated. + - prealloc + # Check for improper duration handling. + - durationcheck + # Enforce tests being in the _test package. +# - testpackage + + # endregion +linters-settings: + depguard: + rules: + main: + list-mode: strict + allow: + - $gostd + - go.flow.arcalot.io/ + - go.arcalot.io/ + - github.com/docker/ + - github.com/opencontainers/ + - gopkg.in/yaml.v3 + - github.com/fxamacker/cbor + - golang.org/ + govet: + enable-all: true + check-shadowing: false + disable: + # We don't care about variable shadowing. + - shadow + - fieldalignment + stylecheck: + checks: + - all +issues: + exclude-use-default: false diff --git a/cli_plugin.go b/cli_plugin.go index 97fca65..a99bd3b 100644 --- a/cli_plugin.go +++ b/cli_plugin.go @@ -17,8 +17,6 @@ type CliPlugin struct { stdout io.ReadCloser } -// TODO: unwrap the whole config - func (p *CliPlugin) Write(b []byte) (n int, err error) { return p.stdin.Write(b) } diff --git a/factory.go b/factory.go index bbb1fe0..e8323a5 100644 --- a/factory.go +++ b/factory.go @@ -48,7 +48,7 @@ func (f factory) Create(config *Config, logger log.Logger) (deployer.Connector, } else { rngSeed = config.Podman.RngSeed } - rng := rand.New(rand.NewSource(rngSeed)) + rng := rand.New(rand.NewSource(rngSeed)) //nolint:gosec // random number is not a security credential var containerNamePrefix string if config.Podman.ContainerNamePrefix == "" { diff --git a/go.mod b/go.mod index 7ba4ec7..868239b 100644 --- a/go.mod +++ b/go.mod @@ -1,13 +1,13 @@ module go.flow.arcalot.io/podmandeployer -go 1.18 +go 1.21 require ( github.com/docker/docker v24.0.7+incompatible github.com/docker/go-connections v0.4.0 - go.arcalot.io/assert v1.6.0 - go.arcalot.io/lang v1.0.0 - go.flow.arcalot.io/deployer v0.4.0 + go.arcalot.io/assert v1.7.0 + go.arcalot.io/lang v1.1.0 + go.flow.arcalot.io/deployer v0.5.0 ) require ( @@ -17,6 +17,6 @@ require ( ) require ( - go.arcalot.io/log/v2 v2.0.0 - go.flow.arcalot.io/pluginsdk v0.5.1 + go.arcalot.io/log/v2 v2.1.0 + go.flow.arcalot.io/pluginsdk v0.8.0 ) diff --git a/go.sum b/go.sum index 88683bd..a30fddb 100644 --- a/go.sum +++ b/go.sum @@ -1,63 +1,28 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/docker/docker v24.0.6+incompatible h1:hceabKCtUgDqPu+qm0NgsaXf28Ljf4/pWFL7xjWWDgE= -github.com/docker/docker v24.0.6+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/docker/docker v24.0.7+incompatible h1:Wo6l37AuwP3JaMnZa226lzVXGA3F9Ig1seQen0cKYlM= github.com/docker/docker v24.0.7+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= -github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.arcalot.io/assert v1.6.0 h1:iKA8SZZ1MRblMX5QAwwY5RbpR+VNyp//4IU7vo08Xu0= -go.arcalot.io/assert v1.6.0/go.mod h1:Xy3ScX0p9IMY89gdsgexOKxnmDr0nGHG9dV7p8Uxg7w= -go.arcalot.io/lang v1.0.0 h1:mgDaieT4wWdZTnR4V7+/pgYRmzfU7VZZgIzHccuxAbY= -go.arcalot.io/lang v1.0.0/go.mod h1:ALqfYEhAzC2WoGLaycmJoNJd5NmkR7V1PSKp/c5D278= -go.arcalot.io/log/v2 v2.0.0 h1:mbmsWDVBXZNWrDzUh5JLzeGCQ59kTuMFs+pyfJGc1hk= -go.arcalot.io/log/v2 v2.0.0/go.mod h1:1V8jnFIIGwh2CtcGkHNOmy1nCo7LbazQNkUcnKYNMn4= -go.flow.arcalot.io/deployer v0.4.0 h1:5YveLCX+zc8Ra/aukHOwD5OrJD2W8WRzoruf3bpJfqY= -go.flow.arcalot.io/deployer v0.4.0/go.mod h1:x6gsz/hANR8qN1nerpyY3vXpdaqofDH5Wlg+Nsqg/x0= -go.flow.arcalot.io/pluginsdk v0.5.0 h1:TRS/waCTcdoMZ9neDAcfy3zpzyDnPHRbhV+Y1kpcw3Y= -go.flow.arcalot.io/pluginsdk v0.5.0/go.mod h1:2s2f//7uOkBjr1QaiWJD/bqDIeLlINJtD1BhiY4aGPM= -go.flow.arcalot.io/pluginsdk v0.5.1 h1:ebb2ThAqmjmwGpDyKpd1wEDUisPqPabgARjFohy47Io= -go.flow.arcalot.io/pluginsdk v0.5.1/go.mod h1:2s2f//7uOkBjr1QaiWJD/bqDIeLlINJtD1BhiY4aGPM= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +go.arcalot.io/assert v1.7.0 h1:PTLyeisNMUKpM9wXRDxResanBhuGOYO1xFK3v5b3FSw= +go.arcalot.io/assert v1.7.0/go.mod h1:nNmWPoNUHFyrPkNrD2aASm5yPuAfiWdB/4X7Lw3ykHk= +go.arcalot.io/lang v1.1.0 h1:ugglRKpd3qIMkdghAjKJxsziIgHm8QpxrzZPSXoa08I= +go.arcalot.io/lang v1.1.0/go.mod h1:2BZJO4csY7NnN/Nf1+eTdIQH4A2vxtOMneaO+PJl+Co= +go.arcalot.io/log/v2 v2.1.0 h1:lNO931hJ82LgS6WcCFCxpLWXQXPFhOkz6PyAJ/augq4= +go.arcalot.io/log/v2 v2.1.0/go.mod h1:PNWOSkkPmgS2OMlWTIlB/WqOw0yaBvDYd8ENAP80H4k= +go.flow.arcalot.io/deployer v0.5.0 h1:yXYogvL3shNBEEoTx9U9CNbfxuf8777uAH5Vn3hv1Yo= +go.flow.arcalot.io/deployer v0.5.0/go.mod h1:whj8wOUursCnfZCt1a7eY5hU3EyOcUG48vM4NeAe5N8= +go.flow.arcalot.io/pluginsdk v0.8.0 h1:cShsshrR17ZFLcbgi3aZvqexLttcp3JISFNqPUPuDvA= +go.flow.arcalot.io/pluginsdk v0.8.0/go.mod h1:sk7ssInR/T+Gy+RSRr+QhKqZcECFFxMyn1hPQCTZSyU= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU= gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= diff --git a/internal/cliwrapper/cliwrapper.go b/internal/cliwrapper/cliwrapper.go index c11ea13..063c47e 100644 --- a/internal/cliwrapper/cliwrapper.go +++ b/internal/cliwrapper/cliwrapper.go @@ -42,7 +42,7 @@ func (p *cliWrapper) ImageExists(image string) (*bool, error) { p.logger.Debugf("Checking whether image exists with command %v", cmd.Args) if err := cmd.Run(); err != nil { return nil, fmt.Errorf( - "error while determining if image exists. Stdout: '%s', Stderr: '%s', Cmd error: '%s'", + "error while determining if image exists. Stdout: '%s', Stderr: '%s', Cmd error: (%w)", out.String(), errOut.String(), err) } outStr := out.String() @@ -66,7 +66,7 @@ func (p *cliWrapper) PullImage(image string, platform *string) error { cmd.Stderr = &errOut if err := cmd.Run(); err != nil { return fmt.Errorf( - "error while pulling image. Stdout: '%s', Stderr: '%s', Cmd error: '%s'", + "error while pulling image. Stdout: '%s', Stderr: '%s', Cmd error: (%w)", out.String(), errOut.String(), err) } return nil diff --git a/internal/cliwrapper/cliwrapper_test.go b/internal/cliwrapper/cliwrapper_test.go index 145d1f1..76bfe75 100644 --- a/internal/cliwrapper/cliwrapper_test.go +++ b/internal/cliwrapper/cliwrapper_test.go @@ -50,28 +50,28 @@ func TestPodman_ImageExists(t *testing.T) { func TestPodman_PullImage(t *testing.T) { logger := log.NewTestLogger(t) - tests.RemoveImage(logger, tests.TestImage) + tests.RemoveImage(logger, tests.TestImageMultiPlatform) podman := NewCliWrapper(tests.GetPodmanPath(), logger) assert.NotNil(t, tests.GetPodmanPath()) // pull without platform - if err := podman.PullImage(tests.TestImage, nil); err != nil { + if err := podman.PullImage(tests.TestImageMultiPlatform, nil); err != nil { assert.Nil(t, err) } - imageArch := tests.InspectImage(logger, tests.TestImage) + imageArch := tests.InspectImage(logger, tests.TestImageMultiPlatform) assert.NotNil(t, imageArch) - tests.RemoveImage(logger, tests.TestImage) + tests.RemoveImage(logger, tests.TestImageMultiPlatform) // pull with platform platform := "linux/arm64" - if err := podman.PullImage(tests.TestImage, &platform); err != nil { + if err := podman.PullImage(tests.TestImageMultiPlatform, &platform); err != nil { assert.Nil(t, err) } - imageArch = tests.InspectImage(logger, tests.TestImage) + imageArch = tests.InspectImage(logger, tests.TestImageMultiPlatform) assert.Equals(t, platform, fmt.Sprintf("%s/%s", imageArch.Os, imageArch.Architecture)) - tests.RemoveImage(logger, tests.TestImage) + tests.RemoveImage(logger, tests.TestImageMultiPlatform) // pull not existing image without baseUrl (cli interactively asks for the image repository) if err := podman.PullImage(tests.TestNotExistingImageNoBaseURL, nil); err != nil { diff --git a/tests/common.go b/tests/common.go index fba4cac..e897ef1 100644 --- a/tests/common.go +++ b/tests/common.go @@ -13,6 +13,9 @@ import ( "time" ) +// TestImage repository manifest must include an image built for +// platform linux/arm64 +const TestImageMultiPlatform = "quay.io/arcalot/arcaflow-plugin-baseimage-python-osbase:latest" const TestImage = "quay.io/podman/hello:latest" const TestImageNoTag = "quay.io/podman/hello" const TestImageNoBaseURL = "hello:latest"