Skip to content
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

Add Volume Storage Adapter for Devfiles #2651

Merged

Conversation

maysunfaisal
Copy link
Contributor

@maysunfaisal maysunfaisal commented Feb 27, 2020

Signed-off-by: Maysun J Faisal maysun.j.faisal@ibm.com

What type of PR is this?
/kind feature

What does does this PR do / why we need it:
This PR implements the Storage Adapter for Devfiles. It reads the parsed Devfile data, creates the storage and adds them to the component deployment.

For Acceptance Criteria, pls have a look at the issue post #2472 (comment)

List of changes:

Which issue(s) this PR fixes:

Fixes #2472

How to test changes / Special notes to the reviewer:

All pkg adapter tests (includes new TestStorageAdapter, TestStorageCreate and updated TestComponentAdapter ):
maysuns-mbp:adapters maysun$ pwd
/Users/maysun/go/src/github.com/openshift/odo/pkg/devfile/adapters
maysuns-mbp:adapters maysun$ go clean -testcache && go test ./... -v
=== RUN   TestNewPlatformAdapter
=== RUN   TestNewPlatformAdapter/get_platform_adapter
--- PASS: TestNewPlatformAdapter (0.00s)
    --- PASS: TestNewPlatformAdapter/get_platform_adapter (0.00s)
PASS
ok  	github.com/openshift/odo/pkg/devfile/adapters	0.592s
?   	github.com/openshift/odo/pkg/devfile/adapters/common	[no test files]
?   	github.com/openshift/odo/pkg/devfile/adapters/kubernetes	[no test files]
=== RUN   TestComponentAdapter
=== RUN   TestComponentAdapter/Case:_Invalid_devfile
=== RUN   TestComponentAdapter/Case:_Valid_devfile
 •  Waiting for component to start  ...
 ✓  Waiting for component to start [128563ns]
--- PASS: TestComponentAdapter (0.00s)
    --- PASS: TestComponentAdapter/Case:_Invalid_devfile (0.00s)
    --- PASS: TestComponentAdapter/Case:_Valid_devfile (0.00s)
PASS
ok  	github.com/openshift/odo/pkg/devfile/adapters/kubernetes/component	0.765s
=== RUN   TestStorageAdapter
=== RUN   TestStorageAdapter/Case:_Invalid_devfile
=== RUN   TestStorageAdapter/Case:_Valid_devfile
--- PASS: TestStorageAdapter (0.00s)
    --- PASS: TestStorageAdapter/Case:_Invalid_devfile (0.00s)
    --- PASS: TestStorageAdapter/Case:_Valid_devfile (0.00s)
=== RUN   TestStorageCreate
=== RUN   TestStorageCreate/storage_test
--- PASS: TestStorageCreate (0.00s)
    --- PASS: TestStorageCreate/storage_test (0.00s)
PASS
ok  	github.com/openshift/odo/pkg/devfile/adapters/kubernetes/storage	0.430s
?   	github.com/openshift/odo/pkg/devfile/adapters/kubernetes/utils	[no test files]
All the kclient pkg tests:
maysuns-mbp:kclient maysun$ pwd
/Users/maysun/go/src/github.com/openshift/odo/pkg/kclient
maysuns-mbp:kclient maysun$ go clean -testcache && go test ./... -v
=== RUN   TestCreateDeployment
=== RUN   TestCreateDeployment/Case:_Valid_deployment_name
=== RUN   TestCreateDeployment/Case:_Invalid_deployment_name
--- PASS: TestCreateDeployment (0.00s)
    --- PASS: TestCreateDeployment/Case:_Valid_deployment_name (0.00s)
    --- PASS: TestCreateDeployment/Case:_Invalid_deployment_name (0.00s)
=== RUN   TestUpdateDeployment
=== RUN   TestUpdateDeployment/Case:_Valid_deployment_name
=== RUN   TestUpdateDeployment/Case:_Invalid_deployment_name
--- PASS: TestUpdateDeployment (0.00s)
    --- PASS: TestUpdateDeployment/Case:_Valid_deployment_name (0.00s)
    --- PASS: TestUpdateDeployment/Case:_Invalid_deployment_name (0.00s)
=== RUN   TestGenerateContainer
=== RUN   TestGenerateContainer/#00
=== RUN   TestGenerateContainer/container1
--- PASS: TestGenerateContainer (0.00s)
    --- PASS: TestGenerateContainer/#00 (0.00s)
    --- PASS: TestGenerateContainer/container1 (0.00s)
=== RUN   TestGeneratePodTemplateSpec
=== RUN   TestGeneratePodTemplateSpec/podSpecTest
--- PASS: TestGeneratePodTemplateSpec (0.00s)
    --- PASS: TestGeneratePodTemplateSpec/podSpecTest (0.00s)
