client/pkg/serving/v1/gitops_test.go

269 lines
9.7 KiB
Go

// 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 v1
import (
"context"
"path/filepath"
"testing"
"time"
"gotest.tools/v3/assert"
corev1 "k8s.io/api/core/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
servingtest "knative.dev/serving/pkg/testing/v1"
libtest "knative.dev/client/lib/test"
"knative.dev/pkg/ptr"
servingv1 "knative.dev/serving/pkg/apis/serving/v1"
)
func TestGitOpsOperations(t *testing.T) {
c1TempDir := t.TempDir()
c2TempDir := t.TempDir()
// create clients
fooclient := NewKnServingGitOpsClient("foo-ns", c1TempDir)
bazclient := NewKnServingGitOpsClient("baz-ns", c1TempDir)
globalclient := NewKnServingGitOpsClient("", c1TempDir)
diffClusterClient := NewKnServingGitOpsClient("", "tmp")
// set up test services
fooSvc := libtest.BuildServiceWithOptions("foo", servingtest.WithConfigSpec(buildConfiguration()))
barSvc := libtest.BuildServiceWithOptions("bar", servingtest.WithConfigSpec(buildConfiguration()))
fooUpdateSvc := libtest.BuildServiceWithOptions("foo", servingtest.WithConfigSpec(buildConfiguration()), servingtest.WithEnv(corev1.EnvVar{Name: "a", Value: "mouse"}))
mockUpdateSvc := libtest.BuildServiceWithOptions("mock", servingtest.WithConfigSpec(buildConfiguration()), servingtest.WithEnv(corev1.EnvVar{Name: "a", Value: "mouse"}))
fooserviceList := getServiceList([]servingv1.Service{*barSvc, *fooSvc})
allServices := getServiceList([]servingv1.Service{*barSvc, *barSvc, *fooSvc})
t.Run("get file path for foo service in foo namespace", func(t *testing.T) {
fp := fooclient.(*knServingGitOpsClient).getKsvcFilePath("foo")
assert.Equal(t, filepath.Join(c1TempDir, "foo-ns/ksvc/foo.yaml"), fp)
})
t.Run("get namespace for bazclient client", func(t *testing.T) {
ns := bazclient.Namespace()
assert.Equal(t, "baz-ns", ns)
})
t.Run("create service foo in foo namespace", func(t *testing.T) {
err := fooclient.CreateService(context.Background(), fooSvc)
assert.NilError(t, err)
})
t.Run("wait for foo service in foo namespace", func(t *testing.T) {
err, d := fooclient.WaitForService(context.Background(), "foo", WaitConfig{
Timeout: time.Duration(5) * time.Second,
ErrorWindow: time.Duration(2) * time.Second,
}, nil)
assert.NilError(t, err)
assert.Equal(t, 1*time.Second, d)
})
t.Run("get service foo", func(t *testing.T) {
result, err := fooclient.GetService(context.Background(), "foo")
assert.NilError(t, err)
assert.DeepEqual(t, fooSvc, result)
})
t.Run("create service bar in foo namespace", func(t *testing.T) {
err := fooclient.CreateService(context.Background(), barSvc)
assert.NilError(t, err)
})
t.Run("create service bar in baz namespace", func(t *testing.T) {
err := bazclient.CreateService(context.Background(), barSvc)
assert.NilError(t, err)
})
t.Run("list services in foo namespace", func(t *testing.T) {
result, err := fooclient.ListServices(context.Background())
assert.NilError(t, err)
assert.DeepEqual(t, fooserviceList, result)
})
t.Run("create service without tmp directory", func(t *testing.T) {
err := diffClusterClient.CreateService(context.Background(), fooSvc)
assert.ErrorContains(t, err, "directory 'tmp' not present, please create the directory and try again")
})
diffClusterClient = NewKnServingGitOpsClient("", c2TempDir)
t.Run("create service foo in foo namespace in cluster 2", func(t *testing.T) {
err := diffClusterClient.CreateService(context.Background(), fooSvc)
assert.NilError(t, err)
})
t.Run("list services in all namespaces in cluster 1", func(t *testing.T) {
result, err := globalclient.ListServices(context.Background())
assert.NilError(t, err)
assert.DeepEqual(t, allServices, result)
})
t.Run("update service with retry foo", func(t *testing.T) {
changed, err := fooclient.UpdateServiceWithRetry(context.Background(), "foo", func(svc *servingv1.Service) (*servingv1.Service, error) {
return svc, nil
}, 1)
assert.Assert(t, changed)
assert.NilError(t, err)
})
t.Run("update service foo", func(t *testing.T) {
changed, err := fooclient.UpdateService(context.Background(), fooUpdateSvc)
assert.Assert(t, changed)
assert.NilError(t, err)
})
t.Run("check updated service foo", func(t *testing.T) {
result, err := fooclient.GetService(context.Background(), "foo")
assert.NilError(t, err)
assert.DeepEqual(t, fooUpdateSvc, result)
})
t.Run("delete service foo", func(t *testing.T) {
err := fooclient.DeleteService(context.Background(), "foo", 5*time.Second)
assert.NilError(t, err)
})
t.Run("get service foo", func(t *testing.T) {
_, err := fooclient.GetService(context.Background(), "foo")
assert.ErrorType(t, err, apierrors.IsNotFound)
})
t.Run("update service foo", func(t *testing.T) {
_, err := fooclient.UpdateService(context.Background(), mockUpdateSvc)
assert.ErrorType(t, err, apierrors.IsNotFound)
})
}
func TestGitOpsSingleFile(t *testing.T) {
tmpDir := t.TempDir()
// create clients
fooclient := NewKnServingGitOpsClient("", filepath.Join(tmpDir, "test.yaml"))
barclient := NewKnServingGitOpsClient("", filepath.Join(tmpDir, "test.yml"))
bazclient := NewKnServingGitOpsClient("", filepath.Join(tmpDir, "test.json"))
mockclient := NewKnServingGitOpsClient("", filepath.Join(tmpDir, "mockfile"))
mockDirclient := NewKnServingGitOpsClient("", tmpDir)
// set up test services
testSvc := libtest.BuildServiceWithOptions("test", servingtest.WithConfigSpec(buildConfiguration()))
updateSvc := libtest.BuildServiceWithOptions("test", servingtest.WithConfigSpec(buildConfiguration()), servingtest.WithEnv(corev1.EnvVar{Name: "a", Value: "mouse"}))
svcList := getServiceList([]servingv1.Service{*updateSvc})
t.Run("get file path for fooclient", func(t *testing.T) {
fp := fooclient.(*knServingGitOpsClient).getKsvcFilePath("test")
assert.Equal(t, filepath.Join(tmpDir, "test.yaml"), fp)
})
t.Run("get namespace for fooclient", func(t *testing.T) {
ns := fooclient.Namespace()
assert.Equal(t, "", ns)
})
t.Run("create service in single file mode in different formats", func(t *testing.T) {
err := fooclient.CreateService(context.Background(), testSvc)
assert.NilError(t, err)
err = barclient.CreateService(context.Background(), testSvc)
assert.NilError(t, err)
err = bazclient.CreateService(context.Background(), testSvc)
assert.NilError(t, err)
})
t.Run("retrieve services", func(t *testing.T) {
result, err := fooclient.GetService(context.Background(), "test")
assert.NilError(t, err)
assert.DeepEqual(t, testSvc, result)
result, err = barclient.GetService(context.Background(), "test")
assert.NilError(t, err)
assert.DeepEqual(t, testSvc, result)
result, err = bazclient.GetService(context.Background(), "test")
assert.NilError(t, err)
assert.DeepEqual(t, testSvc, result)
})
t.Run("update service foo", func(t *testing.T) {
changed, err := fooclient.UpdateService(context.Background(), updateSvc)
assert.NilError(t, err)
assert.Assert(t, changed)
changed, err = barclient.UpdateService(context.Background(), updateSvc)
assert.NilError(t, err)
assert.Assert(t, changed)
changed, err = bazclient.UpdateService(context.Background(), updateSvc)
assert.NilError(t, err)
assert.Assert(t, changed)
})
t.Run("list services", func(t *testing.T) {
result, err := fooclient.ListServices(context.Background())
assert.NilError(t, err)
assert.DeepEqual(t, svcList, result)
result, err = barclient.ListServices(context.Background())
assert.NilError(t, err)
assert.DeepEqual(t, svcList, result)
result, err = bazclient.ListServices(context.Background())
assert.NilError(t, err)
assert.DeepEqual(t, svcList, result)
_, err = mockclient.ListServices(context.Background())
assert.ErrorContains(t, err, "no such file")
_, err = mockDirclient.ListServices(context.Background())
assert.NilError(t, err)
})
t.Run("delete service foo", func(t *testing.T) {
err := fooclient.DeleteService(context.Background(), "test", 5*time.Second)
assert.NilError(t, err)
err = barclient.DeleteService(context.Background(), "test", 5*time.Second)
assert.NilError(t, err)
err = bazclient.DeleteService(context.Background(), "test", 5*time.Second)
assert.NilError(t, err)
})
t.Run("get service foo", func(t *testing.T) {
_, err := fooclient.GetService(context.Background(), "test")
assert.ErrorType(t, err, apierrors.IsNotFound)
_, err = barclient.GetService(context.Background(), "test")
assert.ErrorType(t, err, apierrors.IsNotFound)
_, err = bazclient.GetService(context.Background(), "test")
assert.ErrorType(t, err, apierrors.IsNotFound)
})
}
func getServiceList(services []servingv1.Service) *servingv1.ServiceList {
return &servingv1.ServiceList{
TypeMeta: metav1.TypeMeta{
APIVersion: "v1",
Kind: "List",
},
Items: services,
}
}
func buildConfiguration() *servingv1.ConfigurationSpec {
c := &servingv1.Configuration{
Spec: servingv1.ConfigurationSpec{
Template: servingv1.RevisionTemplateSpec{
Spec: *revisionSpec.DeepCopy(),
},
},
}
c.SetDefaults(context.Background())
return &c.Spec
}
var revisionSpec = servingv1.RevisionSpec{
PodSpec: corev1.PodSpec{
Containers: []corev1.Container{{
Image: "busybox",
}},
EnableServiceLinks: ptr.Bool(false),
},
TimeoutSeconds: ptr.Int64(300),
}