-
Notifications
You must be signed in to change notification settings - Fork 9
Provide warning for ImageStreams #31
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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,24 @@ | ||
| name: PR Checks | ||
|
|
||
| on: | ||
| pull_request: | ||
| branches: | ||
| - main | ||
|
|
||
| jobs: | ||
| test-and-build: | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - name: Set up Go | ||
| uses: actions/setup-go@v5 | ||
| with: | ||
| go-version: "1.25.0" | ||
|
|
||
| - name: Check out code | ||
| uses: actions/checkout@v4 | ||
|
|
||
| - name: Run tests | ||
| run: go test ./... | ||
|
|
||
| - name: Build | ||
| run: go build -o bin/crane-plugin-openshift . | ||
This file contains hidden or 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 |
|---|---|---|
| @@ -1,2 +1,81 @@ | ||
| # crane-plugin-openshift | ||
| Openshift plugin for crane | ||
|
|
||
| OpenShift plugin for [crane](https://github.com/konveyor/crane) - handles OpenShift-specific resource transformations during cluster migrations. | ||
|
|
||
| ## Features | ||
|
|
||
| This plugin provides transformations for OpenShift-specific resources including: | ||
|
|
||
| - **BuildConfigs**: Updates pull secrets and registry references | ||
| - **DeploymentConfigs**: Handles PVC renames and pod template transformations | ||
| - **Routes**: Removes auto-generated hostnames | ||
| - **ServiceAccounts**: Strips default secrets and pull secrets | ||
| - **RoleBindings**: Removes namespace references for ServiceAccount subjects | ||
| - **ImageStreams**: Detects usage (see limitations below) | ||
| - Automatic whiteout of OpenShift-specific resources (Builds, ImageStreamTags, ImageTags) | ||
| - Optional stripping of default RBAC, CA bundles, and pull secrets | ||
|
|
||
| ## Limitations | ||
|
|
||
| ### Internal Image Registry Migration | ||
|
|
||
| **Important**: This plugin does **NOT** migrate container images stored in OpenShift's internal image registry. | ||
|
|
||
| When the plugin detects `ImageStream` resources during migration, it will log warnings like: | ||
|
|
||
| ```text | ||
| WARNING: ImageStream 'my-namespace/my-app' detected - images from internal registry are NOT migrated automatically | ||
| INFO: To migrate internal registry images, use tools like skopeo. Example: skopeo sync --src docker --dest docker SOURCE_REGISTRY/REPO DEST_REGISTRY/REPO | ||
| ``` | ||
|
|
||
| #### Why aren't images migrated? | ||
|
|
||
| - Crane focuses on Kubernetes resource manifests (YAML) | ||
| - Container images are data stored separately in container registries | ||
| - Internal registry images require specialized tools for migration | ||
|
|
||
| #### How to migrate images manually | ||
|
|
||
| Use [skopeo](https://github.com/containers/skopeo) to copy images between registries: | ||
|
|
||
| ```bash | ||
| # Example: Copy a single image | ||
| skopeo copy \ | ||
| docker://source-registry.example.com:5000/namespace/image:tag \ | ||
| docker://dest-registry.example.com:5000/namespace/image:tag | ||
|
|
||
| # Example: Sync multiple images | ||
| skopeo sync \ | ||
| --src docker --dest docker \ | ||
| source-registry.example.com:5000/namespace \ | ||
| dest-registry.example.com:5000/namespace | ||
| ``` | ||
|
|
||
| For more details, see [crane issue #452](https://github.com/migtools/crane/issues/452). | ||
|
|
||
| ## Usage | ||
|
|
||
| This plugin is used automatically by crane when processing OpenShift resources. Optional flags can be configured: | ||
|
|
||
| - `--strip-default-rbac` (default: true) - Strip default RBAC resources | ||
| - `--strip-default-cabundle` (default: true) - Strip default CA bundle ConfigMaps | ||
| - `--strip-default-pull-secrets` (default: true) - Strip default pull secrets | ||
| - `--pull-secret-replacement` - Map of pull secret replacements | ||
| - `--registry-replacement` - Map of registry path replacements | ||
| - `--pvc-rename-map` - Map of PVC name changes | ||
|
|
||
| ## Development | ||
|
|
||
| For more information about developing crane plugins, see [crane-plugins](https://github.com/migtools/crane-plugins). | ||
|
|
||
| ### Running Tests | ||
|
|
||
| ```bash | ||
| go test ./... | ||
| ``` | ||
|
|
||
| ### Building | ||
|
|
||
| ```bash | ||
| go build -o crane-plugin-openshift . | ||
| ``` |
This file contains hidden or 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 hidden or 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,187 @@ | ||
| package openshift | ||
|
|
||
| import ( | ||
| "bytes" | ||
| "testing" | ||
|
|
||
| "github.com/konveyor/crane-lib/transform" | ||
| "github.com/sirupsen/logrus" | ||
| "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" | ||
| ) | ||
|
|
||
| func TestImageStreamDetection(t *testing.T) { | ||
| tests := []struct { | ||
| name string | ||
| resource *unstructured.Unstructured | ||
| expectWhiteOut bool | ||
| expectWarning bool | ||
| warningContains string | ||
| }{ | ||
| { | ||
| name: "ImageStream should be marked as whiteout and warn", | ||
| resource: &unstructured.Unstructured{ | ||
| Object: map[string]interface{}{ | ||
| "apiVersion": "image.openshift.io/v1", | ||
| "kind": "ImageStream", | ||
| "metadata": map[string]interface{}{ | ||
| "name": "my-app", | ||
| "namespace": "my-namespace", | ||
| }, | ||
| "spec": map[string]interface{}{ | ||
| "lookupPolicy": map[string]interface{}{ | ||
| "local": false, | ||
| }, | ||
| }, | ||
| }, | ||
| }, | ||
| expectWhiteOut: true, | ||
| expectWarning: true, | ||
| warningContains: "my-namespace/my-app", | ||
| }, | ||
| { | ||
| name: "ImageStreamTag should be marked as whiteout without ImageStream warning", | ||
| resource: &unstructured.Unstructured{ | ||
| Object: map[string]interface{}{ | ||
| "apiVersion": "image.openshift.io/v1", | ||
| "kind": "ImageStreamTag", | ||
| "metadata": map[string]interface{}{ | ||
| "name": "my-app:latest", | ||
| "namespace": "my-namespace", | ||
| }, | ||
| }, | ||
| }, | ||
| expectWhiteOut: true, | ||
| expectWarning: false, | ||
| }, | ||
| { | ||
| name: "ImageTag should be marked as whiteout without ImageStream warning", | ||
| resource: &unstructured.Unstructured{ | ||
| Object: map[string]interface{}{ | ||
| "apiVersion": "image.openshift.io/v1", | ||
| "kind": "ImageTag", | ||
| "metadata": map[string]interface{}{ | ||
| "name": "sha256:abc123", | ||
| "namespace": "my-namespace", | ||
| }, | ||
| }, | ||
| }, | ||
| expectWhiteOut: true, | ||
| expectWarning: false, | ||
| }, | ||
| { | ||
| name: "Regular Pod should not be marked as whiteout", | ||
| resource: &unstructured.Unstructured{ | ||
| Object: map[string]interface{}{ | ||
| "apiVersion": "v1", | ||
| "kind": "Pod", | ||
| "metadata": map[string]interface{}{ | ||
| "name": "my-pod", | ||
| "namespace": "my-namespace", | ||
| }, | ||
| }, | ||
| }, | ||
| expectWhiteOut: false, | ||
| expectWarning: false, | ||
| }, | ||
| } | ||
|
|
||
| for _, tt := range tests { | ||
| t.Run(tt.name, func(t *testing.T) { | ||
| // Create a buffer to capture log output | ||
| var logBuffer bytes.Buffer | ||
| logger := logrus.New() | ||
| logger.SetOutput(&logBuffer) | ||
|
|
||
| plugin := &OpenShiftTransformPlugin{ | ||
| Log: logger, | ||
| } | ||
|
|
||
| request := transform.PluginRequest{ | ||
| Unstructured: *tt.resource, | ||
| Extras: map[string]string{}, | ||
| } | ||
|
|
||
| response, err := plugin.Run(request) | ||
| if err != nil { | ||
| t.Fatalf("unexpected error: %v", err) | ||
| } | ||
|
|
||
| if response.IsWhiteOut != tt.expectWhiteOut { | ||
| t.Errorf("expected IsWhiteOut=%v, got %v", tt.expectWhiteOut, response.IsWhiteOut) | ||
| } | ||
|
|
||
| logOutput := logBuffer.String() | ||
| if tt.expectWarning { | ||
| if logOutput == "" { | ||
| t.Error("expected warning log but got no output") | ||
| } | ||
| if tt.warningContains != "" && !contains(logOutput, tt.warningContains) { | ||
| t.Errorf("expected log to contain '%s', got: %s", tt.warningContains, logOutput) | ||
| } | ||
| if !contains(logOutput, "NOT migrated automatically") { | ||
| t.Errorf("expected warning about migration, got: %s", logOutput) | ||
| } | ||
| if !contains(logOutput, "skopeo") { | ||
| t.Errorf("expected log to mention skopeo tool, got: %s", logOutput) | ||
| } | ||
| } else { | ||
| if contains(logOutput, "NOT migrated automatically") { | ||
| t.Errorf("unexpected ImageStream warning for %s: %s", tt.resource.GetKind(), logOutput) | ||
| } | ||
| } | ||
| }) | ||
| } | ||
| } | ||
|
|
||
| func TestImageStreamWithEmptyNamespace(t *testing.T) { | ||
| var logBuffer bytes.Buffer | ||
| logger := logrus.New() | ||
| logger.SetOutput(&logBuffer) | ||
|
|
||
| plugin := &OpenShiftTransformPlugin{ | ||
| Log: logger, | ||
| } | ||
|
|
||
| resource := &unstructured.Unstructured{ | ||
| Object: map[string]interface{}{ | ||
| "apiVersion": "image.openshift.io/v1", | ||
| "kind": "ImageStream", | ||
| "metadata": map[string]interface{}{ | ||
| "name": "my-app", | ||
| // namespace intentionally omitted | ||
| }, | ||
| }, | ||
| } | ||
|
|
||
| request := transform.PluginRequest{ | ||
| Unstructured: *resource, | ||
| Extras: map[string]string{}, | ||
| } | ||
|
|
||
| response, err := plugin.Run(request) | ||
| if err != nil { | ||
| t.Fatalf("unexpected error: %v", err) | ||
| } | ||
|
|
||
| if !response.IsWhiteOut { | ||
| t.Error("expected ImageStream to be marked as whiteout") | ||
| } | ||
|
|
||
| logOutput := logBuffer.String() | ||
| if !contains(logOutput, "ImageStream") { | ||
| t.Errorf("expected ImageStream warning, got: %s", logOutput) | ||
| } | ||
| } | ||
|
|
||
| func contains(s, substr string) bool { | ||
| return len(s) >= len(substr) && (s == substr || len(substr) == 0 || findSubstring(s, substr)) | ||
| } | ||
|
|
||
| func findSubstring(s, substr string) bool { | ||
| for i := 0; i <= len(s)-len(substr); i++ { | ||
| if s[i:i+len(substr)] == substr { | ||
| return true | ||
| } | ||
| } | ||
| return false | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.