Skip to content

Commit

Permalink
Add support to pass CSI workspace
Browse files Browse the repository at this point in the history
Since Pipelines version v0.38.0, an user can pass CSI Volume
as a workspace. A sample CSI file can look like

```yaml
driver: secrets-store.csi.k8s.io
readOnly: true
volumeAttributes:
  secretProviderClass: "vault-database"
```

This requires feature flag to be alpha. Once feature flag is enabled
user can pass in `tkn` start like

```sh
$ tkn pipeline start foobar -w=csiFile=csi.yaml
```

Signed-off-by: vinamra28 <[email protected]>
  • Loading branch information
vinamra28 authored and tekton-robot committed Dec 26, 2022
1 parent 8196435 commit 1d3f2a7
Show file tree
Hide file tree
Showing 16 changed files with 215 additions and 35 deletions.
7 changes: 7 additions & 0 deletions docs/cmd/tkn_clustertask_start.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,13 @@ For passing the workspaces via flags:
resources:
requests:
storage: 1Gi
- In case of binding a CSI workspace, you can pass it like -w name=my-csi,csiFile=csi.yaml
but you need to create a csi.yaml file before hand. Sample contents of the file are as follows:

driver: secrets-store.csi.k8s.io
readOnly: true
volumeAttributes:
secretProviderClass: "vault-database"


### Options
Expand Down
12 changes: 12 additions & 0 deletions docs/cmd/tkn_pipeline_start.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,17 @@ To create a workspace-template.yaml
storage: 1Gi
EOF

To create a csi-template.yaml

```sh
$ cat <<EOF > csi-template.yaml
driver: secrets-store.csi.k8s.io
readOnly: true
volumeAttributes:
secretProviderClass: "vault-database"
EOF
```

To run a Pipeline that has one git resource, one image resource,
two parameters (foo and bar) and four workspaces (my-config, my-pvc,
my-secret, my-empty-dir and my-volume-claim-template)
Expand All @@ -47,6 +58,7 @@ my-secret, my-empty-dir and my-volume-claim-template)
--workspace name=my-empty-dir,emptyDir="" \
--workspace name=my-pvc,claimName=pvc1,subPath=dir
--workspace name=my-volume-claim-template,volumeClaimTemplateFile=workspace-template.yaml
--workspace name=my-csi-template,csiFile=csi-template.yaml

### Options

Expand Down
7 changes: 7 additions & 0 deletions docs/cmd/tkn_task_start.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,13 @@ For passing the workspaces via flags:
resources:
requests:
storage: 1Gi
- In case of binding a CSI workspace, you can pass it like -w name=my-csi,csiFile=csi.yaml
but you need to create a csi.yaml file before hand. Sample contents of the file are as follows:

driver: secrets-store.csi.k8s.io
readOnly: true
volumeAttributes:
secretProviderClass: "vault-database"


### Options
Expand Down
11 changes: 11 additions & 0 deletions docs/man/man1/tkn-clustertask-start.1
Original file line number Diff line number Diff line change
Expand Up @@ -157,9 +157,20 @@ requests:
storage: 1Gi

