Skip to content

Commit

Permalink
add resource create -f option
Browse files Browse the repository at this point in the history
  • Loading branch information
danielhelfand authored and tekton-robot committed Dec 9, 2019
1 parent 1193d44 commit e126197
Show file tree
Hide file tree
Showing 8 changed files with 247 additions and 21 deletions.
2 changes: 1 addition & 1 deletion docs/cmd/tkn_resource.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ Manage pipeline resources
### SEE ALSO

* [tkn](tkn.md) - CLI for tekton pipelines
* [tkn resource create](tkn_resource_create.md) - Creates pipeline resource
* [tkn resource create](tkn_resource_create.md) - Create a pipeline resource in a namespace
* [tkn resource delete](tkn_resource_delete.md) - Delete a pipeline resource in a namespace
* [tkn resource describe](tkn_resource_describe.md) - Describes a pipeline resource in a namespace
* [tkn resource list](tkn_resource_list.md) - Lists pipeline resources in a namespace
Expand Down
19 changes: 12 additions & 7 deletions docs/cmd/tkn_resource_create.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
## tkn resource create

Creates pipeline resource
Create a pipeline resource in a namespace

### Usage

Expand All @@ -10,20 +10,25 @@ tkn resource create

### Synopsis

Creates pipeline resource
Create a pipeline resource in a namespace

### Examples


# creates new resource as per the given input
tkn resource create -n namespace


# Creates new PipelineResource as per the given input
tkn resource create -n namespace

# Create a PipelineResource defined by foo.yaml in namespace 'bar'
tkn resource create -f foo.yaml -n bar

### Options

```
-h, --help help for create
--allow-missing-template-keys If true, ignore any errors in templates when a field or map key is missing in the template. Only applies to golang and jsonpath output formats. (default true)
-f, --from string local or remote filename to use to create the pipeline resource
-h, --help help for create
-o, --output string Output format. One of: json|yaml|name|go-template|go-template-file|template|templatefile|jsonpath|jsonpath-file.
--template string Template string or path to template file to use when -o=go-template, -o=go-template-file. The template format is golang templates [http://golang.org/pkg/text/template/#pkg-overview].
```

### Options inherited from parent commands
Expand Down
27 changes: 24 additions & 3 deletions docs/man/man1/tkn-resource-create.1
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

.SH NAME
.PP
tkn\-resource\-create \- Creates pipeline resource
tkn\-resource\-create \- Create a pipeline resource in a namespace


.SH SYNOPSIS
Expand All @@ -15,14 +15,31 @@ tkn\-resource\-create \- Creates pipeline resource

.SH DESCRIPTION
.PP
Creates pipeline resource
Create a pipeline resource in a namespace


.SH OPTIONS
.PP
\fB\-\-allow\-missing\-template\-keys\fP[=true]
If true, ignore any errors in templates when a field or map key is missing in the template. Only applies to golang and jsonpath output formats.

.PP
\fB\-f\fP, \fB\-\-from\fP=""
local or remote filename to use to create the pipeline resource

.PP
\fB\-h\fP, \fB\-\-help\fP[=false]
help for create

.PP
\fB\-o\fP, \fB\-\-output\fP=""
Output format. One of: json|yaml|name|go\-template|go\-template\-file|template|templatefile|jsonpath|jsonpath\-file.

