Skip to content

feat: implicit container contributions #1013

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 3 commits into from
Jan 10, 2023

Conversation

AObuchow
Copy link
Collaborator

@AObuchow AObuchow commented Jan 5, 2023

What does this PR do?

This PR introduces 3 changes to the container contribution mechanism:

  1. The controller.devfile.io/merge-contribution component attribute is no longer required in order to define a target for container contributions. The first container component in a DevWorkspace (that is not imported by a plugin or parent DevWorkspace) is automatically selected as a merge target if the controller.devfile.io/container-contribution is used on at least one other DevWorkspace component. However, if the controller.devfile.io/merge-contribution attribute is set to true for a container component, it will be selected as a target for container contributions.

  2. Users can opt out a container component from being implicitly selected as a container contribution merge target by setting the controller.devfile.io/merge-contribution attribute to false.

  3. If a DevWorkspace has multiple container components with the controller.devfile.io/merge-contribution attribute set to true, the workspace fails. The webhook was extended to prevent the creation of a DevWorkspace that has multiple container components with the controller.devfile.io/merge-contribution attribute set to true, and to prevent updating a DevWorkspace to have multiple container components with the merge-contribution attribute set to true.

What issues does this PR fix or reference?

Fix #993

Is it tested? How?

Automated tests

Automated tests were added to check that implicit container contributions (with the spec.contributions field and the attribute) work as expected; these are based off of the tests previously created in #844 and #939. A test was also added to ensure that DevWorkspaces with multiple container components with the controller.devfile.io/merge-contribution: true attribute will fail.

Manual testing

First, checkout the changes from this PR and install DWO onto your cluster, e.g set your DWO_IMG environment variable to point to your quay repo and make docker install on OpenShift.

The following DevWorkspaces were based off of the Che-Theia + Golang example from #844. They should behave the same as the original example, except for the opt-out cases and multiple merge-contribution attribute cases.

Ensure implicit container contributions work

Apply the following DevWorkspace:

kind: DevWorkspace
apiVersion: workspace.devfile.io/v1alpha2
metadata:
  name: test-contrib-theia
spec:
  started: true
  template:
    attributes:
      controller.devfile.io/storage-type: ephemeral
    projects:
      - name: golang-sample
        git:
          remotes:
            origin: "https://github.com/che-samples/golang-example.git"
    components:
      - name: tools
        attributes:
          che-theia.eclipse.org/vscode-extensions:
            - https://github.com/golang/vscode-go/releases/download/v0.23.0/go-0.23.0.vsix
        container:
          image: quay.io/devfile/universal-developer-image:ubi8-0e189d9
          env:
            - name: GOPATH
              value: /projects:/home/user/go
            - name: GOCACHE
              value: /tmp/.cache
          endpoints:
            - name: 8080-tcp
              targetPort: 8080
          memoryLimit: 2Gi
          mountSources: true
      - name: theia-ide
        plugin:
          uri: https://gist.githubusercontent.com/amisevsk/b342b9ae064b5a79e08945d04d02c208/raw/84cd2df9266b4a608fbc0fd0cc18816bca03e344/theia-contrib.devfile.yaml
          # workaround to make Theia listen on localhost rather than 127.0.0.1; can be
          # dropped if routingClass: che
          components:
            - name: theia-ide
              container:
                env:
                  - name: THEIA_HOST
                    value: 0.0.0.0

When inspecting the tools container, you should see that contributions from the theia-ide plugin component have been added, e.g. the PLUGIN_REMOTE_ENDPOINT_EXECUTABLE environment variable is set.

Ensure implicit container contributions work with spec.contributions

Apply the following DevWorkspace, and similar to the last test case, ensure you can see contributions from theia-ide (e.g. environment variables)

kind: DevWorkspace
apiVersion: workspace.devfile.io/v1alpha2
metadata:
  name: test-spec-contrib-theia
spec:
  started: true
  contributions:
  - name: theia-ide
    uri: https://gist.githubusercontent.com/amisevsk/b342b9ae064b5a79e08945d04d02c208/raw/84cd2df9266b4a608fbc0fd0cc18816bca03e344/theia-contrib.devfile.yaml
    # workaround to make Theia listen on localhost rather than 127.0.0.1; can be
    # dropped if routingClass: che
    components:
      - name: theia-ide
        container:
          env:
            - name: THEIA_HOST
              value: 0.0.0.0
  template:
    attributes:
      controller.devfile.io/storage-type: ephemeral
    projects:
      - name: golang-sample
        git:
          remotes:
            origin: "https://github.com/che-samples/golang-example.git"
    components:
      - name: tools
        attributes:
          che-theia.eclipse.org/vscode-extensions:
            - https://github.com/golang/vscode-go/releases/download/v0.23.0/go-0.23.0.vsix
        container:
          image: quay.io/devfile/universal-developer-image:ubi8-0e189d9
          env:
            - name: GOPATH
              value: /projects:/home/user/go
            - name: GOCACHE
              value: /tmp/.cache
          endpoints:
            - name: 8080-tcp
              targetPort: 8080
          memoryLimit: 2Gi
          mountSources: true
