diff --git a/README.md b/README.md index 46701e3c4..051fce1eb 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ Replace this value with a real registry host, or create a `docker.io/library/reg 1. Create then publish to your mirror registry: ```sh ./bin/oc-bundle create full --config imageset-config.yaml --dir test-create --output archives --log-level debug - ./bin/oc-bundle publish --archive archives --dir test-publish --to-mirror reg.mirror.com + ./bin/oc-bundle publish --archive archives --dir test-publish --to-mirror reg.mirror.com --output results ``` For configuration and options, see the [expanded overview](./docs/overview.md) and [usage](./docs/usage.md) docs. diff --git a/data/imageset-config.yaml b/data/imageset-config.yaml index fe77c39be..4508298b7 100644 --- a/data/imageset-config.yaml +++ b/data/imageset-config.yaml @@ -28,6 +28,16 @@ mirror: - name: nginx additionalimages: - name: registry.redhat.io/ubi8/ubi:latest + helm: + local: + - name: podinfo + path: /test/podinfo-5.0.0.tar.gz + repos: + - name: podinfo + url: https://stefanprodan.github.io/podinfo + charts: + - name: podinfo + version: 5.0.0 blockedimages: - name: alpine - name: redis diff --git a/go.mod b/go.mod index a6997399d..f19f1dc1c 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.16 require ( github.com/blang/semver/v4 v4.0.0 github.com/bshuster-repo/logrus-logstash-hook v1.0.2 // indirect - github.com/containerd/containerd v1.5.2 + github.com/containerd/containerd v1.5.4 github.com/containers/image/v5 v5.15.2 github.com/docker/distribution v2.7.1+incompatible github.com/go-git/go-git/v5 v5.4.2 @@ -28,13 +28,14 @@ require ( github.com/stretchr/testify v1.7.0 golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a gopkg.in/yaml.v2 v2.4.0 + helm.sh/helm/v3 v3.7.0 k8s.io/apimachinery v0.22.1 - k8s.io/cli-runtime v0.22.0 + k8s.io/cli-runtime v0.22.1 k8s.io/client-go v0.22.1 k8s.io/klog v1.0.0 k8s.io/klog/v2 v2.9.0 - k8s.io/kubectl v0.22.0 - rsc.io/letsencrypt v0.0.3 // indirect + k8s.io/kubectl v0.22.1 + sigs.k8s.io/kustomize/kyaml v0.11.0 sigs.k8s.io/yaml v1.2.0 ) diff --git a/go.sum b/go.sum index c1c23e5f7..8bb946710 100644 --- a/go.sum +++ b/go.sum @@ -56,11 +56,28 @@ github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935 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/toml v0.4.1 h1:GaI7EiDXDRfa8VshkTj7Fym7ha+y8/XxIgD2okUIjLw= github.com/BurntSushi/toml v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20OEh60= +github.com/DATA-DOG/go-sqlmock v1.5.0/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd h1:sjQovDkwrZp8u+gxLtPgKGjk5hCxuy2hrRejBTA9xFU= github.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd/go.mod h1:64YHyfSL2R96J44Nlwm39UHepQbyR5q10x7iYa1ks2E= +github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= +github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= +github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= +github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= +github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= +github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc= +github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= +github.com/Masterminds/sprig v2.22.0+incompatible h1:z4yfnGrZ7netVz+0EDJ0Wi+5VZCSYp4Z0m2dk6cEM60= +github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o= +github.com/Masterminds/sprig/v3 v3.2.2 h1:17jRggJu518dr3QaafizSXOjKYp94wKfABxUmyxvxX8= +github.com/Masterminds/sprig/v3 v3.2.2/go.mod h1:UoaO7Yp8KlPnJIYWTFkMaqPUYKTfGFPhxNuwnnxkKlk= +github.com/Masterminds/squirrel v1.5.0 h1:JukIZisrUXadA9pl3rMkjhiamxiB0cXiu+HGp/Y8cY8= +github.com/Masterminds/squirrel v1.5.0/go.mod h1:NNaOrjSoIDfDA40n7sr2tPNZRfjzjA400rg+riTZj10= +github.com/Masterminds/vcs v1.13.1/go.mod h1:N09YCmOQr6RLxC6UNHzuVwAdodYbbnycGHSmwVJjcKA= github.com/Microsoft/go-winio v0.4.11/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= @@ -78,6 +95,7 @@ github.com/Microsoft/hcsshim v0.8.9/go.mod h1:5692vkUqntj1idxauYlpoINNKeqCiG6Sg3 github.com/Microsoft/hcsshim v0.8.14/go.mod h1:NtVKoYxQuTLx6gEq0L96c9Ju4JbRJ4nY2ow3VK6a9Lg= github.com/Microsoft/hcsshim v0.8.15/go.mod h1:x38A4YbHbdxJtc0sF6oIz+RG0npwSCAvn69iY6URG00= github.com/Microsoft/hcsshim v0.8.16/go.mod h1:o5/SZqmR7x9JNKsW3pu+nqHm0MF8vbA+VxGOoXdC600= +github.com/Microsoft/hcsshim v0.8.18/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwTOcER2fw4I4= github.com/Microsoft/hcsshim v0.8.20 h1:ZTwcx3NS8n07kPf/JZ1qwU6vnjhVPMUWlXBF8r9UxrE= github.com/Microsoft/hcsshim v0.8.20/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwTOcER2fw4I4= github.com/Microsoft/hcsshim/test v0.0.0-20201218223536-d3e5debf77da/go.mod h1:5hlzMzRKMLyo42nCZ9oml8AdTlq/0cvIaBv6tK1RehU= @@ -136,12 +154,14 @@ github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPd github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= -github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a h1:idn718Q4B6AGu/h5Sxe66HYVdqdGu2l9Iebqhi/AEoA= github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= +github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535 h1:4daAzAu0S6Vi7/lbWECcX0j45yZReDZ56BQsrVBOEEY= +github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg= github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= github.com/aws/aws-sdk-go v1.15.11/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0= github.com/aws/aws-sdk-go v1.17.7/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aws/aws-sdk-go v1.34.9/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0= github.com/aws/aws-sdk-go v1.35.24 h1:U3GNTg8+7xSM6OAJ8zksiSM4bRqxBWmVwwehvOSNG3A= github.com/aws/aws-sdk-go v1.35.24/go.mod h1:tlPOdRjfxPBpNIwqDj61rmsnA85v9jc0Ps9+muhnW+k= github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= @@ -247,8 +267,9 @@ github.com/containerd/containerd v1.5.0-beta.3/go.mod h1:/wr9AVtEM7x9c+n0+stptlo github.com/containerd/containerd v1.5.0-beta.4/go.mod h1:GmdgZd2zA2GYIBZ0w09ZvgqEq8EfBp/m3lcVZIvPHhI= github.com/containerd/containerd v1.5.0-rc.0/go.mod h1:V/IXoMqNGgBlabz3tHD2TWDoTJseu1FGOKuoA4nNb2s= github.com/containerd/containerd v1.5.1/go.mod h1:0DOxVqwDy2iZvrZp2JUx/E+hS0UNTVn7dJnIOwtYR4g= -github.com/containerd/containerd v1.5.2 h1:MG/Bg1pbmMb61j3wHCFWPxESXHieiKr2xG64px/k8zQ= github.com/containerd/containerd v1.5.2/go.mod h1:0DOxVqwDy2iZvrZp2JUx/E+hS0UNTVn7dJnIOwtYR4g= +github.com/containerd/containerd v1.5.4 h1:uPF0og3ByFzDnaStfiQj3fVGTEtaSNyU+bW7GR/nqGA= +github.com/containerd/containerd v1.5.4/go.mod h1:sx18RgvW6ABJ4iYUw7Q5x7bgFOAB9B6G7+yO0XBc4zw= github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= github.com/containerd/continuity v0.0.0-20190815185530-f2a389ac0a02/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= github.com/containerd/continuity v0.0.0-20191127005431-f65d91d395eb/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= @@ -340,6 +361,7 @@ github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7Do github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.11 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw= github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/cyphar/filepath-securejoin v0.2.2 h1:jCwT2GTP+PY5nBz3c/YL5PAIbusElVrPujOBSCj8xRg= github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4= github.com/cznic/b v0.0.0-20180115125044-35e9bbe41f07/go.mod h1:URriBxXwVq5ijiJ12C7iIZqlA69nTlI+LgI6/pwftG8= github.com/cznic/fileutil v0.0.0-20180108211300-6a051e75936f/go.mod h1:8S58EK26zhXSxzv7NQFpnliaOQsmDUxvoQO3rt154Vg= @@ -367,11 +389,14 @@ 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/daviddengcn/go-colortext v0.0.0-20160507010035-511bcaf42ccd/go.mod h1:dv4zxwHi5C/8AeI+4gX4dCWOIvNi7I6JCSX0HvlKPgE= github.com/denisenkom/go-mssqldb v0.0.0-20190515213511-eb9f6a1743f3/go.mod h1:zAg7JM8CkOJ43xKXIj7eRO9kmWm/TW578qo+oDO6tuM= +github.com/denisenkom/go-mssqldb v0.9.0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= github.com/denverdino/aliyungo v0.0.0-20190125010748-a747050bb1ba/go.mod h1:dV8lFg6daOBZbT6/BDGIz6Y3WFGn8juu6G+CQ6LHtl0= github.com/dgrijalva/jwt-go v0.0.0-20170104182250-a601269ab70c/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/dhui/dktest v0.3.0/go.mod h1:cyzIUfGsBEbZ6BT7tnXqAShHSXCZhSNmFl70sZ7c1yc= +github.com/distribution/distribution/v3 v3.0.0-20210804104954-38ab4c606ee3 h1:rEK0juuU5idazw//KzUcL3yYwUU3DIe2OnfJwjDBqno= +github.com/distribution/distribution/v3 v3.0.0-20210804104954-38ab4c606ee3/go.mod h1:gt38b7cvVKazi5XkHvINNytZXgTEntyhtyM3HQz46Nk= github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= github.com/docker/cli v0.0.0-20200130152716-5d0cf8839492/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/cli v20.10.7+incompatible h1:pv/3NqibQKphWZiAskMzdz8w0PRbtTaEB+f6NwdU7Is= @@ -387,6 +412,7 @@ github.com/docker/docker v0.7.3-0.20190327010347-be7ac8be2ae0/go.mod h1:eEKB0N0r github.com/docker/docker v0.7.3-0.20190817195342-4760db040282/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v1.4.2-0.20191219165747-a9416c67da9f/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v1.4.2-0.20200203170920-46ec8731fbce/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v17.12.0-ce-rc1.0.20200618181300-9dc6525e6118+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v20.10.3-0.20210216175712-646072ed6524+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v20.10.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v20.10.7+incompatible h1:Z6O9Nhsjv+ayUEeI1IojKbYcsGdgYSNqxe1s2MYzUhQ= @@ -397,6 +423,7 @@ github.com/docker/docker-credential-helpers v0.6.4/go.mod h1:ofX3UI0Gz1TteYBjtgs 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-20170721190031-9461782956ad/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= +github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c h1:+pKlWGMw7gf6bQ+oDZB4KHQFypsfjYlq/C4rfL7D3g8= github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= github.com/docker/go-metrics v0.0.0-20180209012529-399ea8c73916/go.mod h1:/u0gXw0Gay3ceNrsHubL3BtdOL2fHf93USgMTe0W5dI= github.com/docker/go-metrics v0.0.1 h1:AgB/0SvBxihN0X8OR4SjsblXkbMvalQ8cjmtKQ2rQV8= @@ -445,6 +472,7 @@ github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZM github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= +github.com/fatih/color v1.12.0 h1:mRhaKNwANqRgUBGKmnI5ZxEk7QXmjQeCcuYFMX2bfcc= github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8SPQ= github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= @@ -559,10 +587,20 @@ github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTM github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= +github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs= +github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/gobuffalo/flect v0.2.0/go.mod h1:W3K3X9ksuZfir8f/LrfVtWmCDQFfayuylOJ7sz/Fj80= github.com/gobuffalo/flect v0.2.2/go.mod h1:vmkQwuZYhN5Pc4ljYQZzP+1sq+NEkK+lh20jmEmX3jc= +github.com/gobuffalo/logger v1.0.3 h1:YaXOTHNPCvkqqA7w05A4v0k2tCdpr+sgFlgINbQ6gqc= +github.com/gobuffalo/logger v1.0.3/go.mod h1:SoeejUwldiS7ZsyCBphOGURmWdwUFXs0J7TCjEhjKxM= +github.com/gobuffalo/packd v1.0.0 h1:6ERZvJHfe24rfFmA9OaoKBdC7+c9sydrytMg8SdFGBM= +github.com/gobuffalo/packd v1.0.0/go.mod h1:6VTc4htmJRFB7u1m/4LeMTWjFoYrUiBkU9Fdec9hrhI= +github.com/gobuffalo/packr/v2 v2.8.1 h1:tkQpju6i3EtMXJ9uoF5GT6kB+LMTimDWD8Xvbz6zDVA= +github.com/gobuffalo/packr/v2 v2.8.1/go.mod h1:c/PLlOuTU+p3SybaJATW3H6lX/iK7xEz5OeMf+NnJpg= +github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= +github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= github.com/goccy/go-yaml v1.8.1/go.mod h1:wS4gNoLalDSJxo/SpngzPQ2BN4uuZVLCmbM4S3vd4+Y= github.com/gocql/gocql v0.0.0-20190301043612-f6df8288f9b4/go.mod h1:4Fw1eo5iaEhDUs8XyuhSVCVy52Jq3L+/3GJgYkwc+/0= github.com/godbus/dbus v0.0.0-20151105175453-c7fdd8b5cd55/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= @@ -570,6 +608,8 @@ github.com/godbus/dbus v0.0.0-20180201030542-885f9cc04c9c/go.mod h1:/YcGZj5zSblf github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= 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/godror/godror v0.24.2/go.mod h1:wZv/9vPiUib6tkoDl+AZ/QLf5YZgMravZ7jxH2eQWAE= +github.com/gofrs/flock v0.8.0/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= github.com/gofrs/uuid v3.3.0+incompatible h1:8K4tyRfvU1CYPgJsveYFQMhpFd/wXNM7iK6rR7UHz84= github.com/gofrs/uuid v3.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= @@ -585,6 +625,7 @@ github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-migrate/migrate/v4 v4.6.2 h1:LDDOHo/q1W5UDj6PbkxdCv7lv9yunyZHXvxuwDkGo3k= github.com/golang-migrate/migrate/v4 v4.6.2/go.mod h1:JYi6reN3+Z734VZ0akNuyOJNcrg45ZL7LDBMW3WGJL0= +github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -630,6 +671,8 @@ github.com/golangplus/bytes v0.0.0-20160111154220-45c989fe5450/go.mod h1:Bk6SMAO github.com/golangplus/fmt v1.0.0/go.mod h1:zpM0OfbMCjPtd2qkTD/jX2MgiFCqklhSUFyDW44gVQE= github.com/golangplus/testing v0.0.0-20180327235837-af21d9c3145e/go.mod h1:0AA//k/eakGydO4jKRoRL2j92ZKSzTgj9tclaCrvXHk= github.com/golangplus/testing v1.0.0/go.mod h1:ZDreixUV3YzhoVraIDyOzHrr76p6NUh6k/pPg/Q3gYA= +github.com/gomodule/redigo v1.8.2 h1:H5XSIre1MB5NbPYFp+i1NBbb5qN1W8Y8YAQoAYbkm8k= +github.com/gomodule/redigo v1.8.2/go.mod h1:P9dn9mFrCBvWhGE1wpxx6fgq7BAeLBk+UUUzlpkBYO0= github.com/gonum/blas v0.0.0-20181208220705-f22b278b28ac/go.mod h1:P32wAyui1PQ58Oce/KYkOqQv8cVw1zAapXOl+dRFGbc= github.com/gonum/floats v0.0.0-20181209220543-c233463c7e82/go.mod h1:PxC8OnwL11+aosOB5+iEPoV3picfs8tUpkVd0pDo+Kg= github.com/gonum/graph v0.0.0-20170401004347-50b27dea7ebb/go.mod h1:ye018NnX1zrbOLqwBvs2HqyyTouQgnL8C+qzYk1snPY= @@ -701,8 +744,9 @@ github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97Dwqy 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/handlers v0.0.0-20150720190736-60c7bfde3e33/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= -github.com/gorilla/handlers v1.4.2 h1:0QniY0USkHQ1RGCLfKxeNHK9bkDHGRYGNDFBCS+YARg= github.com/gorilla/handlers v1.4.2/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= +github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4= +github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q= github.com/gorilla/mux v0.0.0-20191024121256-f395758b854c/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.7.1/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= @@ -714,6 +758,8 @@ github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB7 github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gosuri/uitable v0.0.4 h1:IG2xLKRvErL3uhY6e1BylFzG+aJiwQviDDTfOKeKTpY= +github.com/gosuri/uitable v0.0.4/go.mod h1:tKR86bXuXPZazfOTG1FIzvjIdXzd0mo4Vtn16vt0PJo= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 h1:pdN6V1QBWetyv/0+wjACpqVH+eVULgEjkurDLq3goeM= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= @@ -759,6 +805,9 @@ github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0m github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/huandu/xstrings v1.3.1/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= +github.com/huandu/xstrings v1.3.2 h1:L18LIDzqlW6xN2rEkpdV8+oL/IXWJ1APd+vsdYy4Wdw= +github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= 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= @@ -782,10 +831,13 @@ github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.0.0-20160803190731-bd40a432e4c7/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeYCZ7fLUTSywik= github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= +github.com/jmoiron/sqlx v1.3.1 h1:aLN7YINNZ7cYOPK3QC83dbM6KT0NMqVMw961TqrejlE= +github.com/jmoiron/sqlx v1.3.1/go.mod h1:2BljVx/86SuTyjE+aPYlHCTNvZrnJXghYGpNiXLBMCQ= github.com/joefitzgerald/rainbow-reporter v0.1.0/go.mod h1:481CNgqmVHQZzdIbN52CupLJyoVwB10FQ/IQlF1pdL8= github.com/joelanford/ignore v0.0.0-20210607151042-0d25dc18b62d/go.mod h1:7HQupe4vyNxMKXmM5DFuwXHsqwMyglcYmZBtlDPIcZ8= github.com/joelanford/ignore v0.0.0-20210610194209-63d4919d8fb2 h1:MrNL6nf5H5dLVU3kRAPViSEDD3z/9hlbe674MeCH+IE= @@ -810,6 +862,8 @@ github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7V github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 h1:iQTw/8FWTuc7uiaSepXwyf3o52HaUYcV+Tu66S3F5GA= github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0/go.mod h1:1NbS8ALrpOvjt0rHPNLyCIeMtbizbir8U//inJ+zuB8= +github.com/karrick/godirwalk v1.15.8 h1:7+rWAZPn9zuRxaIqqT8Ohs2Q2Ac0msBqwRdxNCr2VVs= +github.com/karrick/godirwalk v1.15.8/go.mod h1:j4mkqPuvaLI8mp1DroR3P6ad7cyYd4c1qeJ3RV7ULlk= github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 h1:DowS9hvgyYSX4TO5NpyC606/Z4SxnNYbT+WX27or6Ck= github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= @@ -833,6 +887,7 @@ github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQ github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kortschak/utter v1.0.1/go.mod h1:vSmSjbyrlKjjsL71193LmzBOKgwePk9DH6uFaWHIInc= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= @@ -846,8 +901,15 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kshvakov/clickhouse v1.3.5/go.mod h1:DMzX7FxRymoNkVgizH0DWAL8Cur7wHLgx3MUnGwJqpE= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 h1:SOEGU9fKiNWd/HOJuq6+3iTQz8KNCLtVX6idSoTLdUw= +github.com/lann/builder v0.0.0-20180802200727-47ae307949d0/go.mod h1:dXGbAdH5GtBTC4WfIxhKZfyBF/HBFgRZSWwZ9g/He9o= +github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 h1:P6pPBnrTSX3DEVR4fDembhRWSsG5rVo6hYhAB/ADZrk= +github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0/go.mod h1:vmVJ0l/dxyfGW6FmdpVm2joNMFikkuWg0EoCKLGUMNw= github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lib/pq v1.10.0 h1:Zx5DJFEYQXio93kgXnQ09fXNiUKsqv4OUEu2UtGcB1E= +github.com/lib/pq v1.10.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0= github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE= github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= @@ -869,6 +931,12 @@ github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7 github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA= github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/manifoldco/promptui v0.8.0/go.mod h1:n4zTdgP0vr0S3w7/O/g98U+e0gwLScEXGwov2nIKuGQ= +github.com/markbates/errx v1.1.0 h1:QDFeR+UP95dO12JgW+tgi2UVfo0V8YBHiUIOaeBPiEI= +github.com/markbates/errx v1.1.0/go.mod h1:PLa46Oex9KNbVDZhKel8v1OT7hD5JZ2eI7AHhA0wswc= +github.com/markbates/oncer v1.0.0 h1:E83IaVAHygyndzPimgUYJjbshhDTALZyXxvk9FOlQRY= +github.com/markbates/oncer v1.0.0/go.mod h1:Z59JA581E9GP6w96jai+TGqafHPW+cPfRxz2aSZ0mcI= +github.com/markbates/safe v1.0.1 h1:yjZkbvRM6IzKj9tlu/zMJLS0n/V351OZWRnF3QfaUxI= +github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0= github.com/marstr/guid v1.1.0/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHefzho= github.com/matryer/is v1.2.0 h1:92UTHpy8CDwaJ08GqLDzhhuixiBUUD1p3AU6PHddz4A= github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA= @@ -876,21 +944,27 @@ github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaO github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= +github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-oci8 v0.1.1/go.mod h1:wjDx6Xm9q7dFtHJvIlrI99JytznLw5wQ4R+9mNXJwGI= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= github.com/mattn/go-shellwords v1.0.10/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y= +github.com/mattn/go-shellwords v1.0.11/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y= github.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y= github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= +github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/mattn/go-sqlite3 v1.14.8 h1:gDp86IdQsN/xWjIEmr9MF6o9mpksUgh0fu+9ByFxzIU= github.com/mattn/go-sqlite3 v1.14.8/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= @@ -905,6 +979,10 @@ github.com/mikefarah/yq/v3 v3.0.0-20201202084205-8846255d1c37/go.mod h1:dYWq+UWo github.com/mistifyio/go-zfs v2.1.1+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4= github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= +github.com/mitchellh/cli v1.1.2/go.mod h1:6iaV0fGdElS6dPBx0EApTxHrcWvmJphyh2n8YBLPPZ4= +github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= +github.com/mitchellh/copystructure v1.1.1 h1:Bp6x9R1Wn16SIz3OfeDr0b7RnCG2OB66Y7PQyC/cvq4= +github.com/mitchellh/copystructure v1.1.1/go.mod h1:EBArHfARyrSWO/+Wyr9zwEkc6XMFB9XyNgFNmRkZZU4= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= @@ -920,6 +998,9 @@ github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag= github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A= +github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/mitchellh/reflectwalk v1.0.1 h1:FVzMWA5RllMAKIdUSC8mdWo3XtwoecrH79BY70sEEpE= +github.com/mitchellh/reflectwalk v1.0.1/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/moby/buildkit v0.0.0-20181107081847-c3a857e3fca0/go.mod h1:nnELdKPRkUAQR6pAB3mRU3+IlbqL3SSaAWqQL8k/K+4= github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg= github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc= @@ -976,6 +1057,7 @@ github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQ github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= github.com/olekukonko/tablewriter v0.0.4/go.mod h1:zq6QwlOf5SlnkVbMSr5EoBv3636FWnp+qbPhuoO21uA= +github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo v0.0.0-20151202141238-7f8ab55aaf3b/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -1158,12 +1240,16 @@ github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1 github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446/go.mod h1:uYEyJGbgTkfkS4+E/PavXkNJcbFIpEtjt2B0KDQ5+9M= +github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/robfig/cron v1.2.0/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfmt2k= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-charset v0.0.0-20180617210344-2471d30d28b4/go.mod h1:qgYeAmZ5ZIpBWTGllZSQnw97Dj+woV0toclVaRGI8pc= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.5.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rubenv/sql-migrate v0.0.0-20210614095031-55d5740dbbcc h1:BD7uZqkN8CpjJtN/tScAKiccBikU4dlqe/gNrkRaPY4= +github.com/rubenv/sql-migrate v0.0.0-20210614095031-55d5740dbbcc/go.mod h1:HFLT6i9iR4QBOF5rdCyjddC9t59ArqWJV2xx+jwcCMo= github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= @@ -1179,6 +1265,8 @@ github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAm github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= +github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ= +github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= @@ -1202,10 +1290,12 @@ github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTd github.com/spf13/afero v1.6.0 h1:xoax2sJ2DT8S8xA2paPFjDCScCNeWsg75VG0DLRreiY= github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng= github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= +github.com/spf13/cobra v0.0.6/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI= github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo= @@ -1284,9 +1374,12 @@ github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhe github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonpointer v0.0.0-20190809123943-df4f5c81cb3b/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo= github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= github.com/xeipuuv/gojsonschema v0.0.0-20180618132009-1d523034197f/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs= +github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 h1:nIPpBwaJSVYIxUFsDv3M8ofmx9yWTog9BfvIu0q41lo= github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos= @@ -1309,6 +1402,8 @@ github.com/yvasiyarov/gorelic v0.0.7/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96Tg github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg= github.com/yvasiyarov/newrelic_platform_go v0.0.0-20160601141957-9c099fbc30e9 h1:AsFN8kXcCVkUFHyuzp1FtYbzp1nCO/H6+1uPSGEyPzM= github.com/yvasiyarov/newrelic_platform_go v0.0.0-20160601141957-9c099fbc30e9/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg= +github.com/ziutek/mymysql v1.5.4 h1:GB0qdRGsTwQSBVYuVShFBKaXSnSnYYC2d9knnE1LHFs= +github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0= gitlab.com/nyarla/go-crypt v0.0.0-20160106005555-d9a5dc2b789b/go.mod h1:T3BPAOm2cqquPa0MKWeNkmOM5RQsRhkrwMWonFMN7fE= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= @@ -1394,10 +1489,14 @@ golang.org/x/crypto v0.0.0-20190617133340-57b3e21c3d56/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191122220453-ac88ee75c92c/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200128174031-69ecbb4d6d5d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200414173820-0848c9571904/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200423211502-4bdfaf469ed5/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= @@ -1719,6 +1818,7 @@ golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapK golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200308013534-11ec41452d41/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= @@ -1901,6 +2001,8 @@ gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo= gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= gopkg.in/go-playground/validator.v9 v9.30.0/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ= +gopkg.in/gorp.v1 v1.7.2 h1:j3DWlAyGVv8whO7AcIWznQ2Yj7yJkn34B8s63GViAAw= +gopkg.in/gorp.v1 v1.7.2/go.mod h1:Wo3h+DBQZIxATwftsglhdD/62zRFPhGhTiu5jUJmCaw= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= @@ -1937,6 +2039,8 @@ gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81 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= +helm.sh/helm/v3 v3.7.0 h1:jRZCCdrOEfJI1LgStRAbmDJQkAwZkFy6gr4OlwrE2Ro= +helm.sh/helm/v3 v3.7.0/go.mod h1:DajHtQTe8KrjNmvy5gxWkosFKaADrS3uRS5EkDtsmI4= honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 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= @@ -2029,6 +2133,8 @@ modernc.org/golex v1.0.0/go.mod h1:b/QX9oBD/LhixY6NDh+IdGv17hgB+51fET1i2kPSmvk= modernc.org/mathutil v1.0.0/go.mod h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03k= modernc.org/strutil v1.0.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs= modernc.org/xc v1.0.0/go.mod h1:mRNCo0bvLjGhHO9WsyuKVU4q0ceiDDDoEeWDJHrNx8I= +oras.land/oras-go v0.4.0 h1:u6+7D+raZDYHwlz/uOwNANiRmyYDSSMW7A9E1xXycUQ= +oras.land/oras-go v0.4.0/go.mod h1:VJcU+VE4rkclUbum5C0O7deEZbBYnsnpbGSACwTjOcg= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/letsencrypt v0.0.3 h1:H7xDfhkaFFSYEJlKeq38RwX2jYcnTeHuDQyT+mMNMwM= rsc.io/letsencrypt v0.0.3/go.mod h1:buyQKZ6IXrRnB7TdkHP0RyEybLx18HHyOSoTyoOLqNY= diff --git a/pkg/archive/archive.go b/pkg/archive/archive.go index 5c15943a3..504a14b21 100644 --- a/pkg/archive/archive.go +++ b/pkg/archive/archive.go @@ -11,10 +11,11 @@ import ( "runtime" "strings" - "github.com/RedHatGov/bundle/pkg/config" - "github.com/RedHatGov/bundle/pkg/config/v1alpha1" "github.com/mholt/archiver/v3" "github.com/sirupsen/logrus" + + "github.com/RedHatGov/bundle/pkg/config" + "github.com/RedHatGov/bundle/pkg/config/v1alpha1" ) type Archiver interface { @@ -227,7 +228,7 @@ func blobInArchive(file string) string { func includeFile(fpath string) bool { split := strings.Split(filepath.Clean(fpath), string(filepath.Separator)) - return split[0] == config.InternalDir || split[0] == config.PublishDir || split[0] == "catalogs" + return split[0] == config.InternalDir || split[0] == config.PublishDir || split[0] == "catalogs" || split[0] == config.HelmDir } func shouldRemove(fpath string, info fs.FileInfo) bool { diff --git a/pkg/archive/archive_test.go b/pkg/archive/archive_test.go index 31b305926..4f6871e7f 100644 --- a/pkg/archive/archive_test.go +++ b/pkg/archive/archive_test.go @@ -8,7 +8,6 @@ import ( "strings" "testing" - "github.com/RedHatGov/bundle/pkg/bundle" "github.com/RedHatGov/bundle/pkg/config" "github.com/RedHatGov/bundle/pkg/config/v1alpha1" ) @@ -57,8 +56,8 @@ func Test_SplitArchive(t *testing.T) { packager := NewPackager(tt.manifests, tt.blobs) - if err := bundle.MakeCreateDirs(testdir); err != nil { - t.Fatal(err) + if err := os.MkdirAll(filepath.Join(testdir, config.SourceDir), os.ModePerm); err != nil { + t.Fail() } cwd, err := os.Getwd() diff --git a/pkg/bundle/additional.go b/pkg/bundle/additional.go index ef2983078..2048e899c 100644 --- a/pkg/bundle/additional.go +++ b/pkg/bundle/additional.go @@ -1,6 +1,7 @@ package bundle import ( + "context" "fmt" "path/filepath" @@ -23,7 +24,7 @@ func NewAdditionalOptions(ro cli.RootOptions) *AdditionalOptions { } // GetAdditional downloads specified images in the imageset-config.yaml under mirror.additonalImages -func (o *AdditionalOptions) GetAdditional(_ v1alpha1.PastMirror, cfg v1alpha1.ImageSetConfiguration) (image.AssociationSet, error) { +func (o *AdditionalOptions) GetAdditional(cfg v1alpha1.ImageSetConfiguration, imageList []v1alpha1.AdditionalImages) (image.AssociationSet, error) { opts := mirror.NewMirrorImageOptions(o.IOStreams) opts.DryRun = o.DryRun @@ -32,12 +33,12 @@ func (o *AdditionalOptions) GetAdditional(_ v1alpha1.PastMirror, cfg v1alpha1.Im opts.FileDir = filepath.Join(o.Dir, config.SourceDir) opts.FilterOptions = o.FilterOptions - logrus.Infof("Downloading %d image(s) to %s", len(cfg.Mirror.AdditionalImages), opts.FileDir) + logrus.Infof("Downloading %d image(s) to %s", len(imageList), opts.FileDir) var mappings []mirror.Mapping - images := make([]string, len(cfg.Mirror.AdditionalImages)) - assocMappings := make(map[string]string, len(cfg.Mirror.AdditionalImages)) - for i, img := range cfg.Mirror.AdditionalImages { + images := make([]string, len(imageList)) + assocMappings := make(map[string]string, len(imageList)) + for i, img := range imageList { // If the pullSecret is not empty create a cached context // else let `oc mirror` use the default docker config location @@ -74,7 +75,11 @@ func (o *AdditionalOptions) GetAdditional(_ v1alpha1.PastMirror, cfg v1alpha1.Im // Add mapping and image for image association. // The registry component is not included in the final path. - srcImage := srcRef.Ref.String() + srcImage, err := pinImages(context.TODO(), srcRef.Ref.Exact(), "", o.SkipTLS) + if err != nil { + return nil, err + } + dstRef.Ref.Registry = "" assocMappings[srcImage] = dstRef.String() images[i] = srcImage diff --git a/pkg/bundle/additional_test.go b/pkg/bundle/additional_test.go index e946aafa2..6113c85b4 100644 --- a/pkg/bundle/additional_test.go +++ b/pkg/bundle/additional_test.go @@ -1,6 +1,7 @@ package bundle import ( + "context" "os" "testing" @@ -16,7 +17,6 @@ import ( func Test_GetAdditional(t *testing.T) { - mirror := v1alpha1.PastMirror{} cfg := v1alpha1.ImageSetConfiguration{} cfg.Mirror = v1alpha1.Mirror{ BlockedImages: []v1alpha1.BlockedImages{ @@ -39,9 +39,12 @@ func Test_GetAdditional(t *testing.T) { } opts := NewAdditionalOptions(ro) - assocs, err := opts.GetAdditional(mirror, cfg) + assocs, err := opts.GetAdditional(cfg, cfg.Mirror.AdditionalImages) + require.NoError(t, err) + + testerImg, err := pinImages(context.TODO(), "quay.io/estroz/pull-tester-additional:latest", "", false) require.NoError(t, err) if assert.Len(t, assocs, 1) { - require.Contains(t, assocs, "quay.io/estroz/pull-tester-additional:latest") + require.Contains(t, assocs, testerImg) } } diff --git a/pkg/bundle/create/create.go b/pkg/bundle/create/create.go index 19cb33d6e..5b3601351 100644 --- a/pkg/bundle/create/create.go +++ b/pkg/bundle/create/create.go @@ -79,7 +79,16 @@ func (o *Options) RunFull(ctx context.Context, flags *pflag.FlagSet) error { if len(cfg.Mirror.AdditionalImages) != 0 { opts := bundle.NewAdditionalOptions(*o.RootOptions) - assocs, err := opts.GetAdditional(run, cfg) + assocs, err := opts.GetAdditional(cfg, cfg.Mirror.AdditionalImages) + if err != nil { + return meta, run, err + } + allAssocs.Merge(assocs) + } + + if len(cfg.Mirror.Helm.Local) != 0 || len(cfg.Mirror.Helm.Repos) != 0 { + opts := bundle.NewHelmOptions(*o.RootOptions) + assocs, err := opts.PullCharts(cfg) if err != nil { return meta, run, err } @@ -142,7 +151,16 @@ func (o *Options) RunDiff(ctx context.Context, flags *pflag.FlagSet) error { if len(cfg.Mirror.AdditionalImages) != 0 { opts := bundle.NewAdditionalOptions(*o.RootOptions) - assocs, err := opts.GetAdditional(lastRun, cfg) + assocs, err := opts.GetAdditional(cfg, cfg.Mirror.AdditionalImages) + if err != nil { + return meta, run, err + } + allAssocs.Merge(assocs) + } + + if len(cfg.Mirror.Helm.Local) != 0 || len(cfg.Mirror.Helm.Repos) != 0 { + opts := bundle.NewHelmOptions(*o.RootOptions) + assocs, err := opts.PullCharts(cfg) if err != nil { return meta, run, err } diff --git a/pkg/bundle/helm.go b/pkg/bundle/helm.go new file mode 100644 index 000000000..881bbca5f --- /dev/null +++ b/pkg/bundle/helm.go @@ -0,0 +1,280 @@ +package bundle + +import ( + "bytes" + "fmt" + "io/ioutil" + "os" + "path/filepath" + "strings" + + "github.com/sirupsen/logrus" + "helm.sh/helm/v3/pkg/action" + helmchart "helm.sh/helm/v3/pkg/chart" + "helm.sh/helm/v3/pkg/chart/loader" + helmcli "helm.sh/helm/v3/pkg/cli" + "helm.sh/helm/v3/pkg/downloader" + "helm.sh/helm/v3/pkg/getter" + helmrepo "helm.sh/helm/v3/pkg/repo" + "k8s.io/client-go/util/jsonpath" + "sigs.k8s.io/yaml" + + cli "github.com/RedHatGov/bundle/pkg/cli" + "github.com/RedHatGov/bundle/pkg/config" + "github.com/RedHatGov/bundle/pkg/config/v1alpha1" + "github.com/RedHatGov/bundle/pkg/image" +) + +type HelmOptions struct { + cli.RootOptions + settings *helmcli.EnvSettings +} + +func NewHelmOptions(ro cli.RootOptions) *HelmOptions { + settings := helmcli.New() + return &HelmOptions{ + RootOptions: ro, + settings: settings, + } +} + +func (h *HelmOptions) PullCharts(cfg v1alpha1.ImageSetConfiguration) (image.AssociationSet, error) { + + var images []v1alpha1.AdditionalImages + + // Create a temp file for to hold repo information + cleanup, file, err := mktempFile(h.Dir) + if err != nil { + return image.AssociationSet{}, err + } + h.settings.RepositoryConfig = file + defer cleanup() + + // Configure downloader + // TODO: allow configuration of credentials + // and certs + c := downloader.ChartDownloader{ + Out: os.Stdout, + Keyring: "", + Verify: downloader.VerifyNever, + Getters: getter.All(h.settings), + Options: []getter.Option{ + getter.WithInsecureSkipVerifyTLS(h.SkipTLS), + }, + RepositoryConfig: h.settings.RepositoryConfig, + RepositoryCache: h.settings.RepositoryCache, + } + + for _, chart := range cfg.Mirror.Helm.Local { + + // find images associations with chart (default values) + img, err := findImages(chart.Path, chart.ImagePaths...) + if err != nil { + return image.AssociationSet{}, err + } + + images = append(images, img...) + } + + for _, repo := range cfg.Mirror.Helm.Repos { + + // Add repo to temp file + if err := h.repoAdd(repo); err != nil { + return image.AssociationSet{}, err + } + + for _, chart := range repo.Charts { + logrus.Infof("Pulling chart %s", chart.Name) + // TODO: Do something with the returned verifications + ref := fmt.Sprintf("%s/%s", repo.Name, chart.Name) + dest := filepath.Join(h.Dir, config.SourceDir, config.HelmDir) + path, _, err := c.DownloadTo(ref, chart.Version, dest) + if err != nil { + return image.AssociationSet{}, fmt.Errorf("error pulling chart %q: %v", ref, err) + } + + // find images associations with chart (default values) + img, err := findImages(path, chart.ImagePaths...) + if err != nil { + return image.AssociationSet{}, err + } + + images = append(images, img...) + } + } + + // Image download + opts := NewAdditionalOptions(h.RootOptions) + return opts.GetAdditional(cfg, images) +} + +// FindImages will download images found in a Helm chart on disk +func findImages(path string, imagePaths ...string) (images []v1alpha1.AdditionalImages, err error) { + + logrus.Debugf("Reading from path %s", path) + + // Get all json paths where images + // are located + p := getImagesPath(imagePaths...) + + chart, err := loader.Load(path) + if err != nil { + return nil, err + } + + manifest, err := render(chart) + if err != nil { + return nil, err + } + + // Process each YAML document seperately + for _, single := range bytes.Split([]byte(manifest), []byte("\n---\n")) { + + imgs, err := search(single, p...) + + if err != nil { + return nil, err + } + + images = append(images, imgs...) + } + + return images, nil +} + +// getImagesPath returns known jsonpaths and user defined +// json paths where images are found +func getImagesPath(paths ...string) []string { + pathlist := []string{ + "{.spec.template.spec.initContainers[*].image}", + "{.spec.template.spec.containers[*].image}", + "{.spec.initContainers[*].image}", + "{.spec.containers[*].image}", + } + return append(pathlist, paths...) +} + +// render will return a templated chart +// TODO: add input for client.APIVersion +func render(chart *helmchart.Chart) (string, error) { + + // Client setup + cfg := new(action.Configuration) + client := action.NewInstall(cfg) + client.DryRun = true + client.ReleaseName = "RELEASE-NAME" + client.Replace = true + client.ClientOnly = true + client.IncludeCRDs = true + + // Create empty extra values options + valueOpts := make(map[string]interface{}) + + // Run a relase dry run to get the manifest + rel, err := client.Run(chart, valueOpts) + + return rel.Manifest, err +} + +// repoAdd adds a Helm repo with given name and url +func (h *HelmOptions) repoAdd(chartRepo v1alpha1.Repo) error { + + entry := helmrepo.Entry{ + Name: chartRepo.Name, + URL: chartRepo.URL, + } + + b, err := ioutil.ReadFile(h.settings.RepositoryConfig) + if err != nil && !os.IsNotExist(err) { + return err + } + + var helmFile helmrepo.File + if err := yaml.Unmarshal(b, &helmFile); err != nil { + return err + } + + // Check for existing repo name + if helmFile.Has(chartRepo.Name) { + logrus.Infof("repository name (%s) already exists", chartRepo.Name) + return nil + } + + // Check that the provided repo info is valid + r, err := helmrepo.NewChartRepository(&entry, getter.All(h.settings)) + if err != nil { + return err + } + + if _, err := r.DownloadIndexFile(); err != nil { + return fmt.Errorf("invalid chart repository %q: %v", chartRepo.URL, err) + } + + // Update temp file with chart entry + helmFile.Update(&entry) + + if err := helmFile.WriteFile(h.settings.RepositoryConfig, 0644); err != nil { + return fmt.Errorf("error writing helm repo file: %v", err) + } + + return nil +} + +// parseJSONPath will parse data and filter for a provide jsonpath template +func parseJSONPath(input interface{}, parser *jsonpath.JSONPath, template string) ([]string, error) { + buf := new(bytes.Buffer) + if err := parser.Parse(template); err != nil { + return nil, err + } + if err := parser.Execute(buf, input); err != nil { + return nil, err + } + + f := func(s rune) bool { return s == ' ' } + r := strings.FieldsFunc(buf.String(), f) + return r, nil +} + +// search will return images from parsed object +func search(yamlData []byte, paths ...string) (images []v1alpha1.AdditionalImages, err error) { + + var data interface{} + // yaml.Unmarshal will convert YAMl to JSON first + if err := yaml.Unmarshal(yamlData, &data); err != nil { + logrus.Error(err) + } + + j := jsonpath.New("") + j.AllowMissingKeys(true) + + for _, path := range paths { + results, err := parseJSONPath(data, j, path) + if err != nil { + return nil, err + } + + for _, result := range results { + logrus.Debugf("Found image %s", result) + img := v1alpha1.AdditionalImages{ + Image: v1alpha1.Image{ + Name: result, + }, + } + + images = append(images, img) + } + } + + return images, nil +} + +// mkTempFile will make a temporary file and return the name +// and cleanup method +func mktempFile(dir string) (func(), string, error) { + file, err := ioutil.TempFile(dir, "repo.*") + return func() { + if err := os.Remove(file.Name()); err != nil { + logrus.Fatal(err) + } + }, file.Name(), err +} diff --git a/pkg/bundle/helm_test.go b/pkg/bundle/helm_test.go new file mode 100644 index 000000000..e10ccbdd7 --- /dev/null +++ b/pkg/bundle/helm_test.go @@ -0,0 +1,164 @@ +package bundle + +import ( + "io/ioutil" + "reflect" + "testing" + + "github.com/RedHatGov/bundle/pkg/config/v1alpha1" + "github.com/stretchr/testify/require" + "helm.sh/helm/v3/pkg/chart/loader" + "k8s.io/client-go/util/jsonpath" + "sigs.k8s.io/kustomize/kyaml/yaml" +) + +func Test_GetCustomPaths(t *testing.T) { + tests := []struct { + name string + paths []string + want int + }{ + { + name: "tests no additional paths", + paths: []string{}, + want: 4, + }, + { + name: "tests custom paths", + paths: []string{ + "{.spec.template.spec.tests[*].image}", + }, + want: 5, + }, + } + for _, tt := range tests { + + paths := getImagesPath(tt.paths...) + + if len(paths) != tt.want { + t.Errorf("in %s, expect to get %d, got %d", tt.name, tt.want, len(paths)) + } + } + +} + +func Test_Search(t *testing.T) { + tests := []struct { + name string + path string + ipaths []string + want []v1alpha1.AdditionalImages + wantErr bool + }{ + { + name: "test podinfo", + path: "../../test/helm/testdata/podinfo.yaml", + ipaths: getImagesPath(), + want: []v1alpha1.AdditionalImages{ + {Image: v1alpha1.Image{ + Name: "ghcr.io/stefanprodan/podinfo:6.0.0"}}, + }, + wantErr: false, + }, + } + for _, tt := range tests { + + b, err := ioutil.ReadFile(tt.path) + require.NoError(t, err) + + imgs, err := search(b, tt.ipaths...) + require.NoError(t, err) + + if !reflect.DeepEqual(imgs, tt.want) { + if !tt.wantErr { + t.Errorf(`in %s, expect to get "%s", got "%s"`, tt.name, tt.want, imgs) + } + } + } +} + +func Test_ParseJSON(t *testing.T) { + + types := map[string]interface{}{ + "images": "test", + } + + tests := []struct { + name string + template string + input interface{} + want []string + wantErr bool + }{ + { + name: "tests paths", + template: "{.images }", + input: types, + want: []string{"test"}, + wantErr: false, + }, + { + name: "tests failure", + template: "{.images }", + input: types, + want: []string{"nottest"}, + wantErr: true, + }, + } + for _, tt := range tests { + j := jsonpath.New(tt.name) + j.AllowMissingKeys(true) + out, err := parseJSONPath(tt.input, j, tt.template) + require.NoError(t, err) + + if !reflect.DeepEqual(out, tt.want) { + if !tt.wantErr { + t.Errorf(`in %s, expect to get "%s", got "%s from %v"`, tt.name, tt.want, out, tt.input) + } + } + } +} + +func Test_Render(t *testing.T) { + tests := []struct { + name string + path string + ipaths []string + wantErr bool + }{ + { + name: "test podinfo", + path: "../../test/helm/testdata/podinfo-6.0.0.tgz", + wantErr: false, + }, + } + for _, tt := range tests { + + chart, err := loader.Load(tt.path) + require.NoError(t, err) + + result, err := render(chart) + require.NoError(t, err) + + if _, err = yaml.Marshal(result); err != nil { + t.Errorf("in %s, render result want not valid %v", tt.name, err) + } + } +} + +func Test_FindImages(t *testing.T) { + + ipaths := []string{} + path := "../../test/helm/testdata/podinfo-6.0.0.tgz" + want := []v1alpha1.AdditionalImages{ + {Image: v1alpha1.Image{ + Name: "ghcr.io/stefanprodan/podinfo:6.0.0"}}, + } + + imgs, err := findImages(path, ipaths...) + require.NoError(t, err) + + if !reflect.DeepEqual(imgs, want) { + t.Errorf(`in %s, expect to get "%s", got "%s"`, "", want, imgs) + } +} diff --git a/pkg/bundle/image.go b/pkg/bundle/image.go index a41722ea2..2f155699f 100644 --- a/pkg/bundle/image.go +++ b/pkg/bundle/image.go @@ -1,10 +1,15 @@ package bundle import ( + "context" + "fmt" + "github.com/openshift/library-go/pkg/image/reference" + "github.com/operator-framework/operator-registry/pkg/image/containerdregistry" "github.com/sirupsen/logrus" "github.com/RedHatGov/bundle/pkg/config/v1alpha1" + "github.com/RedHatGov/bundle/pkg/image" ) // IsBlocked will return a boolean value on whether an image @@ -21,3 +26,16 @@ func IsBlocked(cfg v1alpha1.ImageSetConfiguration, imgRef reference.DockerImageR } return false } + +func pinImages(ctx context.Context, ref, resolverConfigPath string, insecure bool) (string, error) { + resolver, err := containerdregistry.NewResolver(resolverConfigPath, insecure, nil) + if err != nil { + return "", fmt.Errorf("error creating image resolver: %v", err) + } + + if !image.IsImagePinned(ref) { + return image.ResolveToPin(ctx, resolver, ref) + } + + return ref, nil +} diff --git a/pkg/bundle/init.go b/pkg/bundle/init.go index ff058c9e6..225c7e532 100644 --- a/pkg/bundle/init.go +++ b/pkg/bundle/init.go @@ -12,6 +12,7 @@ func MakeCreateDirs(rootDir string) error { paths := []string{ filepath.Join(config.SourceDir, config.PublishDir), filepath.Join(config.SourceDir, "v2"), + filepath.Join(config.SourceDir, config.HelmDir), } for _, p := range paths { dir := filepath.Join(rootDir, p) diff --git a/pkg/bundle/publish/options.go b/pkg/bundle/publish/options.go index 9a23ab58b..244159037 100644 --- a/pkg/bundle/publish/options.go +++ b/pkg/bundle/publish/options.go @@ -11,9 +11,9 @@ import ( type Options struct { *cli.RootOptions - ArchivePath string - ToMirror string - + ArchivePath string + ToMirror string + OutputDir string BuildxPlatforms []string } @@ -25,6 +25,7 @@ func (o *Options) BindFlags(fs *pflag.FlagSet) { "for the specified platforms, ex. linux/amd64, instead of 'podman build' for the host platform. "+ "The 'buildx' plugin and accompanying configuration MUST be installed on the build host. "+ "This list does NOT filter operator bundle manifest list platforms within the catalog") + fs.StringVar(&o.OutputDir, "output", "", "Output directory for publish result artifacts") } // ValidatePaths validate the existence of paths from user flags diff --git a/pkg/bundle/publish/publish.go b/pkg/bundle/publish/publish.go index e2297e2c4..1091da876 100644 --- a/pkg/bundle/publish/publish.go +++ b/pkg/bundle/publish/publish.go @@ -78,6 +78,15 @@ func (o *Options) Run(ctx context.Context, cmd *cobra.Command, f kcmdutil.Factor return err } + // Set target dir for resulting artifacts + if o.OutputDir == "" { + dir, err := o.createResultsDir() + o.OutputDir = dir + if err != nil { + return err + } + } + // Create workspace cleanup, tmpdir, err := mktempDir(o.Dir) if err != nil { @@ -159,6 +168,12 @@ func (o *Options) Run(ctx context.Context, cmd *cobra.Command, f kcmdutil.Factor } } + // Unpack chart to user destination if it exists + logrus.Debugf("Unpacking any provided Helm charts to %s", o.OutputDir) + if err := unpack(config.HelmDir, o.OutputDir, filesInArchive); err != nil { + return err + } + if err := o.unpackImageSet(a, o.Dir); err != nil { return err } @@ -183,12 +198,6 @@ func (o *Options) Run(ctx context.Context, cmd *cobra.Command, f kcmdutil.Factor allICSPs []operatorv1alpha1.ImageContentSourcePolicy ) - // Create target dir for manifest directory - manifestDir, err := o.createManifestDir() - if err != nil { - return err - } - namedICSPMappings := map[string]map[reference.DockerImageReference]reference.DockerImageReference{} for _, imageName := range assocs.Keys() { @@ -205,6 +214,7 @@ func (o *Options) Run(ctx context.Context, cmd *cobra.Command, f kcmdutil.Factor } dstRef := imageRef dstRef.Registry = toMirrorRef.Ref.Registry + namedICSPMappings[imageRef.Name] = map[reference.DockerImageReference]reference.DockerImageReference{ imageRef: dstRef, } @@ -212,7 +222,7 @@ func (o *Options) Run(ctx context.Context, cmd *cobra.Command, f kcmdutil.Factor values, _ := assocs.Search(imageName) // Create temp workspace for image processing - _, unpackDir, err := mktempDir(tmpdir) + cleanUnpackDir, unpackDir, err := mktempDir(tmpdir) if err != nil { return err } @@ -222,8 +232,6 @@ func (o *Options) Run(ctx context.Context, cmd *cobra.Command, f kcmdutil.Factor manifestPath := filepath.Join("v2", assoc.Path, "manifests") // Ensure child manifests are all unpacked - // TODO: find a way to ensure these will be process on their - // No longer stored in the map logrus.Debugf("reading assoc: %s", assoc.Name) if len(assoc.ManifestDigests) != 0 { for _, manifestDigest := range assoc.ManifestDigests { @@ -312,7 +320,7 @@ func (o *Options) Run(ctx context.Context, cmd *cobra.Command, f kcmdutil.Factor case image.TypeOperatorCatalog: // Create a catalog source file for index mapping := map[imagesource.TypedImageReference]imagesource.TypedImageReference{m.Source: m.Destination} - if err := o.writeCatalogSource(manifestDir, mapping); err != nil { + if err := o.writeCatalogSource(o.OutputDir, mapping); err != nil { errs = append(errs, fmt.Errorf("image %q: error writing catalog source: %v", imageName, err)) continue } @@ -339,6 +347,11 @@ func (o *Options) Run(ctx context.Context, cmd *cobra.Command, f kcmdutil.Factor errs = append(errs, err) } } + + // Cleanup temp image processing workspace as images are processed + if !o.SkipCleanup { + cleanUnpackDir() + } } if len(errs) != 0 { return utilerrors.NewAggregate(errs) @@ -356,7 +369,7 @@ func (o *Options) Run(ctx context.Context, cmd *cobra.Command, f kcmdutil.Factor for _, ref := range ctlgRefs { namedICSPMappings[ref.Ref.Name] = map[reference.DockerImageReference]reference.DockerImageReference{ref.Ref: ref.Ref} - if err := writeCatalogSource(ref, ref, manifestDir); err != nil { + if err := writeCatalogSource(ref, ref, o.OutputDir); err != nil { return fmt.Errorf("error writing CatalogSource for catalog image %q: %v", ref.Ref.Exact(), err) } } @@ -371,7 +384,7 @@ func (o *Options) Run(ctx context.Context, cmd *cobra.Command, f kcmdutil.Factor } // Write an aggregation of ICSPs - if err := WriteICSPs(manifestDir, allICSPs); err != nil { + if err := WriteICSPs(o.OutputDir, allICSPs); err != nil { return fmt.Errorf("error writing ICSPs: %v", err) } @@ -421,7 +434,7 @@ func (o *Options) unpackImageSet(a archive.Archiver, dest string) error { if extension == a.String() { logrus.Debugf("Extracting archive %s", path) - if err := archive.Unarchive(a, path, dest, []string{"blobs", "v2"}); err != nil { + if err := archive.Unarchive(a, path, dest, []string{"blobs", "v2", config.HelmDir}); err != nil { return err } } @@ -702,15 +715,15 @@ func (o *Options) writeCatalogSource(manifestDir string, mapping map[imagesource return utilerrors.NewAggregate(errs) } -func (o *Options) createManifestDir() (manifestDir string, err error) { - manifestDir = filepath.Join( +func (o *Options) createResultsDir() (resultsDir string, err error) { + resultsDir = filepath.Join( o.Dir, - fmt.Sprintf("manifest-%v", time.Now().Unix()), + fmt.Sprintf("results-%v", time.Now().Unix()), ) - if err := os.MkdirAll(manifestDir, os.ModePerm); err != nil { - return manifestDir, err + if err := os.MkdirAll(resultsDir, os.ModePerm); err != nil { + return resultsDir, err } - return manifestDir, nil + return resultsDir, nil } diff --git a/pkg/bundle/release.go b/pkg/bundle/release.go index a0393e524..bd33e0a35 100644 --- a/pkg/bundle/release.go +++ b/pkg/bundle/release.go @@ -348,7 +348,6 @@ func (o *ReleaseOptions) getMapping(opts release.MirrorOptions, arch string) (ma // store in buffer for manipulation before outputting to mapping.txt var buffer bytes.Buffer opts.IOStreams.Out = &buffer - opts.ToMirror = true if err := opts.Run(); err != nil { @@ -366,26 +365,35 @@ func (o *ReleaseOptions) getMapping(opts release.MirrorOptions, arch string) (ma for scanner.Scan() { text := scanner.Text() split := strings.Split(text, " ") + srcRef := split[0] // Get release image name from mapping - if strings.Contains(split[0], "ocp-release") { - o.release = split[0] + // Only the top release need to be resolve because all other image key associated to the + // will be updated to this value + if strings.Contains(srcRef, "ocp-release") { + if !image.IsImagePinned(srcRef) { + srcRef, err = pinImages(context.TODO(), srcRef, "", o.SkipTLS) + } + o.release = srcRef } - // Proccess name and add arch to dir name - // TODO: architecture handling + // Generate name of target directory var names []string - name := opts.TargetFn(split[1]).Exact() - nameSplit := strings.Split(name, "-") + dstRef := opts.TargetFn(split[1]).Exact() + + // TODO: arch is not provided when getting mapping from release does not included + // the arch in the directory. Need to investigate, but adding it here as a workaround + nameSplit := strings.Split(dstRef, "-") names = []string{nameSplit[1], arch} names = append(names, nameSplit[2:]...) - name = strings.Join(names, "-") - if _, err := file.WriteString(split[0] + "=" + name + "\n"); err != nil { + dstRef = strings.Join(names, "-") + + if _, err := file.WriteString(srcRef + "=" + dstRef + "\n"); err != nil { return mappings, images, err } - images = append(images, split[0]) + images = append(images, srcRef) } mappings, err = image.ReadImageMapping(mappingPath) diff --git a/pkg/config/metadata.go b/pkg/config/metadata.go index a9918bd4e..e535ac7de 100644 --- a/pkg/config/metadata.go +++ b/pkg/config/metadata.go @@ -8,6 +8,7 @@ const ( SourceDir = "src" PublishDir = "publish" InternalDir = "internal" + HelmDir = "charts" MetadataFile = ".metadata.json" AssociationsFile = "image-associations.gob" ) diff --git a/pkg/config/v1alpha1/config_types.go b/pkg/config/v1alpha1/config_types.go index 8e8c328ff..5d2424759 100644 --- a/pkg/config/v1alpha1/config_types.go +++ b/pkg/config/v1alpha1/config_types.go @@ -30,6 +30,7 @@ type Mirror struct { OCP OCP `json:"ocp,omitempty"` Operators []Operator `json:"operators,omitempty"` AdditionalImages []AdditionalImages `json:"additionalImages,omitempty"` + Helm Helm `json:"helm,omitempty"` BlockedImages []BlockedImages `json:"blockedImages,omitempty"` Samples []SampleImages `json:"samples,omitempty"` } @@ -76,6 +77,33 @@ type Operator struct { InlineIndex bool `json:"inlineIndex,omitempty"` } +type Helm struct { + // Repo is the helm repository containing the charts + Repos []Repo `json:"repos,omitempty"` + // Local is the configuration for locally stored helm charts + Local []Chart `json:"local,omitempty"` +} + +// Repo is the configuration for a Helm Repo +type Repo struct { + // URL is the url of the helm repository + URL string `json:"url"` + // Name is the name of the helm repository + Name string `json:"name"` + // Charts is a list of charts to pull from the repo + Charts []Chart `json:"charts"` +} + +// Chart is the information an individual Helm chart +type Chart struct { + Name string `json:"name"` + Version string `json:"version,omitempty"` + Path string `json:"path,omitempty"` + // ImagePaths are custom JSON paths for images location + // in the helm manifest or templates + ImagePaths []string `json:"imagepaths,omitempty"` +} + // Image contains image pull information. type Image struct { // Name of the image. This should be an exact image pin (registry/namespace/name@sha256:) diff --git a/pkg/config/v1alpha1/testdata/config/valid.yaml b/pkg/config/v1alpha1/testdata/config/valid.yaml index ec86743f0..4f3a049f6 100644 --- a/pkg/config/v1alpha1/testdata/config/valid.yaml +++ b/pkg/config/v1alpha1/testdata/config/valid.yaml @@ -31,6 +31,16 @@ mirror: - name: nginx additionalimages: - name: registry.redhat.io/ubi8/ubi:latest + helm: + local: + - name: podinfo + path: /test/podinfo-5.0.0.tar.gz + repos: + - name: podinfo + url: https://stefanprodan.github.io/podinfo + charts: + - name: podinfo + version: 5.0.0 blockedimages: - name: alpine - name: redis diff --git a/pkg/image/resolve.go b/pkg/image/resolve.go index 7e34751f9..acb706fe1 100644 --- a/pkg/image/resolve.go +++ b/pkg/image/resolve.go @@ -2,6 +2,7 @@ package image import ( "context" + "strings" "github.com/containerd/containerd/remotes" imgreference "github.com/openshift/library-go/pkg/image/reference" @@ -26,3 +27,13 @@ func ResolveToPin(ctx context.Context, resolver remotes.Resolver, unresolvedImag return ref.String(), nil } + +// IsImagePinned returns true if img looks canonical. +func IsImagePinned(img string) bool { + return strings.Contains(img, "@") +} + +// isImageTagged returns true if img has a tag. +func IsImageTagged(img string) bool { + return strings.Contains(img, ":") +} diff --git a/pkg/operator/mirror.go b/pkg/operator/mirror.go index 085aae50e..0e169ffbb 100644 --- a/pkg/operator/mirror.go +++ b/pkg/operator/mirror.go @@ -324,9 +324,9 @@ func pinImages(ctx context.Context, dc *declcfg.DeclarativeConfig, resolverConfi var errs []error for i, b := range dc.Bundles { - if !isImagePinned(b.Image) { + if !image.IsImagePinned(b.Image) { - if !isImageTagged(b.Image) { + if !image.IsImageTagged(b.Image) { logrus.Warnf("bundle %s: bundle image tag not set", b.Name) continue } @@ -336,9 +336,9 @@ func pinImages(ctx context.Context, dc *declcfg.DeclarativeConfig, resolverConfi } } for j, ri := range b.RelatedImages { - if !isImagePinned(ri.Image) { + if !image.IsImagePinned(ri.Image) { - if !isImageTagged(ri.Image) { + if !image.IsImageTagged(ri.Image) { logrus.Warnf("bundle %s: related image tag not set", b.Name) continue } @@ -354,16 +354,6 @@ func pinImages(ctx context.Context, dc *declcfg.DeclarativeConfig, resolverConfi return utilerrors.NewAggregate(errs) } -// isImagePinned returns true if img looks canonical. -func isImagePinned(img string) bool { - return strings.Contains(img, "@") -} - -// isImageTagged returns true if img has a tag. -func isImageTagged(img string) bool { - return strings.Contains(img, ":") -} - func (o *MirrorOptions) writeDC(dc *declcfg.DeclarativeConfig, ctlgRef imgreference.DockerImageReference) (string, error) { // Write catalog declarative config file to src so it is included in the archive diff --git a/test/helm/testdata/podinfo-6.0.0.tgz b/test/helm/testdata/podinfo-6.0.0.tgz new file mode 100644 index 000000000..19ae93449 Binary files /dev/null and b/test/helm/testdata/podinfo-6.0.0.tgz differ diff --git a/test/helm/testdata/podinfo.yaml b/test/helm/testdata/podinfo.yaml new file mode 100644 index 000000000..853639722 --- /dev/null +++ b/test/helm/testdata/podinfo.yaml @@ -0,0 +1,83 @@ + apiVersion: apps/v1 + kind: Deployment + metadata: + name: RELEASE-NAME-podinfo + labels: + helm.sh/chart: podinfo-6.0.0 + app.kubernetes.io/name: RELEASE-NAME-podinfo + app.kubernetes.io/version: "6.0.0" + app.kubernetes.io/managed-by: Helm + spec: + replicas: 1 + strategy: + type: RollingUpdate + rollingUpdate: + maxUnavailable: 1 + selector: + matchLabels: + app.kubernetes.io/name: RELEASE-NAME-podinfo + template: + metadata: + labels: + app.kubernetes.io/name: RELEASE-NAME-podinfo + annotations: + prometheus.io/scrape: "true" + prometheus.io/port: "9898" + spec: + terminationGracePeriodSeconds: 30 + containers: + - name: podinfo + image: "ghcr.io/stefanprodan/podinfo:6.0.0" + imagePullPolicy: IfNotPresent + command: + - ./podinfo + - --port=9898 + - --cert-path=/data/cert + - --port-metrics=9797 + - --grpc-port=9999 + - --grpc-service-name=podinfo + - --level=info + - --random-delay=false + - --random-error=false + env: + - name: PODINFO_UI_COLOR + value: "#34577c" + ports: + - name: http + containerPort: 9898 + protocol: TCP + - name: http-metrics + containerPort: 9797 + protocol: TCP + - name: grpc + containerPort: 9999 + protocol: TCP + livenessProbe: + exec: + command: + - podcli + - check + - http + - localhost:9898/healthz + initialDelaySeconds: 1 + timeoutSeconds: 5 + readinessProbe: + exec: + command: + - podcli + - check + - http + - localhost:9898/readyz + initialDelaySeconds: 1 + timeoutSeconds: 5 + volumeMounts: + - name: data + mountPath: /data + resources: + limits: null + requests: + cpu: 1m + memory: 16Mi + volumes: + - name: data + emptyDir: {}