=== RUN   TestGeneratePVCSpec
=== RUN   TestGeneratePVCSpec/1
=== RUN   TestGeneratePVCSpec/2
--- PASS: TestGeneratePVCSpec (0.00s)
    --- PASS: TestGeneratePVCSpec/1 (0.00s)
    --- PASS: TestGeneratePVCSpec/2 (0.00s)
=== RUN   TestWaitAndGetPod
=== RUN   TestWaitAndGetPod/phase:_running
 •  Waiting for component to start  ...
 ✓  Waiting for component to start [181543ns]
=== RUN   TestWaitAndGetPod/phase:_failed
 •  Waiting for component to start  ...
 ✗  Waiting for component to start [71530ns]
=== RUN   TestWaitAndGetPod/phase:_unknown
 •  Waiting for component to start  ...
 ✗  Waiting for component to start [60171ns]
--- PASS: TestWaitAndGetPod (0.00s)
    --- PASS: TestWaitAndGetPod/phase:_running (0.00s)
    --- PASS: TestWaitAndGetPod/phase:_failed (0.00s)
    --- PASS: TestWaitAndGetPod/phase:_unknown (0.00s)
=== RUN   TestCreatePVC
=== RUN   TestCreatePVC/Case:_Valid_pvc_name
=== RUN   TestCreatePVC/Case:_Invalid_pvc_name
--- PASS: TestCreatePVC (0.00s)
    --- PASS: TestCreatePVC/Case:_Valid_pvc_name (0.00s)
    --- PASS: TestCreatePVC/Case:_Invalid_pvc_name (0.00s)
=== RUN   TestAddPVCToPodTemplateSpec
=== RUN   TestAddPVCToPodTemplateSpec/podSpecTest
--- PASS: TestAddPVCToPodTemplateSpec (0.00s)
    --- PASS: TestAddPVCToPodTemplateSpec/podSpecTest (0.00s)
=== RUN   TestAddVolumeMountToPodTemplateSpec
=== RUN   TestAddVolumeMountToPodTemplateSpec/podSpecTest
=== RUN   TestAddVolumeMountToPodTemplateSpec/podSpecTest#01
--- PASS: TestAddVolumeMountToPodTemplateSpec (0.00s)
    --- PASS: TestAddVolumeMountToPodTemplateSpec/podSpecTest (0.00s)
    --- PASS: TestAddVolumeMountToPodTemplateSpec/podSpecTest#01 (0.00s)
=== RUN   TestGetPVCsFromSelector
=== RUN   TestGetPVCsFromSelector/Case:_Valid_pvc_name
=== RUN   TestGetPVCsFromSelector/Case:_Wrong_Label_Selector
--- PASS: TestGetPVCsFromSelector (0.00s)
    --- PASS: TestGetPVCsFromSelector/Case:_Valid_pvc_name (0.00s)
    --- PASS: TestGetPVCsFromSelector/Case:_Wrong_Label_Selector (0.00s)
PASS
ok  	github.com/openshift/odo/pkg/kclient	0.418s
To test it out manually:
  • Set experiment to true odo preference set experimental true
  • Copy devfile to project dir and execute odo push (Pls remember to check if your devfile has volumes) for example:
components:
  -
    type: dockerimage
    image: websphere-liberty:19.0.0.3-webProfile7
    alias: runtime
    volumes:
      - name: m3
        containerPath: /home/user/.m3runtime
      - name: m2
        containerPath: /home/user/.m2runtime
      - name: m2
        containerPath: /home/user/.m2runtime222
  -
    type: dockerimage
    alias: tools
    image: quay.io/eclipse/che-java8-maven:nightly
    volumes:
      - name: m2
        containerPath: /home/user/.m2tools
      - name: m3
        containerPath: /home/user/.m3tools
      - name: m4
        containerPath: /home/user/.m4tools
  • Execute kubectl get po,deploy,pvc and confirm the pvc created
  • Execute kubectl describe po <component pod> and confirm the volume mounts for the containers
maysuns-mbp:scripts maysun$ oc get pvc
NAME                                   STATUS   VOLUME            CAPACITY   ACCESS MODES   STORAGECLASS   AGE   LABELS
persistentvolumeclaim/m2-spring-gbrz   Bound    che-workspace7    8Gi        RWO,RWX                       2h    component=spring,storage-name=m2
persistentvolumeclaim/m3-spring-vijx   Bound    che-workspace8    8Gi        RWO,RWX                       16s   component=spring,storage-name=m3
persistentvolumeclaim/m4-spring-hnie   Bound    che-workspace6    8Gi        RWO,RWX                       16s   component=spring,storage-name=m4
maysuns-mbp:.odo maysun$ oc get po
NAME                                READY   STATUS    RESTARTS   AGE
spring-b5dcd448b-fjf6f              2/2     Running   0          41m

