Skip to content

Commit

Permalink
RepositoryServer CR update validation (#2080)
Browse files Browse the repository at this point in the history
* Add validation

Signed-off-by: Rajat Gupta <rajat.gupta@veeam.com>

* Add unit test

Signed-off-by: Rajat Gupta <rajat.gupta@veeam.com>

* Update message

Signed-off-by: Rajat Gupta <rajat.gupta@veeam.com>

---------

Signed-off-by: Rajat Gupta <rajat.gupta@veeam.com>
  • Loading branch information
r4rajat committed Jun 5, 2023
1 parent 255be73 commit a76c23f
Show file tree
Hide file tree
Showing 4 changed files with 400 additions and 265 deletions.
1 change: 1 addition & 0 deletions pkg/apis/cr/v1alpha1/doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

// Package v1alpha1 is the v1alpha1 version of the API.
// +groupName=cr.kanister.io
// +versionName=v1alpha1
package v1alpha1

// While generating client files, we need code-generator package to be installed
Expand Down
16 changes: 14 additions & 2 deletions pkg/apis/cr/v1alpha1/repositoryserver_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,20 +51,26 @@ type RepositoryServerSpec struct {

// Storage references the backend store where a repository already exists
// and the credential necessary to connect to the backend store
// +kubebuilder:validation:XValidation:rule="!has(oldSelf.secretRef) || has(self.secretRef)",message="secretRef field must not be allowed to be removed"
type Storage struct {
// SecretRef has the details of the object storage (location)
// where the kopia would backup the data
// +kubebuilder:validation:Optional
// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="Value is immutable"
SecretRef corev1.SecretReference `json:"secretRef"`
// CredentialSecretRef stores the credentials required
// to connect to the object storage specified in `SecretRef` field
CredentialSecretRef corev1.SecretReference `json:"credentialSecretRef"`
}

// Repository has the details required by the repository server to connect to kopia repository
// +kubebuilder:validation:XValidation:rule="!has(oldSelf.rootPath) || has(self.rootPath)",message="rootPath field must not be allowed to be removed"
type Repository struct {
// Path for the repository,it will be relative sub path
// Path for the repository, it will be a relative sub path
// within the path prefix specified in the location
// More info: https://kopia.io/docs/reference/command-line/common/#commands-to-manipulate-repository
// +kubebuilder:validation:Optional
// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="Value is immutable"
RootPath string `json:"rootPath"`
// If specified, these values will be used by the controller to
// override default username when connecting to the
Expand All @@ -79,21 +85,27 @@ type Repository struct {
CacheSizeSettings CacheSizeSettings `json:"cacheSizeSettings,omitempty"`
}

// CacheSettings are the metadata/content cache size details
// CacheSizeSettings are the metadata/content cache size details
// that can be used while establishing connection to the kopia repository
type CacheSizeSettings struct {
Metadata string `json:"metadata"`
Content string `json:"content"`
}

// Server details required for starting the repository proxy server and initializing the repository client users
// +kubebuilder:validation:XValidation:rule="!has(oldSelf.adminSecretRef) || has(self.adminSecretRef)",message="adminSecretRef field must not be allowed to be removed"
// +kubebuilder:validation:XValidation:rule="!has(oldSelf.tlsSecretRef) || has(self.tlsSecretRef)",message="tlsSecretRef field must not be allowed to be removed"
type Server struct {
UserAccess UserAccess `json:"userAccess"`
// AdminSecretRef has the username and password required to start the
// kopia repository server
// +kubebuilder:validation:Optional
// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="Value is immutable"
AdminSecretRef corev1.SecretReference `json:"adminSecretRef"`
// TLSSecretRef has the certificates required for kopia repository
// client server connection
// +kubebuilder:validation:Optional
// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="Value is immutable"
TLSSecretRef corev1.SecretReference `json:"tlsSecretRef"`
}

Expand Down
92 changes: 92 additions & 0 deletions pkg/apis/cr/v1alpha1/repositoryserver_types_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
// Copyright 2023 The Kanister 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 v1alpha1

import (
"testing"

"github.com/pkg/errors"
. "gopkg.in/check.v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/serializer"
)

const repoServerSpec = `
apiVersion: cr.kanister.io/v1alpha1
kind: RepositoryServer
metadata:
name: test-kopia-repo-server
namespace: kanister
spec:
storage:
secretRef:
name: test-s3-location
namespace: kanister
credentialSecretRef:
name: test-s3-creds
namespace: kanister
repository:
rootPath: /test-repo-controller/
passwordSecretRef:
name: test-repo-pass
namespace: kanister
username: test-repository-user
hostname: localhost
server:
adminSecretRef:
name: test-repository-admin-user
namespace: kanister
tlsSecretRef:
name: test-repository-server-tls-cert
namespace: kanister
userAccess:
userAccessSecretRef:
name: test-repository-server-user-access
namespace: kanister
username: test-kanister-user
`

func TestRepositoryServer(t *testing.T) { TestingT(t) }

func (s *TypesSuite) TestRepositoryServerDecode(c *C) {
rs, err := getRepositoryServerFromSpec([]byte(repoServerSpec))
c.Assert(err, IsNil)
c.Assert(rs, NotNil)
c.Assert(rs.Spec.Storage.SecretRef.Name, Equals, "test-s3-location")
c.Assert(rs.Spec.Storage.SecretRef.Namespace, Equals, "kanister")
c.Assert(rs.Spec.Storage.CredentialSecretRef.Name, Equals, "test-s3-creds")
c.Assert(rs.Spec.Storage.CredentialSecretRef.Namespace, Equals, "kanister")
c.Assert(rs.Spec.Repository.RootPath, Equals, "/test-repo-controller/")
c.Assert(rs.Spec.Repository.PasswordSecretRef.Name, Equals, "test-repo-pass")
c.Assert(rs.Spec.Repository.PasswordSecretRef.Namespace, Equals, "kanister")
c.Assert(rs.Spec.Repository.Username, Equals, "test-repository-user")
c.Assert(rs.Spec.Repository.Hostname, Equals, "localhost")
c.Assert(rs.Spec.Server.AdminSecretRef.Name, Equals, "test-repository-admin-user")
c.Assert(rs.Spec.Server.AdminSecretRef.Namespace, Equals, "kanister")
c.Assert(rs.Spec.Server.TLSSecretRef.Name, Equals, "test-repository-server-tls-cert")
c.Assert(rs.Spec.Server.TLSSecretRef.Namespace, Equals, "kanister")
c.Assert(rs.Spec.Server.UserAccess.UserAccessSecretRef.Name, Equals, "test-repository-server-user-access")
c.Assert(rs.Spec.Server.UserAccess.UserAccessSecretRef.Namespace, Equals, "kanister")
c.Assert(rs.Spec.Server.UserAccess.Username, Equals, "test-kanister-user")
}

func getRepositoryServerFromSpec(spec []byte) (*RepositoryServer, error) {
repositoryServer := &RepositoryServer{}
d := serializer.NewCodecFactory(runtime.NewScheme()).UniversalDeserializer()
if _, _, err := d.Decode([]byte(spec), nil, repositoryServer); err != nil {
return nil, errors.Wrap(err, "Failed to decode RepositoryServer")
}
return repositoryServer, nil
}
Loading

0 comments on commit a76c23f

Please sign in to comment.