.RE
.IP \(bu 2
In case of binding a CSI workspace, you can pass it like \-w name=my\-csi,csiFile=csi.yaml
but you need to create a csi.yaml file before hand. Sample contents of the file are as follows:

.br

.RE

.PP
driver: secrets\-store.csi.k8s.io
readOnly: true
volumeAttributes:
secretProviderClass: "vault\-database"


.SH SEE ALSO
.PP
Expand Down
20 changes: 20 additions & 0 deletions docs/man/man1/tkn-pipeline-start.1
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,25 @@ EOF
.fi
.RE

.PP
To create a csi\-template.yaml

.PP
.RS

.nf
```sh
$ cat <<EOF > csi\-template.yaml
driver: secrets\-store.csi.k8s.io
readOnly: true
volumeAttributes:
secretProviderClass: "vault\-database"
EOF
```

.fi
.RE

.PP
To run a Pipeline that has one git resource, one image resource,
two parameters (foo and bar) and four workspaces (my\-config, my\-pvc,
Expand All @@ -176,6 +195,7 @@ $ tkn pipeline start \-\-resource source=samples\-git \\
\-\-workspace name=my\-empty\-dir,emptyDir="" \\
\-\-workspace name=my\-pvc,claimName=pvc1,subPath=dir
\-\-workspace name=my\-volume\-claim\-template,volumeClaimTemplateFile=workspace\-template.yaml
\-\-workspace name=my\-csi\-template,csiFile=csi\-template.yaml

.fi
.RE
Expand Down
11 changes: 11 additions & 0 deletions docs/man/man1/tkn-task-start.1
Original file line number Diff line number Diff line change
Expand Up @@ -157,9 +157,20 @@ requests:
storage: 1Gi

.RE
.IP \(bu 2
In case of binding a CSI workspace, you can pass it like \-w name=my\-csi,csiFile=csi.yaml
but you need to create a csi.yaml file before hand. Sample contents of the file are as follows:

.br

.RE

.PP
driver: secrets\-store.csi.k8s.io
readOnly: true
volumeAttributes:
secretProviderClass: "vault\-database"


.SH SEE ALSO
.PP
Expand Down
14 changes: 13 additions & 1 deletion docs/reference/cmd/pipeline_start.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,17 @@ To create a workspace-template.yaml
storage: 1Gi
EOF

To create a csi-template.yaml

```sh
$ cat <<EOF > csi-template.yaml
driver: secrets-store.csi.k8s.io
readOnly: true
volumeAttributes:
secretProviderClass: "vault-database"
EOF
```

To run a Pipeline that has one git resource, one image resource,
two parameters (foo and bar) and four workspaces (my-config, my-pvc,
my-secret, my-empty-dir and my-volume-claim-template)
Expand All @@ -38,4 +49,5 @@ my-secret, my-empty-dir and my-volume-claim-template)
--workspace name=my-config,config=rpg,item=ultimav=1 \
--workspace name=my-empty-dir,emptyDir="" \
--workspace name=my-pvc,claimName=pvc1,subPath=dir
--workspace name=my-volume-claim-template,volumeClaimTemplateFile=workspace-template.yaml
--workspace name=my-volume-claim-template,volumeClaimTemplateFile=workspace-template.yaml
--workspace name=my-csi-template,csiFile=csi-template.yaml
7 changes: 7 additions & 0 deletions pkg/cmd/clustertask/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,13 @@ For passing the workspaces via flags:
resources:
requests:
storage: 1Gi
- In case of binding a CSI workspace, you can pass it like -w name=my-csi,csiFile=csi.yaml
but you need to create a csi.yaml file before hand. Sample contents of the file are as follows:
driver: secrets-store.csi.k8s.io
readOnly: true
volumeAttributes:
secretProviderClass: "vault-database"
`

c := &cobra.Command{
Expand Down
7 changes: 7 additions & 0 deletions pkg/cmd/pipeline/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,13 @@ For passing the workspaces via flags:
resources:
requests:
storage: 1Gi
- In case of binding a CSI workspace, you can pass it like -w name=my-csi,csiFile=csi.yaml
but you need to create a csi.yaml file before hand. Sample contents of the file are as follows:
driver: secrets-store.csi.k8s.io
readOnly: true
volumeAttributes:
secretProviderClass: "vault-database"
`,
SilenceUsage: true,

Expand Down
7 changes: 7 additions & 0 deletions pkg/cmd/task/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,13 @@ For passing the workspaces via flags:
resources:
requests:
storage: 1Gi
- In case of binding a CSI workspace, you can pass it like -w name=my-csi,csiFile=csi.yaml
but you need to create a csi.yaml file before hand. Sample contents of the file are as follows:
driver: secrets-store.csi.k8s.io
readOnly: true
volumeAttributes:
secretProviderClass: "vault-database"
`,
SilenceUsage: true,
ValidArgsFunction: formatted.ParentCompletion,
Expand Down
3 changes: 3 additions & 0 deletions pkg/formatted/workspace.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ func Workspace(ws v1beta1.WorkspaceBinding) string {
secret := getWorkspaceSecret(ws.Secret)
return fmt.Sprintf("Secret (%s)", secret)
}
if ws.CSI != nil {
return fmt.Sprintf("CSI (Driver=%s)", ws.CSI.Driver)
}
return ""
}

Expand Down
9 changes: 9 additions & 0 deletions pkg/formatted/workspace_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,12 @@ func TestWorkspace(t *testing.T) {
SecretName: "foobar",
},
},
{
Name: "csi",
CSI: &corev1.CSIVolumeSource{
Driver: "secrets-store.csi.k8s.io",
},
},
}
defaultEmptyWorkspaceStr := Workspace(workspaceSpec[0]) // EmptyDir workspace with default storage medium
assert.Equal(t, defaultEmptyWorkspaceStr, "EmptyDir (emptyDir=)")
Expand All @@ -59,4 +65,7 @@ func TestWorkspace(t *testing.T) {

secretWorkspaceStr := Workspace(workspaceSpec[3]) // Secret Workspace
assert.Equal(t, secretWorkspaceStr, "Secret (secret=foobar)")

csiWorkspaceStr := Workspace(workspaceSpec[4]) // CSI Workspace
assert.Equal(t, csiWorkspaceStr, "CSI (Driver=secrets-store.csi.k8s.io)")
}
4 changes: 4 additions & 0 deletions pkg/workspaces/testdata/csi-typo.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
drive: secrets-store.csi.k8s.io
readOnly: true
volumeAttributes:
secretProviderClass: "vault-database"
4 changes: 4 additions & 0 deletions pkg/workspaces/testdata/csi.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
driver: secrets-store.csi.k8s.io
readOnly: true
volumeAttributes:
secretProviderClass: "vault-database"
98 changes: 67 additions & 31 deletions pkg/workspaces/workspaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ var (
secretParam = "secret"
configItemParam = "item"
volumeClaimTemplateFile = "volumeClaimTemplateFile"
csiFile = "csiFile"
)

const invalidWorkspace = "invalid input format for workspace : "
Expand Down Expand Up @@ -88,47 +89,54 @@ func parseWorkspace(w []string, httpClient http.Client) (map[string]v1beta1.Work
return nil, err
}

// check for volumeClaimTemplate
vctFile, err := getPar(r, volumeClaimTemplateFile)
if err != nil {
err = setWorkspaceConfig(r, &wB)
if err == nil {
ws[name] = wB
nWB++
} else if err != errNotFoundParam {
if vctFile, err := getPar(r, volumeClaimTemplateFile); err == nil {
err = setWorkspaceVCTemplate(r, &wB, vctFile, httpClient)
if err != nil {
return nil, err
}
ws[name] = wB
continue
}

err = setWorkspaceSecret(r, &wB)
if err == nil {
ws[name] = wB
nWB++
} else if err != errNotFoundParam {
if csiFile, err := getPar(r, csiFile); err == nil {
err = setWorkspaceCSITemplate(r, &wB, csiFile, httpClient)
if err != nil {
return nil, err
}
ws[name] = wB
continue
}

err = setWorkspaceEmptyDir(r, &wB)
if err == nil {
ws[name] = wB
nWB++
}
err = setWorkspaceConfig(r, &wB)
if err == nil {
ws[name] = wB
nWB++
} else if err != errNotFoundParam {
return nil, err
}

err = setWorkspacePVC(r, &wB)
if err == nil {
ws[name] = wB
nWB++
}
err = setWorkspaceSecret(r, &wB)
if err == nil {
ws[name] = wB
nWB++
} else if err != errNotFoundParam {
return nil, err
}

if nWB != 1 {
return nil, errors.New(invalidWorkspace + v)
}
} else {
err = setWorkspaceVCTemplate(r, &wB, vctFile, httpClient)
if err != nil {
return nil, err
}
if err = setWorkspaceEmptyDir(r, &wB); err == nil {
ws[name] = wB
nWB++
}

if err = setWorkspacePVC(r, &wB); err == nil {
ws[name] = wB
nWB++
}

if nWB != 1 {
return nil, errors.New(invalidWorkspace + v)
}

}

return ws, nil
Expand Down Expand Up @@ -246,6 +254,16 @@ func setWorkspaceVCTemplate(r []string, wB *v1beta1.WorkspaceBinding, vctFile st
return nil
}

func setWorkspaceCSITemplate(r []string, wB *v1beta1.WorkspaceBinding, vctFile string, httpClient http.Client) error {
csi, err := parseCSITemplate(vctFile, httpClient)
if err != nil {
return err
}

wB.CSI = csi
return nil
}

func parseVolumeClaimTemplate(filePath string, httpClient http.Client) (*corev1.PersistentVolumeClaim, error) {
b, err := file.LoadFileContent(httpClient, filePath, file.IsYamlFile(), fmt.Errorf("invalid file format for %s: .yaml or .yml file extension and format required", filePath))
if err != nil {
Expand All @@ -264,6 +282,24 @@ func parseVolumeClaimTemplate(filePath string, httpClient http.Client) (*corev1.
return &pvc, nil
}

func parseCSITemplate(filePath string, httpClient http.Client) (*corev1.CSIVolumeSource, error) {
b, err := file.LoadFileContent(httpClient, filePath, file.IsYamlFile(), fmt.Errorf("invalid file format for %s: .yaml or .yml file extension and format required", filePath))
if err != nil {
return nil, err
}
m := map[string]interface{}{}
err = yaml.UnmarshalStrict(b, &m)
if err != nil {
return nil, err
}

csi := corev1.CSIVolumeSource{}
if err := yaml.UnmarshalStrict(b, &csi); err != nil {
return nil, err
}
return &csi, nil
}

func getPar(r []string, par string) (string, error) {
var p string
for i := range r {
Expand Down
Loading

0 comments on commit 1d3f2a7

Please sign in to comment.