Ensure opting out from implicit container contributions works

Apply the following DevWorkspace. It has 2 container components, with the first one (opt-out) explicitly opting out from being a container contribution target. Ensure that the opt-out container does not have contributions from theia-ide, and that the tools container does have the contributions.

kind: DevWorkspace
apiVersion: workspace.devfile.io/v1alpha2
metadata:
  name: test-contrib-theia-opt-out
spec:
  started: true
  template:
    attributes:
      controller.devfile.io/storage-type: ephemeral
    projects:
      - name: golang-sample
        git:
          remotes:
            origin: "https://github.com/che-samples/golang-example.git"
    components:
      - name: opt-out
        attributes:
          controller.devfile.io/merge-contribution: false
        container:
          image: quay.io/devfile/universal-developer-image:ubi8-0e189d9
          memoryLimit: 2Gi
          mountSources: true
      - name: tools
        attributes:
          che-theia.eclipse.org/vscode-extensions:
            - https://github.com/golang/vscode-go/releases/download/v0.23.0/go-0.23.0.vsix
        container:
          image: quay.io/devfile/universal-developer-image:ubi8-0e189d9
          env:
            - name: GOPATH
              value: /projects:/home/user/go
            - name: GOCACHE
              value: /tmp/.cache
          endpoints:
            - name: 8080-tcp
              targetPort: 8080
          memoryLimit: 2Gi
          mountSources: true
      - name: theia-ide
        plugin:
          uri: https://gist.githubusercontent.com/amisevsk/b342b9ae064b5a79e08945d04d02c208/raw/84cd2df9266b4a608fbc0fd0cc18816bca03e344/theia-contrib.devfile.yaml
          # workaround to make Theia listen on localhost rather than 127.0.0.1; can be
          # dropped if routingClass: che
          components:
            - name: theia-ide
              container:
                env:
                  - name: THEIA_HOST
                    value: 0.0.0.0
Ensure DevWorkspaces with multiple container components that have the merge-contribution: true attribute are rejected

Apply the following DevWorkspace:

kind: DevWorkspace
apiVersion: workspace.devfile.io/v1alpha2
metadata:
  name: test-contrib-theia-multiple-merge-contributions
spec:
  started: true
  template:
    attributes:
      controller.devfile.io/storage-type: ephemeral
    projects:
      - name: golang-sample
        git:
          remotes:
            origin: "https://github.com/che-samples/golang-example.git"
    components:
      - name: tools
        attributes:
          controller.devfile.io/merge-contribution: true
          che-theia.eclipse.org/vscode-extensions:
            - https://github.com/golang/vscode-go/releases/download/v0.23.0/go-0.23.0.vsix
        container:
          image: quay.io/devfile/universal-developer-image:ubi8-0e189d9
          env:
            - name: GOPATH
              value: /projects:/home/user/go
            - name: GOCACHE
              value: /tmp/.cache
          endpoints:
            - name: 8080-tcp
              targetPort: 8080
          memoryLimit: 2Gi
          mountSources: true
      - name: tools-2
        attributes:
          controller.devfile.io/merge-contribution: true
          che-theia.eclipse.org/vscode-extensions:
            - https://github.com/golang/vscode-go/releases/download/v0.23.0/go-0.23.0.vsix
        container:
          image: quay.io/devfile/universal-developer-image:ubi8-0e189d9
          memoryLimit: 2Gi
          mountSources: true
      - name: theia-ide
        plugin:
          uri: https://gist.githubusercontent.com/amisevsk/b342b9ae064b5a79e08945d04d02c208/raw/84cd2df9266b4a608fbc0fd0cc18816bca03e344/theia-contrib.devfile.yaml
          # workaround to make Theia listen on localhost rather than 127.0.0.1; can be
          # dropped if routingClass: che
          components:
            - name: theia-ide
              container:
                env:
                  - name: THEIA_HOST
                    value: 0.0.0.0

You should get a response similar to the following:

$ kubectl apply -f theia-golang-multiple-merge-contributions.yaml -n $NAMESPACE

Error from server (only a single component may have the controller.devfile.io/merge-contribution attribute set to true. The following 2 components have the controller.devfile.io/merge-contribution attribute set to true: tools, tools-2): error when creating "theia-golang-multiple-merge-contributions.yaml": admission webhook "mutate.devworkspace-controller.svc" denied the request: only a single component may have the controller.devfile.io/merge-contribution attribute set to true. The following 2 components have the controller.devfile.io/merge-contribution attribute set to true: tools, tools-2
Ensure DevWorkspaces modifications to make multiple container components have the merge-contribution: true attribute are rejected

Apply the following DevWorkspace:

kind: DevWorkspace
apiVersion: workspace.devfile.io/v1alpha2
metadata:
  name: test-contrib-theia-add-multiple-merge-contributions
spec:
  started: true
  template:
    attributes:
      controller.devfile.io/storage-type: ephemeral
    projects:
      - name: golang-sample
        git:
          remotes:
            origin: "https://github.com/che-samples/golang-example.git"
    components:
      - name: tools
        attributes:
          controller.devfile.io/merge-contribution: true
          che-theia.eclipse.org/vscode-extensions:
            - https://github.com/golang/vscode-go/releases/download/v0.23.0/go-0.23.0.vsix
        container:
          image: quay.io/devfile/universal-developer-image:ubi8-0e189d9
          env:
            - name: GOPATH
              value: /projects:/home/user/go
            - name: GOCACHE
              value: /tmp/.cache
          endpoints:
            - name: 8080-tcp
              targetPort: 8080
          memoryLimit: 2Gi
          mountSources: true
      - name: tools-2
        attributes:
          che-theia.eclipse.org/vscode-extensions:
            - https://github.com/golang/vscode-go/releases/download/v0.23.0/go-0.23.0.vsix
        container:
          image: quay.io/devfile/universal-developer-image:ubi8-0e189d9
          memoryLimit: 2Gi
          mountSources: true
      - name: theia-ide
        plugin:
          uri: https://gist.githubusercontent.com/amisevsk/b342b9ae064b5a79e08945d04d02c208/raw/84cd2df9266b4a608fbc0fd0cc18816bca03e344/theia-contrib.devfile.yaml
          # workaround to make Theia listen on localhost rather than 127.0.0.1; can be
          # dropped if routingClass: che
          components:
            - name: theia-ide
              container:
                env:
                  - name: THEIA_HOST
                    value: 0.0.0.0

Now do a kubectl edit dw test-contrib-theia-add-multiple-merge-contributions -n $NAMESPACE to add an extra merge-contribution: true attribute to the tools-2 component

kind: DevWorkspace
apiVersion: workspace.devfile.io/v1alpha2
metadata:
  name: test-contrib-theia-add-multiple-merge-contributions
spec:
(...)
      - name: tools-2
        attributes:
+          controller.devfile.io/merge-contribution: true
          che-theia.eclipse.org/vscode-extensions:
            - https://github.com/golang/vscode-go/releases/download/v0.23.0/go-0.23.0.vsix
        container:
          image: quay.io/devfile/universal-developer-image:ubi8-0e189d9
          memoryLimit: 2Gi
          mountSources: true
(...)

You should get an error mentioning that multiple container components have the merge-contribution: true.

PR Checklist

  • E2E tests pass (when PR is ready, comment /test v8-devworkspace-operator-e2e, v8-che-happy-path to trigger)
    • v8-devworkspace-operator-e2e: DevWorkspace e2e test
    • v8-che-happy-path: Happy path for verification integration with Che

Copy link
Collaborator

@amisevsk amisevsk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, though I haven't tested. Great work on the tests!

Comment on lines 229 to 258
// First check for explicit merge contributtion attribute
for _, component := range flattenedSpec.Components {
if component.Container == nil {
continue
}

if component.Attributes.Exists(constants.MergeContributionAttribute) {
if component.Attributes.GetBoolean(constants.MergeContributionAttribute, nil) {
return component.Name, nil
}
}
}