maysuns-mbp:.odo maysun$ oc describe po spring-b5dcd448b-fjf6f 
Name:               spring-b5dcd448b-fjf6f
[...]
Containers:
  runtime:
    Container ID:   docker://d232eb20c57c0550a403a6e58c790a6b9322227b9c78446556eb8f8a9c3a2843
    Image:          websphere-liberty:19.0.0.3-webProfile7
    [...]
    Mounts:
      /home/user/.m2runtime from m2-spring-gbrz-kcmxb-volume (rw)
      /home/user/.m2runtime222 from m2-spring-gbrz-kcmxb-volume (rw)
      /home/user/.m3runtime from m3-spring-vijx-mwljq-volume (rw)
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-k6wc8 (ro)
  tools:
    Container ID:   docker://7b976f1b0d8a5935defb6ebb9411432fc5ceed1c5e06df63c37de98ccc2fc564
    Image:          quay.io/eclipse/che-java8-maven:nightly
    [...]
    Mounts:
      /home/user/.m2tools from m2-spring-gbrz-kcmxb-volume (rw)
      /home/user/.m3tools from m3-spring-vijx-mwljq-volume (rw)
      /home/user/.m4tools from m4-spring-hnie-yxpxy-volume (rw)
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-k6wc8 (ro)
[...]
Volumes:
  m3-spring-vijx-mwljq-volume:
    Type:       PersistentVolumeClaim (a reference to a PersistentVolumeClaim in the same namespace)
    ClaimName:  m3-spring-vijx
    ReadOnly:   false
  m2-spring-gbrz-kcmxb-volume:
    Type:       PersistentVolumeClaim (a reference to a PersistentVolumeClaim in the same namespace)
    ClaimName:  m2-spring-gbrz
    ReadOnly:   false
  m4-spring-hnie-yxpxy-volume:
    Type:       PersistentVolumeClaim (a reference to a PersistentVolumeClaim in the same namespace)
    ClaimName:  m4-spring-hnie
    ReadOnly:   false
  default-token-k6wc8:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-k6wc8
    Optional:    false
[...]
Events:
  Type    Reason     Age   From                         Message
  ----    ------     ----  ----                         -------
  Normal  Scheduled  32s   default-scheduler            Successfully assigned che/spring-b5dcd448b-fjf6f to maysun-okd-worker3
  Normal  Pulling    30s   kubelet, maysun-okd-worker3  pulling image "websphere-liberty:19.0.0.3-webProfile7"
  Normal  Pulled     29s   kubelet, maysun-okd-worker3  Successfully pulled image "websphere-liberty:19.0.0.3-webProfile7"
  Normal  Created    29s   kubelet, maysun-okd-worker3  Created container
  Normal  Started    29s   kubelet, maysun-okd-worker3  Started container
  Normal  Pulling    29s   kubelet, maysun-okd-worker3  pulling image "quay.io/eclipse/che-java8-maven:nightly"
  Normal  Pulled     28s   kubelet, maysun-okd-worker3  Successfully pulled image "quay.io/eclipse/che-java8-maven:nightly"
  Normal  Created    28s   kubelet, maysun-okd-worker3  Created container
  Normal  Started    28s   kubelet, maysun-okd-worker3  Started container

Integration tests to be covered by #2673

@openshift-ci-robot openshift-ci-robot added do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. Required by Prow. kind/feature Categorizes issue as a feature request. For PRs, that means that the PR is the implementation size/L labels Feb 27, 2020
@maysunfaisal maysunfaisal marked this pull request as ready for review February 28, 2020 19:10
@openshift-ci-robot openshift-ci-robot removed the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. Required by Prow. label Feb 28, 2020
@kadel
Copy link
Member

kadel commented Mar 2, 2020

/approve

@openshift-ci-robot
Copy link
Collaborator

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: kadel

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

@openshift-ci-robot openshift-ci-robot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. Required by Prow. label Mar 2, 2020
Copy link
Contributor

@rajivnathan rajivnathan left a comment

Choose a reason for hiding this comment

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

Works well. Nice job. Have some general comments.

@@ -1,6 +1,16 @@
package common

