-
Notifications
You must be signed in to change notification settings - Fork 23
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add support for selective plugin migration using plugin groups for ai…
…r-gapped environments (#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
Showing
25 changed files
with
1,620 additions
and
131 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | ||
}) | ||
} | ||
} |
Oops, something went wrong.