// Then see if there's a container that can implicitly be selected as a merge target
for _, component := range flattenedSpec.Components {
if component.Container == nil {
continue
}

// Don't select components that opt out as a merge contribution target
if component.Attributes.Exists(constants.MergeContributionAttribute) && !component.Attributes.GetBoolean(constants.MergeContributionAttribute, nil) {
continue
}

// The target must not have been imported by a plugin or parent.
if component.Attributes.Exists(constants.PluginSourceAttribute) {
continue
}
return component.Name, nil
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could be simplified into a single pass in a pretty straightforward way:

firstComponent := ""
for _, component := range flattenedSpec.Components {
	if component.Container == nil {
		continue
	}

	if component.Attributes.Exists(constants.MergeContributionAttribute) {
		if component.Attributes.GetBoolean(constants.MergeContributionAttribute, nil) {
			return component.Name, nil
		}
	}

	if component.Attributes.Exists(constants.PluginSourceAttribute) {
		continue
	}

	if firstComponent == "" {
		firstComponent = component.Name
	}
}

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good call, I added a fixup for this (I included an extra continue to prevent accidentally selecting a component that opts out as a merge contribution target)

@codecov
Copy link

codecov bot commented Jan 5, 2023

Codecov Report

Base: 49.87% // Head: 49.98% // Increases project coverage by +0.11% 🎉

Coverage data is based on head (52fb3cd) compared to base (7e8aa72).
Patch coverage: 54.09% of modified lines in pull request are covered.

❗ Current head 52fb3cd differs from pull request most recent head 44bc365. Consider uploading reports for the commit 44bc365 to get more accurate results

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1013      +/-   ##
==========================================
+ Coverage   49.87%   49.98%   +0.11%     
==========================================
  Files          68       69       +1     
  Lines        5911     5968      +57     
==========================================
+ Hits         2948     2983      +35     
- Misses       2736     2759      +23     
+ Partials      227      226       -1     
Impacted Files Coverage Δ
webhook/workspace/handler/attributes.go 0.00% <0.00%> (ø)
webhook/workspace/handler/workspace.go 0.00% <0.00%> (ø)
pkg/library/flatten/merge.go 77.06% <89.18%> (+1.92%) ⬆️
controllers/workspace/devworkspace_controller.go 60.63% <0.00%> (+0.53%) ⬆️
pkg/library/flatten/flatten.go 79.18% <0.00%> (+1.35%) ⬆️

Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here.

☔ View full report at Codecov.
📢 Do you have feedback about the report comment? Let us know in this issue.

@openshift-ci openshift-ci bot removed the lgtm label Jan 6, 2023
@AObuchow AObuchow force-pushed the implicit-merge-contribution branch from 2d38d67 to 52fb3cd Compare January 6, 2023 20:16
@AObuchow
Copy link
Collaborator Author

AObuchow commented Jan 6, 2023

Added an extra test case to account for the case where the first component could be implicitly selected as a merge target, but a later component explicitly opts in as a merge target. A duplicate test could be added for spec.contributions if desired.

@openshift-ci openshift-ci bot added the lgtm label Jan 9, 2023
This commit introduces 3 changes to the container contribution mechanism:

1. The `controller.devfile.io/merge-contribution` component attribute is no longer required in order to define a target for container contributions. The first container component in a DevWorkspace (that is not imported by a plugin or parent DevWorkspace) is automatically selected as a merge target if the `controller.devfile.io/container-contribution` is used on at least one other DevWorkspace component. However, if the `controller.devfile.io/merge-contribution` attribute is set to `true` for a container component, it will be selected as a target for container contributions.

2. Users can opt out a container component from being implicitly selected as a container contribution merge target by setting the `controller.devfile.io/merge-contribution` attribute to false.

3. If a DevWorkspace has multiple container components with the `controller.devfile.io/merge-contribution` attribute set to true, the workspace fails.

Fix devfile#993

Signed-off-by: Andrew Obuchowicz <[email protected]>
…ner contribution merge target

This commit adds a webhook handler to ensure:

- A newly created DevWorkspace cannot have more than one container component with the controller.devfile.io/merge-contribution set to true.

- An existing DevWorkspace cannot be modified to have more than one container component with the controller.devfile.io/merge-contribution set to true.

Signed-off-by: Andrew Obuchowicz <[email protected]>
@AObuchow AObuchow force-pushed the implicit-merge-contribution branch from 52fb3cd to 44bc365 Compare January 9, 2023 20:30
@openshift-ci openshift-ci bot removed the lgtm label Jan 9, 2023
@AObuchow
Copy link
Collaborator Author

AObuchow commented Jan 9, 2023

Squashed the fixups

@openshift-ci
Copy link

openshift-ci bot commented Jan 10, 2023

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: amisevsk, AObuchow, ibuziuk

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@ibuziuk ibuziuk merged commit fc8d007 into devfile:main Jan 10, 2023
@amisevsk amisevsk mentioned this pull request Feb 1, 2023
3 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Implicitly set merge-contribution:true on first template component
3 participants