// ComponentAdapter defines the functions that platform-specific adapters must implement
import (
corev1 "k8s.io/api/core/v1"
Copy link
Contributor

Choose a reason for hiding this comment

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

The common package is meant to be platform neutral so we should avoid platform-specific imports like this kubernetes import in this package. For example, if we had a docker platform adapter then it wouldn't need it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

updated

type ComponentAdapter interface {
Start() error
Initialize() (*corev1.PodTemplateSpec, error)
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we really need an initialize function? Seems like we could remove it if the component adapter uses the storage adapter within its start function.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

updated


// StorageAdapter defines the storage functions that platform-specific adapters must implement
type StorageAdapter interface {
Start(*corev1.PodTemplateSpec) error
Copy link
Contributor

Choose a reason for hiding this comment

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

Not sure Start makes much sense in terms of storage. Maybe Create instead, where create could be responsible for creating the PVC?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

updated

}
}

// Start creates Kubernetes resources that correspond to the devfile if they don't already exist
func (k Adapter) Start() error {

err := k.componentAdapter.Start()
podTemplateSpec, err := k.componentAdapter.Initialize()
Copy link
Contributor

Choose a reason for hiding this comment

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

Same question as above about whether we really need an initialize function. Seems like the component adapter can make use of the storage adapter? Then in the component adapter's Start function it can call the storage adapter to add the volume mounts to the pod spec.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

updated

componentAliasToVolumes := make(map[string][]common.DockerimageVolume)
// Only components with aliases are considered because without an alias commands cannot reference them
for _, comp := range devfileObj.Data.GetAliasedComponents() {
if comp.Type == common.DevfileComponentTypeDockerimage {
Copy link
Contributor

Choose a reason for hiding this comment

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

There are a few places in the code where we're calling GetAliasedComponents() and then filtering by type for DevfileComponentTypeDockerimage. I think we should create a common function like GetSupportedComponents() on the odo level (ie. not on the parser level) that will call GetAliasedComponents() and then filter. The benefit would be if we decide to support other types then we would only need to update that single function.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

updated

@@ -44,6 +44,21 @@ func GetContainers(devfileObj devfile.DevfileObj) []corev1.Container {
return containers
}

// GetVolumes iterates through the components in the devfile and returns a map of component alias to the devfile volumes
func GetVolumes(devfileObj devfile.DevfileObj) map[string][]common.DockerimageVolume {
Copy link
Contributor

Choose a reason for hiding this comment

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

Should the return type be something more generic than common.DockerimageVolume? When we support Kubernetes or other component types might be weird for them to have to convert to use the Docker image the type. I'm on the fence about this though because I think if we do create a generic type it will likely have the same properties.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

updated

@@ -13,6 +15,9 @@ import (
const (
PersistentVolumeClaimKind = "PersistentVolumeClaim"
PersistentVolumeClaimAPIVersion = "v1"

// The length of the string to be generated for names of resources
nameLength = 5
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm assuming we'd want to use this constant through kclient so makes sense to move it to kclient.go?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

updated

func AddVolumeMountToPodTemplateSpec(podTemplateSpec *corev1.PodTemplateSpec, volumeName, pvc string, containerMountPathsMap map[string][]string) error {
// AddVolumeMountToPodTemplateSpec adds the Volume Mounts in componentAliasToMountPaths to the podTemplateSpec containers for a given pvc and volumeName
// componentAliasToMountPaths is a map of a container alias to an array of its Mount Paths
func AddVolumeMountToPodTemplateSpec(podTemplateSpec *corev1.PodTemplateSpec, volumeName, pvc string, componentAliasToMountPaths map[string][]string) error {
Copy link
Contributor

Choose a reason for hiding this comment

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

pvc doesn't appear to be used in this function

Copy link
Contributor Author

Choose a reason for hiding this comment

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

updated

Signed-off-by: Maysun J Faisal <maysun.j.faisal@ibm.com>
Signed-off-by: Maysun J Faisal <maysun.j.faisal@ibm.com>
Signed-off-by: Maysun J Faisal <maysun.j.faisal@ibm.com>
@maysunfaisal
Copy link
Contributor Author

@rajivnathan PR has been updated with your feedback, thanks for the help with the interfaces!

Tests after feedback refactor commit

maysuns-mbp:adapters maysun$ pwd
/Users/maysun/go/src/github.com/openshift/odo/pkg/devfile/adapters

maysuns-mbp:adapters maysun$ go clean -testcache && go test ./... -v
=== RUN   TestNewPlatformAdapter
=== RUN   TestNewPlatformAdapter/get_platform_adapter
--- PASS: TestNewPlatformAdapter (0.00s)
    --- PASS: TestNewPlatformAdapter/get_platform_adapter (0.00s)
PASS
ok  	github.com/openshift/odo/pkg/devfile/adapters	0.763s
?   	github.com/openshift/odo/pkg/devfile/adapters/common	[no test files]
?   	github.com/openshift/odo/pkg/devfile/adapters/kubernetes	[no test files]
=== RUN   TestComponentAdapter
=== RUN   TestComponentAdapter/Case:_Invalid_devfile
=== RUN   TestComponentAdapter/Case:_Valid_devfile
 •  Waiting for component to start  ...
 ✓  Waiting for component to start [159065ns]
--- PASS: TestComponentAdapter (0.00s)
    --- PASS: TestComponentAdapter/Case:_Invalid_devfile (0.00s)
    --- PASS: TestComponentAdapter/Case:_Valid_devfile (0.00s)
PASS
ok  	github.com/openshift/odo/pkg/devfile/adapters/kubernetes/component	0.687s
=== RUN   TestStorageCreate
=== RUN   TestStorageCreate/storage_test
--- PASS: TestStorageCreate (0.00s)
    --- PASS: TestStorageCreate/storage_test (0.00s)
PASS
ok  	github.com/openshift/odo/pkg/devfile/adapters/kubernetes/storage	0.637s
?   	github.com/openshift/odo/pkg/devfile/adapters/kubernetes/utils	[no test files]
maysuns-mbp:kclient maysun$ pwd
/Users/maysun/go/src/github.com/openshift/odo/pkg/kclient

maysuns-mbp:kclient maysun$ go clean -testcache && go test ./... -v
=== RUN   TestCreateDeployment
=== RUN   TestCreateDeployment/Case:_Valid_deployment_name
=== RUN   TestCreateDeployment/Case:_Invalid_deployment_name
--- PASS: TestCreateDeployment (0.00s)
    --- PASS: TestCreateDeployment/Case:_Valid_deployment_name (0.00s)
    --- PASS: TestCreateDeployment/Case:_Invalid_deployment_name (0.00s)
=== RUN   TestUpdateDeployment
=== RUN   TestUpdateDeployment/Case:_Valid_deployment_name
=== RUN   TestUpdateDeployment/Case:_Invalid_deployment_name
--- PASS: TestUpdateDeployment (0.00s)
    --- PASS: TestUpdateDeployment/Case:_Valid_deployment_name (0.00s)
    --- PASS: TestUpdateDeployment/Case:_Invalid_deployment_name (0.00s)
=== RUN   TestGenerateContainer
=== RUN   TestGenerateContainer/#00
=== RUN   TestGenerateContainer/container1
--- PASS: TestGenerateContainer (0.00s)
    --- PASS: TestGenerateContainer/#00 (0.00s)
    --- PASS: TestGenerateContainer/container1 (0.00s)
=== RUN   TestGeneratePodTemplateSpec
=== RUN   TestGeneratePodTemplateSpec/podSpecTest
--- PASS: TestGeneratePodTemplateSpec (0.00s)
    --- PASS: TestGeneratePodTemplateSpec/podSpecTest (0.00s)
=== RUN   TestGeneratePVCSpec
=== RUN   TestGeneratePVCSpec/1
=== RUN   TestGeneratePVCSpec/2
--- PASS: TestGeneratePVCSpec (0.00s)
    --- PASS: TestGeneratePVCSpec/1 (0.00s)
    --- PASS: TestGeneratePVCSpec/2 (0.00s)
=== RUN   TestWaitAndGetPod
=== RUN   TestWaitAndGetPod/phase:_running
 •  Waiting for component to start  ...
 ✓  Waiting for component to start [164875ns]
=== RUN   TestWaitAndGetPod/phase:_failed
 •  Waiting for component to start  ...
 ✗  Waiting for component to start [91273ns]
=== RUN   TestWaitAndGetPod/phase:_unknown
 •  Waiting for component to start  ...
 ✗  Waiting for component to start [97284ns]
--- PASS: TestWaitAndGetPod (0.00s)
    --- PASS: TestWaitAndGetPod/phase:_running (0.00s)
    --- PASS: TestWaitAndGetPod/phase:_failed (0.00s)
    --- PASS: TestWaitAndGetPod/phase:_unknown (0.00s)
=== RUN   TestCreatePVC
=== RUN   TestCreatePVC/Case:_Valid_pvc_name
=== RUN   TestCreatePVC/Case:_Invalid_pvc_name
--- PASS: TestCreatePVC (0.00s)
    --- PASS: TestCreatePVC/Case:_Valid_pvc_name (0.00s)
    --- PASS: TestCreatePVC/Case:_Invalid_pvc_name (0.00s)
=== RUN   TestAddPVCToPodTemplateSpec
=== RUN   TestAddPVCToPodTemplateSpec/podSpecTest
--- PASS: TestAddPVCToPodTemplateSpec (0.00s)
    --- PASS: TestAddPVCToPodTemplateSpec/podSpecTest (0.00s)
=== RUN   TestAddVolumeMountToPodTemplateSpec
=== RUN   TestAddVolumeMountToPodTemplateSpec/podSpecTest
=== RUN   TestAddVolumeMountToPodTemplateSpec/podSpecTest#01
--- PASS: TestAddVolumeMountToPodTemplateSpec (0.00s)
    --- PASS: TestAddVolumeMountToPodTemplateSpec/podSpecTest (0.00s)
    --- PASS: TestAddVolumeMountToPodTemplateSpec/podSpecTest#01 (0.00s)
=== RUN   TestGetPVCsFromSelector
=== RUN   TestGetPVCsFromSelector/Case:_Valid_pvc_name
=== RUN   TestGetPVCsFromSelector/Case:_Wrong_Label_Selector
--- PASS: TestGetPVCsFromSelector (0.00s)
    --- PASS: TestGetPVCsFromSelector/Case:_Valid_pvc_name (0.00s)
    --- PASS: TestGetPVCsFromSelector/Case:_Wrong_Label_Selector (0.00s)
=== RUN   TestAddPVCAndVolumeMount
=== RUN   TestAddPVCAndVolumeMount/Case:_Valid_case
=== RUN   TestAddPVCAndVolumeMount/Case:_Error_case
--- PASS: TestAddPVCAndVolumeMount (0.00s)
    --- PASS: TestAddPVCAndVolumeMount/Case:_Valid_case (0.00s)
    --- PASS: TestAddPVCAndVolumeMount/Case:_Error_case (0.00s)
PASS
ok  	github.com/openshift/odo/pkg/kclient	1.764s
maysuns-mbp:odo maysun$ make golint
golangci-lint run ./... --timeout 5m

Signed-off-by: Maysun J Faisal <maysun.j.faisal@ibm.com>
@codecov
Copy link

codecov bot commented Mar 5, 2020

Codecov Report

Merging #2651 into master will increase coverage by 0.22%.
The diff coverage is 52.12%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #2651      +/-   ##
==========================================
+ Coverage   43.65%   43.87%   +0.22%     
==========================================
  Files          81       85       +4     
  Lines        7498     7663     +165     
==========================================
+ Hits         3273     3362      +89     
- Misses       3910     3971      +61     
- Partials      315      330      +15
Impacted Files Coverage Δ
pkg/kclient/kclient.go 30.43% <ø> (ø) ⬆️
pkg/devfile/adapters/kubernetes/storage/adapter.go 0% <0%> (ø)
pkg/kclient/generators.go 90.78% <0%> (-9.22%) ⬇️
pkg/testingutil/devfile.go 0% <0%> (ø) ⬆️
pkg/devfile/adapters/common/utils.go 100% <100%> (ø)
pkg/kclient/fakeclient.go 100% <100%> (ø) ⬆️
...g/devfile/adapters/kubernetes/component/adapter.go 69.35% <65.62%> (-5.65%) ⬇️
pkg/devfile/adapters/kubernetes/storage/utils.go 66.07% <66.07%> (ø)
pkg/kclient/volumes.go 93.22% <83.33%> (-1.66%) ⬇️
pkg/component/watch.go 66.66% <0%> (-7.34%) ⬇️
... and 11 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 7ad9d66...a5bb07d. Read the comment docs.

Copy link
Contributor

@rajivnathan rajivnathan left a comment

Choose a reason for hiding this comment

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

Thanks for the changes. Couple minor comments. Also, are we missing unit tests for pkg/devfile/adapters/kubernetes/storage/adapter.go ?

var components []common.DevfileComponent
// Only components with aliases are considered because without an alias commands cannot reference them
for _, comp := range data.GetAliasedComponents() {
if comp.Type == common.DevfileComponentTypeDockerimage {
Copy link
Contributor

Choose a reason for hiding this comment

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

We should probably add a comment explaining that we're only handling components of Dockerimage type to begin with because most of the devfiles in the che devfile registry use it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

updated


// Add PVC and Volume Mounts to the podTemplateSpec
err = kclient.AddPVCAndVolumeMount(podTemplateSpec, volumeNameToPVC, componentAliasToVolumes)
a.VolumeNameToPVCName, err = CreateComponentStorage(&a.Client, volumes, componentName)
Copy link
Contributor

Choose a reason for hiding this comment

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

We can use a.ComponentName directly and remove the line above

Copy link
Contributor Author

Choose a reason for hiding this comment

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

updated

@maysunfaisal
Copy link
Contributor Author

maysunfaisal commented Mar 5, 2020

@rajivnathan I have removed the storage adapter test because it's Create just calls function CreateComponentStorage, which is in utils.go and I have unit tests for that in utils_test.go and I have also moved all the unit testing of storage's adapter_test.go to volumes_test.go. The new tests in volumes_test.go was basically just a cut paste of the previous storage adapter tests. You can have a look at this in the prev commit e22cd68

Signed-off-by: Maysun J Faisal <maysun.j.faisal@ibm.com>
Copy link
Contributor

@rajivnathan rajivnathan left a comment

Choose a reason for hiding this comment

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

One more thing, the ownerReferences should be set to the deployment so that when the deployment is deleted the pvc will be deleted as well. That is what odo already does in the non-devfile case.

eg.

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  annotations:
    pv.kubernetes.io/bind-completed: "yes"
    pv.kubernetes.io/bound-by-controller: "yes"
  creationTimestamp: 2020-03-05T16:02:20Z
  finalizers:
  - kubernetes.io/pvc-protection
  labels:
    app: app
    app.kubernetes.io/instance: nodejs-nodejs-ex-qnxf
    app.kubernetes.io/managed-by: odo
    app.kubernetes.io/managed-by-version: v1.1.0
    app.kubernetes.io/name: nodejs
    app.kubernetes.io/part-of: app
    app.openshift.io/runtime-version: latest
  name: nodejs-nodejs-ex-qnxf-app-s2idata
  namespace: odo
  ownerReferences:
  - apiVersion: apps.openshift.io/v1
    kind: DeploymentConfig
    name: nodejs-nodejs-ex-qnxf-app
    uid: b195a66b-5efa-11ea-ab06-00000a1f025e
  resourceVersion: "60867020"
  selfLink: /api/v1/namespaces/odo/persistentvolumeclaims/nodejs-nodejs-ex-qnxf-app-s2idata
  uid: b19d2b22-5efa-11ea-ab06-00000a1f025e
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
  volumeName: volume6
status:
  accessModes:
  - ReadWriteOnce
  capacity:
    storage: 8Gi
  phase: Bound

Signed-off-by: Maysun J Faisal <maysun.j.faisal@ibm.com>
Signed-off-by: Maysun J Faisal <maysun.j.faisal@ibm.com>
Copy link
Contributor

@rajivnathan rajivnathan left a comment

Choose a reason for hiding this comment

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

Couple minor comments but also when I tried it the first time I hit an error.

odo push -v 3
 •  Push devfile component spring-devfile  ...
I0305 18:08:51.091152   73206 utils.go:17] Found component dockerimage with alias tools
I0305 18:08:51.091267   73206 utils.go:17] Found component dockerimage with alias tools
I0305 18:08:51.091279   73206 utils.go:26] Checking for PVC with name m2 and label component=spring-devfile,storage-name=m2
I0305 18:08:51.133687   73206 utils.go:37] Creating a PVC with name m2 and label component=spring-devfile,storage-name=m2
I0305 18:08:51.133723   73206 utils.go:77] Creating a PVC with name m2-spring-devfile-yfyz
I0305 18:08:51.142243   73206 adapter.go:77] Creating deployment spring-devfile
I0305 18:08:51.142261   73206 adapter.go:78] The component name is spring-devfile
I0305 18:08:51.158319   73206 adapter.go:93] Successfully created component spring-devfile
I0305 18:08:51.184479   73206 volumes.go:135] Updating owner references for pvc m2-spring-devfile-yfyz
 ✗  Failed to start component with name spring-devfile.
Error: Failed to create the component: Operation cannot be fulfilled on persistentvolumeclaims "m2-spring-devfile-yfyz": the object has been modified; please apply your changes to the latest version and try again

Looks like it is hit or miss. I think we should create the volume after the deployment and just set the owner reference when we're creating the volume instead of trying to update it after the fact?

// GenerateOwnerReference genertes an ownerReference from the deployment which can then be set as
// owner for various Kubernetes objects and ensure that when the owner object is deleted from the
// cluster, all other objects are automatically removed by Kubernetes garbage collector
func GenerateOwnerReference(deployment *appsv1.Deployment) metav1.OwnerReference {
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this function should be moved to the generators.go file?

func GenerateOwnerReference(deployment *appsv1.Deployment) metav1.OwnerReference {

ownerReference := metav1.OwnerReference{
APIVersion: "extensions/v1beta1",
Copy link
Contributor

Choose a reason for hiding this comment

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

Think it's probably safer to get the APIVersion from the deployment directly. ie. deployment.APIVersion That way in the future if we update our deployment spec generation code to use a newer version we wouldn't need to update this code as well. It will just work.

Copy link
Member

Choose a reason for hiding this comment

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

To add on to what Rajiv said and why we might not want to reference it directly: we should not be using or referencing Deployments in the extensions/v1beta1 API group.

Starting with Kube 1.16, it’s been removed from the Kube API and cant be referenced.

Copy link
Member

@johnmcollier johnmcollier left a comment

Choose a reason for hiding this comment

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

Overall looks good, mostly a few nits here and there

package storage

// HelperAdapter defines functions that kubernetes storage adapters may implement
type HelperAdapter interface {
Copy link
Member

Choose a reason for hiding this comment

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

Should this be called something other than HelperAdapter? I know we can't conflict with StorageAdapter, but I think HelperAdapter is confusing here.

Copy link
Contributor Author

@maysunfaisal maysunfaisal Mar 6, 2020

Choose a reason for hiding this comment

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

being removed with the latest commit already

}

randomChars := util.GenerateRandomString(4)
namespaceKubernetesObject, err := util.NamespaceOpenShiftObject(name, componentName)
Copy link
Member

Choose a reason for hiding this comment

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

Nit: I know that functionally it's the same and that you didn't write the function, but given that the code we're running here is Kube generic, could we rename the utils function to NamespaceKubernetesObject?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

wanted to, but a lot of code in odo1 is using it. Still change the function name?

Copy link
Member

Choose a reason for hiding this comment

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

If it's just a rename, it should be safe to do in my opinion. @kadel what are your thoughts?

volNames := [...]string{"vol1", "vol2", "vol3"}
volSize := "5Gi"

tests := []struct {
Copy link
Member

Choose a reason for hiding this comment

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

Could you add some more test cases for:

  • Volune names that might cause issues (0 length, over kubernetes maximum, etc)
  • Different numbers of volumes (0, and 1)
  • Different sizes of volumes, and making sure the functions error out with invalid values

Copy link
Contributor Author

Choose a reason for hiding this comment

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

let me see what I can do with these

)

// GetSupportedComponents iterates through the components in the devfile and returns a list of odo supported components
func GetSupportedComponents(data versions.DevfileData) []common.DevfileComponent {
Copy link
Member

Choose a reason for hiding this comment

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

Could you add a unit test for GetSupportedComponents?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

makes sense, let me see

@@ -42,26 +45,63 @@ func (a Adapter) Start() (err error) {

objectMeta := kclient.CreateObjectMeta(componentName, a.Client.Namespace, labels, nil)
Copy link
Member

Choose a reason for hiding this comment

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

We're probably unlikely to hit this issue with component names, but to be safe, we should probably trim and sanitize componentName with either utils.DNS1123Name() or utils.NamespaceOpenShiftObject before passing it into CreateObjectMeta.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

updated

// generateVolumeNameFromPVC generates a random volume name based on the name
// of the given PVC
func generateVolumeNameFromPVC(pvc string) string {
return fmt.Sprintf("%v-%v-volume", pvc, util.GenerateRandomString(nameLength))
Copy link
Member

Choose a reason for hiding this comment

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

Nit: Any reason why we wouldn't just want to call utils.NamespacedOpenShiftObject here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think volume name is not limited to 63 limit since its not a kube resource(need to confirm tho).

Copy link
Member

Choose a reason for hiding this comment

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

You're right, it might be 253

Copy link
Contributor Author

@maysunfaisal maysunfaisal Mar 6, 2020

Choose a reason for hiding this comment

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

actually, does not allow my vol name to be more than 63, updated

 [spec.template.spec.volumes[0].name: Invalid value: "m3-abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxy-tmnm-ccdde-volume": must be no more than 63 characters

@maysunfaisal
Copy link
Contributor Author

/retest

Signed-off-by: Maysun J Faisal <maysun.j.faisal@ibm.com>
@maysunfaisal
Copy link
Contributor Author

@rajivnathan @johnmcollier I've pushed a new commit, pls review at your convenience, thx!

@kadel
Copy link
Member

kadel commented Mar 10, 2020

@rajivnathan @johnmcollier I've pushed a new commit, pls review at your convenience, thx!

@rajivnathan @johnmcollier, after you review this you can just do /lgtm on a separate line in a comment and this PR will get automaticaly merged.

@rajivnathan
Copy link
Contributor

Looks good to me now. @johnmcollier please add the /lgtm once you're ready

Copy link
Member

@johnmcollier johnmcollier left a comment

Choose a reason for hiding this comment

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

/lgtm

@openshift-ci-robot openshift-ci-robot added the lgtm Indicates that a PR is ready to be merged. Required by Prow. label Mar 11, 2020
@openshift-bot
Copy link

/retest

Please review the full test history for this PR and help us cut down flakes.

5 similar comments
@openshift-bot
Copy link

/retest

Please review the full test history for this PR and help us cut down flakes.

@openshift-bot
Copy link

/retest

Please review the full test history for this PR and help us cut down flakes.

@openshift-bot
Copy link

/retest

Please review the full test history for this PR and help us cut down flakes.

@openshift-bot
Copy link

/retest

Please review the full test history for this PR and help us cut down flakes.

@openshift-bot
Copy link

/retest

Please review the full test history for this PR and help us cut down flakes.

@openshift-bot
Copy link

/retest

Please review the full test history for this PR and help us cut down flakes.

@openshift-merge-robot openshift-merge-robot merged commit 4852786 into redhat-developer:master Mar 11, 2020
@rm3l rm3l added the estimated-size/XL (40-60) Rough sizing for Epics. About 3 sprints of work for a person label Jun 19, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
approved Indicates a PR has been approved by an approver from all required OWNERS files. Required by Prow. estimated-size/XL (40-60) Rough sizing for Epics. About 3 sprints of work for a person kind/feature Categorizes issue as a feature request. For PRs, that means that the PR is the implementation lgtm Indicates that a PR is ready to be merged. Required by Prow.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Implement Devfile volume support
8 participants