feat: migrate from libcompose to compose-go (#1547)

* feat: migrate from libcompose to compose-go

libcompose has been deprecated since summer 2021 in favor of https://github.com/compose-spec/compose-go.
Kompose should now be able to load all versions of compose.

* chore: replace golint with staticcheck

golint has been deprecated. Recommended replacement is staticcheck.
This commit is contained in:
Lctrs 2023-01-12 21:17:22 +01:00 committed by GitHub
parent 7304bb6013
commit 2ad5745d58
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
57 changed files with 1407 additions and 1867 deletions

View File

@ -17,19 +17,20 @@ jobs:
steps:
- name: Set up Go 1.x
uses: actions/setup-go@v2
uses: actions/setup-go@v3
with:
go-version: ^1.16
go-version: ^1.19
id: go
- name: Check out code into the Go module directory
uses: actions/checkout@v2
uses: actions/checkout@v3
- name: Build
run: make bin
- name: Upload a Build Artifact
uses: actions/upload-artifact@v2.1.4
with:
uses: actions/upload-artifact@v3
with:
name: "kompose"
path: "kompose"

View File

@ -1,21 +0,0 @@
name: golangci-lint
on:
pull_request:
jobs:
golangci:
strategy:
matrix:
go: [1.16, 1.17]
name: lint
runs-on: ubuntu-latest
steps:
- uses: actions/setup-go@v3
with:
go-version: ${{ matrix.go }}
- uses: actions/checkout@v2
- name: golangci-lint
uses: golangci/golangci-lint-action@v3
with:
# Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version.
version: v1.29
args: --timeout 5m

26
.github/workflows/lint.yml vendored Normal file
View File

@ -0,0 +1,26 @@
name: lint
on:
pull_request:
jobs:
lint:
strategy:
matrix:
go: [1.18, 1.19]
name: lint
runs-on: ubuntu-latest
steps:
- name: "Checkout"
uses: actions/checkout@v3
- name: "Install golang"
uses: actions/setup-go@v3
with:
go-version: ${{ matrix.go }}
- name: "Run go vet"
run: "go vet ./pkg/..."
- name: "Run staticcheck"
uses: dominikh/staticcheck-action@v1
with:
cache-key: "${{ matrix.go }}"
install-go: false
version: "latest"
working-directory: "pkg"

View File

@ -10,14 +10,14 @@ env:
jobs:
test:
name: Test with ${{ matrix.go }} and CROSS_COMPILE=${{ matrix.cross_compile }}
runs-on: ubuntu-18.04
runs-on: ubuntu-latest
strategy:
matrix:
go: [1.16, 1.17]
go: [1.18, 1.19]
cross_compile: [true, false]
steps:
- uses: actions/checkout@v2
- uses: actions/setup-go@v2
- uses: actions/checkout@v3
- uses: actions/setup-go@v3
with:
go-version: ${{ matrix.go }}
- name: Run tests
@ -27,13 +27,13 @@ jobs:
run: make cross
docs:
name: Build docs and Coveralls integration
runs-on: ubuntu-18.04
runs-on: ubuntu-latest
needs: test
steps:
- uses: actions/checkout@v2
- uses: actions/setup-go@v2
- uses: actions/checkout@v3
- uses: actions/setup-go@v3
with:
go-version: 1.16
go-version: 1.19
- name: Create .coverprofile for each targeted directory by re:running tests
run: make test
- name: Collect all .coverprofile files and save it to one file gover.coverprofile

View File

@ -12,7 +12,7 @@ linters:
# - errcheck
# - goconst
- goimports
# - golint
# - staticcheck
- goprintffuncname
# - gosimple
- govet

View File

@ -91,15 +91,15 @@ gen-cmd:
# run all validation tests
.PHONY: validate
validate: gofmt vet lint
validate: gofmt vet staticcheck
.PHONY: vet
vet:
go vet ./pkg/...
.PHONY: lint
lint:
golint ./pkg/...
.PHONY: staticcheck
staticcheck:
staticcheck ./pkg/...
.PHONY: gofmt
gofmt:
@ -114,7 +114,7 @@ test: bin test-dep validate test-unit-cover install test-cmd
test-dep:
go install github.com/mattn/goveralls@latest
go install github.com/modocache/gover@latest
go install golang.org/x/lint/golint@latest
go install honnef.co/go/tools/cmd/staticcheck@latest
go install github.com/mitchellh/gox@latest

View File

@ -63,7 +63,7 @@ func init() {
}
/*
Fish shell auto-completion support
Fish shell auto-completion support
*/
func runCompletionFish(out io.Writer, kompose *cobra.Command) error {
kompose.GenFishCompletion(out, true)
@ -79,9 +79,9 @@ complete -c kompose -n "__fish_seen_subcommand_from completion" -a "bash zsh fis
}
/*
This is copied from
https://github.com/kubernetes/kubernetes/blob/ea18d5c32ee7c320fe96dda6b0c757476908e696/pkg/kubectl/cmd/completion.go
in order to generate ZSH completion support.
This is copied from
https://github.com/kubernetes/kubernetes/blob/ea18d5c32ee7c320fe96dda6b0c757476908e696/pkg/kubectl/cmd/completion.go
in order to generate ZSH completion support.
*/
func runCompletionZsh(out io.Writer, kompose *cobra.Command) error {
zshInitialization := `

View File

@ -14,26 +14,10 @@ redirect_from:
This document outlines all possible conversion details regarding `docker-compose.yaml` values to Kubernetes / OpenShift artifacts.
## Version Table
## Version Support
| Supported | Compose Version | Docker Engine Version |
|------------|-----------------|-----------------------|
| N | 3.8 | 19.03.0+ |
| N | 3.7 | 18.06.0+ |
| N | 3.6 | 18.02.0+ |
| N | 3.5 | 17.12.0+ |
| N | 3.4 | 17.09.0+ |
| Y | 3.3 | 17.06.0+ |
| Y | 3.2 | 17.04.0+ |
| Y | 3.1 | 1.13.1+ |
| Y | 3.0 | 1.13.0+ |
| Y | 2.4 | 17.12.0+ |
| Y | 2.3 | 17.06.0+ |
| Y | 2.2 | 1.13.0+ |
| Y | 2.1 | 1.12.0+ |
| Y | 2.0 | 1.10.0+ |
**Note:** We don't support anything 3.4 and above at the moment. It is reccomended to specify `version: "3.3"` in your `docker-compose.yaml` and converting. We use a library called [libcompose](https://github.com/docker/libcompose) that supports up to version `3.3`. If you are interested in adding additional support, please open up a PR!
Under the hood, we're using [compose-go](https://github.com/compose-spec/compose-go), the reference library for parsing Compose files. We should be able to load all versions of Compose files.
We're doing our best to keep it up to date as soon as possible in our releases to be compatible with the latest features defined in the [Compose specification](https://github.com/compose-spec/compose-spec/blob/master/spec.md). If you absolutely need a feature we don't support yet, please open a PR!
## Conversion Table

13
go.mod
View File

@ -4,8 +4,6 @@ go 1.13
replace github.com/Sirupsen/logrus => github.com/sirupsen/logrus v1.8.1
replace github.com/docker/libcompose => github.com/docker/libcompose v0.4.1-0.20190808084053-143e0f3f1ab9
replace github.com/docker/cli => github.com/docker/cli v20.10.16+incompatible
replace github.com/xeipuuv/gojsonschema => github.com/xeipuuv/gojsonschema v1.2.1-0.20201027075954-b076d39a02e5
@ -31,28 +29,25 @@ replace github.com/emicklei/go-restful => github.com/emicklei/go-restful v2.16.0
replace golang.org/x/crypto => golang.org/x/crypto v0.0.0-20220826181053-bd7e27e6170d
require (
github.com/compose-spec/compose-go v1.8.2
github.com/containerd/containerd v1.6.4 // indirect
github.com/deckarep/golang-set v1.7.1
github.com/docker/cli v0.0.0-20191017083524-a8ff7f821017
github.com/docker/go-connections v0.4.0
github.com/docker/libcompose v0.4.0
github.com/fatih/structs v1.1.0
github.com/fsouza/go-dockerclient v1.6.6
github.com/google/go-cmp v0.5.8
github.com/google/go-cmp v0.5.9
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510
github.com/joho/godotenv v1.3.0
github.com/novln/docker-parser v1.0.0
github.com/openshift/api v0.0.0-20200803131051-87466835fcc0
github.com/pkg/errors v0.9.1
github.com/sirupsen/logrus v1.8.1
github.com/sirupsen/logrus v1.9.0
github.com/spf13/cast v1.3.1
github.com/spf13/cobra v1.1.3
github.com/spf13/viper v1.7.1
golang.org/x/net v0.0.0-20220906165146-f3363e06e74c // indirect
golang.org/x/text v0.3.8 // indirect
golang.org/x/tools v0.1.12
gopkg.in/yaml.v2 v2.4.0
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
gopkg.in/yaml.v3 v3.0.1
k8s.io/api v0.22.5
k8s.io/apimachinery v0.22.5
)

88
go.sum
View File

@ -35,27 +35,29 @@ cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RX
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/AdaLogics/go-fuzz-headers v0.0.0-20210715213245-6c3934b029d8/go.mod h1:CzsSbkDixRphAF5hS6wbMKq0eI6ccJRb7/A0M6JBnwg=
github.com/Azure/azure-sdk-for-go v56.3.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
github.com/Azure/go-ansiterm v0.0.0-20210608223527-2377c96fe795/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8=
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
github.com/Azure/go-autorest/autorest v0.11.18/go.mod h1:dSiJPy22c3u0OtOKDNttNgqpNFY/GeWa7GH/Pz56QRA=
github.com/Azure/go-autorest/autorest v0.11.24/go.mod h1:G6kyRlFnTuSbEYkQGawPfsCswgme4iYf6rfSKUDzbCc=
github.com/Azure/go-autorest/autorest/adal v0.9.13/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M=
github.com/Azure/go-autorest/autorest/adal v0.9.18/go.mod h1:XVVeme+LZwABT8K5Lc3hA4nAe8LDBVle26gTrguhhPQ=
github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74=
github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k=
github.com/Azure/go-autorest/autorest/to v0.4.0/go.mod h1:fE8iZBn7LQR7zH/9XU2NcPR4o9jEImooCeWJcYV/zLE=
github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8=
github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/Microsoft/go-winio v0.3.8/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA=
github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw=
github.com/Microsoft/go-winio v0.4.15-0.20200113171025-3fe6c5262873/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw=
github.com/Microsoft/go-winio v0.4.17/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
github.com/Microsoft/go-winio v0.5.1 h1:aPJp2QD7OOrhO5tQXqQoGSJc+DjDtWTGLOmNyAm6FgY=
github.com/Microsoft/go-winio v0.5.1/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg=
github.com/Microsoft/hcsshim v0.8.9/go.mod h1:5692vkUqntj1idxauYlpoINNKeqCiG6Sg38RRsjT5y8=
github.com/Microsoft/hcsshim v0.8.20/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwTOcER2fw4I4=
github.com/Microsoft/hcsshim v0.9.2/go.mod h1:7pLA8lDk46WKDWlVsENo92gC0XFa8rbKfyFRBqxEbCc=
@ -68,6 +70,7 @@ github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbt
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
@ -80,14 +83,20 @@ github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
github.com/aws/aws-sdk-go v1.43.16/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo=
github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA=
github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
github.com/bshuster-repo/logrus-logstash-hook v1.0.0/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk=
github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0=
github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8=
github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50=
github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE=
github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
github.com/cenkalti/backoff/v4 v4.1.2/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
@ -113,6 +122,8 @@ github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWH
github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo=
github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoCr5oaCLELYA=
github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI=
github.com/compose-spec/compose-go v1.8.2 h1:sUQvDxnPgpcOyoxC/lz7mFTrTlHeZ6LWyuASYetkOqw=
github.com/compose-spec/compose-go v1.8.2/go.mod h1:Tb5Ae2PsYN3GTqYqzl2IRbTPiJtPZZjMw8UKUvmehFk=
github.com/containerd/aufs v1.0.0/go.mod h1:kL5kd6KM5TzQjR79jljyi4olc1Vrx6XBlcyj3gNv2PU=
github.com/containerd/btrfs v1.0.0/go.mod h1:zMcX3qkXTAi9GI50+0HOeuV8LU2ryCE/V2vG/ZBiTss=
github.com/containerd/cgroups v0.0.0-20190919134610-bf292b21730f/go.mod h1:OApqhQ4XNSNC13gXIwDjhOQxjWa/NxkwZXJ1EvqT0ko=
@ -174,24 +185,24 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/deckarep/golang-set v1.7.1 h1:SCQV0S6gTtp6itiFrTqI+pfmJ4LN85S1YzhDf9rTHJQ=
github.com/deckarep/golang-set v1.7.1/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ=
github.com/denverdino/aliyungo v0.0.0-20190125010748-a747050bb1ba/go.mod h1:dV8lFg6daOBZbT6/BDGIz6Y3WFGn8juu6G+CQ6LHtl0=
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
github.com/docker/cli v20.10.16+incompatible h1:aLQ8XowgKpR3/IysPj8qZQJBVQ+Qws61icFuZl6iKYs=
github.com/distribution/distribution/v3 v3.0.0-20221103125252-ebfa2a0ac0a9 h1:doprs/RuXCuN864IfxC3h2qocrt158wGv3A5mcqSZQw=
github.com/distribution/distribution/v3 v3.0.0-20221103125252-ebfa2a0ac0a9/go.mod h1:6rIc5NMSjXjjnwzWWy3HAm9gDBu+X7aCzL8VrHIKgxM=
github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E=
github.com/docker/cli v20.10.16+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/distribution v2.8.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/docker v20.10.0-beta1.0.20201030232932-c2cc352355d4+incompatible h1:7Wcl0zstnDmC7woif4M/PWN8kql0+m1h38WhF/raC4E=
github.com/docker/docker v20.10.0-beta1.0.20201030232932-c2cc352355d4+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y=
github.com/docker/go-connections v0.3.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
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-events v0.0.0-20190806004212-e31b211e4f1c/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA=
github.com/docker/go-metrics v0.0.0-20181218153428-b84716841b82/go.mod h1:/u0gXw0Gay3ceNrsHubL3BtdOL2fHf93USgMTe0W5dI=
github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw=
github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw=
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/docker/libcompose v0.4.1-0.20190808084053-143e0f3f1ab9 h1:Z+aRYtQXR6iFSAnoaAq/dUTcZvL1ph8uWlsrmfIP8Bs=
github.com/docker/libcompose v0.4.1-0.20190808084053-143e0f3f1ab9/go.mod h1:YZ/h8H7gZ7/SOoviPEvSYgHomvbB82iyHvGXLVTNFwQ=
github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE=
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/docker/libtrust v0.0.0-20150114040149-fa567046d9b1/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE=
github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
@ -212,8 +223,6 @@ github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5Kwzbycv
github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BHsljHzVlRcyQhjrss6TZTdY2VfCqZPbv5k3iBFa2ZQ=
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k=
@ -263,6 +272,7 @@ github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6
github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
github.com/gogo/googleapis v1.4.0/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
@ -270,6 +280,8 @@ github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXP
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
@ -303,6 +315,7 @@ github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaS
github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM=
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/gomodule/redigo v1.8.2/go.mod h1:P9dn9mFrCBvWhGE1wpxx6fgq7BAeLBk+UUUzlpkBYO0=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA=
@ -318,8 +331,8 @@ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
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/google/go-containerregistry v0.5.1/go.mod h1:Ct15B4yir3PLOP5jsy0GNeYVaIZs/MK/Jz5any1wFW0=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
@ -348,8 +361,7 @@ github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2c
github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97DwqyJO1AENw9kA=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
github.com/gorilla/mux v0.0.0-20160317213430-0eeaf8392f5b/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q=
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
@ -377,6 +389,7 @@ github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/b
github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
@ -387,11 +400,14 @@ github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpO
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU=
github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk=
github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg=
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/intel/goresctrl v0.2.0/go.mod h1:+CZdzouYFn5EsxgqAQTEzMfwKwuc0fVdMrT9FCCAVRQ=
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
github.com/joefitzgerald/rainbow-reporter v0.1.0/go.mod h1:481CNgqmVHQZzdIbN52CupLJyoVwB10FQ/IQlF1pdL8=
github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc=
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
@ -424,7 +440,6 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pty v0.0.0-20150511174710-5cf931ef8f76/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
@ -442,6 +457,7 @@ github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJ
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-shellwords v1.0.6/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o=
github.com/mattn/go-shellwords v1.0.12 h1:M2zGm7EW6UQJvDeQxo4T51eKPurbeFbe8WtebGE2xrk=
github.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
@ -456,8 +472,10 @@ github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eI
github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A=
github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc=
github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c=
github.com/moby/sys/mount v0.1.0 h1:Ytx78EatgFKtrqZ0BvJ0UtJE472ZvawVmil6pIfuCCU=
@ -477,7 +495,6 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ=
@ -486,6 +503,7 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8m
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
github.com/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM=
github.com/networkplumbing/go-nft v0.2.0/go.mod h1:HnnM+tYvlGAsMU7yoYwXEVLLiDW9gdMmb5HoGcwpuQs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/novln/docker-parser v1.0.0 h1:PjEBd9QnKixcWczNGyEdfUrP6GR0YUilAqG7Wksg3uc=
@ -512,12 +530,10 @@ github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoT
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/onsi/gomega v1.15.0/go.mod h1:cIuvLEne0aoVhAgh/O6ac0Op8WWw9H6eYCriF+tEHG0=
github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/opencontainers/image-spec v0.0.0-20170515205857-f03dbe35d449/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799 h1:rc3tiVYb5z54aKaDfakKn0dDjIyPpTtszkjuMzyt7ec=
@ -555,6 +571,7 @@ github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQ
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
github.com/prometheus/client_golang v1.11.1/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
@ -566,6 +583,7 @@ github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=
github.com/prometheus/common v0.30.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=
github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=
github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
@ -593,8 +611,9 @@ github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMB
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
@ -628,13 +647,18 @@ github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
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.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
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/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
@ -644,7 +668,6 @@ github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1
github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c/go.mod h1:hzIxponao9Kjc7aWznkXaL4U4TWaDSs8zcsY4Ka08nM=
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
github.com/urfave/cli v1.21.0/go.mod h1:lxDj6qX9Q6lWQxIrbrT0nwecwUtRnhVZAJjJZrVUZZQ=
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE=
@ -667,6 +690,9 @@ github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs=
github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA=
github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg=
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4=
go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs=
@ -796,6 +822,7 @@ golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qx
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211209124913-491a49abca63/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.0.0-20220906165146-f3363e06e74c h1:yKufUcDwucU5urd+50/Opbt4AYpqthk7wHpHok8f1lo=
golang.org/x/net v0.0.0-20220906165146-f3363e06e74c/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
@ -817,8 +844,9 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 h1:uVc8UZUe6tr40fFVnUP5Oj+veunVezqYl9z7DYw9xzw=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad h1:ntjMns5wyP/fN65tdBD4g8J5w8n015+iIIs9rtjXkY0=
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
@ -899,6 +927,7 @@ golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc
golang.org/x/tools v0.0.0-20200916195026-c9a70fc28ce3/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU=
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
@ -933,6 +962,7 @@ google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/cloud v0.0.0-20151119220103-975617b05ea8/go.mod h1:0H1ncTHf11KCFhTc/+EFRbzSCOZx+VUbRMk55Yv5MYk=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
@ -974,7 +1004,6 @@ google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZi
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
@ -1039,13 +1068,16 @@ gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
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 v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk=
gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0=
gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8=
gotest.tools/v3 v3.4.0 h1:ZazjZUfuVeZGLAmlKKuyv3IKP5orXcwtOwDQH6YVr6o=
gotest.tools/v3 v3.4.0/go.mod h1:CtbdzLSsqVhDgMtKsx03ird5YTGB3ar27v0u/yKBW5g=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=

View File

@ -21,8 +21,7 @@ import (
"strconv"
"time"
dockerCliTypes "github.com/docker/cli/cli/compose/types"
"github.com/docker/libcompose/yaml"
"github.com/compose-spec/compose-go/types"
deployapi "github.com/openshift/api/apps/v1"
"github.com/pkg/errors"
"github.com/spf13/cast"
@ -38,7 +37,7 @@ type KomposeObject struct {
// as they can have different names. For example environment variables are called environment in compose but Env in bundle.
LoadedFrom string
Secrets map[string]dockerCliTypes.SecretConfig
Secrets types.Secrets
}
// ConvertOptions holds all options that controls transformation process
@ -99,64 +98,64 @@ type ServiceConfigGroup []ServiceConfig
type ServiceConfig struct {
Name string
ContainerName string
Image string `compose:"image"`
Environment []EnvVar `compose:"environment"`
EnvFile []string `compose:"env_file"`
Port []Ports `compose:"ports"`
Command []string `compose:"command"`
WorkingDir string `compose:""`
DomainName string `compose:"domainname"`
HostName string `compose:"hostname"`
Args []string `compose:"args"`
VolList []string `compose:"volumes"`
Network []string `compose:"network"`
Labels map[string]string `compose:"labels"`
Annotations map[string]string `compose:""`
CPUSet string `compose:"cpuset"`
CPUShares int64 `compose:"cpu_shares"`
CPUQuota int64 `compose:"cpu_quota"`
CPULimit int64 `compose:""`
CPUReservation int64 `compose:""`
CapAdd []string `compose:"cap_add"`
CapDrop []string `compose:"cap_drop"`
Expose []string `compose:"expose"`
ImagePullPolicy string `compose:"kompose.image-pull-policy"`
Pid string `compose:"pid"`
Privileged bool `compose:"privileged"`
Restart string `compose:"restart"`
User string `compose:"user"`
VolumesFrom []string `compose:"volumes_from"`
ServiceType string `compose:"kompose.service.type"`
NodePortPort int32 `compose:"kompose.service.nodeport.port"`
StopGracePeriod string `compose:"stop_grace_period"`
Build string `compose:"build"`
BuildArgs map[string]*string `compose:"build-args"`
ExposeService string `compose:"kompose.service.expose"`
ExposeServicePath string `compose:"kompose.service.expose.path"`
BuildLabels map[string]string `compose:"build-labels"`
ExposeServiceTLS string `compose:"kompose.service.expose.tls-secret"`
ExposeServiceIngressClassName string `compose:"kompose.service.expose.ingress-class-name"`
ImagePullSecret string `compose:"kompose.image-pull-secret"`
Stdin bool `compose:"stdin_open"`
Tty bool `compose:"tty"`
MemLimit yaml.MemStringorInt `compose:"mem_limit"`
MemReservation yaml.MemStringorInt `compose:""`
DeployMode string `compose:""`
Image string `compose:"image"`
Environment []EnvVar `compose:"environment"`
EnvFile []string `compose:"env_file"`
Port []Ports `compose:"ports"`
Command []string `compose:"command"`
WorkingDir string `compose:""`
DomainName string `compose:"domainname"`
HostName string `compose:"hostname"`
Args []string `compose:"args"`
VolList []string `compose:"volumes"`
Network []string `compose:"network"`
Labels map[string]string `compose:"labels"`
Annotations map[string]string `compose:""`
CPUSet string `compose:"cpuset"`
CPUShares int64 `compose:"cpu_shares"`
CPUQuota int64 `compose:"cpu_quota"`
CPULimit int64 `compose:""`
CPUReservation int64 `compose:""`
CapAdd []string `compose:"cap_add"`
CapDrop []string `compose:"cap_drop"`
Expose []string `compose:"expose"`
ImagePullPolicy string `compose:"kompose.image-pull-policy"`
Pid string `compose:"pid"`
Privileged bool `compose:"privileged"`
Restart string `compose:"restart"`
User string `compose:"user"`
VolumesFrom []string `compose:"volumes_from"`
ServiceType string `compose:"kompose.service.type"`
NodePortPort int32 `compose:"kompose.service.nodeport.port"`
StopGracePeriod string `compose:"stop_grace_period"`
Build string `compose:"build"`
BuildArgs map[string]*string `compose:"build-args"`
ExposeService string `compose:"kompose.service.expose"`
ExposeServicePath string `compose:"kompose.service.expose.path"`
BuildLabels map[string]string `compose:"build-labels"`
ExposeServiceTLS string `compose:"kompose.service.expose.tls-secret"`
ExposeServiceIngressClassName string `compose:"kompose.service.expose.ingress-class-name"`
ImagePullSecret string `compose:"kompose.image-pull-secret"`
Stdin bool `compose:"stdin_open"`
Tty bool `compose:"tty"`
MemLimit types.UnitBytes `compose:"mem_limit"`
MemReservation types.UnitBytes `compose:""`
DeployMode string `compose:""`
// DeployLabels mapping to kubernetes labels
DeployLabels map[string]string `compose:""`
DeployUpdateConfig dockerCliTypes.UpdateConfig `compose:""`
TmpFs []string `compose:"tmpfs"`
Dockerfile string `compose:"dockerfile"`
Replicas int `compose:"replicas"`
GroupAdd []int64 `compose:"group_add"`
Volumes []Volumes `compose:""`
Secrets []dockerCliTypes.ServiceSecretConfig
DeployLabels map[string]string `compose:""`
DeployUpdateConfig types.UpdateConfig `compose:""`
TmpFs []string `compose:"tmpfs"`
Dockerfile string `compose:"dockerfile"`
Replicas int `compose:"replicas"`
GroupAdd []int64 `compose:"group_add"`
Volumes []Volumes `compose:""`
Secrets []types.ServiceSecretConfig
HealthChecks HealthChecks `compose:""`
Placement Placement `compose:""`
//This is for long LONG SYNTAX link(https://docs.docker.com/compose/compose-file/#long-syntax)
Configs []dockerCliTypes.ServiceConfigObjConfig `compose:""`
Configs []types.ServiceConfigObjConfig `compose:""`
//This is for SHORT SYNTAX link(https://docs.docker.com/compose/compose-file/#configs)
ConfigsMetaData map[string]dockerCliTypes.ConfigObjConfig `compose:""`
ConfigsMetaData types.Configs `compose:""`
WithKomposeAnnotation bool `compose:""`
InGroup bool

View File

@ -18,30 +18,36 @@ package compose
import (
"fmt"
"os"
"reflect"
"strconv"
"strings"
"time"
"gopkg.in/yaml.v2"
"github.com/docker/libcompose/project"
"github.com/compose-spec/compose-go/cli"
"github.com/compose-spec/compose-go/types"
"github.com/fatih/structs"
"github.com/google/shlex"
"github.com/kubernetes/kompose/pkg/kobject"
"github.com/kubernetes/kompose/pkg/transformer"
"github.com/pkg/errors"
log "github.com/sirupsen/logrus"
"github.com/spf13/cast"
api "k8s.io/api/core/v1"
)
//StdinData is data bytes read from stdin
// StdinData is data bytes read from stdin
var StdinData []byte
// Compose is docker compose file loader, implements Loader interface
type Compose struct {
}
// checkUnsupportedKey checks if libcompose project contains
// checkUnsupportedKey checks if compose-go project contains
// keys that are not supported by this loader.
// list of all unsupported keys are stored in unsupportedKey variable
// returns list of unsupported YAML keys from docker-compose
func checkUnsupportedKey(composeProject *project.Project) []string {
func checkUnsupportedKey(composeProject *types.Project) []string {
// list of all unsupported keys for this loader
// this is map to make searching for keys easier
// to make sure that unsupported key is not going to be reported twice
@ -79,18 +85,18 @@ func checkUnsupportedKey(composeProject *project.Project) []string {
// Root level keys are not yet supported except Network
// Check to see if the default network is available and length is only equal to one.
if _, ok := composeProject.NetworkConfigs["default"]; ok && len(composeProject.NetworkConfigs) == 1 {
if _, ok := composeProject.Networks["default"]; ok && len(composeProject.Networks) == 1 {
log.Debug("Default network found")
}
// Root level volumes are not yet supported
if len(composeProject.VolumeConfigs) > 0 {
if len(composeProject.Volumes) > 0 {
keysFound = append(keysFound, "root level volumes")
}
for _, serviceConfig := range composeProject.ServiceConfigs.All() {
for _, serviceConfig := range composeProject.AllServices() {
// this reflection is used in check for empty arrays
val := reflect.ValueOf(serviceConfig).Elem()
val := reflect.ValueOf(serviceConfig)
s := structs.New(serviceConfig)
for _, f := range s.Fields() {
@ -109,7 +115,7 @@ func checkUnsupportedKey(composeProject *project.Project) []string {
yamlTagName := strings.Split(f.Tag("yaml"), ",")[0]
if f.Name() == "Networks" {
// networks always contains one default element, even it isn't declared in compose v2.
if len(serviceConfig.Networks.Networks) == 1 && serviceConfig.Networks.Networks[0].Name == "default" {
if len(serviceConfig.Networks) == 1 && serviceConfig.NetworksByPriority()[0] == "default" {
// this is empty Network definition, skip it
continue
}
@ -144,61 +150,733 @@ func checkUnsupportedKey(composeProject *project.Project) []string {
// LoadFile loads a compose file into KomposeObject
func (c *Compose) LoadFile(files []string) (kobject.KomposeObject, error) {
// Load the json / yaml file in order to get the version value
var version string
for _, file := range files {
composeVersion, err := getVersionFromFile(file)
if err != nil {
return kobject.KomposeObject{}, errors.Wrap(err, "Unable to load yaml/json file for version parsing")
}
// Check that the previous file loaded matches.
if len(files) > 0 && version != "" && version != composeVersion {
return kobject.KomposeObject{}, errors.New("All Docker Compose files must be of the same version")
}
version = composeVersion
// Gather the working directory
workingDir, err := getComposeFileDir(files)
if err != nil {
return kobject.KomposeObject{}, err
}
log.Debugf("Docker Compose version: %s", version)
projectOptions, err := cli.NewProjectOptions(files, cli.WithOsEnv, cli.WithWorkingDirectory(workingDir), cli.WithInterpolation(false))
if err != nil {
return kobject.KomposeObject{}, errors.Wrap(err, "Unable to create compose options")
}
// Convert based on version
switch version {
// Use libcompose for 1 or 2
// If blank, it's assumed it's 1 or 2
case "", "1", "1.0", "2", "2.0", "2.1", "2.2":
komposeObject, err := parseV1V2(files)
if err != nil {
return kobject.KomposeObject{}, err
project, err := cli.ProjectFromOptions(projectOptions)
if err != nil {
return kobject.KomposeObject{}, errors.Wrap(err, "Unable to load files")
}
komposeObject, err := dockerComposeToKomposeMapping(project)
if err != nil {
return kobject.KomposeObject{}, err
}
return komposeObject, nil
}
func loadPlacement(placement types.Placement) kobject.Placement {
komposePlacement := kobject.Placement{
PositiveConstraints: make(map[string]string),
NegativeConstraints: make(map[string]string),
Preferences: make([]string, 0, len(placement.Preferences)),
}
// Convert constraints
equal, notEqual := " == ", " != "
for _, j := range placement.Constraints {
operator := equal
if strings.Contains(j, notEqual) {
operator = notEqual
}
return komposeObject, nil
// Use docker/cli for 3
case "3", "3.0", "3.1", "3.2", "3.3", "3.4", "3.5", "3.6", "3.7", "3.8":
komposeObject, err := parseV3(files)
if err != nil {
return kobject.KomposeObject{}, err
p := strings.Split(j, operator)
if len(p) < 2 {
log.Warnf("Failed to parse placement constraints %s, the correct format is 'label == xxx'", j)
continue
}
return komposeObject, nil
key, err := convertDockerLabel(p[0])
if err != nil {
log.Warn("Ignore placement constraints: ", err.Error())
continue
}
if operator == equal {
komposePlacement.PositiveConstraints[key] = p[1]
} else if operator == notEqual {
komposePlacement.NegativeConstraints[key] = p[1]
}
}
// Convert preferences
for _, p := range placement.Preferences {
// Spread is the only supported strategy currently
label, err := convertDockerLabel(p.Spread)
if err != nil {
log.Warn("Ignore placement preferences: ", err.Error())
continue
}
komposePlacement.Preferences = append(komposePlacement.Preferences, label)
}
return komposePlacement
}
// Convert docker label to k8s label
func convertDockerLabel(dockerLabel string) (string, error) {
switch dockerLabel {
case "node.hostname":
return "kubernetes.io/hostname", nil
case "engine.labels.operatingsystem":
return "kubernetes.io/os", nil
default:
return kobject.KomposeObject{}, fmt.Errorf("version %s of Docker Compose is not supported. Please use version 1, 2 or 3", version)
if strings.HasPrefix(dockerLabel, "node.labels.") {
return strings.TrimPrefix(dockerLabel, "node.labels."), nil
}
}
errMsg := fmt.Sprint(dockerLabel, " is not supported, only 'node.hostname', 'engine.labels.operatingsystem' and 'node.labels.xxx' (ex: node.labels.something == anything) is supported")
return "", errors.New(errMsg)
}
// Convert the Docker Compose volumes to []string (the old way)
// TODO: Check to see if it's a "bind" or "volume". Ignore for now.
// TODO: Refactor it similar to loadPorts
// See: https://docs.docker.com/compose/compose-file/#long-syntax-3
func loadVolumes(volumes []types.ServiceVolumeConfig) []string {
var volArray []string
for _, vol := range volumes {
// There will *always* be Source when parsing
v := vol.Source
if vol.Target != "" {
v = v + ":" + vol.Target
}
if vol.ReadOnly {
v = v + ":ro"
}
volArray = append(volArray, v)
}
return volArray
}
// Convert Docker Compose ports to kobject.Ports
// expose ports will be treated as TCP ports
func loadPorts(ports []types.ServicePortConfig, expose []string) []kobject.Ports {
komposePorts := []kobject.Ports{}
exist := map[string]bool{}
for _, port := range ports {
// Convert to a kobject struct with ports
komposePorts = append(komposePorts, kobject.Ports{
HostPort: cast.ToInt32(port.Published),
ContainerPort: int32(port.Target),
HostIP: port.HostIP,
Protocol: strings.ToUpper(port.Protocol),
})
exist[cast.ToString(port.Target)+port.Protocol] = true
}
for _, port := range expose {
portValue := port
protocol := string(api.ProtocolTCP)
if strings.Contains(portValue, "/") {
splits := strings.Split(port, "/")
portValue = splits[0]
protocol = splits[1]
}
if exist[portValue+protocol] {
continue
}
komposePorts = append(komposePorts, kobject.Ports{
HostPort: cast.ToInt32(portValue),
ContainerPort: cast.ToInt32(portValue),
HostIP: "",
Protocol: strings.ToUpper(protocol),
})
}
return komposePorts
}
/*
Convert the HealthCheckConfig as designed by Docker to
a Kubernetes-compatible format.
*/
func parseHealthCheckReadiness(labels types.Labels) (kobject.HealthCheck, error) {
var test []string
var httpPath string
var httpPort, tcpPort, timeout, interval, retries, startPeriod int32
var disable bool
for key, value := range labels {
switch key {
case HealthCheckReadinessDisable:
disable = cast.ToBool(value)
case HealthCheckReadinessTest:
if len(value) > 0 {
test, _ = shlex.Split(value)
}
case HealthCheckReadinessHTTPGetPath:
httpPath = value
case HealthCheckReadinessHTTPGetPort:
httpPort = cast.ToInt32(value)
case HealthCheckReadinessTCPPort:
tcpPort = cast.ToInt32(value)
case HealthCheckReadinessInterval:
parse, err := time.ParseDuration(value)
if err != nil {
return kobject.HealthCheck{}, errors.Wrap(err, "unable to parse health check interval variable")
}
interval = int32(parse.Seconds())
case HealthCheckReadinessTimeout:
parse, err := time.ParseDuration(value)
if err != nil {
return kobject.HealthCheck{}, errors.Wrap(err, "unable to parse health check timeout variable")
}
timeout = int32(parse.Seconds())
case HealthCheckReadinessRetries:
retries = cast.ToInt32(value)
case HealthCheckReadinessStartPeriod:
parse, err := time.ParseDuration(value)
if err != nil {
return kobject.HealthCheck{}, errors.Wrap(err, "unable to parse health check startPeriod variable")
}
startPeriod = int32(parse.Seconds())
}
}
if len(test) > 0 {
if test[0] == "NONE" {
disable = true
test = test[1:]
}
// Due to docker/cli adding "CMD-SHELL" to the struct, we remove the first element of composeHealthCheck.Test
if test[0] == "CMD" || test[0] == "CMD-SHELL" {
test = test[1:]
}
}
return kobject.HealthCheck{
Test: test,
HTTPPath: httpPath,
HTTPPort: httpPort,
TCPPort: tcpPort,
Timeout: timeout,
Interval: interval,
Retries: retries,
StartPeriod: startPeriod,
Disable: disable,
}, nil
}
/*
Convert the HealthCheckConfig as designed by Docker to
a Kubernetes-compatible format.
*/
func parseHealthCheck(composeHealthCheck types.HealthCheckConfig, labels types.Labels) (kobject.HealthCheck, error) {
var httpPort, tcpPort, timeout, interval, retries, startPeriod int32
var test []string
var httpPath string
// Here we convert the timeout from 1h30s (example) to 36030 seconds.
if composeHealthCheck.Timeout != nil {
parse, err := time.ParseDuration(composeHealthCheck.Timeout.String())
if err != nil {
return kobject.HealthCheck{}, errors.Wrap(err, "unable to parse health check timeout variable")
}
timeout = int32(parse.Seconds())
}
if composeHealthCheck.Interval != nil {
parse, err := time.ParseDuration(composeHealthCheck.Interval.String())
if err != nil {
return kobject.HealthCheck{}, errors.Wrap(err, "unable to parse health check interval variable")
}
interval = int32(parse.Seconds())
}
if composeHealthCheck.Retries != nil {
retries = int32(*composeHealthCheck.Retries)
}
if composeHealthCheck.StartPeriod != nil {
parse, err := time.ParseDuration(composeHealthCheck.StartPeriod.String())
if err != nil {
return kobject.HealthCheck{}, errors.Wrap(err, "unable to parse health check startPeriod variable")
}
startPeriod = int32(parse.Seconds())
}
if composeHealthCheck.Test != nil {
test = composeHealthCheck.Test[1:]
}
for key, value := range labels {
switch key {
case HealthCheckLivenessHTTPGetPath:
httpPath = value
case HealthCheckLivenessHTTPGetPort:
httpPort = cast.ToInt32(value)
case HealthCheckLivenessTCPPort:
tcpPort = cast.ToInt32(value)
}
}
// Due to docker/cli adding "CMD-SHELL" to the struct, we remove the first element of composeHealthCheck.Test
return kobject.HealthCheck{
Test: test,
TCPPort: tcpPort,
HTTPPath: httpPath,
HTTPPort: httpPort,
Timeout: timeout,
Interval: interval,
Retries: retries,
StartPeriod: startPeriod,
}, nil
}
func dockerComposeToKomposeMapping(composeObject *types.Project) (kobject.KomposeObject, error) {
// Step 1. Initialize what's going to be returned
komposeObject := kobject.KomposeObject{
ServiceConfigs: make(map[string]kobject.ServiceConfig),
LoadedFrom: "compose",
Secrets: composeObject.Secrets,
}
// Step 2. Parse through the object and convert it to kobject.KomposeObject!
// Here we "clean up" the service configuration so we return something that includes
// all relevant information as well as avoid the unsupported keys as well.
for _, composeServiceConfig := range composeObject.Services {
// Standard import
// No need to modify before importation
name := composeServiceConfig.Name
serviceConfig := kobject.ServiceConfig{}
serviceConfig.Name = name
serviceConfig.Image = composeServiceConfig.Image
serviceConfig.WorkingDir = composeServiceConfig.WorkingDir
serviceConfig.Annotations = composeServiceConfig.Labels
serviceConfig.CapAdd = composeServiceConfig.CapAdd
serviceConfig.CapDrop = composeServiceConfig.CapDrop
serviceConfig.Expose = composeServiceConfig.Expose
serviceConfig.Privileged = composeServiceConfig.Privileged
serviceConfig.User = composeServiceConfig.User
serviceConfig.Stdin = composeServiceConfig.StdinOpen
serviceConfig.Tty = composeServiceConfig.Tty
serviceConfig.TmpFs = composeServiceConfig.Tmpfs
serviceConfig.ContainerName = normalizeContainerNames(composeServiceConfig.ContainerName)
serviceConfig.Command = composeServiceConfig.Entrypoint
serviceConfig.Args = composeServiceConfig.Command
serviceConfig.Labels = composeServiceConfig.Labels
serviceConfig.HostName = composeServiceConfig.Hostname
serviceConfig.DomainName = composeServiceConfig.DomainName
serviceConfig.Secrets = composeServiceConfig.Secrets
if composeServiceConfig.StopGracePeriod != nil {
serviceConfig.StopGracePeriod = composeServiceConfig.StopGracePeriod.String()
}
if err := parseNetwork(&composeServiceConfig, &serviceConfig, composeObject); err != nil {
return kobject.KomposeObject{}, err
}
if err := parseResources(&composeServiceConfig, &serviceConfig); err != nil {
return kobject.KomposeObject{}, err
}
serviceConfig.Restart = composeServiceConfig.Restart
if composeServiceConfig.Deploy != nil {
// Deploy keys
// mode:
serviceConfig.DeployMode = composeServiceConfig.Deploy.Mode
// labels
serviceConfig.DeployLabels = composeServiceConfig.Deploy.Labels
// restart-policy: deploy.restart_policy.condition will rewrite restart option
// see: https://docs.docker.com/compose/compose-file/#restart_policy
if composeServiceConfig.Deploy.RestartPolicy != nil {
serviceConfig.Restart = composeServiceConfig.Deploy.RestartPolicy.Condition
}
// replicas:
if composeServiceConfig.Deploy.Replicas != nil {
serviceConfig.Replicas = int(*composeServiceConfig.Deploy.Replicas)
}
// placement:
serviceConfig.Placement = loadPlacement(composeServiceConfig.Deploy.Placement)
if composeServiceConfig.Deploy.UpdateConfig != nil {
serviceConfig.DeployUpdateConfig = *composeServiceConfig.Deploy.UpdateConfig
}
if composeServiceConfig.Deploy.EndpointMode == "vip" {
serviceConfig.ServiceType = string(api.ServiceTypeNodePort)
}
}
// HealthCheck Liveness
if composeServiceConfig.HealthCheck != nil && !composeServiceConfig.HealthCheck.Disable {
var err error
serviceConfig.HealthChecks.Liveness, err = parseHealthCheck(*composeServiceConfig.HealthCheck, composeServiceConfig.Labels)
if err != nil {
return kobject.KomposeObject{}, errors.Wrap(err, "Unable to parse health check")
}
}
// HealthCheck Readiness
var readiness, errReadiness = parseHealthCheckReadiness(composeServiceConfig.Labels)
if !readiness.Disable {
serviceConfig.HealthChecks.Readiness = readiness
if errReadiness != nil {
return kobject.KomposeObject{}, errors.Wrap(errReadiness, "Unable to parse health check")
}
}
if serviceConfig.Restart == "unless-stopped" {
log.Warnf("Restart policy 'unless-stopped' in service %s is not supported, convert it to 'always'", name)
serviceConfig.Restart = "always"
}
if composeServiceConfig.Build != nil {
serviceConfig.Build = composeServiceConfig.Build.Context
serviceConfig.Dockerfile = composeServiceConfig.Build.Dockerfile
serviceConfig.BuildArgs = composeServiceConfig.Build.Args
serviceConfig.BuildLabels = composeServiceConfig.Build.Labels
}
// env
parseEnvironment(&composeServiceConfig, &serviceConfig)
// Get env_file
serviceConfig.EnvFile = composeServiceConfig.EnvFile
// Parse the ports
// v3 uses a new format called "long syntax" starting in 3.2
// https://docs.docker.com/compose/compose-file/#ports
// here we will translate `expose` too, they basically means the same thing in kubernetes
serviceConfig.Port = loadPorts(composeServiceConfig.Ports, serviceConfig.Expose)
// Parse the volumes
// Again, in v3, we use the "long syntax" for volumes in terms of parsing
// https://docs.docker.com/compose/compose-file/#long-syntax-3
serviceConfig.VolList = loadVolumes(composeServiceConfig.Volumes)
if err := parseKomposeLabels(composeServiceConfig.Labels, &serviceConfig); err != nil {
return kobject.KomposeObject{}, err
}
// Log if the name will been changed
if normalizeServiceNames(name) != name {
log.Infof("Service name in docker-compose has been changed from %q to %q", name, normalizeServiceNames(name))
}
serviceConfig.Configs = composeServiceConfig.Configs
serviceConfig.ConfigsMetaData = composeObject.Configs
// Get GroupAdd, group should be mentioned in gid format but not the group name
groupAdd, err := getGroupAdd(composeServiceConfig.GroupAdd)
if err != nil {
return kobject.KomposeObject{}, errors.Wrap(err, "GroupAdd should be mentioned in gid format, not a group name")
}
serviceConfig.GroupAdd = groupAdd
// Final step, add to the array!
komposeObject.ServiceConfigs[normalizeServiceNames(name)] = serviceConfig
}
handleVolume(&komposeObject, &composeObject.Volumes)
return komposeObject, nil
}
func parseNetwork(composeServiceConfig *types.ServiceConfig, serviceConfig *kobject.ServiceConfig, composeObject *types.Project) error {
if len(composeServiceConfig.Networks) == 0 {
if defaultNetwork, ok := composeObject.Networks["default"]; ok {
normalizedNetworkName, err := normalizeNetworkNames(defaultNetwork.Name)
if err != nil {
return errors.Wrap(err, "Unable to normalize network name")
}
serviceConfig.Network = append(serviceConfig.Network, normalizedNetworkName)
}
} else {
var alias = ""
for key := range composeServiceConfig.Networks {
alias = key
netName := composeObject.Networks[alias].Name
// if Network Name Field is empty in the docker-compose definition
// we will use the alias name defined in service config file
if netName == "" {
netName = alias
}
normalizedNetworkName, err := normalizeNetworkNames(netName)
if err != nil {
return errors.Wrap(err, "Unable to normalize network name")
}
serviceConfig.Network = append(serviceConfig.Network, normalizedNetworkName)
}
}
return nil
}
func parseResources(composeServiceConfig *types.ServiceConfig, serviceConfig *kobject.ServiceConfig) error {
serviceConfig.MemLimit = composeServiceConfig.MemLimit
if composeServiceConfig.Deploy != nil {
// memory:
// See: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/
// "The expression 0.1 is equivalent to the expression 100m, which can be read as “one hundred millicpu”."
// Since Deploy.Resources.Limits does not initialize, we must check type Resources before continuing
if composeServiceConfig.Deploy.Resources.Limits != nil {
serviceConfig.MemLimit = composeServiceConfig.Deploy.Resources.Limits.MemoryBytes
if composeServiceConfig.Deploy.Resources.Limits.NanoCPUs != "" {
cpuLimit, err := strconv.ParseFloat(composeServiceConfig.Deploy.Resources.Limits.NanoCPUs, 64)
if err != nil {
return errors.Wrap(err, "Unable to convert cpu limits resources value")
}
serviceConfig.CPULimit = int64(cpuLimit * 1000)
}
}
if composeServiceConfig.Deploy.Resources.Reservations != nil {
serviceConfig.MemReservation = composeServiceConfig.Deploy.Resources.Reservations.MemoryBytes
if composeServiceConfig.Deploy.Resources.Reservations.NanoCPUs != "" {
cpuReservation, err := strconv.ParseFloat(composeServiceConfig.Deploy.Resources.Reservations.NanoCPUs, 64)
if err != nil {
return errors.Wrap(err, "Unable to convert cpu limits reservation value")
}
serviceConfig.CPUReservation = int64(cpuReservation * 1000)
}
}
}
return nil
}
func parseEnvironment(composeServiceConfig *types.ServiceConfig, serviceConfig *kobject.ServiceConfig) {
// Gather the environment values
// DockerCompose uses map[string]*string while we use []string
// So let's convert that using this hack
// Note: unset env pick up the env value on host if exist
for name, value := range composeServiceConfig.Environment {
var env kobject.EnvVar
if value != nil {
env = kobject.EnvVar{Name: name, Value: *value}
} else {
result, ok := os.LookupEnv(name)
if ok {
env = kobject.EnvVar{Name: name, Value: result}
} else {
continue
}
}
serviceConfig.Environment = append(serviceConfig.Environment, env)
}
}
func getVersionFromFile(file string) (string, error) {
type ComposeVersion struct {
Version string `json:"version"` // This affects YAML as well
}
var version ComposeVersion
loadedFile, err := ReadFile(file)
if err != nil {
return "", err
// parseKomposeLabels parse kompose labels, also do some validation
func parseKomposeLabels(labels map[string]string, serviceConfig *kobject.ServiceConfig) error {
// Label handler
// Labels used to influence conversion of kompose will be handled
// from here for docker-compose. Each loader will have such handler.
if serviceConfig.Labels == nil {
serviceConfig.Labels = make(map[string]string)
}
err = yaml.Unmarshal(loadedFile, &version)
if err != nil {
return "", err
for key, value := range labels {
switch key {
case LabelServiceType:
serviceType, err := handleServiceType(value)
if err != nil {
return errors.Wrap(err, "handleServiceType failed")
}
serviceConfig.ServiceType = serviceType
case LabelServiceExpose:
serviceConfig.ExposeService = strings.Trim(strings.ToLower(value), " ,")
case LabelNodePortPort:
serviceConfig.NodePortPort = cast.ToInt32(value)
case LabelServiceExposeTLSSecret:
serviceConfig.ExposeServiceTLS = value
case LabelServiceExposeIngressClassName:
serviceConfig.ExposeServiceIngressClassName = value
case LabelImagePullSecret:
serviceConfig.ImagePullSecret = value
case LabelImagePullPolicy:
serviceConfig.ImagePullPolicy = value
default:
serviceConfig.Labels[key] = value
}
}
return version.Version, nil
if serviceConfig.ExposeService == "" && serviceConfig.ExposeServiceTLS != "" {
return errors.New("kompose.service.expose.tls-secret was specified without kompose.service.expose")
}
if serviceConfig.ExposeService == "" && serviceConfig.ExposeServiceIngressClassName != "" {
return errors.New("kompose.service.expose.ingress-class-name was specified without kompose.service.expose")
}
if serviceConfig.ServiceType != string(api.ServiceTypeNodePort) && serviceConfig.NodePortPort != 0 {
return errors.New("kompose.service.type must be nodeport when assign node port value")
}
if len(serviceConfig.Port) > 1 && serviceConfig.NodePortPort != 0 {
return errors.New("cannot set kompose.service.nodeport.port when service has multiple ports")
}
return nil
}
func handleVolume(komposeObject *kobject.KomposeObject, volumes *types.Volumes) {
for name := range komposeObject.ServiceConfigs {
// retrieve volumes of service
vols, err := retrieveVolume(name, *komposeObject)
if err != nil {
errors.Wrap(err, "could not retrieve vvolume")
}
for volName, vol := range vols {
size, selector := getVolumeLabels(vol.VolumeName, volumes)
if len(size) > 0 || len(selector) > 0 {
// We can't assign value to struct field in map while iterating over it, so temporary variable `temp` is used here
var temp = vols[volName]
temp.PVCSize = size
temp.SelectorValue = selector
vols[volName] = temp
}
}
// We can't assign value to struct field in map while iterating over it, so temporary variable `temp` is used here
var temp = komposeObject.ServiceConfigs[name]
temp.Volumes = vols
komposeObject.ServiceConfigs[name] = temp
}
}
// returns all volumes associated with service, if `volumes_from` key is used, we have to retrieve volumes from the services which are mentioned there. Hence, recursive function is used here.
func retrieveVolume(svcName string, komposeObject kobject.KomposeObject) (volume []kobject.Volumes, err error) {
// if volumes-from key is present
if komposeObject.ServiceConfigs[svcName].VolumesFrom != nil {
// iterating over services from `volumes-from`
for _, depSvc := range komposeObject.ServiceConfigs[svcName].VolumesFrom {
// recursive call for retrieving volumes of services from `volumes-from`
dVols, err := retrieveVolume(depSvc, komposeObject)
if err != nil {
return nil, errors.Wrapf(err, "could not retrieve the volume")
}
var cVols []kobject.Volumes
cVols, err = ParseVols(komposeObject.ServiceConfigs[svcName].VolList, svcName)
if err != nil {
return nil, errors.Wrapf(err, "error generating current volumes")
}
for _, cv := range cVols {
// check whether volumes of current service is same or not as that of dependent volumes coming from `volumes-from`
ok, dv := getVol(cv, dVols)
if ok {
// change current volumes service name to dependent service name
if dv.VFrom == "" {
cv.VFrom = dv.SvcName
cv.SvcName = dv.SvcName
} else {
cv.VFrom = dv.VFrom
cv.SvcName = dv.SvcName
}
cv.PVCName = dv.PVCName
}
volume = append(volume, cv)
}
// iterating over dependent volumes
for _, dv := range dVols {
// check whether dependent volume is already present or not
if checkVolDependent(dv, volume) {
// if found, add service name to `VFrom`
dv.VFrom = dv.SvcName
volume = append(volume, dv)
}
}
}
} else {
// if `volumes-from` is not present
volume, err = ParseVols(komposeObject.ServiceConfigs[svcName].VolList, svcName)
if err != nil {
return nil, errors.Wrapf(err, "error generating current volumes")
}
}
return
}
// checkVolDependent returns false if dependent volume is present
func checkVolDependent(dv kobject.Volumes, volume []kobject.Volumes) bool {
for _, vol := range volume {
if vol.PVCName == dv.PVCName {
return false
}
}
return true
}
// ParseVols parse volumes
func ParseVols(volNames []string, svcName string) ([]kobject.Volumes, error) {
var volumes []kobject.Volumes
var err error
for i, vn := range volNames {
var v kobject.Volumes
v.VolumeName, v.Host, v.Container, v.Mode, err = transformer.ParseVolume(vn)
if err != nil {
return nil, errors.Wrapf(err, "could not parse volume %q: %v", vn, err)
}
v.VolumeName = normalizeVolumes(v.VolumeName)
v.SvcName = svcName
v.MountPath = fmt.Sprintf("%s:%s", v.Host, v.Container)
v.PVCName = fmt.Sprintf("%s-claim%d", v.SvcName, i)
volumes = append(volumes, v)
}
return volumes, nil
}
// for dependent volumes, returns true and the respective volume if mountpath are same
func getVol(toFind kobject.Volumes, Vols []kobject.Volumes) (bool, kobject.Volumes) {
for _, dv := range Vols {
if toFind.MountPath == dv.MountPath {
return true, dv
}
}
return false, kobject.Volumes{}
}
func getVolumeLabels(name string, volumes *types.Volumes) (string, string) {
size, selector := "", ""
if volume, ok := (*volumes)[name]; ok {
for key, value := range volume.Labels {
if key == "kompose.volume.size" {
size = value
} else if key == "kompose.volume.selector" {
selector = value
}
}
}
return size, selector
}
// getGroupAdd will return group in int64 format
func getGroupAdd(group []string) ([]int64, error) {
var groupAdd []int64
for _, i := range group {
j, err := strconv.Atoi(i)
if err != nil {
return nil, errors.Wrap(err, "unable to get group_add key")
}
groupAdd = append(groupAdd, int64(j))
}
return groupAdd, nil
}

View File

@ -24,10 +24,7 @@ import (
"testing"
"time"
"github.com/docker/cli/cli/compose/types"
"github.com/docker/libcompose/config"
"github.com/docker/libcompose/project"
"github.com/docker/libcompose/yaml"
"github.com/compose-spec/compose-go/types"
"github.com/google/go-cmp/cmp"
"github.com/kubernetes/kompose/pkg/kobject"
"github.com/pkg/errors"
@ -203,7 +200,7 @@ func TestLoadV3Volumes(t *testing.T) {
ReadOnly: true,
}
volumes := []types.ServiceVolumeConfig{vol}
output := loadV3Volumes(volumes)
output := loadVolumes(volumes)
expected := "/tmp/foobar:/tmp/foobar:ro"
if output[0] != expected {
@ -220,7 +217,7 @@ func TestLoadV3Ports(t *testing.T) {
}{
{
desc: "ports with expose",
ports: []types.ServicePortConfig{{Target: 80, Published: 80, Protocol: string(api.ProtocolTCP)}},
ports: []types.ServicePortConfig{{Target: 80, Published: "80", Protocol: string(api.ProtocolTCP)}},
expose: []string{"80", "8080"},
want: []kobject.Ports{
{HostPort: 80, ContainerPort: 80, Protocol: string(api.ProtocolTCP)},
@ -229,7 +226,7 @@ func TestLoadV3Ports(t *testing.T) {
},
{
desc: "exposed port including /protocol",
ports: []types.ServicePortConfig{{Target: 80, Published: 80, Protocol: string(api.ProtocolTCP)}},
ports: []types.ServicePortConfig{{Target: 80, Published: "80", Protocol: string(api.ProtocolTCP)}},
expose: []string{"80/udp"},
want: []kobject.Ports{
{HostPort: 80, ContainerPort: 80, Protocol: string(api.ProtocolTCP)},
@ -238,7 +235,7 @@ func TestLoadV3Ports(t *testing.T) {
},
} {
t.Run(tt.desc, func(t *testing.T) {
got := loadV3Ports(tt.ports, tt.expose)
got := loadPorts(tt.ports, tt.expose)
if diff := cmp.Diff(tt.want, got); diff != "" {
t.Errorf("loadV3Ports() mismatch (-want +got):\n%s", diff)
}
@ -275,92 +272,90 @@ func TestHandleServiceType(t *testing.T) {
// Test loading of ports
func TestLoadPorts(t *testing.T) {
portWithIPAddress, _ := types.ParsePortConfig("127.0.0.1:80:80/tcp")
portWithoutIPAddress, _ := types.ParsePortConfig("80:80/tcp")
portWithoutProtocol, _ := types.ParsePortConfig("80:80")
singlePort, _ := types.ParsePortConfig("80")
singlePortsRange, _ := types.ParsePortConfig("3000-3002")
targetAndContainerPortsRange, _ := types.ParsePortConfig("3000-3002:5000-5002")
targetAndContainerPortsRangeWithIPAddress, _ := types.ParsePortConfig("127.0.0.1:3000-3002:5000-5002")
port3000, _ := types.ParsePortConfig("3000")
tests := []struct {
ports []string
ports []types.ServicePortConfig
expose []string
want []kobject.Ports
}{
{
ports: []string{"127.0.0.1:80:80/tcp"},
ports: portWithIPAddress,
want: []kobject.Ports{
{HostIP: "127.0.0.1", HostPort: 80, ContainerPort: 80, Protocol: string(api.ProtocolTCP)},
},
},
{
ports: []string{"80:80/tcp"},
ports: portWithoutIPAddress,
want: []kobject.Ports{
{HostPort: 80, ContainerPort: 80, Protocol: string(api.ProtocolTCP)},
},
},
{
ports: []string{"80:80"},
ports: portWithoutProtocol,
want: []kobject.Ports{
{HostPort: 80, ContainerPort: 80, Protocol: string(api.ProtocolTCP)},
},
},
{
ports: []string{"80"},
ports: singlePort,
want: []kobject.Ports{
{ContainerPort: 80, Protocol: string(api.ProtocolTCP)},
},
},
{
ports: []string{"3000-3005"},
ports: singlePortsRange,
want: []kobject.Ports{
{ContainerPort: 3000, Protocol: string(api.ProtocolTCP)},
{ContainerPort: 3001, Protocol: string(api.ProtocolTCP)},
{ContainerPort: 3002, Protocol: string(api.ProtocolTCP)},
{ContainerPort: 3003, Protocol: string(api.ProtocolTCP)},
{ContainerPort: 3004, Protocol: string(api.ProtocolTCP)},
{ContainerPort: 3005, Protocol: string(api.ProtocolTCP)},
},
},
{
ports: []string{"3000-3005:5000-5005"},
ports: targetAndContainerPortsRange,
want: []kobject.Ports{
{HostPort: 3000, ContainerPort: 5000, Protocol: string(api.ProtocolTCP)},
{HostPort: 3001, ContainerPort: 5001, Protocol: string(api.ProtocolTCP)},
{HostPort: 3002, ContainerPort: 5002, Protocol: string(api.ProtocolTCP)},
{HostPort: 3003, ContainerPort: 5003, Protocol: string(api.ProtocolTCP)},
{HostPort: 3004, ContainerPort: 5004, Protocol: string(api.ProtocolTCP)},
{HostPort: 3005, ContainerPort: 5005, Protocol: string(api.ProtocolTCP)},
},
},
{
ports: []string{"127.0.0.1:3000-3005:5000-5005"},
ports: targetAndContainerPortsRangeWithIPAddress,
want: []kobject.Ports{
{HostIP: "127.0.0.1", HostPort: 3000, ContainerPort: 5000, Protocol: string(api.ProtocolTCP)},
{HostIP: "127.0.0.1", HostPort: 3001, ContainerPort: 5001, Protocol: string(api.ProtocolTCP)},
{HostIP: "127.0.0.1", HostPort: 3002, ContainerPort: 5002, Protocol: string(api.ProtocolTCP)},
{HostIP: "127.0.0.1", HostPort: 3003, ContainerPort: 5003, Protocol: string(api.ProtocolTCP)},
{HostIP: "127.0.0.1", HostPort: 3004, ContainerPort: 5004, Protocol: string(api.ProtocolTCP)},
{HostIP: "127.0.0.1", HostPort: 3005, ContainerPort: 5005, Protocol: string(api.ProtocolTCP)},
},
},
{
ports: []string{"80", "3000"},
ports: append(append([]types.ServicePortConfig{}, singlePort...), port3000...),
want: []kobject.Ports{
{HostPort: 0, ContainerPort: 80, Protocol: string(api.ProtocolTCP)},
{HostPort: 0, ContainerPort: 3000, Protocol: string(api.ProtocolTCP)},
},
},
{
ports: []string{"80", "3000"},
ports: append(append([]types.ServicePortConfig{}, singlePort...), port3000...),
expose: []string{"80", "8080"},
want: []kobject.Ports{
{HostPort: 0, ContainerPort: 80, Protocol: string(api.ProtocolTCP)},
{HostPort: 0, ContainerPort: 3000, Protocol: string(api.ProtocolTCP)},
{HostPort: 0, ContainerPort: 8080, Protocol: string(api.ProtocolTCP)},
{ContainerPort: 80, Protocol: string(api.ProtocolTCP)},
{ContainerPort: 3000, Protocol: string(api.ProtocolTCP)},
{HostPort: 80, ContainerPort: 80, Protocol: string(api.ProtocolTCP)},
{HostPort: 8080, ContainerPort: 8080, Protocol: string(api.ProtocolTCP)},
},
},
}
for _, tt := range tests {
t.Run(fmt.Sprintf("port=%q,expose=%q", tt.ports, tt.expose), func(t *testing.T) {
got, err := loadPorts(tt.ports, tt.expose)
if err != nil {
t.Fatalf("Unexpected error with loading ports %v", err)
}
got := loadPorts(tt.ports, tt.expose)
if diff := cmp.Diff(tt.want, got); diff != "" {
t.Errorf("loadPorts() mismatch (-want +got):\n%s", diff)
}
@ -438,71 +433,60 @@ func TestLoadEnvVar(t *testing.T) {
// docker-compose projects
func TestUnsupportedKeys(t *testing.T) {
// create project that will be used in test cases
projectWithNetworks := project.NewProject(&project.Context{}, nil, nil)
projectWithNetworks.ServiceConfigs = config.NewServiceConfigs()
projectWithNetworks.ServiceConfigs.Add("foo", &config.ServiceConfig{
Image: "foo/bar",
Build: yaml.Build{
Context: "./build",
projectWithNetworks := &types.Project{
Networks: types.Networks{
"foo": types.NetworkConfig{
Name: "foo",
Driver: "bridge",
},
},
Hostname: "localhost",
Ports: []string{}, // test empty array
Networks: &yaml.Networks{
Networks: []*yaml.Network{
{
Name: "net1",
Services: types.Services{
types.ServiceConfig{
Name: "foo",
Image: "foo/bar",
Build: &types.BuildConfig{
Context: "./build",
},
Hostname: "localhost",
Ports: []types.ServicePortConfig{}, // test empty array
Networks: map[string]*types.ServiceNetworkConfig{
"net1": {},
},
},
types.ServiceConfig{
Name: "bar",
Image: "bar/foo",
Build: &types.BuildConfig{
Context: "./build",
},
Hostname: "localhost",
Ports: []types.ServicePortConfig{}, // test empty array
Networks: map[string]*types.ServiceNetworkConfig{
"net1": {},
},
},
},
})
projectWithNetworks.ServiceConfigs.Add("bar", &config.ServiceConfig{
Image: "bar/foo",
Build: yaml.Build{
Context: "./build",
},
Hostname: "localhost",
Ports: []string{}, // test empty array
Networks: &yaml.Networks{
Networks: []*yaml.Network{
{
Name: "net1",
},
Volumes: types.Volumes{
"foo": types.VolumeConfig{
Name: "foo",
Driver: "storage",
},
},
})
projectWithNetworks.VolumeConfigs = map[string]*config.VolumeConfig{
"foo": {
Driver: "storage",
},
}
projectWithNetworks.NetworkConfigs = map[string]*config.NetworkConfig{
"foo": {
Driver: "bridge",
},
}
projectWithEmptyNetwork := project.NewProject(&project.Context{}, nil, nil)
projectWithEmptyNetwork.ServiceConfigs = config.NewServiceConfigs()
projectWithEmptyNetwork.ServiceConfigs.Add("foo", &config.ServiceConfig{
Networks: &yaml.Networks{},
})
projectWithDefaultNetwork := project.NewProject(&project.Context{}, nil, nil)
projectWithDefaultNetwork.ServiceConfigs = config.NewServiceConfigs()
projectWithDefaultNetwork.ServiceConfigs.Add("foo", &config.ServiceConfig{
Networks: &yaml.Networks{
Networks: []*yaml.Network{
{
Name: "default",
projectWithDefaultNetwork := &types.Project{
Services: types.Services{
types.ServiceConfig{
Networks: map[string]*types.ServiceNetworkConfig{
"default": {},
},
},
},
})
}
// define all test cases for checkUnsupportedKey function
testCases := map[string]struct {
composeProject *project.Project
composeProject *types.Project
expectedUnsupportedKeys []string
}{
"With Networks (service and root level)": {
@ -567,28 +551,6 @@ func TestNormalizeNetworkNames(t *testing.T) {
}
}
func TestCheckLabelsPorts(t *testing.T) {
testCases := []struct {
name string
noOfPort int
labels string
svcName string
expectError bool
}{
{"ports is defined", 1, "NodePort", "foo", false},
{"ports is not defined", 0, "NodePort", "foo", true},
}
var err error
for _, testcase := range testCases {
t.Log(testcase.name)
err = checkLabelsPorts(testcase.noOfPort, testcase.labels, testcase.svcName)
if testcase.expectError && err == nil {
t.Log("Expected error, got ", err)
}
}
}
func TestCheckPlacementCustomLabels(t *testing.T) {
placement := types.Placement{
Constraints: []string{
@ -601,7 +563,7 @@ func TestCheckPlacementCustomLabels(t *testing.T) {
{Spread: "node.labels.ssd"},
},
}
output := loadV3Placement(placement)
output := loadPlacement(placement)
expected := kobject.Placement{
PositiveConstraints: map[string]string{

View File

@ -1,417 +0,0 @@
/*
Copyright 2017 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package compose
import (
"fmt"
"net"
"os"
"path/filepath"
"sort"
"strconv"
"strings"
"github.com/docker/cli/opts"
"github.com/docker/go-connections/nat"
"github.com/docker/libcompose/config"
"github.com/docker/libcompose/lookup"
"github.com/docker/libcompose/project"
"github.com/kubernetes/kompose/pkg/kobject"
"github.com/kubernetes/kompose/pkg/transformer"
"github.com/pkg/errors"
log "github.com/sirupsen/logrus"
"github.com/spf13/cast"
api "k8s.io/api/core/v1"
)
// Parse Docker Compose with libcompose (only supports v1 and v2). Eventually we will
// switch to using only libcompose once v3 is supported.
func parseV1V2(files []string) (kobject.KomposeObject, error) {
// Gather the appropriate context for parsing
context := &project.Context{}
context.ComposeFiles = files
if context.ResourceLookup == nil {
context.ResourceLookup = &lookup.FileResourceLookup{}
}
if context.EnvironmentLookup == nil {
cwd, err := os.Getwd()
if err != nil {
return kobject.KomposeObject{}, nil
}
context.EnvironmentLookup = &lookup.ComposableEnvLookup{
Lookups: []config.EnvironmentLookup{
&lookup.EnvfileLookup{
Path: filepath.Join(cwd, ".env"),
},
&lookup.OsEnvLookup{},
},
}
}
// Load the context and let's start parsing
composeObject := project.NewProject(context, nil, nil)
err := composeObject.Parse()
if err != nil {
return kobject.KomposeObject{}, errors.Wrap(err, "composeObject.Parse() failed, Failed to load compose file")
}
noSupKeys := checkUnsupportedKey(composeObject)
for _, keyName := range noSupKeys {
log.Warningf("Unsupported %s key - ignoring", keyName)
}
// Map the parsed struct to a struct we understand (kobject)
komposeObject, err := libComposeToKomposeMapping(composeObject)
if err != nil {
return kobject.KomposeObject{}, err
}
return komposeObject, nil
}
// Load ports from compose file
// also load `expose` here
func loadPorts(composePorts []string, expose []string) ([]kobject.Ports, error) {
kp := []kobject.Ports{}
exist := map[string]bool{}
for _, cp := range composePorts {
var hostIP string
if parts := strings.Split(cp, ":"); len(parts) == 3 {
if ip := net.ParseIP(parts[0]); ip.To4() == nil && ip.To16() == nil {
return nil, fmt.Errorf("%q contains an invalid IPv4 or IPv6 IP address", parts[0])
}
hostIP = parts[0]
}
np, pbs, err := nat.ParsePortSpecs([]string{cp})
if err != nil {
return nil, fmt.Errorf("invalid port, error = %v", err)
}
// Force HostIP value to avoid warning raised by github.com/docker/cli/opts
// The opts package will warn if the bindings contains host IP except
// 0.0.0.0. However, the message is not useful in this case since the value
// should be handled by kompose properly.
for _, pb := range pbs {
for i, p := range pb {
p.HostIP = ""
pb[i] = p
}
}
var ports []string
for p := range np {
ports = append(ports, string(p))
}
sort.Strings(ports)
for _, p := range ports {
pc, err := opts.ConvertPortToPortConfig(nat.Port(p), pbs)
if err != nil {
return nil, fmt.Errorf("invalid port, error = %v", err)
}
for _, cfg := range pc {
kp = append(kp, kobject.Ports{
HostPort: int32(cfg.PublishedPort),
ContainerPort: int32(cfg.TargetPort),
HostIP: hostIP,
Protocol: strings.ToUpper(string(cfg.Protocol)),
})
}
}
}
// load remain expose ports
for _, p := range kp {
// must use cast...
exist[cast.ToString(p.ContainerPort)+p.Protocol] = true
}
if expose != nil {
for _, port := range expose {
portValue := port
protocol := string(api.ProtocolTCP)
if strings.Contains(portValue, "/") {
splits := strings.Split(port, "/")
portValue = splits[0]
protocol = splits[1]
}
if !exist[portValue+protocol] {
kp = append(kp, kobject.Ports{
ContainerPort: cast.ToInt32(portValue),
Protocol: strings.ToUpper(protocol),
})
}
}
}
return kp, nil
}
// Uses libcompose's APIProject type and converts it to a Kompose object for us to understand
func libComposeToKomposeMapping(composeObject *project.Project) (kobject.KomposeObject, error) {
// Initialize what's going to be returned
komposeObject := kobject.KomposeObject{
ServiceConfigs: make(map[string]kobject.ServiceConfig),
LoadedFrom: "compose",
}
// Here we "clean up" the service configuration so we return something that includes
// all relevant information as well as avoid the unsupported keys as well.
for name, composeServiceConfig := range composeObject.ServiceConfigs.All() {
serviceConfig := kobject.ServiceConfig{}
serviceConfig.Name = name
serviceConfig.Image = composeServiceConfig.Image
serviceConfig.Build = composeServiceConfig.Build.Context
newName := normalizeContainerNames(composeServiceConfig.ContainerName)
serviceConfig.ContainerName = newName
if newName != composeServiceConfig.ContainerName {
log.Infof("Container name in service %q has been changed from %q to %q", name, composeServiceConfig.ContainerName, newName)
}
serviceConfig.Command = composeServiceConfig.Entrypoint
serviceConfig.HostName = composeServiceConfig.Hostname
serviceConfig.DomainName = composeServiceConfig.DomainName
serviceConfig.Args = composeServiceConfig.Command
serviceConfig.Dockerfile = composeServiceConfig.Build.Dockerfile
serviceConfig.BuildArgs = composeServiceConfig.Build.Args
serviceConfig.Expose = composeServiceConfig.Expose
envs := loadEnvVars(composeServiceConfig.Environment)
serviceConfig.Environment = envs
// Validate dockerfile path
if filepath.IsAbs(serviceConfig.Dockerfile) {
log.Fatalf("%q defined in service %q is an absolute path, it must be a relative path.", serviceConfig.Dockerfile, name)
}
// load ports, same as v3, we also load `expose`
ports, err := loadPorts(composeServiceConfig.Ports, serviceConfig.Expose)
if err != nil {
return kobject.KomposeObject{}, errors.Wrap(err, "loadPorts failed. "+name+" failed to load ports from compose file")
}
serviceConfig.Port = ports
serviceConfig.WorkingDir = composeServiceConfig.WorkingDir
if composeServiceConfig.Volumes != nil {
for _, volume := range composeServiceConfig.Volumes.Volumes {
v := volume.String()
serviceConfig.VolList = append(serviceConfig.VolList, v)
}
}
// canonical "Custom Labels" handler
// Labels used to influence conversion of kompose will be handled
// from here for docker-compose. Each loader will have such handler.
if err := parseKomposeLabels(composeServiceConfig.Labels, &serviceConfig); err != nil {
return kobject.KomposeObject{}, err
}
err = checkLabelsPorts(len(serviceConfig.Port), composeServiceConfig.Labels[LabelServiceType], name)
if err != nil {
return kobject.KomposeObject{}, errors.Wrap(err, "kompose.service.type can't be set if service doesn't expose any ports.")
}
// convert compose labels to annotations
serviceConfig.Annotations = composeServiceConfig.Labels
serviceConfig.CPUQuota = int64(composeServiceConfig.CPUQuota)
serviceConfig.CapAdd = composeServiceConfig.CapAdd
serviceConfig.CapDrop = composeServiceConfig.CapDrop
serviceConfig.Pid = composeServiceConfig.Pid
serviceConfig.Privileged = composeServiceConfig.Privileged
serviceConfig.User = composeServiceConfig.User
serviceConfig.VolumesFrom = composeServiceConfig.VolumesFrom
serviceConfig.Stdin = composeServiceConfig.StdinOpen
serviceConfig.Tty = composeServiceConfig.Tty
serviceConfig.MemLimit = composeServiceConfig.MemLimit
serviceConfig.TmpFs = composeServiceConfig.Tmpfs
serviceConfig.StopGracePeriod = composeServiceConfig.StopGracePeriod
// pretty much same as v3
serviceConfig.Restart = composeServiceConfig.Restart
if serviceConfig.Restart == "unless-stopped" {
log.Warnf("Restart policy 'unless-stopped' in service %s is not supported, convert it to 'always'", name)
serviceConfig.Restart = "always"
}
if composeServiceConfig.Networks != nil {
if len(composeServiceConfig.Networks.Networks) > 0 {
for _, value := range composeServiceConfig.Networks.Networks {
if value.Name != "default" {
nomalizedNetworkName, err := normalizeNetworkNames(value.RealName)
if err != nil {
return kobject.KomposeObject{}, errors.Wrap(err, "Error trying to normalize network names")
}
if nomalizedNetworkName != value.RealName {
log.Warnf("Network name in docker-compose has been changed from %q to %q", value.RealName, nomalizedNetworkName)
}
serviceConfig.Network = append(serviceConfig.Network, nomalizedNetworkName)
}
}
}
}
// Get GroupAdd, group should be mentioned in gid format but not the group name
groupAdd, err := getGroupAdd(composeServiceConfig.GroupAdd)
if err != nil {
return kobject.KomposeObject{}, errors.Wrap(err, "GroupAdd should be mentioned in gid format, not a group name")
}
serviceConfig.GroupAdd = groupAdd
komposeObject.ServiceConfigs[normalizeServiceNames(name)] = serviceConfig
if normalizeServiceNames(name) != name {
log.Infof("Service name in docker-compose has been changed from %q to %q", name, normalizeServiceNames(name))
}
}
// This will handle volume at earlier stage itself, it will resolves problems occurred due to `volumes_from` key
handleVolume(&komposeObject)
return komposeObject, nil
}
// This function will retrieve volumes for each service, as well as it will parse volume information and store it in Volumes struct
func handleVolume(komposeObject *kobject.KomposeObject) {
for name := range komposeObject.ServiceConfigs {
// retrieve volumes of service
vols, err := retrieveVolume(name, *komposeObject)
if err != nil {
errors.Wrap(err, "could not retrieve volume")
}
// We can't assign value to struct field in map while iterating over it, so temporary variable `temp` is used here
var temp = komposeObject.ServiceConfigs[name]
temp.Volumes = vols
komposeObject.ServiceConfigs[name] = temp
}
}
func checkLabelsPorts(noOfPort int, labels string, svcName string) error {
if noOfPort == 0 && (labels == "NodePort" || labels == "LoadBalancer") {
return errors.Errorf("%s defined in service %s with no ports present. Issues may occur when bringing up artifacts.", labels, svcName)
}
return nil
}
// returns all volumes associated with service, if `volumes_from` key is used, we have to retrieve volumes from the services which are mentioned there. Hence, recursive function is used here.
func retrieveVolume(svcName string, komposeObject kobject.KomposeObject) (volume []kobject.Volumes, err error) {
// if volumes-from key is present
if komposeObject.ServiceConfigs[svcName].VolumesFrom != nil {
// iterating over services from `volumes-from`
for _, depSvc := range komposeObject.ServiceConfigs[svcName].VolumesFrom {
// recursive call for retrieving volumes of services from `volumes-from`
dVols, err := retrieveVolume(depSvc, komposeObject)
if err != nil {
return nil, errors.Wrapf(err, "could not retrieve the volume")
}
var cVols []kobject.Volumes
cVols, err = ParseVols(komposeObject.ServiceConfigs[svcName].VolList, svcName)
if err != nil {
return nil, errors.Wrapf(err, "error generating current volumes")
}
for _, cv := range cVols {
// check whether volumes of current service is same or not as that of dependent volumes coming from `volumes-from`
ok, dv := getVol(cv, dVols)
if ok {
// change current volumes service name to dependent service name
if dv.VFrom == "" {
cv.VFrom = dv.SvcName
cv.SvcName = dv.SvcName
} else {
cv.VFrom = dv.VFrom
cv.SvcName = dv.SvcName
}
cv.PVCName = dv.PVCName
}
volume = append(volume, cv)
}
// iterating over dependent volumes
for _, dv := range dVols {
// check whether dependent volume is already present or not
if checkVolDependent(dv, volume) {
// if found, add service name to `VFrom`
dv.VFrom = dv.SvcName
volume = append(volume, dv)
}
}
}
} else {
// if `volumes-from` is not present
volume, err = ParseVols(komposeObject.ServiceConfigs[svcName].VolList, svcName)
if err != nil {
return nil, errors.Wrapf(err, "error generating current volumes")
}
}
return
}
// checkVolDependent returns false if dependent volume is present
func checkVolDependent(dv kobject.Volumes, volume []kobject.Volumes) bool {
for _, vol := range volume {
if vol.PVCName == dv.PVCName {
return false
}
}
return true
}
// ParseVols parse volumes
func ParseVols(volNames []string, svcName string) ([]kobject.Volumes, error) {
var volumes []kobject.Volumes
var err error
for i, vn := range volNames {
var v kobject.Volumes
v.VolumeName, v.Host, v.Container, v.Mode, err = transformer.ParseVolume(vn)
if err != nil {
return nil, errors.Wrapf(err, "could not parse volume %q: %v", vn, err)
}
v.VolumeName = normalizeVolumes(v.VolumeName)
v.SvcName = svcName
v.MountPath = fmt.Sprintf("%s:%s", v.Host, v.Container)
v.PVCName = fmt.Sprintf("%s-claim%d", v.SvcName, i)
volumes = append(volumes, v)
}
return volumes, nil
}
// for dependent volumes, returns true and the respective volume if mountpath are same
func getVol(toFind kobject.Volumes, Vols []kobject.Volumes) (bool, kobject.Volumes) {
for _, dv := range Vols {
if toFind.MountPath == dv.MountPath {
return true, dv
}
}
return false, kobject.Volumes{}
}
// getGroupAdd will return group in int64 format
func getGroupAdd(group []string) ([]int64, error) {
var groupAdd []int64
for _, i := range group {
j, err := strconv.Atoi(i)
if err != nil {
return nil, errors.Wrap(err, "unable to get group_add key")
}
groupAdd = append(groupAdd, int64(j))
}
return groupAdd, nil
}

File diff suppressed because it is too large Load Diff

View File

@ -493,10 +493,8 @@ func (k *Kubernetes) UpdateKubernetesObjects(name string, service kobject.Servic
}
}
if cms != nil {
for _, c := range cms {
*objects = append(*objects, c)
}
for _, c := range cms {
*objects = append(*objects, c)
}
// Configure the container ports.
@ -724,8 +722,6 @@ func TranslatePodResource(service *kobject.ServiceConfig, template *api.PodTempl
template.Spec.Containers[0].Resources.Requests = resourceRequests
}
return
}
// GetImagePullPolicy get image pull settings

View File

@ -39,8 +39,8 @@ func TestCreateService(t *testing.T) {
service := kobject.ServiceConfig{
ContainerName: "name",
Image: "image",
Environment: []kobject.EnvVar{kobject.EnvVar{Name: "env", Value: "value"}},
Port: []kobject.Ports{kobject.Ports{HostPort: 123, ContainerPort: 456, Protocol: string(corev1.ProtocolTCP)}},
Environment: []kobject.EnvVar{{Name: "env", Value: "value"}},
Port: []kobject.Ports{{HostPort: 123, ContainerPort: 456, Protocol: string(corev1.ProtocolTCP)}},
Command: []string{"cmd"},
WorkingDir: "dir",
Args: []string{"arg1", "arg2"},
@ -82,8 +82,8 @@ func TestCreateServiceWithMemLimit(t *testing.T) {
service := kobject.ServiceConfig{
ContainerName: "name",
Image: "image",
Environment: []kobject.EnvVar{kobject.EnvVar{Name: "env", Value: "value"}},
Port: []kobject.Ports{kobject.Ports{HostPort: 123, ContainerPort: 456, Protocol: string(corev1.ProtocolTCP)}},
Environment: []kobject.EnvVar{{Name: "env", Value: "value"}},
Port: []kobject.Ports{{HostPort: 123, ContainerPort: 456, Protocol: string(corev1.ProtocolTCP)}},
Command: []string{"cmd"},
WorkingDir: "dir",
Args: []string{"arg1", "arg2"},
@ -134,8 +134,8 @@ func TestCreateServiceWithCPULimit(t *testing.T) {
service := kobject.ServiceConfig{
ContainerName: "name",
Image: "image",
Environment: []kobject.EnvVar{kobject.EnvVar{Name: "env", Value: "value"}},
Port: []kobject.Ports{kobject.Ports{HostPort: 123, ContainerPort: 456, Protocol: string(corev1.ProtocolTCP)}},
Environment: []kobject.EnvVar{{Name: "env", Value: "value"}},
Port: []kobject.Ports{{HostPort: 123, ContainerPort: 456, Protocol: string(corev1.ProtocolTCP)}},
Command: []string{"cmd"},
WorkingDir: "dir",
Args: []string{"arg1", "arg2"},
@ -187,8 +187,8 @@ func TestCreateServiceWithServiceUser(t *testing.T) {
service := kobject.ServiceConfig{
ContainerName: "name",
Image: "image",
Environment: []kobject.EnvVar{kobject.EnvVar{Name: "env", Value: "value"}},
Port: []kobject.Ports{kobject.Ports{HostPort: 123, ContainerPort: 456, Protocol: string(corev1.ProtocolTCP)}},
Environment: []kobject.EnvVar{{Name: "env", Value: "value"}},
Port: []kobject.Ports{{HostPort: 123, ContainerPort: 456, Protocol: string(corev1.ProtocolTCP)}},
Command: []string{"cmd"},
WorkingDir: "dir",
Args: []string{"arg1", "arg2"},
@ -230,8 +230,8 @@ func TestTransformWithPid(t *testing.T) {
service := kobject.ServiceConfig{
ContainerName: "name",
Image: "image",
Environment: []kobject.EnvVar{kobject.EnvVar{Name: "env", Value: "value"}},
Port: []kobject.Ports{kobject.Ports{HostPort: 123, ContainerPort: 456, Protocol: string(corev1.ProtocolTCP)}},
Environment: []kobject.EnvVar{{Name: "env", Value: "value"}},
Port: []kobject.Ports{{HostPort: 123, ContainerPort: 456, Protocol: string(corev1.ProtocolTCP)}},
Command: []string{"cmd"},
WorkingDir: "dir",
Args: []string{"arg1", "arg2"},
@ -266,8 +266,8 @@ func TestTransformWithInvalidPid(t *testing.T) {
service := kobject.ServiceConfig{
ContainerName: "name",
Image: "image",
Environment: []kobject.EnvVar{kobject.EnvVar{Name: "env", Value: "value"}},
Port: []kobject.Ports{kobject.Ports{HostPort: 123, ContainerPort: 456, Protocol: string(corev1.ProtocolTCP)}},
Environment: []kobject.EnvVar{{Name: "env", Value: "value"}},
Port: []kobject.Ports{{HostPort: 123, ContainerPort: 456, Protocol: string(corev1.ProtocolTCP)}},
Command: []string{"cmd"},
WorkingDir: "dir",
Args: []string{"arg1", "arg2"},

View File

@ -29,7 +29,7 @@ import (
"strconv"
"strings"
"github.com/docker/cli/cli/compose/types"
"github.com/compose-spec/compose-go/types"
"github.com/fatih/structs"
"github.com/kubernetes/kompose/pkg/kobject"
"github.com/kubernetes/kompose/pkg/loader/compose"
@ -871,7 +871,7 @@ func (k *Kubernetes) getSecretPathsLegacy(secretConfig types.ServiceSecretConfig
}
// if the target isn't absolute path
if strings.HasPrefix(secretConfig.Target, "/") == false {
if !strings.HasPrefix(secretConfig.Target, "/") {
// concat the default secret directory
mountPath = "/run/secrets/" + mountPath
}
@ -1474,20 +1474,17 @@ func (k *Kubernetes) Transform(komposeObject kobject.KomposeObject, opt kobject.
SetVolumes(volumes),
)
if pvc != nil {
// Looping on the slice pvc instead of `*objects = append(*objects, pvc...)`
// because the type of objects and pvc is different, but when doing append
// one element at a time it gets converted to runtime.Object for objects slice
for _, p := range pvc {
objects = append(objects, p)
}
// Looping on the slice pvc instead of `*objects = append(*objects, pvc...)`
// because the type of objects and pvc is different, but when doing append
// one element at a time it gets converted to runtime.Object for objects slice
for _, p := range pvc {
objects = append(objects, p)
}
if cms != nil {
for _, c := range cms {
objects = append(objects, c)
}
for _, c := range cms {
objects = append(objects, c)
}
podSpec.Append(
SetPorts(service),
ImagePullPolicy(name, service),

View File

@ -23,7 +23,7 @@ import (
"strings"
"testing"
dockerCliTypes "github.com/docker/cli/cli/compose/types"
"github.com/compose-spec/compose-go/types"
"github.com/kubernetes/kompose/pkg/kobject"
"github.com/kubernetes/kompose/pkg/loader/compose"
@ -43,8 +43,8 @@ func newServiceConfig() kobject.ServiceConfig {
Name: "app",
ContainerName: "name",
Image: "image",
Environment: []kobject.EnvVar{kobject.EnvVar{Name: "env", Value: "value"}},
Port: []kobject.Ports{kobject.Ports{HostPort: 123, ContainerPort: 456}, kobject.Ports{HostPort: 123, ContainerPort: 456, Protocol: string(api.ProtocolUDP)}, kobject.Ports{HostPort: 55564, ContainerPort: 55564}, kobject.Ports{HostPort: 55563, ContainerPort: 55563}},
Environment: []kobject.EnvVar{{Name: "env", Value: "value"}},
Port: []kobject.Ports{{HostPort: 123, ContainerPort: 456}, {HostPort: 123, ContainerPort: 456, Protocol: string(api.ProtocolUDP)}, {HostPort: 55564, ContainerPort: 55564}, {HostPort: 55563, ContainerPort: 55563}},
Command: []string{"cmd"},
WorkingDir: "dir",
Args: []string{"arg1", "arg2"},
@ -65,8 +65,8 @@ func newServiceConfig() kobject.ServiceConfig {
Replicas: 2,
Volumes: []kobject.Volumes{{SvcName: "app", MountPath: "/tmp/volume", PVCName: "app-claim0"}},
GroupAdd: []int64{1003, 1005},
Configs: []dockerCliTypes.ServiceConfigObjConfig{{Source: "config", Target: "/etc/world"}},
ConfigsMetaData: map[string]dockerCliTypes.ConfigObjConfig{"config": dockerCliTypes.ConfigObjConfig{Name: "myconfig", File: "kubernetes_test.go"}},
Configs: []types.ServiceConfigObjConfig{{Source: "config", Target: "/etc/world"}},
ConfigsMetaData: types.Configs{"config": types.ConfigObjConfig{Name: "myconfig", File: "kubernetes_test.go"}},
}
}
@ -495,7 +495,7 @@ func TestKomposeConvert(t *testing.T) {
if (int)(dc.Spec.Replicas) != replicas {
t.Errorf("Expected %d replicas, got %d", replicas, dc.Spec.Replicas)
}
if len(dc.Spec.Selector) < 0 {
if len(dc.Spec.Selector) == 0 {
t.Errorf("Expect selector be set, got: %#v", dc.Spec.Selector)
}
foundDC = true
@ -529,8 +529,8 @@ func TestConvertRestartOptions(t *testing.T) {
svc kobject.KomposeObject
restartPolicy api.RestartPolicy
}{
"'restart' is set to 'no'": {kobject.KomposeObject{ServiceConfigs: map[string]kobject.ServiceConfig{"app": kobject.ServiceConfig{Image: "foobar", Restart: "no"}}}, api.RestartPolicyNever},
"'restart' is set to 'on-failure'": {kobject.KomposeObject{ServiceConfigs: map[string]kobject.ServiceConfig{"app": kobject.ServiceConfig{Image: "foobar", Restart: "on-failure"}}}, api.RestartPolicyOnFailure},
"'restart' is set to 'no'": {kobject.KomposeObject{ServiceConfigs: map[string]kobject.ServiceConfig{"app": {Image: "foobar", Restart: "no"}}}, api.RestartPolicyNever},
"'restart' is set to 'on-failure'": {kobject.KomposeObject{ServiceConfigs: map[string]kobject.ServiceConfig{"app": {Image: "foobar", Restart: "on-failure"}}}, api.RestartPolicyOnFailure},
}
for name, test := range testCases {

View File

@ -190,10 +190,10 @@ func (o *OpenShift) initDeploymentConfig(name string, service kobject.ServiceCon
},
Triggers: []deployapi.DeploymentTriggerPolicy{
// Trigger new deploy when DeploymentConfig is created (config change)
deployapi.DeploymentTriggerPolicy{
{
Type: deployapi.DeploymentTriggerOnConfigChange,
},
deployapi.DeploymentTriggerPolicy{
{
Type: deployapi.DeploymentTriggerOnImageChange,
ImageChangeParams: &deployapi.DeploymentTriggerImageChangeParams{
//Automatic - if new tag is detected - update image update inside the pod template

View File

@ -36,8 +36,8 @@ func newServiceConfig() kobject.ServiceConfig {
return kobject.ServiceConfig{
ContainerName: "myfoobarname",
Image: "image",
Environment: []kobject.EnvVar{kobject.EnvVar{Name: "env", Value: "value"}},
Port: []kobject.Ports{kobject.Ports{HostPort: 123, ContainerPort: 456, Protocol: string(corev1.ProtocolTCP)}},
Environment: []kobject.EnvVar{{Name: "env", Value: "value"}},
Port: []kobject.Ports{{HostPort: 123, ContainerPort: 456, Protocol: string(corev1.ProtocolTCP)}},
Command: []string{"cmd"},
WorkingDir: "dir",
Args: []string{"arg1", "arg2"},
@ -125,7 +125,7 @@ func TestKomposeConvertRoute(t *testing.T) {
}
}
//Test getting git remote url for a directory
// Test getting git remote url for a directory
func TestGetGitRemote(t *testing.T) {
var output string
var err error

View File

@ -342,7 +342,7 @@ func GetComposeFileDir(inputFiles []string) (string, error) {
return filepath.Dir(inputFile), nil
}
//BuildDockerImage builds docker image
// BuildDockerImage builds docker image
func BuildDockerImage(service kobject.ServiceConfig, name string) error {
wd, err := os.Getwd()
if err != nil {

View File

@ -119,7 +119,7 @@ func TestParseWindowsVolumeMountLinuxContainer(t *testing.T) {
},
{
"container",
fmt.Sprintf("%s", linuxContainer),
linuxContainer,
"",
"",
linuxContainer,
@ -214,7 +214,7 @@ func TestParseWindowsVolumeMountWindowsContainer(t *testing.T) {
},
{
"container",
fmt.Sprintf("%s", windowsContainer),
windowsContainer,
"",
"",
windowsContainer,
@ -311,7 +311,7 @@ func TestParseVolume(t *testing.T) {
},
{
"container",
fmt.Sprintf("%s", container2),
container2,
"",
"",
container2,

View File

@ -82,9 +82,10 @@ func (c *Push) PushImage(image Image) error {
// handleDockerRegistry adapt legacy docker registry address
// After docker login to docker.io, there must be https://index.docker.io/v1/ in config.json of authentication
// Reference: https://docs.docker.com/engine/api/v1.23/
// > However (for legacy reasons) the “official” Docker, Inc. hosted registry
// > must be specified with both a “https://” prefix and a “/v1/” suffix
// > even though Docker will prefer to use the v2 registry API.
//
// > However (for legacy reasons) the “official” Docker, Inc. hosted registry
// > must be specified with both a “https://” prefix and a “/v1/” suffix
// > even though Docker will prefer to use the v2 registry API.
func handleDockerRegistry(auth *dockerlib.AuthConfigurations) {
const address = "docker.io"
const legacyAddress = "https://index.docker.io/v1/"

View File

@ -148,7 +148,7 @@ k8s_output="$KOMPOSE_ROOT/script/test/fixtures/change-in-volume/output-k8s-empty
os_cmd="kompose --provider=openshift -f $KOMPOSE_ROOT/script/test/fixtures/change-in-volume/docker-compose.yml convert --with-kompose-annotation=false --stdout --volumes emptyDir"
os_output="$KOMPOSE_ROOT/script/test/fixtures/change-in-volume/output-os-empty-vols-template.yaml"
convert::expect_success_and_warning "$k8s_cmd" "$k8s_output"
convert::expect_success_and_warning "$os_cmd" "$os_output"
convert::expect_success "$os_cmd" "$os_output"
# Test that emptyvols works
k8s_cmd="kompose -f $KOMPOSE_ROOT/script/test/fixtures/change-in-volume/docker-compose.yml convert --with-kompose-annotation=false --stdout --emptyvols"
@ -163,7 +163,7 @@ k8s_cmd="kompose -f $KOMPOSE_ROOT/script/test/fixtures/expose/compose.yaml conve
ocp_cmd="kompose --provider=openshift -f $KOMPOSE_ROOT/script/test/fixtures/expose/compose.yaml convert --stdout --with-kompose-annotation=false"
k8s_output="$KOMPOSE_ROOT/script/test/fixtures/expose/output-k8s.yaml"
ocp_output="$KOMPOSE_ROOT/script/test/fixtures/expose/output-os.yaml"
convert::expect_success "$k8s_cmd" "$k8s_output"
convert::expect_success_and_warning "$k8s_cmd" "$k8s_output"
convert::expect_success "$ocp_cmd" "$ocp_output"
@ -193,7 +193,7 @@ k8s_cmd="kompose -f $KOMPOSE_ROOT/script/test/fixtures/statefulset/docker-compos
ocp_cmd="kompose --provider=openshift -f $KOMPOSE_ROOT/script/test/fixtures/statefulset/docker-compose.yaml convert --stdout --with-kompose-annotation=false --controller statefulset"
k8s_output="$KOMPOSE_ROOT/script/test/fixtures/statefulset/output-k8s.yaml"
ocp_output="$KOMPOSE_ROOT/script/test/fixtures/statefulset/output-os.yaml"
convert::expect_success "$k8s_cmd" "$k8s_output"
convert::expect_success_and_warning "$k8s_cmd" "$k8s_output"
convert::expect_success "$ocp_cmd" "$ocp_output"
# test specifying volume type using service label

View File

@ -59,6 +59,7 @@ spec:
kompose.service.type: headless
creationTimestamp: null
labels:
io.kompose.network/change-in-volume-default: "true"
io.kompose.service: redis
spec:
containers:
@ -68,6 +69,22 @@ spec:
restartPolicy: Always
status: {}
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
creationTimestamp: null
name: change-in-volume-default
spec:
ingress:
- from:
- podSelector:
matchLabels:
io.kompose.network/change-in-volume-default: "true"
podSelector:
matchLabels:
io.kompose.network/change-in-volume-default: "true"
---
apiVersion: apps/v1
kind: Deployment
@ -87,6 +104,7 @@ spec:
metadata:
creationTimestamp: null
labels:
io.kompose.network/change-in-volume-default: "true"
io.kompose.service: web
spec:
containers:
@ -106,3 +124,4 @@ spec:
- emptyDir: {}
name: code-volume
status: {}

View File

@ -59,6 +59,7 @@ spec:
kompose.service.type: headless
creationTimestamp: null
labels:
io.kompose.network/change-in-volume-default: "true"
io.kompose.service: redis
spec:
containers:
@ -68,6 +69,22 @@ spec:
restartPolicy: Always
status: {}
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
creationTimestamp: null
name: change-in-volume-default
spec:
ingress:
- from:
- podSelector:
matchLabels:
io.kompose.network/change-in-volume-default: "true"
podSelector:
matchLabels:
io.kompose.network/change-in-volume-default: "true"
---
apiVersion: apps/v1
kind: Deployment
@ -87,6 +104,7 @@ spec:
metadata:
creationTimestamp: null
labels:
io.kompose.network/change-in-volume-default: "true"
io.kompose.service: web
spec:
containers:

View File

@ -57,6 +57,7 @@ spec:
metadata:
creationTimestamp: null
labels:
io.kompose.network/change-in-volume-default: "true"
io.kompose.service: redis
spec:
containers:
@ -126,6 +127,7 @@ spec:
metadata:
creationTimestamp: null
labels:
io.kompose.network/change-in-volume-default: "true"
io.kompose.service: web
spec:
containers:

View File

@ -57,6 +57,7 @@ spec:
metadata:
creationTimestamp: null
labels:
io.kompose.network/change-in-volume-default: "true"
io.kompose.service: redis
spec:
containers:
@ -126,6 +127,7 @@ spec:
metadata:
creationTimestamp: null
labels:
io.kompose.network/change-in-volume-default: "true"
io.kompose.service: web
spec:
containers:

View File

@ -21,6 +21,7 @@ spec:
kompose.volume.type: configMap
creationTimestamp: null
labels:
io.kompose.network/configmap-volume-default: "true"
io.kompose.service: db
spec:
containers:
@ -54,6 +55,22 @@ metadata:
io.kompose.service: db
name: db-cm0
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
creationTimestamp: null
name: configmap-volume-default
spec:
ingress:
- from:
- podSelector:
matchLabels:
io.kompose.network/configmap-volume-default: "true"
podSelector:
matchLabels:
io.kompose.network/configmap-volume-default: "true"
---
apiVersion: apps/v1
kind: Deployment
@ -77,6 +94,7 @@ spec:
kompose.volume.type: configMap
creationTimestamp: null
labels:
io.kompose.network/configmap-volume-default: "true"
io.kompose.service: web
spec:
containers:

View File

@ -17,6 +17,7 @@ spec:
metadata:
creationTimestamp: null
labels:
io.kompose.network/configmap-volume-default: "true"
io.kompose.service: db
spec:
containers:
@ -50,6 +51,22 @@ metadata:
io.kompose.service: db
name: db-cm0
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
creationTimestamp: null
name: configmap-volume-default
spec:
ingress:
- from:
- podSelector:
matchLabels:
io.kompose.network/configmap-volume-default: "true"
podSelector:
matchLabels:
io.kompose.network/configmap-volume-default: "true"
---
apiVersion: apps/v1
kind: Deployment
@ -69,6 +86,7 @@ spec:
metadata:
creationTimestamp: null
labels:
io.kompose.network/configmap-volume-default: "true"
io.kompose.service: web
spec:
containers:

View File

@ -19,6 +19,7 @@ spec:
metadata:
creationTimestamp: null
labels:
io.kompose.network/configmap-volume-default: "true"
io.kompose.service: db
spec:
containers:
@ -114,6 +115,7 @@ spec:
metadata:
creationTimestamp: null
labels:
io.kompose.network/configmap-volume-default: "true"
io.kompose.service: web
spec:
containers:

View File

@ -17,6 +17,7 @@ spec:
metadata:
creationTimestamp: null
labels:
io.kompose.network/configmap-volume-default: "true"
io.kompose.service: db
spec:
containers:
@ -110,6 +111,7 @@ spec:
metadata:
creationTimestamp: null
labels:
io.kompose.network/configmap-volume-default: "true"
io.kompose.service: web
spec:
containers:

View File

@ -34,6 +34,7 @@ spec:
metadata:
creationTimestamp: null
labels:
io.kompose.network/placement-default: "true"
io.kompose.service: redis
spec:
affinity:
@ -75,3 +76,19 @@ spec:
whenUnsatisfiable: ScheduleAnyway
status: {}
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
creationTimestamp: null
name: placement-default
spec:
ingress:
- from:
- podSelector:
matchLabels:
io.kompose.network/placement-default: "true"
podSelector:
matchLabels:
io.kompose.network/placement-default: "true"

View File

@ -34,6 +34,7 @@ spec:
metadata:
creationTimestamp: null
labels:
io.kompose.network/placement-default: "true"
io.kompose.service: redis
spec:
affinity:

View File

@ -16,6 +16,7 @@ spec:
metadata:
creationTimestamp: null
labels:
io.kompose.network/envvars-interpolation-default: "true"
io.kompose.service: myservice
spec:
containers:
@ -33,3 +34,19 @@ spec:
restartPolicy: Always
status: {}
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
creationTimestamp: null
name: envvars-interpolation-default
spec:
ingress:
- from:
- podSelector:
matchLabels:
io.kompose.network/envvars-interpolation-default: "true"
podSelector:
matchLabels:
io.kompose.network/envvars-interpolation-default: "true"

View File

@ -16,6 +16,7 @@ spec:
metadata:
creationTimestamp: null
labels:
io.kompose.network/envvars-interpolation-default: "true"
io.kompose.service: myservice
spec:
containers:

View File

@ -56,6 +56,7 @@ spec:
metadata:
creationTimestamp: null
labels:
io.kompose.network/expose-default: "true"
io.kompose.service: redis
spec:
containers:
@ -67,6 +68,22 @@ spec:
restartPolicy: Always
status: {}
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
creationTimestamp: null
name: expose-default
spec:
ingress:
- from:
- podSelector:
matchLabels:
io.kompose.network/expose-default: "true"
podSelector:
matchLabels:
io.kompose.network/expose-default: "true"
---
apiVersion: apps/v1
kind: Deployment
@ -93,6 +110,7 @@ spec:
kompose.service.expose.tls-secret: test-secret
creationTimestamp: null
labels:
io.kompose.network/expose-default: "true"
io.kompose.service: web
spec:
containers:
@ -146,3 +164,4 @@ spec:
secretName: test-secret
status:
loadBalancer: {}

View File

@ -56,6 +56,7 @@ spec:
metadata:
creationTimestamp: null
labels:
io.kompose.network/expose-default: "true"
io.kompose.service: redis
spec:
containers:
@ -130,6 +131,7 @@ spec:
metadata:
creationTimestamp: null
labels:
io.kompose.network/expose-default: "true"
io.kompose.service: web
spec:
containers:

View File

@ -1,28 +1,3 @@
---
apiVersion: v1
kind: Service
metadata:
annotations:
kompose.service.group: my-group
kompose.service.healthcheck.liveness.tcp_port: "8080"
kompose.service.healthcheck.readiness.interval: 10s
kompose.service.healthcheck.readiness.retries: "5"
kompose.service.healthcheck.readiness.tcp_port: "9090"
kompose.service.healthcheck.readiness.timeout: 1s
creationTimestamp: null
labels:
io.kompose.service: my-group
name: mongo
spec:
ports:
- name: "27017"
port: 27017
targetPort: 27017
selector:
io.kompose.service: my-group
status:
loadBalancer: {}
---
apiVersion: v1
kind: Service
@ -48,6 +23,31 @@ spec:
status:
loadBalancer: {}
---
apiVersion: v1
kind: Service
metadata:
annotations:
kompose.service.group: my-group
kompose.service.healthcheck.liveness.tcp_port: "8080"
kompose.service.healthcheck.readiness.interval: 10s
kompose.service.healthcheck.readiness.retries: "5"
kompose.service.healthcheck.readiness.tcp_port: "9090"
kompose.service.healthcheck.readiness.timeout: 1s
creationTimestamp: null
labels:
io.kompose.service: my-group
name: mongo
spec:
ports:
- name: "27017"
port: 27017
targetPort: 27017
selector:
io.kompose.service: my-group
status:
loadBalancer: {}
---
apiVersion: v1
kind: Service
@ -103,11 +103,11 @@ kind: Deployment
metadata:
annotations:
kompose.service.group: my-group
kompose.service.healthcheck.liveness.tcp_port: "8081"
kompose.service.healthcheck.readiness.interval: 11s
kompose.service.healthcheck.readiness.retries: "6"
kompose.service.healthcheck.readiness.tcp_port: "9091"
kompose.service.healthcheck.readiness.timeout: 2s
kompose.service.healthcheck.liveness.tcp_port: "8080"
kompose.service.healthcheck.readiness.interval: 10s
kompose.service.healthcheck.readiness.retries: "5"
kompose.service.healthcheck.readiness.tcp_port: "9090"
kompose.service.healthcheck.readiness.timeout: 1s
creationTimestamp: null
labels:
io.kompose.service: my-group
@ -122,33 +122,17 @@ spec:
metadata:
annotations:
kompose.service.group: my-group
kompose.service.healthcheck.liveness.tcp_port: "8080"
kompose.service.healthcheck.readiness.interval: 10s
kompose.service.healthcheck.readiness.retries: "5"
kompose.service.healthcheck.readiness.tcp_port: "9090"
kompose.service.healthcheck.readiness.timeout: 1s
kompose.service.healthcheck.liveness.tcp_port: "8081"
kompose.service.healthcheck.readiness.interval: 11s
kompose.service.healthcheck.readiness.retries: "6"
kompose.service.healthcheck.readiness.tcp_port: "9091"
kompose.service.healthcheck.readiness.timeout: 2s
creationTimestamp: null
labels:
io.kompose.network/healthcheck-default: "true"
io.kompose.service: my-group
spec:
containers:
- image: mongo
livenessProbe:
failureThreshold: 5
periodSeconds: 10
tcpSocket:
port: 8080
timeoutSeconds: 1
name: mongo
ports:
- containerPort: 27017
readinessProbe:
failureThreshold: 5
periodSeconds: 10
tcpSocket:
port: 9090
timeoutSeconds: 1
resources: {}
- image: mysql
livenessProbe:
failureThreshold: 6
@ -166,9 +150,42 @@ spec:
port: 9091
timeoutSeconds: 2
resources: {}
- image: mongo
livenessProbe:
failureThreshold: 5
periodSeconds: 10
tcpSocket:
port: 8080
timeoutSeconds: 1
name: mongo
ports:
- containerPort: 27017
readinessProbe:
failureThreshold: 5
periodSeconds: 10
tcpSocket:
port: 9090
timeoutSeconds: 1
resources: {}
restartPolicy: Always
status: {}
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
creationTimestamp: null
name: healthcheck-default
spec:
ingress:
- from:
- podSelector:
matchLabels:
io.kompose.network/healthcheck-default: "true"
podSelector:
matchLabels:
io.kompose.network/healthcheck-default: "true"
---
apiVersion: apps/v1
kind: Deployment
@ -203,6 +220,7 @@ spec:
kompose.service.healthcheck.readiness.timeout: 1s
creationTimestamp: null
labels:
io.kompose.network/healthcheck-default: "true"
io.kompose.service: postgresql
spec:
containers:
@ -256,6 +274,7 @@ spec:
kompose.service.healthcheck.readiness.timeout: 1s
creationTimestamp: null
labels:
io.kompose.network/healthcheck-default: "true"
io.kompose.service: redis
spec:
containers:

View File

@ -122,6 +122,7 @@ spec:
metadata:
creationTimestamp: null
labels:
io.kompose.network/healthcheck-default: "true"
io.kompose.service: mongo
spec:
containers:
@ -211,6 +212,7 @@ spec:
metadata:
creationTimestamp: null
labels:
io.kompose.network/healthcheck-default: "true"
io.kompose.service: mysql
spec:
containers:
@ -301,6 +303,7 @@ spec:
metadata:
creationTimestamp: null
labels:
io.kompose.network/healthcheck-default: "true"
io.kompose.service: postgresql
spec:
containers:
@ -390,6 +393,7 @@ spec:
metadata:
creationTimestamp: null
labels:
io.kompose.network/healthcheck-default: "true"
io.kompose.service: redis
spec:
containers:

View File

@ -16,6 +16,7 @@ spec:
metadata:
creationTimestamp: null
labels:
io.kompose.network/multiple-files-default: "true"
io.kompose.service: bar
spec:
containers:
@ -25,6 +26,22 @@ spec:
restartPolicy: Always
status: {}
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
creationTimestamp: null
name: multiple-files-default
spec:
ingress:
- from:
- podSelector:
matchLabels:
io.kompose.network/multiple-files-default: "true"
podSelector:
matchLabels:
io.kompose.network/multiple-files-default: "true"
---
apiVersion: apps/v1
kind: Deployment
@ -43,6 +60,7 @@ spec:
metadata:
creationTimestamp: null
labels:
io.kompose.network/multiple-files-default: "true"
io.kompose.service: foo
spec:
containers:
@ -51,3 +69,4 @@ spec:
resources: {}
restartPolicy: Always
status: {}

View File

@ -16,6 +16,7 @@ spec:
metadata:
creationTimestamp: null
labels:
io.kompose.network/multiple-files-default: "true"
io.kompose.service: bar
spec:
containers:
@ -84,6 +85,7 @@ spec:
metadata:
creationTimestamp: null
labels:
io.kompose.network/multiple-files-default: "true"
io.kompose.service: foo
spec:
containers:

View File

@ -21,6 +21,7 @@ spec:
kompose.volume.type: persistentVolumeClaim
creationTimestamp: null
labels:
io.kompose.network/multiple-type-volumes-default: "true"
io.kompose.service: db
spec:
containers:
@ -53,6 +54,22 @@ spec:
storage: 100Mi
status: {}
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
creationTimestamp: null
name: multiple-type-volumes-default
spec:
ingress:
- from:
- podSelector:
matchLabels:
io.kompose.network/multiple-type-volumes-default: "true"
podSelector:
matchLabels:
io.kompose.network/multiple-type-volumes-default: "true"
---
apiVersion: apps/v1
kind: Deployment
@ -76,6 +93,7 @@ spec:
kompose.volume.type: configMap
creationTimestamp: null
labels:
io.kompose.network/multiple-type-volumes-default: "true"
io.kompose.service: web
spec:
containers:

View File

@ -19,6 +19,7 @@ spec:
metadata:
creationTimestamp: null
labels:
io.kompose.network/multiple-type-volumes-default: "true"
io.kompose.service: db
spec:
containers:
@ -113,6 +114,7 @@ spec:
metadata:
creationTimestamp: null
labels:
io.kompose.network/multiple-type-volumes-default: "true"
io.kompose.service: web
spec:
containers:

View File

@ -1,10 +1,11 @@
web:
image: tuna/docker-counter23
ports:
- "5000:5000"
links:
- redis
redis:
image: redis:3.0
ports:
- "6379"
services:
web:
image: tuna/docker-counter23
ports:
- "5000:5000"
links:
- redis
redis:
image: redis:3.0
ports:
- "6379"

View File

@ -35,6 +35,7 @@ spec:
metadata:
creationTimestamp: null
labels:
io.kompose.network/service-group-default: "true"
io.kompose.service: librenms-dispatcher
spec:
containers:
@ -82,3 +83,19 @@ spec:
storage: 100Mi
status: {}
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
creationTimestamp: null
name: service-group-default
spec:
ingress:
- from:
- podSelector:
matchLabels:
io.kompose.network/service-group-default: "true"
podSelector:
matchLabels:
io.kompose.network/service-group-default: "true"

View File

@ -43,6 +43,7 @@ spec:
kompose.service.expose.ingress-class-name: nginx
creationTimestamp: null
labels:
io.kompose.network/single-file-output-default: "true"
io.kompose.service: front-end
spec:
containers:
@ -83,3 +84,20 @@ spec:
pathType: Prefix
status:
loadBalancer: {}
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
creationTimestamp: null
name: single-file-output-default
spec:
ingress:
- from:
- podSelector:
matchLabels:
io.kompose.network/single-file-output-default: "true"
podSelector:
matchLabels:
io.kompose.network/single-file-output-default: "true"

View File

@ -56,6 +56,7 @@ spec:
metadata:
creationTimestamp: null
labels:
io.kompose.network/statefulset-default: "true"
io.kompose.service: db
spec:
containers:
@ -94,6 +95,22 @@ spec:
status:
replicas: 0
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
creationTimestamp: null
name: statefulset-default
spec:
ingress:
- from:
- podSelector:
matchLabels:
io.kompose.network/statefulset-default: "true"
podSelector:
matchLabels:
io.kompose.network/statefulset-default: "true"
---
apiVersion: apps/v1
kind: StatefulSet
@ -112,6 +129,7 @@ spec:
metadata:
creationTimestamp: null
labels:
io.kompose.network/statefulset-default: "true"
io.kompose.service: wordpress
spec:
containers:

View File

@ -52,6 +52,7 @@ spec:
metadata:
creationTimestamp: null
labels:
io.kompose.network/statefulset-default: "true"
io.kompose.service: db
spec:
containers:
@ -109,6 +110,7 @@ spec:
metadata:
creationTimestamp: null
labels:
io.kompose.network/statefulset-default: "true"
io.kompose.service: db
spec:
containers:
@ -191,6 +193,7 @@ spec:
metadata:
creationTimestamp: null
labels:
io.kompose.network/statefulset-default: "true"
io.kompose.service: wordpress
spec:
containers:
@ -248,6 +251,7 @@ spec:
metadata:
creationTimestamp: null
labels:
io.kompose.network/statefulset-default: "true"
io.kompose.service: wordpress
spec:
containers:

View File

@ -138,6 +138,7 @@ kind: Pod
metadata:
creationTimestamp: null
labels:
io.kompose.network/v2-default: "true"
io.kompose.service: foo
name: foo
spec:
@ -194,6 +195,22 @@ spec:
- 1234
status: {}
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
creationTimestamp: null
name: v2-default
spec:
ingress:
- from:
- podSelector:
matchLabels:
io.kompose.network/v2-default: "true"
podSelector:
matchLabels:
io.kompose.network/v2-default: "true"
---
apiVersion: apps/v1
kind: Deployment
@ -216,6 +233,7 @@ spec:
kompose.service.type: loadbalancer
creationTimestamp: null
labels:
io.kompose.network/v2-default: "true"
io.kompose.service: redis
spec:
containers:

View File

@ -138,6 +138,7 @@ kind: Pod
metadata:
creationTimestamp: null
labels:
io.kompose.network/v2-default: "true"
io.kompose.service: foo
name: foo
spec:
@ -214,6 +215,7 @@ spec:
metadata:
creationTimestamp: null
labels:
io.kompose.network/v2-default: "true"
io.kompose.service: redis
spec:
containers:

View File

@ -38,7 +38,7 @@ spec:
creationTimestamp: null
labels:
io.kompose.network/app-network: "true"
io.kompose.network/normalized-network: "true"
io.kompose.network/v30-normalized-network: "true"
io.kompose.network/web-network: "true"
io.kompose.service: foo
spec:
@ -90,16 +90,16 @@ apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
creationTimestamp: null
name: normalized-network
name: v30-normalized-network
spec:
ingress:
- from:
- podSelector:
matchLabels:
io.kompose.network/normalized-network: "true"
io.kompose.network/v30-normalized-network: "true"
podSelector:
matchLabels:
io.kompose.network/normalized-network: "true"
io.kompose.network/v30-normalized-network: "true"
---
apiVersion: apps/v1
@ -123,6 +123,7 @@ spec:
kompose.service.type: headless
creationTimestamp: null
labels:
io.kompose.network/v30-default: "true"
io.kompose.service: redis
spec:
containers:
@ -139,3 +140,19 @@ spec:
restartPolicy: Always
status: {}
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
creationTimestamp: null
name: v30-default
spec:
ingress:
- from:
- podSelector:
matchLabels:
io.kompose.network/v30-default: "true"
podSelector:
matchLabels:
io.kompose.network/v30-default: "true"

View File

@ -38,7 +38,7 @@ spec:
creationTimestamp: null
labels:
io.kompose.network/app-network: "true"
io.kompose.network/normalized-network: "true"
io.kompose.network/v30-normalized-network: "true"
io.kompose.network/web-network: "true"
io.kompose.service: foo
spec:
@ -114,6 +114,7 @@ spec:
metadata:
creationTimestamp: null
labels:
io.kompose.network/v30-default: "true"
io.kompose.service: redis
spec:
containers:

View File

@ -35,6 +35,7 @@ spec:
metadata:
creationTimestamp: null
labels:
io.kompose.network/windows-default: "true"
io.kompose.service: db
spec:
containers:
@ -69,3 +70,19 @@ spec:
storage: 100Mi
status: {}
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
creationTimestamp: null
name: windows-default
spec:
ingress:
- from:
- podSelector:
matchLabels:
io.kompose.network/windows-default: "true"
podSelector:
matchLabels:
io.kompose.network/windows-default: "true"

View File

@ -35,6 +35,7 @@ spec:
metadata:
creationTimestamp: null
labels:
io.kompose.network/windows-default: "true"
io.kompose.service: db
spec:
containers:

View File

@ -36,7 +36,7 @@ ENV PATH="$PATH:$GOPATH/bin:$GOROOT/bin" \
WORKDIR /tmp/go
RUN curl https://storage.googleapis.com/golang/go$GOVERSION.linux-amd64.tar.gz | tar -xz -C /usr/local
RUN go get golang.org/x/lint/golint
RUN go get honnef.co/go/tools/cmd/staticcheck@latest
WORKDIR $KOMPOSE_SRC
# This image can be run as any user