Skip to content

Commit

Permalink
Add support for selective plugin migration using plugin groups for ai…
Browse files Browse the repository at this point in the history
…r-gapped environments (vmware-tanzu#231)

* Selective plugin migration using plugin groups for airgapped environments

This change adds support for users to do partial migration of plugins
using plugin groups instead of migrating all available plugins.

- Allows users to pass `--group` flag with `tanzu plugin
  download-bundle` to do selective plugin download and generates tar file
- Users can use the generated tar file with the `tanzu plugin
  upload-bundle` command to do partial plugin migration
  • Loading branch information
anujc25 committed Apr 27, 2023
1 parent 59508d7 commit bf44267
Show file tree
Hide file tree
Showing 25 changed files with 1,620 additions and 131 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ require (
github.com/k14s/kbld v0.32.0
github.com/lithammer/dedent v1.1.0
github.com/logrusorgru/aurora v2.0.3+incompatible
github.com/novln/docker-parser v1.0.0
github.com/onsi/ginkgo/v2 v2.9.2
github.com/onsi/gomega v1.27.6
github.com/otiai10/copy v1.4.2
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -972,6 +972,8 @@ github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OS
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/nightlyone/lockfile v1.0.0/go.mod h1:rywoIealpdNse2r832aiD9jRk8ErCatROs6LzC841CI=
github.com/nishanths/predeclared v0.0.0-20200524104333-86fad755b4d3/go.mod h1:nt3d53pc1VYcphSCIaYAJtnPYnr3Zyn8fMq2wvPGPso=
github.com/novln/docker-parser v1.0.0 h1:PjEBd9QnKixcWczNGyEdfUrP6GR0YUilAqG7Wksg3uc=
github.com/novln/docker-parser v1.0.0/go.mod h1:oCeM32fsoUwkwByB5wVjsrsVQySzPWkl3JdlTn1txpE=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
Expand Down
12 changes: 1 addition & 11 deletions go.work.sum
Original file line number Diff line number Diff line change
Expand Up @@ -127,40 +127,31 @@ cloud.google.com/go/webrisk v1.7.0/go.mod h1:mVMHgEYH0r337nmt1JyLthzMr6YxwN1aAIE
cloud.google.com/go/websecurityscanner v1.4.0/go.mod h1:ebit/Fp0a+FWu5j4JOmJEV8S8CzdTkAS77oDsiSqYWQ=
cloud.google.com/go/workflows v1.9.0/go.mod h1:ZGkj1aFIOd9c8Gerkjjq7OW7I5+l6cSvT3ujaO/WwSA=
github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c=
github.com/aws/aws-sdk-go-v2/service/ecr v1.15.0 h1:lY2Z2sBP+zSbJ6CvvmnFgPcgknoQ0OJV88AwVetRRFk=
github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.12.0 h1:LsqBpyRofMG6eDs6YGud6FhdGyIyXelAasPOZ6wWLro=
github.com/apex/log v1.1.4 h1:3Zk+boorIQAAGBrHn0JUtAau4ihMamT4WdnfdnXM1zQ=
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
github.com/chzyer/logex v1.2.0/go.mod h1:9+9sk7u7pGNWYMkh0hdiL++6OeibzJccyQU4p4MedaY=
github.com/chzyer/readline v1.5.0/go.mod h1:x22KAscuvRqlLoK9CsoYsmxoXZMMFVyOl86cAH8qUic=
github.com/chzyer/test v0.0.0-20210722231415-061457976a23/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/cpuguy83/go-md2man v1.0.10 h1:BSKMNlYxDvnunlTymqtgONjNnaRV1sTpcovwwjF22jk=
github.com/emicklei/go-restful v2.16.0+incompatible h1:rgqiKNjTnFQA6kkhFe16D8epTksy9HQ1MyrbDXSdYhM=
github.com/emicklei/go-restful/v3 v3.8.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/google/go-github v17.0.0+incompatible h1:N0LgJ1j65A7kfXrZnUDaYCs/Sf4rEjNlfyDHW9dolSY=
github.com/google/martian/v3 v3.3.2/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk=
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo=
github.com/googleapis/enterprise-certificate-proxy v0.1.0/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8=
github.com/googleapis/enterprise-certificate-proxy v0.2.0/go.mod h1:8C0jb7/mgJe/9KK8Lm7X9ctZC2t60YyIpYEI16jx0Qg=
github.com/googleapis/enterprise-certificate-proxy v0.2.1/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k=
github.com/googleapis/gax-go/v2 v2.5.1/go.mod h1:h6B0KMMFNtI2ddbGJn3T3ZbwkeT6yqEF02fYlzkUCyo=
github.com/googleapis/gax-go/v2 v2.7.0/go.mod h1:TEop28CZZQ2y+c0VxMUmu1lV+fQx57QpBWsYpwqHJx8=
github.com/ianlancetaylor/demangle v0.0.0-20220319035150-800ac71e25c2/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w=
github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
github.com/onsi/ginkgo/v2 v2.1.4/go.mod h1:um6tUpWM/cxCK3/FK8BXqEiUMUwRgSM4JXG47RKZmLU=
github.com/onsi/ginkgo/v2 v2.9.1/go.mod h1:FEcmzVcCHl+4o9bQZVab+4dC9+j+91t2FHSzmGAPfuo=
github.com/onsi/ginkgo/v2 v2.9.2/go.mod h1:WHcJJG2dIlcCqVfBAwUCrJxSPFb6v4azBwgxeMeDuts=
github.com/onsi/gomega v1.27.4/go.mod h1:riYq/GJKh8hhoM01HN6Vmuy93AarCXCBGpvFDK3q3fQ=
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
github.com/russross/blackfriday v1.6.0 h1:KqfZb0pUVN2lYqZUYRddxF4OR8ZMURnJIG5Y3VRLtww=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.9.0 h1:KENHtAZL2y3NLMYZeHY9DW8HW8V+kQyJsY/V9JlKvCs=
golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.0.0-20220909164309-bea034e7d591/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
golang.org/x/net v0.0.0-20221014081412-f15817d10f9b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
Expand All @@ -181,7 +172,6 @@ golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ=
golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s=
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
google.golang.org/api v0.97.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s=
google.golang.org/api v0.102.0/go.mod h1:3VFl6/fzoA+qNuS1N1/VfXY4LjoXN/wzeIp7TweWwGo=
Expand Down
40 changes: 40 additions & 0 deletions pkg/airgapped/helper.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Copyright 2023 VMware, Inc. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

package airgapped

import (
"fmt"
"strings"

dockerparser "github.com/novln/docker-parser"
"github.com/pkg/errors"
)

// GetPluginInventoryMetadataImage returns the plugin inventory metadata
// image based on plugin inventory image.
// E.g. if plugin inventory image is `fake.repo.com/plugin/plugin-inventory:latest`
// it returns metadata image as `fake.repo.com/plugin/plugin-inventory-metadata:latest`
func GetPluginInventoryMetadataImage(pluginInventoryImage string) (string, error) {
ref, err := dockerparser.Parse(pluginInventoryImage)
if err != nil {
return "", errors.Wrapf(err, "invalid image %q", pluginInventoryImage)
}
return fmt.Sprintf("%s-metadata:%s", ref.Repository(), ref.Tag()), nil
}

// GetImageRelativePath returns the relative path of the image with respect to `basePath`
// E.g. If the image is `fake.repo.com/plugin/database/plugin-inventory:latest` with
// basePath as `fake.repo.com/plugin` it should return
// `database/plugin-inventory:latest` if withTag is true and
// `database/plugin-inventory` if withTag is false
func GetImageRelativePath(image, basePath string, withTag bool) string {
relativePath := strings.TrimPrefix(image, basePath)
if withTag {
return relativePath
}
if idx := strings.LastIndex(relativePath, ":"); idx != -1 {
return relativePath[:idx]
}
return relativePath
}
102 changes: 102 additions & 0 deletions pkg/airgapped/helper_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
// Copyright 2023 VMware, Inc. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

package airgapped

import (
"testing"

"github.com/tj/assert"
)

func Test_GetPluginInventoryMetadataImage(t *testing.T) {
assert := assert.New(t)

tests := []struct {
pluginInventoryImage string
expectedMetadataImage string
errString string
}{
{
pluginInventoryImage: "fake.repo.com/plugin/plugin-inventory:latest",
expectedMetadataImage: "fake.repo.com/plugin/plugin-inventory-metadata:latest",
errString: "",
},
{
pluginInventoryImage: "fake.repo.com/plugin/airgapped:v1.0.0",
expectedMetadataImage: "fake.repo.com/plugin/airgapped-metadata:v1.0.0",
errString: "",
},
{
pluginInventoryImage: "fake.repo.com/plugin/metadata",
expectedMetadataImage: "fake.repo.com/plugin/metadata-metadata:latest",
errString: "",
},
{
pluginInventoryImage: "invalid-inventory-image$#",
expectedMetadataImage: "",
errString: "invalid image",
},
}

for _, test := range tests {
t.Run(test.pluginInventoryImage, func(t *testing.T) {
actualMetadataImage, err := GetPluginInventoryMetadataImage(test.pluginInventoryImage)
assert.Equal(actualMetadataImage, test.expectedMetadataImage)
if test.errString == "" {
assert.Nil(err)
} else {
assert.Contains(err.Error(), test.errString)
}
})
}
}

func Test_GetImageRelativePath(t *testing.T) {
assert := assert.New(t)

tests := []struct {
image string
basePath string
withTag bool
expectedRelativePath string
}{
{
image: "fake.repo.com/plugin/plugin-inventory:latest",
basePath: "fake.repo.com/plugin/",
withTag: true,
expectedRelativePath: "plugin-inventory:latest",
},
{
image: "fake.repo.com/plugin/plugin-inventory:latest",
basePath: "fake.repo.com/plugin/",
withTag: false,
expectedRelativePath: "plugin-inventory",
},
{
image: "fake.repo.com/plugin/airgapped:v1.0.0",
basePath: "fake.repo.com/",
withTag: true,
expectedRelativePath: "plugin/airgapped:v1.0.0",
},
{
image: "fake.repo.com/plugin/metadata",
basePath: "fake.repo.com/",
withTag: false,
expectedRelativePath: "plugin/metadata",
},
{
image: "fake.repo.com/plugin/metadata:latest",
basePath: "fake.repo.com/plugin/metadata-metadata",
withTag: true,
expectedRelativePath: "fake.repo.com/plugin/metadata:latest",
},
}

for _, test := range tests {
t.Run(test.image, func(t *testing.T) {
actualImage := GetImageRelativePath(test.image, test.basePath, test.withTag)
assert.Equal(actualImage, test.expectedRelativePath)
})
}
}

0 comments on commit bf44267

Please sign in to comment.