.PP
\fB\-\-template\fP=""
Template string or path to template file to use when \-o=go\-template, \-o=go\-template\-file. The template format is golang templates [
\[la]http://golang.org/pkg/text/template/#pkg-overview\[ra]].


.SH OPTIONS INHERITED FROM PARENT COMMANDS
.PP
Expand All @@ -44,9 +61,13 @@ Creates pipeline resource

.SH EXAMPLE
.PP
# creates new resource as per the given input
# Creates new PipelineResource as per the given input
tkn resource create \-n namespace

.PP
# Create a PipelineResource defined by foo.yaml in namespace 'bar'
tkn resource create \-f foo.yaml \-n bar


.SH SEE ALSO
.PP
Expand Down
72 changes: 64 additions & 8 deletions pkg/cmd/pipelineresource/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,22 @@ import (

"github.com/AlecAivazis/survey/v2"
"github.com/AlecAivazis/survey/v2/terminal"
"github.com/ghodss/yaml"
"github.com/spf13/cobra"
"github.com/tektoncd/cli/pkg/cli"
"github.com/tektoncd/cli/pkg/helper/file"
validateinput "github.com/tektoncd/cli/pkg/helper/validate"
"github.com/tektoncd/pipeline/pkg/apis/pipeline/v1alpha1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
cliopts "k8s.io/cli-runtime/pkg/genericclioptions"
)

type Resource struct {
Params cli.Params
stream *cli.Stream
AskOpts survey.AskOpt
PipelineResource v1alpha1.PipelineResource
from string
}

func createCommand(p cli.Params) *cobra.Command {
Expand All @@ -47,16 +51,19 @@ func createCommand(p cli.Params) *cobra.Command {
return nil
},
}

f := cliopts.NewPrintFlags("create")
opts := &Resource{from: ""}
eg := `
# creates new resource as per the given input
tkn resource create -n namespace
# Creates new PipelineResource as per the given input
tkn resource create -n namespace
# Create a PipelineResource defined by foo.yaml in namespace 'bar'
tkn resource create -f foo.yaml -n bar`

`
c := &cobra.Command{
Use: "create",
DisableFlagsInUseLine: true,
Short: "Creates pipeline resource",
Short: "Create a pipeline resource in a namespace",
Example: eg,
SilenceUsage: true,
Annotations: map[string]string{
Expand All @@ -74,14 +81,24 @@ func createCommand(p cli.Params) *cobra.Command {
return err
}

return res.create()
if opts.from != "" {
s := &cli.Stream{
In: cmd.InOrStdin(),
Out: cmd.OutOrStdout(),
Err: cmd.OutOrStderr(),
}
return createFrom(s, p, opts.from)
}

return res.createInteractive()
},
}

f.AddFlags(c)
c.Flags().StringVarP(&opts.from, "from", "f", "", "local or remote filename to use to create the pipeline resource")
return c
}

func (res *Resource) create() error {
func (res *Resource) createInteractive() error {
res.PipelineResource.Namespace = res.Params.Namespace()

// ask for the object meta data name, namespace
Expand Down Expand Up @@ -575,3 +592,42 @@ func validate(name string, p cli.Params) error {

return nil
}

func createFrom(s *cli.Stream, p cli.Params, path string) error {
cs, err := p.Clients()
if err != nil {
return fmt.Errorf("failed to create tekton client")
}

resource, err := loadResource(p, path)
if err != nil {
return err
}

_, err = cs.Tekton.TektonV1alpha1().PipelineResources(p.Namespace()).Create(resource)
if err != nil {
return fmt.Errorf("failed to create pipeline resource %q: %s", resource.Name, err)
}

fmt.Fprintf(s.Out, "PipelineResource created: %s\n", resource.Name)
return nil
}

func loadResource(p cli.Params, target string) (*v1alpha1.PipelineResource, error) {
content, err := file.LoadFileContent(p, target, file.IsYamlFile(), fmt.Errorf("inavlid file format for %s: .yaml or .yml file extension and format required", target))
if err != nil {
return nil, err
}

var resource v1alpha1.PipelineResource
err = yaml.Unmarshal(content, &resource)
if err != nil {
return nil, err
}

if resource.Kind != "PipelineResource" {
return nil, fmt.Errorf("provided kind %s instead of kind PipelineResource", resource.Kind)
}

return &resource, nil
}
93 changes: 93 additions & 0 deletions pkg/cmd/pipelineresource/create_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ package pipelineresource
import (
"bytes"
"errors"
"io"
"testing"

"github.com/AlecAivazis/survey/v2/core"
Expand Down Expand Up @@ -1610,6 +1611,98 @@ func TestPipelineResource_create_buildGCSstorageResource(t *testing.T) {
}
}

func Test_Pipeline_Resource_Create(t *testing.T) {

ns := []*corev1.Namespace{
{
ObjectMeta: metav1.ObjectMeta{
Name: "ns",
},
},
}

seeds := make([]pipelinetest.Clients, 0)
for i := 0; i < 1; i++ {
cs, _ := test.SeedTestData(t, pipelinetest.Data{Namespaces: ns})
seeds = append(seeds, cs)
}

testParams := []struct {
name string
command []string
input pipelinetest.Clients
inputStream io.Reader
wantError bool
want string
}{
{
name: "Create pipeline resource successfully",
command: []string{"create", "--from", "./testdata/pipelineresource.yaml", "-n", "ns"},
input: seeds[0],
inputStream: nil,
wantError: false,
want: "PipelineResource created: test-resource\n",
},
{
name: "Filename does not exist",
command: []string{"create", "-f", "./testdata/notexist.yaml", "-n", "ns"},
input: seeds[0],
inputStream: nil,
wantError: true,
want: "open ./testdata/notexist.yaml: no such file or directory",
},
{
name: "Unsupported file type",
command: []string{"create", "-f", "./testdata/pipelineresource.txt", "-n", "ns"},
input: seeds[0],
inputStream: nil,
wantError: true,
want: "inavlid file format for ./testdata/pipelineresource.txt: .yaml or .yml file extension and format required",
},
{
name: "Mismatched resource file",
command: []string{"create", "-f", "./testdata/pipelinerun.yaml", "-n", "ns"},
input: seeds[0],
inputStream: nil,
wantError: true,
want: "provided kind PipelineRun instead of kind PipelineResource",
},
{
name: "Existing pipeline",
command: []string{"create", "-f", "./testdata/pipelineresource.yaml", "-n", "ns"},
input: seeds[0],
inputStream: nil,
wantError: true,
want: "failed to create pipeline resource \"test-resource\": pipelineresources.tekton.dev \"test-resource\" already exists",
},
}

for _, tp := range testParams {
t.Run(tp.name, func(t *testing.T) {
p := &test.Params{Tekton: tp.input.Pipeline, Kube: tp.input.Kube}
resource := Command(p)

if tp.inputStream != nil {
resource.SetIn(tp.inputStream)
}

out, err := test.ExecuteCommand(resource, tp.command...)
if tp.wantError {
if err == nil {
t.Errorf("Error expected here")
} else {
test.AssertOutput(t, tp.want, err.Error())
}
} else {
if err != nil {
t.Errorf("Unexpected error")
}
test.AssertOutput(t, tp.want, out)
}
})
}
}

func resOpts(ns string, cs pipelinetest.Clients) *Resource {

p := test.Params{
Expand Down
3 changes: 1 addition & 2 deletions pkg/cmd/pipelineresource/resource_testUtil.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,8 @@ type promptTest struct {

func (res *Resource) RunPromptTest(t *testing.T, test promptTest) {
test.runTest(t, test.procedure, func(stdio terminal.Stdio) error {
var err error
res.AskOpts = WithStdio(stdio)
err = res.create()
err := res.createInteractive()
if err != nil {
if err.Error() == "resource already exist" {
return nil
Expand Down
24 changes: 24 additions & 0 deletions pkg/cmd/pipelineresource/testdata/pipelineresource.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Copyright © 2019 The Tekton Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
apiVersion: tekton.dev/v1alpha1
kind: PipelineResource
metadata:
name: test-resource
spec:
type: git
params:
- name: revision
value: master
- name: url
value: https://github.com/GoogleContainerTools/skaffold
28 changes: 28 additions & 0 deletions pkg/cmd/pipelineresource/testdata/pipelinerun.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Copyright © 2019 The Tekton Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
apiVersion: tekton.dev/v1alpha1
kind: PipelineRun
metadata:
name: tutorial-pipeline-run-1
spec:
serviceAccountName: tutorial-service
pipelineRef:
name: tutorial-pipeline
resources:
- name: source-repo
resourceRef:
name: skaffold-git
- name: web-image
resourceRef:
name: skaffold-image-leeroy-web

0 comments on commit e126197

Please sign in to comment.