mirror of https://github.com/knative/client.git
feat: Add service import command (#1065)
* feat: Add service import command * fix: Fix e2e test * fix: Add retry when retrieving Configuration * fix: Reflect review feedback * fix: Fix error message Co-authored-by: Roland Huß <rhuss@redhat.com> * fix: Add missing mock tests * fix: Polish unit test assertions * fix: Mark import as experimental * chore: Add changelog entry * Update CHANGELOG.adoc Co-authored-by: Roland Huß <rhuss@redhat.com> * fix: Remove deprecated flag Co-authored-by: Roland Huß <rhuss@redhat.com>
This commit is contained in:
parent
45ffadecec
commit
b72e4be300
|
|
@ -45,6 +45,10 @@
|
|||
| 🎁
|
||||
| Add WithLabel list filter to serving client lib
|
||||
| https://github.com/knative/client/pull/1054[#1054]
|
||||
|
||||
| 🎁
|
||||
| Add `kn service import` command (experimental)
|
||||
| https://github.com/knative/client/pull/1065[#1065]
|
||||
|===
|
||||
|
||||
## v0.18.1 (2020-10-13)
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ kn service
|
|||
* [kn service delete](kn_service_delete.md) - Delete services
|
||||
* [kn service describe](kn_service_describe.md) - Show details of a service
|
||||
* [kn service export](kn_service_export.md) - Export a service and its revisions
|
||||
* [kn service import](kn_service_import.md) - Import a service and its revisions (experimental)
|
||||
* [kn service list](kn_service_list.md) - List services
|
||||
* [kn service update](kn_service_update.md) - Update a service
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,45 @@
|
|||
## kn service import
|
||||
|
||||
Import a service and its revisions (experimental)
|
||||
|
||||
### Synopsis
|
||||
|
||||
Import a service and its revisions (experimental)
|
||||
|
||||
```
|
||||
kn service import FILENAME
|
||||
```
|
||||
|
||||
### Examples
|
||||
|
||||
```
|
||||
|
||||
# Import a service from YAML file
|
||||
kn service import /path/to/file.yaml
|
||||
|
||||
# Import a service from JSON file
|
||||
kn service import /path/to/file.json
|
||||
```
|
||||
|
||||
### Options
|
||||
|
||||
```
|
||||
-h, --help help for import
|
||||
-n, --namespace string Specify the namespace to operate in.
|
||||
--no-wait Do not wait for 'service import' operation to be completed.
|
||||
--wait Wait for 'service import' operation to be completed. (default true)
|
||||
--wait-timeout int Seconds to wait before giving up on waiting for service to be ready. (default 600)
|
||||
```
|
||||
|
||||
### Options inherited from parent commands
|
||||
|
||||
```
|
||||
--config string kn configuration file (default: ~/.config/kn/config.yaml)
|
||||
--kubeconfig string kubectl configuration file (default: ~/.kube/config)
|
||||
--log-http log http traffic
|
||||
```
|
||||
|
||||
### SEE ALSO
|
||||
|
||||
* [kn service](kn_service.md) - Manage Knative services
|
||||
|
||||
|
|
@ -0,0 +1,143 @@
|
|||
// Copyright © 2020 The Knative 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.
|
||||
|
||||
package service
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/util/yaml"
|
||||
"k8s.io/client-go/util/retry"
|
||||
|
||||
clientv1alpha1 "knative.dev/client/pkg/apis/client/v1alpha1"
|
||||
"knative.dev/client/pkg/kn/commands"
|
||||
clientservingv1 "knative.dev/client/pkg/serving/v1"
|
||||
"knative.dev/pkg/kmeta"
|
||||
servingv1 "knative.dev/serving/pkg/apis/serving/v1"
|
||||
)
|
||||
|
||||
// NewServiceImportCommand returns a new command for importing a service.
|
||||
func NewServiceImportCommand(p *commands.KnParams) *cobra.Command {
|
||||
var waitFlags commands.WaitFlags
|
||||
|
||||
command := &cobra.Command{
|
||||
Use: "import FILENAME",
|
||||
Short: "Import a service and its revisions (experimental)",
|
||||
Example: `
|
||||
# Import a service from YAML file
|
||||
kn service import /path/to/file.yaml
|
||||
|
||||
# Import a service from JSON file
|
||||
kn service import /path/to/file.json`,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
if len(args) != 1 {
|
||||
return errors.New("'kn service import' requires filename of import file as single argument")
|
||||
}
|
||||
filename := args[0]
|
||||
|
||||
namespace, err := p.GetNamespace(cmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
client, err := p.NewServingClient(namespace)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return importWithOwnerRef(client, filename, cmd.OutOrStdout(), waitFlags)
|
||||
},
|
||||
}
|
||||
flags := command.Flags()
|
||||
commands.AddNamespaceFlags(flags, false)
|
||||
waitFlags.AddConditionWaitFlags(command, commands.WaitDefaultTimeout, "import", "service", "ready")
|
||||
|
||||
return command
|
||||
}
|
||||
|
||||
func importWithOwnerRef(client clientservingv1.KnServingClient, filename string, out io.Writer, waitFlags commands.WaitFlags) error {
|
||||
var export clientv1alpha1.Export
|
||||
file, err := os.Open(filename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
decoder := yaml.NewYAMLOrJSONDecoder(file, 512)
|
||||
err = decoder.Decode(&export)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if export.Spec.Service.Name == "" {
|
||||
return fmt.Errorf("provided import file doesn't contain service name, please note that only kn's custom export format is supported")
|
||||
}
|
||||
|
||||
serviceName := export.Spec.Service.Name
|
||||
|
||||
// Return error if service already exists
|
||||
svcExists, err := serviceExists(client, serviceName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if svcExists {
|
||||
return fmt.Errorf("cannot import service '%s' in namespace '%s' because the service already exists",
|
||||
serviceName, client.Namespace())
|
||||
}
|
||||
|
||||
err = client.CreateService(&export.Spec.Service)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Retrieve current Configuration to be use in OwnerReference
|
||||
currentConf, err := getConfigurationWithRetry(client, serviceName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Create revision with current Configuration's OwnerReference
|
||||
if len(export.Spec.Revisions) > 0 {
|
||||
for _, r := range export.Spec.Revisions {
|
||||
tmp := r.DeepCopy()
|
||||
// OwnerRef ensures that Revisions are recognized by controller
|
||||
tmp.OwnerReferences = []metav1.OwnerReference{*kmeta.NewControllerRef(currentConf)}
|
||||
if err = client.CreateRevision(tmp); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
err = waitIfRequested(client, serviceName, waitFlags, "Importing", "imported", out)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func getConfigurationWithRetry(client clientservingv1.KnServingClient, name string) (*servingv1.Configuration, error) {
|
||||
var conf *servingv1.Configuration
|
||||
var err error
|
||||
err = retry.OnError(retry.DefaultBackoff, func(err error) bool {
|
||||
return apierrors.IsNotFound(err)
|
||||
}, func() error {
|
||||
conf, err = client.GetConfiguration(name)
|
||||
return err
|
||||
})
|
||||
return conf, err
|
||||
}
|
||||
|
|
@ -0,0 +1,280 @@
|
|||
// Copyright © 2020 The Knative 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.
|
||||
|
||||
package service
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"gotest.tools/assert"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
knclient "knative.dev/client/pkg/serving/v1"
|
||||
"knative.dev/client/pkg/util"
|
||||
"knative.dev/client/pkg/util/mock"
|
||||
"knative.dev/client/pkg/wait"
|
||||
servingv1 "knative.dev/serving/pkg/apis/serving/v1"
|
||||
)
|
||||
|
||||
func TestServiceImportFilenameError(t *testing.T) {
|
||||
client := knclient.NewMockKnServiceClient(t)
|
||||
r := client.Recorder()
|
||||
|
||||
_, err := executeServiceCommand(client, "import")
|
||||
|
||||
assert.Assert(t, err != nil)
|
||||
assert.Assert(t, util.ContainsAll(err.Error(), "'kn service import'", "requires", "file", "single", "argument"))
|
||||
assert.Error(t, err, "'kn service import' requires filename of import file as single argument")
|
||||
r.Validate()
|
||||
}
|
||||
|
||||
func TestServiceImportExistError(t *testing.T) {
|
||||
file, err := generateFile([]byte(exportYAML))
|
||||
assert.NilError(t, err)
|
||||
defer os.RemoveAll(filepath.Dir(file))
|
||||
|
||||
client := knclient.NewMockKnServiceClient(t)
|
||||
r := client.Recorder()
|
||||
|
||||
r.GetService("foo", nil, nil)
|
||||
_, err = executeServiceCommand(client, "import", file)
|
||||
|
||||
assert.Assert(t, err != nil)
|
||||
assert.Assert(t, util.ContainsAll(err.Error(), "'foo'", "default", "service", "already", "exists"))
|
||||
r.Validate()
|
||||
}
|
||||
|
||||
func TestServiceImport(t *testing.T) {
|
||||
file, err := generateFile([]byte(exportYAML))
|
||||
assert.NilError(t, err)
|
||||
defer os.RemoveAll(filepath.Dir(file))
|
||||
|
||||
client := knclient.NewMockKnServiceClient(t)
|
||||
r := client.Recorder()
|
||||
|
||||
r.GetService("foo", nil, errors.NewNotFound(servingv1.Resource("service"), "foo"))
|
||||
r.CreateService(mock.Any(), nil)
|
||||
r.GetConfiguration("foo", nil, nil)
|
||||
r.WaitForService("foo", mock.Any(), wait.NoopMessageCallback(), nil, time.Second)
|
||||
r.GetService("foo", getServiceWithUrl("foo", "http://foo.example.com"), nil)
|
||||
|
||||
out, err := executeServiceCommand(client, "import", file)
|
||||
assert.NilError(t, err)
|
||||
assert.Assert(t, util.ContainsAll(out, "Service", "'foo'", "default", "imported"))
|
||||
r.Validate()
|
||||
}
|
||||
|
||||
func TestServiceImportNoWait(t *testing.T) {
|
||||
file, err := generateFile([]byte(exportYAML))
|
||||
assert.NilError(t, err)
|
||||
defer os.RemoveAll(filepath.Dir(file))
|
||||
|
||||
client := knclient.NewMockKnServiceClient(t)
|
||||
r := client.Recorder()
|
||||
|
||||
r.GetService("foo", nil, errors.NewNotFound(servingv1.Resource("service"), "foo"))
|
||||
r.CreateService(mock.Any(), nil)
|
||||
r.GetConfiguration("foo", nil, nil)
|
||||
|
||||
out, err := executeServiceCommand(client, "import", file, "--no-wait")
|
||||
assert.NilError(t, err)
|
||||
assert.Assert(t, util.ContainsAll(out, "Service", "imported", "foo"))
|
||||
r.Validate()
|
||||
}
|
||||
|
||||
func TestServiceImportWitRevisions(t *testing.T) {
|
||||
file, err := generateFile([]byte(exportWithRevisionsYAML))
|
||||
assert.NilError(t, err)
|
||||
defer os.RemoveAll(filepath.Dir(file))
|
||||
|
||||
client := knclient.NewMockKnServiceClient(t)
|
||||
r := client.Recorder()
|
||||
|
||||
r.GetService("foo", nil, errors.NewNotFound(servingv1.Resource("service"), "foo"))
|
||||
r.CreateService(mock.Any(), nil)
|
||||
r.GetConfiguration("foo", getConfiguration("foo"), nil)
|
||||
// 2 previous Revisions to re-create + 1 latest from CreateService
|
||||
r.CreateRevision(mock.Any(), nil)
|
||||
r.CreateRevision(mock.Any(), nil)
|
||||
r.WaitForService("foo", mock.Any(), wait.NoopMessageCallback(), nil, time.Second)
|
||||
r.GetService("foo", getServiceWithUrl("foo", "http://foo.example.com"), nil)
|
||||
|
||||
out, err := executeServiceCommand(client, "import", file)
|
||||
assert.NilError(t, err)
|
||||
assert.Assert(t, util.ContainsAll(out, "Service", "imported", "foo"))
|
||||
r.Validate()
|
||||
}
|
||||
|
||||
func generateFile(fileContent []byte) (string, error) {
|
||||
tempDir, err := ioutil.TempDir("", "kn-file")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
tempFile := filepath.Join(tempDir, "import.yaml")
|
||||
if err = ioutil.WriteFile(tempFile, fileContent, os.FileMode(0666)); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return tempFile, nil
|
||||
}
|
||||
|
||||
func getConfiguration(name string) *servingv1.Configuration {
|
||||
return &servingv1.Configuration{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: name,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
var exportYAML = `
|
||||
apiVersion: client.knative.dev/v1alpha1
|
||||
kind: Export
|
||||
metadata:
|
||||
creationTimestamp: null
|
||||
spec:
|
||||
revisions: null
|
||||
service:
|
||||
apiVersion: serving.knative.dev/v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: foo
|
||||
spec:
|
||||
template:
|
||||
metadata:
|
||||
spec:
|
||||
containerConcurrency: 0
|
||||
containers:
|
||||
- env:
|
||||
- name: TARGET
|
||||
value: v1
|
||||
image: gcr.io/foo/bar:baz
|
||||
name: user-container
|
||||
readinessProbe:
|
||||
successThreshold: 1
|
||||
tcpSocket:
|
||||
port: 0
|
||||
resources: {}
|
||||
enableServiceLinks: false
|
||||
timeoutSeconds: 300
|
||||
status: {}
|
||||
`
|
||||
|
||||
var exportWithRevisionsYAML = `
|
||||
apiVersion: client.knative.dev/v1alpha1
|
||||
kind: Export
|
||||
metadata:
|
||||
creationTimestamp: null
|
||||
spec:
|
||||
revisions:
|
||||
- apiVersion: serving.knative.dev/v1
|
||||
kind: Revision
|
||||
metadata:
|
||||
annotations:
|
||||
client.knative.dev/user-image: gcr.io/foo/bar:baz
|
||||
serving.knative.dev/routes: foo
|
||||
creationTimestamp: null
|
||||
labels:
|
||||
serving.knative.dev/configuration: foo
|
||||
serving.knative.dev/configurationGeneration: "1"
|
||||
serving.knative.dev/routingState: active
|
||||
serving.knative.dev/service: foo
|
||||
name: foo-rev-1
|
||||
spec:
|
||||
containerConcurrency: 0
|
||||
containers:
|
||||
- env:
|
||||
- name: TARGET
|
||||
value: v1
|
||||
image: gcr.io/foo/bar:baz
|
||||
name: user-container
|
||||
readinessProbe:
|
||||
successThreshold: 1
|
||||
tcpSocket:
|
||||
port: 0
|
||||
resources: {}
|
||||
enableServiceLinks: false
|
||||
timeoutSeconds: 300
|
||||
status: {}
|
||||
- apiVersion: serving.knative.dev/v1
|
||||
kind: Revision
|
||||
metadata:
|
||||
annotations:
|
||||
client.knative.dev/user-image: gcr.io/foo/bar:baz
|
||||
serving.knative.dev/routes: foo
|
||||
creationTimestamp: null
|
||||
labels:
|
||||
serving.knative.dev/configuration: foo
|
||||
serving.knative.dev/configurationGeneration: "2"
|
||||
serving.knative.dev/routingState: active
|
||||
serving.knative.dev/service: foo
|
||||
name: foo-rev-2
|
||||
spec:
|
||||
containerConcurrency: 0
|
||||
containers:
|
||||
- env:
|
||||
- name: TARGET
|
||||
value: v2
|
||||
image: gcr.io/foo/bar:baz
|
||||
name: user-container
|
||||
readinessProbe:
|
||||
successThreshold: 1
|
||||
tcpSocket:
|
||||
port: 0
|
||||
resources: {}
|
||||
enableServiceLinks: false
|
||||
timeoutSeconds: 300
|
||||
status: {}
|
||||
service:
|
||||
apiVersion: serving.knative.dev/v1
|
||||
kind: Service
|
||||
metadata:
|
||||
creationTimestamp: null
|
||||
name: foo
|
||||
spec:
|
||||
template:
|
||||
metadata:
|
||||
annotations:
|
||||
client.knative.dev/user-image: gcr.io/foo/bar:baz
|
||||
name: foo-rev-3
|
||||
spec:
|
||||
containerConcurrency: 0
|
||||
containers:
|
||||
- env:
|
||||
- name: TARGET
|
||||
value: v3
|
||||
image: gcr.io/foo/bar:baz
|
||||
name: user-container
|
||||
readinessProbe:
|
||||
successThreshold: 1
|
||||
tcpSocket:
|
||||
port: 0
|
||||
resources: {}
|
||||
enableServiceLinks: false
|
||||
timeoutSeconds: 300
|
||||
traffic:
|
||||
- latestRevision: false
|
||||
percent: 25
|
||||
revisionName: foo-rev-1
|
||||
- latestRevision: false
|
||||
percent: 25
|
||||
revisionName: foo-rev-2
|
||||
- latestRevision: false
|
||||
percent: 50
|
||||
revisionName: foo-rev-3
|
||||
status: {}
|
||||
`
|
||||
|
|
@ -44,6 +44,7 @@ func NewServiceCommand(p *commands.KnParams) *cobra.Command {
|
|||
serviceCmd.AddCommand(NewServiceUpdateCommand(p))
|
||||
serviceCmd.AddCommand(NewServiceApplyCommand(p))
|
||||
serviceCmd.AddCommand(NewServiceExportCommand(p))
|
||||
serviceCmd.AddCommand(NewServiceImportCommand(p))
|
||||
return serviceCmd
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -97,6 +97,12 @@ type KnServingClient interface {
|
|||
// current template.
|
||||
GetBaseRevision(service *servingv1.Service) (*servingv1.Revision, error)
|
||||
|
||||
// Create revision
|
||||
CreateRevision(revision *servingv1.Revision) error
|
||||
|
||||
// Update revision
|
||||
UpdateRevision(revision *servingv1.Revision) error
|
||||
|
||||
// List revisions
|
||||
ListRevisions(opts ...ListConfig) (*servingv1.RevisionList, error)
|
||||
|
||||
|
|
@ -423,6 +429,24 @@ func getBaseRevision(cl KnServingClient, service *servingv1.Service) (*servingv1
|
|||
return nil, noBaseRevisionError
|
||||
}
|
||||
|
||||
// Create a revision
|
||||
func (cl *knServingClient) CreateRevision(revision *servingv1.Revision) error {
|
||||
rev, err := cl.client.Revisions(cl.namespace).Create(context.TODO(), revision, v1.CreateOptions{})
|
||||
if err != nil {
|
||||
return clienterrors.GetError(err)
|
||||
}
|
||||
return updateServingGvk(rev)
|
||||
}
|
||||
|
||||
// Update the given service
|
||||
func (cl *knServingClient) UpdateRevision(revision *servingv1.Revision) error {
|
||||
_, err := cl.client.Revisions(cl.namespace).Update(context.TODO(), revision, v1.UpdateOptions{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return updateServingGvk(revision)
|
||||
}
|
||||
|
||||
// Delete a revision by name
|
||||
func (cl *knServingClient) DeleteRevision(name string, timeout time.Duration) error {
|
||||
revision, err := cl.client.Revisions(cl.namespace).Get(context.TODO(), name, v1.GetOptions{})
|
||||
|
|
|
|||
|
|
@ -202,6 +202,28 @@ func (c *MockKnServingClient) GetConfiguration(name string) (*servingv1.Configur
|
|||
return call.Result[0].(*servingv1.Configuration), mock.ErrorOrNil(call.Result[1])
|
||||
}
|
||||
|
||||
// CreateRevision records a call CreateRevision
|
||||
func (sr *ServingRecorder) CreateRevision(revision interface{}, err error) {
|
||||
sr.r.Add("CreateRevision", []interface{}{revision}, []interface{}{err})
|
||||
}
|
||||
|
||||
// CreateRevision creates a new revision
|
||||
func (c *MockKnServingClient) CreateRevision(revision *servingv1.Revision) error {
|
||||
call := c.recorder.r.VerifyCall("CreateRevision", revision)
|
||||
return mock.ErrorOrNil(call.Result[0])
|
||||
}
|
||||
|
||||
// UpdateRevision records a call UpdateRevision
|
||||
func (sr *ServingRecorder) UpdateRevision(revision interface{}, err error) {
|
||||
sr.r.Add("UpdateRevision", []interface{}{revision}, []interface{}{err})
|
||||
}
|
||||
|
||||
// UpdateRevision updates given revision
|
||||
func (c *MockKnServingClient) UpdateRevision(revision *servingv1.Revision) error {
|
||||
call := c.recorder.r.VerifyCall("UpdateRevision", revision)
|
||||
return mock.ErrorOrNil(call.Result[0])
|
||||
}
|
||||
|
||||
// Check that every recorded method has been called
|
||||
func (sr *ServingRecorder) Validate() {
|
||||
sr.r.CheckThatAllRecordedMethodsHaveBeenCalled()
|
||||
|
|
|
|||
|
|
@ -42,6 +42,8 @@ func TestMockKnClient(t *testing.T) {
|
|||
recorder.WaitForService("hello", time.Duration(10)*time.Second, wait.NoopMessageCallback(), nil, 10*time.Second)
|
||||
recorder.GetRevision("hello", nil, nil)
|
||||
recorder.ListRevisions(mock.Any(), nil, nil)
|
||||
recorder.CreateRevision(&servingv1.Revision{}, nil)
|
||||
recorder.UpdateRevision(&servingv1.Revision{}, nil)
|
||||
recorder.DeleteRevision("hello", time.Duration(10)*time.Second, nil)
|
||||
recorder.GetRoute("hello", nil, nil)
|
||||
recorder.ListRoutes(mock.Any(), nil, nil)
|
||||
|
|
@ -58,6 +60,8 @@ func TestMockKnClient(t *testing.T) {
|
|||
client.WaitForService("hello", time.Duration(10)*time.Second, wait.NoopMessageCallback())
|
||||
client.GetRevision("hello")
|
||||
client.ListRevisions(WithName("blub"))
|
||||
client.CreateRevision(&servingv1.Revision{})
|
||||
client.UpdateRevision(&servingv1.Revision{})
|
||||
client.DeleteRevision("hello", time.Duration(10)*time.Second)
|
||||
client.GetRoute("hello")
|
||||
client.ListRoutes(WithName("blub"))
|
||||
|
|
|
|||
|
|
@ -0,0 +1,94 @@
|
|||
// Copyright 2019 The Knative 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 im
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// +build e2e
|
||||
// +build !eventing
|
||||
|
||||
package e2e
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"gotest.tools/assert"
|
||||
"knative.dev/client/lib/test"
|
||||
"knative.dev/client/pkg/util"
|
||||
)
|
||||
|
||||
func TestServiceImport(t *testing.T) {
|
||||
t.Parallel()
|
||||
it, err := test.NewKnTest()
|
||||
assert.NilError(t, err)
|
||||
defer func() {
|
||||
assert.NilError(t, it.Teardown())
|
||||
}()
|
||||
|
||||
r := test.NewKnRunResultCollector(t, it)
|
||||
defer r.DumpIfFailed()
|
||||
|
||||
tempDir, err := ioutil.TempDir("", "kn-file")
|
||||
defer os.RemoveAll(tempDir)
|
||||
assert.NilError(t, err)
|
||||
|
||||
t.Log("import service foo with revision")
|
||||
testFile := filepath.Join(tempDir, "foo-with-revisions")
|
||||
|
||||
serviceCreateWithOptions(r, "foo", "--revision-name", "foo-rev-1")
|
||||
test.ServiceUpdate(r, "foo", "--env", "TARGET=v2", "--revision-name", "foo-rev-2")
|
||||
test.ServiceUpdate(r, "foo", "--traffic", "foo-rev-1=50,foo-rev-2=50")
|
||||
serviceExportToFile(r, "foo", testFile, true)
|
||||
test.ServiceDelete(r, "foo")
|
||||
serviceImport(r, testFile)
|
||||
|
||||
t.Log("import existing service foo error")
|
||||
serviceImportExistsError(r, testFile)
|
||||
|
||||
t.Log("import service from missing file error")
|
||||
serviceImportFileError(r, testFile+"-missing")
|
||||
}
|
||||
|
||||
func serviceExportToFile(r *test.KnRunResultCollector, serviceName, filename string, withRevisions bool) {
|
||||
command := []string{"service", "export", serviceName, "-o", "yaml", "--mode", "export"}
|
||||
if withRevisions {
|
||||
command = append(command, "--with-revisions")
|
||||
}
|
||||
out := r.KnTest().Kn().Run(command...)
|
||||
r.AssertNoError(out)
|
||||
err := ioutil.WriteFile(filename, []byte(out.Stdout), test.FileModeReadWrite)
|
||||
assert.NilError(r.T(), err)
|
||||
}
|
||||
|
||||
func serviceImport(r *test.KnRunResultCollector, filename string) {
|
||||
command := []string{"service", "import", filename}
|
||||
|
||||
out := r.KnTest().Kn().Run(command...)
|
||||
r.AssertNoError(out)
|
||||
assert.Check(r.T(), util.ContainsAllIgnoreCase(out.Stdout, "service", "importing", "namespace", r.KnTest().Kn().Namespace(), "ready"))
|
||||
}
|
||||
|
||||
func serviceImportExistsError(r *test.KnRunResultCollector, filename string) {
|
||||
command := []string{"service", "import", filename}
|
||||
|
||||
out := r.KnTest().Kn().Run(command...)
|
||||
r.AssertError(out)
|
||||
assert.Check(r.T(), util.ContainsAllIgnoreCase(out.Stderr, "service", "already", "exists"))
|
||||
}
|
||||
|
||||
func serviceImportFileError(r *test.KnRunResultCollector, filePath string) {
|
||||
out := r.KnTest().Kn().Run("service", "import", filePath)
|
||||
r.AssertError(out)
|
||||
assert.Check(r.T(), util.ContainsAllIgnoreCase(out.Stderr, "no", "such", "file", "directory", filePath))
|
||||
}
|
||||
Loading…
Reference in New Issue