1
0
Fork 0
mirror of https://github.com/arangodb/kube-arangodb.git synced 2024-12-14 11:57:37 +00:00

(Feature) Add generator for CRD validation schemas (#1486)

This commit is contained in:
Nikita Vaniasin 2023-11-13 10:55:15 +01:00 committed by GitHub
parent 4a9a3b913a
commit 828350d86a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 53350 additions and 77 deletions

View file

@ -0,0 +1,234 @@
//
// DISCLAIMER
//
// Copyright 2023 ArangoDB GmbH, Cologne, Germany
//
// 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.
//
// Copyright holder is ArangoDB GmbH, Cologne, Germany
//
package internal
import (
"fmt"
"os"
"path"
"reflect"
"strings"
"testing"
"github.com/stretchr/testify/require"
apiextensions "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
"sigs.k8s.io/yaml"
appsv1 "github.com/arangodb/kube-arangodb/pkg/apis/apps/v1"
backupv1 "github.com/arangodb/kube-arangodb/pkg/apis/backup/v1"
deploymentv1 "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1"
deploymentv2alpha1 "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v2alpha1"
mlApi "github.com/arangodb/kube-arangodb/pkg/apis/ml/v1alpha1"
replicationv1 "github.com/arangodb/kube-arangodb/pkg/apis/replication/v1"
replicationv2alpha1 "github.com/arangodb/kube-arangodb/pkg/apis/replication/v2alpha1"
storagev1alpha "github.com/arangodb/kube-arangodb/pkg/apis/storage/v1alpha"
"github.com/arangodb/kube-arangodb/pkg/util"
)
func (def DocDefinition) ApplyToSchema(s *apiextensions.JSONSchemaProps) {
for _, e := range def.Enum {
z := strings.Split(e, "|")
s.Enum = append(s.Enum, apiextensions.JSON{
Raw: []byte("\"" + z[0] + "\""),
})
}
s.Description = strings.Join(def.Docs, "\n")
}
// Test_GenerateCRValidationSchemas generates validation schema JSONs for each CRD referenced in `input` (see impl)
func Test_GenerateCRValidationSchemas(t *testing.T) {
root := os.Getenv("ROOT")
require.NotEmpty(t, root)
type genSpec struct {
obj interface{}
}
// CR file prefix -> packages to parse -> versions -> obj
input := map[string]map[string]map[string]genSpec{
"apps-job": {
fmt.Sprintf("%s/pkg/apis/apps/v1", root): {
"v1": {
appsv1.ArangoJob{}.Spec,
},
},
},
"backups-backup": {
fmt.Sprintf("%s/pkg/apis/backup/v1", root): {
"v1": {
backupv1.ArangoBackup{}.Spec,
},
"v1alpha": {
backupv1.ArangoBackup{}.Spec,
},
},
},
"backups-backuppolicy": {
fmt.Sprintf("%s/pkg/apis/backup/v1", root): {
"v1": {
backupv1.ArangoBackupPolicy{}.Spec,
},
"v1alpha": {
backupv1.ArangoBackupPolicy{}.Spec,
},
},
},
"database-deployment": {
fmt.Sprintf("%s/pkg/apis/deployment/v1", root): {
"v1": {
deploymentv1.ArangoDeployment{}.Spec,
},
"v1alpha": {
deploymentv1.ArangoDeployment{}.Spec,
},
},
fmt.Sprintf("%s/pkg/apis/deployment/v2alpha1", root): {
"v2alpha1": {
deploymentv2alpha1.ArangoDeployment{}.Spec,
},
},
},
"database-member": {
fmt.Sprintf("%s/pkg/apis/deployment/v1", root): {
"v1": {
deploymentv1.ArangoMember{}.Spec,
},
"v1alpha": {
deploymentv1.ArangoMember{}.Spec,
},
},
fmt.Sprintf("%s/pkg/apis/deployment/v2alpha1", root): {
"v2alpha1": {
deploymentv2alpha1.ArangoMember{}.Spec,
},
},
},
"database-clustersynchronization": {
fmt.Sprintf("%s/pkg/apis/deployment/v1", root): {
"v1": {
deploymentv1.ArangoClusterSynchronization{}.Spec,
},
"v1alpha": {
deploymentv1.ArangoClusterSynchronization{}.Spec,
},
},
fmt.Sprintf("%s/pkg/apis/deployment/v2alpha1", root): {
"v2alpha1": {
deploymentv2alpha1.ArangoClusterSynchronization{}.Spec,
},
},
},
"database-task": {
fmt.Sprintf("%s/pkg/apis/deployment/v1", root): {
"v1": {
deploymentv1.ArangoTask{}.Spec,
},
"v1alpha": {
deploymentv1.ArangoTask{}.Spec,
},
},
fmt.Sprintf("%s/pkg/apis/deployment/v2alpha1", root): {
"v2alpha1": {
deploymentv2alpha1.ArangoTask{}.Spec,
},
},
},
"replication-deploymentreplication": {
fmt.Sprintf("%s/pkg/apis/replication/v1", root): {
"v1": {
replicationv1.ArangoDeploymentReplication{}.Spec,
},
"v1alpha": {
replicationv1.ArangoDeploymentReplication{}.Spec,
},
},
fmt.Sprintf("%s/pkg/apis/replication/v2alpha1", root): {
"v2alpha1": {
replicationv2alpha1.ArangoDeploymentReplication{}.Spec,
},
},
},
"storage-localstorage": {
fmt.Sprintf("%s/pkg/apis/storage/v1alpha", root): {
"v1alpha": {
storagev1alpha.ArangoLocalStorage{}.Spec,
},
},
},
"ml-extension": {
fmt.Sprintf("%s/pkg/apis/ml/v1alpha1", root): {
"v1alpha1": {
mlApi.ArangoMLExtension{}.Spec,
},
},
},
"ml-storage": {
fmt.Sprintf("%s/pkg/apis/ml/v1alpha1", root): {
"v1alpha1": {
mlApi.ArangoMLStorage{}.Spec,
},
},
},
"ml-job-cron": {
fmt.Sprintf("%s/pkg/apis/ml/v1alpha1", root): {
"v1alpha1": {
mlApi.ArangoMLCronJob{}.Spec,
},
},
},
"ml-job-batch": {
fmt.Sprintf("%s/pkg/apis/ml/v1alpha1", root): {
"v1alpha1": {
mlApi.ArangoMLBatchJob{}.Spec,
},
},
},
}
for filePrefix, packagesToVersion := range input {
validationPerVersion := make(map[string]apiextensions.CustomResourceValidation, len(packagesToVersion))
for apiDir, versionMap := range packagesToVersion {
fields, fileSets := parseSourceFiles(t, apiDir)
for version, generationSpec := range versionMap {
sb := newSchemaBuilder(root, fields, fileSets)
s := sb.TypeToSchema(t, reflect.TypeOf(generationSpec.obj), ".spec")
require.NotNil(t, s, version)
validationPerVersion[version] = apiextensions.CustomResourceValidation{
OpenAPIV3Schema: &apiextensions.JSONSchemaProps{
Type: "object",
Properties: map[string]apiextensions.JSONSchemaProps{"spec": *s},
XPreserveUnknownFields: util.NewType(true),
},
}
}
}
yamlRaw, err := yaml.Marshal(validationPerVersion)
require.NoError(t, err)
outPath := path.Join(root, "pkg/crd/crds", fmt.Sprintf("%s.schema.generated.yaml", filePrefix))
err = os.WriteFile(outPath, yamlRaw, 0644)
require.NoError(t, err)
}
}

View file

@ -26,72 +26,65 @@ import (
"go/parser"
"go/token"
"io/fs"
"os"
"path/filepath"
"reflect"
"strings"
"sync"
"testing"
"github.com/stretchr/testify/require"
openapi "k8s.io/kube-openapi/pkg/common"
"github.com/arangodb/kube-arangodb/pkg/util"
)
func parseDocDefinitions(t *testing.T, res map[typeInfo]*ast.Field, fs *token.FileSet) DocDefinitions {
root := os.Getenv("ROOT")
require.NotEmpty(t, root)
defs := make(DocDefinitions, 0, len(res))
for info, field := range res {
def := DocDefinition{
Path: info.path,
Type: info.typ,
}
require.NotNil(t, field)
if links, ok := extract(field, "link"); ok {
def.Links = links
}
if d, ok := extract(field, "default"); ok {
def.Default = util.NewType[string](d[0])
}
if example, ok := extract(field, "example"); ok {
def.Example = example
}
if enum, ok := extract(field, "enum"); ok {
def.Enum = enum
}
if immutable, ok := extract(field, "immutable"); ok {
def.Immutable = util.NewType[string](immutable[0])
}
if important, ok := extract(field, "important"); ok {
def.Important = util.NewType[string](important[0])
}
if docs, ok := extractNotTags(field); !ok {
println(def.Path, " is missing documentation!")
} else {
def.Docs = docs
}
file := fs.File(field.Pos())
filePath, err := filepath.Rel(root, file.Name())
require.NoError(t, err)
def.File = filePath
def.Line = file.Line(field.Pos())
defs = append(defs, def)
func parseDocDefinition(t *testing.T, root, path, typ string, field *ast.Field, fs *token.FileSet) DocDefinition {
def := DocDefinition{
Path: path,
Type: typ,
}
return defs
require.NotNil(t, field)
if links, ok := extract(field, "link"); ok {
def.Links = links
}
if d, ok := extract(field, "default"); ok {
def.Default = util.NewType[string](d[0])
}
if example, ok := extract(field, "example"); ok {
def.Example = example
}
if enum, ok := extract(field, "enum"); ok {
def.Enum = enum
}
if immutable, ok := extract(field, "immutable"); ok {
def.Immutable = util.NewType[string](immutable[0])
}
if important, ok := extract(field, "important"); ok {
def.Important = util.NewType[string](important[0])
}
if docs, ok := extractNotTags(field); !ok {
println(def.Path, " is missing documentation!")
} else {
def.Docs = docs
}
file := fs.File(field.Pos())
filePath, err := filepath.Rel(root, file.Name())
require.NoError(t, err)
def.File = filePath
def.Line = file.Line(field.Pos())
return def
}
type typeInfo struct {
@ -111,7 +104,7 @@ func iterateOverObject(t *testing.T, fields map[string]*ast.Field, name string,
}
func iterateOverObjectDirect(t *testing.T, fields map[string]*ast.Field, name string, object reflect.Type, path string) map[typeInfo]*ast.Field {
if n, simple := isSimpleType(object); simple {
if n, _, simple := isSimpleType(object); simple {
return map[typeInfo]*ast.Field{
typeInfo{
path: fmt.Sprintf("%s.%s", path, name),
@ -124,7 +117,7 @@ func iterateOverObjectDirect(t *testing.T, fields map[string]*ast.Field, name st
switch object.Kind() {
case reflect.Array, reflect.Slice:
if _, simple := isSimpleType(object.Elem()); simple {
if _, _, simple := isSimpleType(object.Elem()); simple {
return map[typeInfo]*ast.Field{
typeInfo{
path: fmt.Sprintf("%s.%s", path, name),
@ -137,7 +130,7 @@ func iterateOverObjectDirect(t *testing.T, fields map[string]*ast.Field, name st
r[k] = v
}
case reflect.Map:
if _, simple := isSimpleType(object.Elem()); simple {
if _, _, simple := isSimpleType(object.Elem()); simple {
return map[typeInfo]*ast.Field{
typeInfo{
path: fmt.Sprintf("%s.%s", path, name),
@ -254,22 +247,10 @@ func extractNotTags(n *ast.Field) ([]string, bool) {
return ret, len(ret) > 0
}
// isSimpleType returns the OpenAPI-compatible type name and boolean indicating if this is simple type or not
func isSimpleType(obj reflect.Type) (string, bool) {
switch obj.Kind() {
case reflect.String:
return "string", true
case reflect.Bool:
return "boolean", true
case reflect.Int, reflect.Int32,
reflect.Uint, reflect.Uint8, reflect.Uint16:
return "integer", true
case reflect.Int64, reflect.Uint64:
return "integer", true
case reflect.Float32:
return "number", true
}
return "", false
// isSimpleType returns the OpenAPI-compatible type name, type format and boolean indicating if this is simple type or not
func isSimpleType(obj reflect.Type) (string, string, bool) {
typ, frmt := openapi.OpenAPITypeFormat(obj.Kind().String())
return typ, frmt, typ != "" || frmt != ""
}
func extractTag(tag string) (string, bool) {
@ -286,9 +267,24 @@ func extractTag(tag string) (string, bool) {
return parts[0], false
}
type parsedSource struct {
fields map[string]*ast.Field
fs *token.FileSet
}
var parsedSourcesCache = make(map[string]parsedSource)
var parsedSourcesCacheLock sync.Mutex
// parseSourceFiles returns map of <path to field in structure> -> AST for structure Field and the token inspector for all files in package
func parseSourceFiles(t *testing.T, paths ...string) (map[string]*ast.Field, *token.FileSet) {
d, fs := parseMultipleDirs(t, parser.ParseComments, paths...)
func parseSourceFiles(t *testing.T, path string) (map[string]*ast.Field, *token.FileSet) {
parsedSourcesCacheLock.Lock()
defer parsedSourcesCacheLock.Unlock()
if ret, ok := parsedSourcesCache[path]; ok {
return ret.fields, ret.fs
}
d, fs := parseMultipleDirs(t, parser.ParseComments, path)
r := map[string]*ast.Field{}
@ -327,6 +323,7 @@ func parseSourceFiles(t *testing.T, paths ...string) (map[string]*ast.Field, *to
})
}
parsedSourcesCache[path] = parsedSource{fields: r, fs: fs}
return r, fs
}

View file

@ -212,7 +212,10 @@ func generateDocs(t *testing.T, objects map[string]map[string]interface{}, field
sectionParsed := iterateOverObject(t, fields, strings.ToLower(section), reflect.TypeOf(fieldInstance), "")
defs := parseDocDefinitions(t, sectionParsed, fs)
defs := make(DocDefinitions, 0, len(sectionParsed))
for k, f := range sectionParsed {
defs = append(defs, parseDocDefinition(t, root, k.path, k.typ, f, fs))
}
defs.Sort()
renderSections[section] = defs.RenderMarkdown(t, repositoryPath)

View file

@ -0,0 +1,211 @@
//
// DISCLAIMER
//
// Copyright 2023 ArangoDB GmbH, Cologne, Germany
//
// 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.
//
// Copyright holder is ArangoDB GmbH, Cologne, Germany
//
package internal
import (
"fmt"
"go/ast"
"go/token"
"reflect"
"testing"
"github.com/stretchr/testify/require"
apiextensions "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
openapi "k8s.io/kube-openapi/pkg/common"
)
type schemaBuilder struct {
root string
fields map[string]*ast.Field
fs *token.FileSet
}
func newSchemaBuilder(root string, fields map[string]*ast.Field, fs *token.FileSet) *schemaBuilder {
return &schemaBuilder{
root: root,
fields: fields,
fs: fs,
}
}
func (b *schemaBuilder) tryGetKubeOpenAPIDefinitions(t *testing.T, obj reflect.Type) *apiextensions.JSONSchemaProps {
if o, ok := reflect.New(obj).Interface().(openapi.OpenAPIV3DefinitionGetter); ok {
return b.openAPIDefToSchemaPros(t, o.OpenAPIV3Definition())
}
if o, ok := reflect.New(obj).Interface().(openapi.OpenAPIDefinitionGetter); ok {
return b.openAPIDefToSchemaPros(t, o.OpenAPIDefinition())
}
type openAPISchemaTypeGetter interface {
OpenAPISchemaType() []string
}
type openAPISchemaFormatGetter interface {
OpenAPISchemaFormat() string
}
var typ, frmt string
if o, ok := reflect.New(obj).Interface().(openAPISchemaTypeGetter); ok {
strs := o.OpenAPISchemaType()
require.Len(t, strs, 1)
typ = strs[0]
}
if o, ok := reflect.New(obj).Interface().(openAPISchemaFormatGetter); ok {
frmt = o.OpenAPISchemaFormat()
}
if typ != "" || frmt != "" {
return &apiextensions.JSONSchemaProps{
Type: typ,
Format: frmt,
}
}
return nil
}
func (b *schemaBuilder) openAPIDefToSchemaPros(t *testing.T, _ *openapi.OpenAPIDefinition) *apiextensions.JSONSchemaProps {
require.Fail(t, "openAPIDefToSchemaPros is not implemented because there were no calls to this function. Add the impl if needed.")
return nil
}
func (b *schemaBuilder) TypeToSchema(t *testing.T, obj reflect.Type, path string) *apiextensions.JSONSchemaProps {
var schema *apiextensions.JSONSchemaProps
t.Run(obj.Name(), func(t *testing.T) {
// first check if type already implements a method to get OpenAPI schema:
schema = b.tryGetKubeOpenAPIDefinitions(t, obj)
if schema != nil {
return
}
// fallback to our impl:
switch obj.Kind() {
case reflect.Pointer:
schema = b.TypeToSchema(t, obj.Elem(), path)
case reflect.Struct:
schema = b.StructToSchema(t, obj, path)
case reflect.Array, reflect.Slice:
schema = b.ArrayToSchema(t, obj.Elem(), path)
case reflect.Map:
schema = b.MapToSchema(t, obj, path)
default:
if typ, frmt, simple := isSimpleType(obj); simple {
schema = &apiextensions.JSONSchemaProps{
Type: typ,
Format: frmt,
}
} else {
t.Fatalf("Unsupported obj kind: %s", obj.Kind())
return
}
}
})
return schema
}
func (b *schemaBuilder) lookupDefinition(t *testing.T, fullName, path string) *DocDefinition {
f := b.fields[fullName]
if f == nil {
return nil
}
d := parseDocDefinition(t, b.root, path, "", f, b.fs)
return &d
}
func (b *schemaBuilder) ArrayToSchema(t *testing.T, elemObj reflect.Type, path string) *apiextensions.JSONSchemaProps {
isByteArray := elemObj.Kind() == reflect.Uint8
if isByteArray {
return &apiextensions.JSONSchemaProps{
Type: "string",
Format: "byte",
}
}
return &apiextensions.JSONSchemaProps{
Type: "array",
Items: &apiextensions.JSONSchemaPropsOrArray{
Schema: b.TypeToSchema(t, elemObj, path),
},
}
}
func (b *schemaBuilder) MapToSchema(t *testing.T, mapObj reflect.Type, path string) *apiextensions.JSONSchemaProps {
require.Equal(t, reflect.String, mapObj.Key().Kind(), "only string keys for map are supported %s", path)
return &apiextensions.JSONSchemaProps{
Type: "object",
AdditionalProperties: &apiextensions.JSONSchemaPropsOrBool{
Schema: b.TypeToSchema(t, mapObj.Elem(), path),
Allows: true, /* set automatically by serialization, but useful for testing */
},
}
}
func (b *schemaBuilder) StructToSchema(t *testing.T, structObj reflect.Type, path string) *apiextensions.JSONSchemaProps {
schema := &apiextensions.JSONSchemaProps{
Type: "object",
Properties: make(map[string]apiextensions.JSONSchemaProps),
}
for field := 0; field < structObj.NumField(); field++ {
f := structObj.Field(field)
if !f.IsExported() {
continue
}
tag, ok := f.Tag.Lookup("json")
if !ok {
if f.Anonymous {
tag = ",inline"
} else {
require.Failf(t, "field %s.%s has no valid json tag: can't build schema", path, f.Name)
}
}
n, inline := extractTag(tag)
if n == "-" {
continue
}
p := path
if !inline {
p = fmt.Sprintf("%s.%s", path, n)
}
s := b.TypeToSchema(t, f.Type, p)
require.NotNil(t, s, p)
fullFieldName := fmt.Sprintf("%s.%s", structObj.String(), f.Name)
def := b.lookupDefinition(t, fullFieldName, p)
if def != nil {
def.ApplyToSchema(s)
}
if inline {
// merge into parent
for k, v := range s.Properties {
schema.Properties[k] = v
}
} else {
require.NotEmpty(t, n, fullFieldName)
schema.Properties[n] = *s
}
}
return schema
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,188 @@
v1:
openAPIV3Schema:
properties:
spec:
properties:
backoff:
properties:
iterations:
description: Iterations defines number of iterations before reaching
MaxDelay. Default to 5
format: int32
type: integer
max_delay:
description: MaxDelay defines maximum delay in seconds. Default to
600
format: int32
type: integer
max_iterations:
description: MaxIterations defines maximum number of iterations after
backoff will be disabled. Default to nil (no limit)
format: int32
type: integer
min_delay:
description: MinDelay defines minimum delay in seconds. Default to
30
format: int32
type: integer
type: object
deployment:
description: Deployment describes the deployment which should have a backup
properties:
name:
description: Name of the ArangoDeployment Custom Resource within same
namespace as ArangoBackup Custom Resource.
type: string
type: object
download:
description: Download Backup download settings
properties:
credentialsSecretName:
description: CredentialsSecretName is the name of the secret used
while accessing repository
type: string
id:
description: ID of the ArangoBackup to be downloaded
type: string
repositoryURL:
description: |-
RepositoryURL is the URL path for file storage
Same repositoryURL needs to be defined in `credentialsSecretName` if protocol is other than local.
Format: `<protocol>:/<path>`
type: string
type: object
lifetime:
description: 'Lifetime is the time after which the backup will be deleted.
Format: "1.5h" or "2h45m".'
type: string
options:
description: Options specifies backup options
properties:
allowInconsistent:
description: |-
AllowInconsistent flag for Backup creation request.
If this value is set to true, backup is taken even if we are not able to acquire lock.
type: boolean
timeout:
description: Timeout for Backup creation request in seconds. Works
only when AsyncBackupCreation feature is set to false.
format: float
type: number
type: object
policyName:
description: PolicyName name of the ArangoBackupPolicy which created this
Custom Resource
type: string
upload:
description: |-
Upload Backup upload settings.
This field can be removed and created again with different values. This operation will trigger upload again.
properties:
credentialsSecretName:
description: CredentialsSecretName is the name of the secret used
while accessing repository
type: string
repositoryURL:
description: |-
RepositoryURL is the URL path for file storage
Same repositoryURL needs to be defined in `credentialsSecretName` if protocol is other than local.
Format: `<protocol>:/<path>`
type: string
type: object
type: object
type: object
x-kubernetes-preserve-unknown-fields: true
v1alpha:
openAPIV3Schema:
properties:
spec:
properties:
backoff:
properties:
iterations:
description: Iterations defines number of iterations before reaching
MaxDelay. Default to 5
format: int32
type: integer
max_delay:
description: MaxDelay defines maximum delay in seconds. Default to
600
format: int32
type: integer
max_iterations:
description: MaxIterations defines maximum number of iterations after
backoff will be disabled. Default to nil (no limit)
format: int32
type: integer
min_delay:
description: MinDelay defines minimum delay in seconds. Default to
30
format: int32
type: integer
type: object
deployment:
description: Deployment describes the deployment which should have a backup
properties:
name:
description: Name of the ArangoDeployment Custom Resource within same
namespace as ArangoBackup Custom Resource.
type: string
type: object
download:
description: Download Backup download settings
properties:
credentialsSecretName:
description: CredentialsSecretName is the name of the secret used
while accessing repository
type: string
id:
description: ID of the ArangoBackup to be downloaded
type: string
repositoryURL:
description: |-
RepositoryURL is the URL path for file storage
Same repositoryURL needs to be defined in `credentialsSecretName` if protocol is other than local.
Format: `<protocol>:/<path>`
type: string
type: object
lifetime:
description: 'Lifetime is the time after which the backup will be deleted.
Format: "1.5h" or "2h45m".'
type: string
options:
description: Options specifies backup options
properties:
allowInconsistent:
description: |-
AllowInconsistent flag for Backup creation request.
If this value is set to true, backup is taken even if we are not able to acquire lock.
type: boolean
timeout:
description: Timeout for Backup creation request in seconds. Works
only when AsyncBackupCreation feature is set to false.
format: float
type: number
type: object
policyName:
description: PolicyName name of the ArangoBackupPolicy which created this
Custom Resource
type: string
upload:
description: |-
Upload Backup upload settings.
This field can be removed and created again with different values. This operation will trigger upload again.
properties:
credentialsSecretName:
description: CredentialsSecretName is the name of the secret used
while accessing repository
type: string
repositoryURL:
description: |-
RepositoryURL is the URL path for file storage
Same repositoryURL needs to be defined in `credentialsSecretName` if protocol is other than local.
Format: `<protocol>:/<path>`
type: string
type: object
type: object
type: object
x-kubernetes-preserve-unknown-fields: true

View file

@ -0,0 +1,206 @@
v1:
openAPIV3Schema:
properties:
spec:
properties:
allowConcurrent:
description: AllowConcurrent if false, ArangoBackup will not be created
when previous Backups are not finished
type: boolean
maxBackups:
description: |-
MaxBackups defines how many backups should be kept in history (per deployment). Oldest healthy Backups will be deleted.
If not specified or 0 then no limit is applied
format: int32
type: integer
schedule:
description: |-
Schedule is cron-compatible specification of backup schedule
Parsed by https://godoc.org/github.com/robfig/cron
type: string
selector:
description: DeploymentSelector Selector definition for selecting matching
ArangoBackup Custom Resources.
properties:
matchExpressions:
items:
properties:
key:
type: string
operator:
type: string
values:
items:
type: string
type: array
type: object
type: array
matchLabels:
additionalProperties:
type: string
type: object
type: object
template:
description: ArangoBackupTemplate specifies additional options for newly
created ArangoBackup
properties:
backoff:
properties:
iterations:
description: Iterations defines number of iterations before reaching
MaxDelay. Default to 5
format: int32
type: integer
max_delay:
description: MaxDelay defines maximum delay in seconds. Default
to 600
format: int32
type: integer
max_iterations:
description: MaxIterations defines maximum number of iterations
after backoff will be disabled. Default to nil (no limit)
format: int32
type: integer
min_delay:
description: MinDelay defines minimum delay in seconds. Default
to 30
format: int32
type: integer
type: object
lifetime:
description: 'Lifetime is the time after which the backup will be
deleted. Format: "1.5h" or "2h45m".'
type: string
options:
properties:
allowInconsistent:
description: |-
AllowInconsistent flag for Backup creation request.
If this value is set to true, backup is taken even if we are not able to acquire lock.
type: boolean
timeout:
description: Timeout for Backup creation request in seconds. Works
only when AsyncBackupCreation feature is set to false.
format: float
type: number
type: object
upload:
properties:
credentialsSecretName:
description: CredentialsSecretName is the name of the secret used
while accessing repository
type: string
repositoryURL:
description: |-
RepositoryURL is the URL path for file storage
Same repositoryURL needs to be defined in `credentialsSecretName` if protocol is other than local.
Format: `<protocol>:/<path>`
type: string
type: object
type: object
type: object
type: object
x-kubernetes-preserve-unknown-fields: true
v1alpha:
openAPIV3Schema:
properties:
spec:
properties:
allowConcurrent:
description: AllowConcurrent if false, ArangoBackup will not be created
when previous Backups are not finished
type: boolean
maxBackups:
description: |-
MaxBackups defines how many backups should be kept in history (per deployment). Oldest healthy Backups will be deleted.
If not specified or 0 then no limit is applied
format: int32
type: integer
schedule:
description: |-
Schedule is cron-compatible specification of backup schedule
Parsed by https://godoc.org/github.com/robfig/cron
type: string
selector:
description: DeploymentSelector Selector definition for selecting matching
ArangoBackup Custom Resources.
properties:
matchExpressions:
items:
properties:
key:
type: string
operator:
type: string
values:
items:
type: string
type: array
type: object
type: array
matchLabels:
additionalProperties:
type: string
type: object
type: object
template:
description: ArangoBackupTemplate specifies additional options for newly
created ArangoBackup
properties:
backoff:
properties:
iterations:
description: Iterations defines number of iterations before reaching
MaxDelay. Default to 5
format: int32
type: integer
max_delay:
description: MaxDelay defines maximum delay in seconds. Default
to 600
format: int32
type: integer
max_iterations:
description: MaxIterations defines maximum number of iterations
after backoff will be disabled. Default to nil (no limit)
format: int32
type: integer
min_delay:
description: MinDelay defines minimum delay in seconds. Default
to 30
format: int32
type: integer
type: object
lifetime:
description: 'Lifetime is the time after which the backup will be
deleted. Format: "1.5h" or "2h45m".'
type: string
options:
properties:
allowInconsistent:
description: |-
AllowInconsistent flag for Backup creation request.
If this value is set to true, backup is taken even if we are not able to acquire lock.
type: boolean
timeout:
description: Timeout for Backup creation request in seconds. Works
only when AsyncBackupCreation feature is set to false.
format: float
type: number
type: object
upload:
properties:
credentialsSecretName:
description: CredentialsSecretName is the name of the secret used
while accessing repository
type: string
repositoryURL:
description: |-
RepositoryURL is the URL path for file storage
Same repositoryURL needs to be defined in `credentialsSecretName` if protocol is other than local.
Format: `<protocol>:/<path>`
type: string
type: object
type: object
type: object
type: object
x-kubernetes-preserve-unknown-fields: true

View file

@ -0,0 +1,57 @@
v1:
openAPIV3Schema:
properties:
spec:
properties:
deploymentName:
type: string
kubeconfig:
properties:
namespace:
type: string
secretKey:
type: string
secretName:
type: string
type: object
type: object
type: object
x-kubernetes-preserve-unknown-fields: true
v1alpha:
openAPIV3Schema:
properties:
spec:
properties:
deploymentName:
type: string
kubeconfig:
properties:
namespace:
type: string
secretKey:
type: string
secretName:
type: string
type: object
type: object
type: object
x-kubernetes-preserve-unknown-fields: true
v2alpha1:
openAPIV3Schema:
properties:
spec:
properties:
deploymentName:
type: string
kubeconfig:
properties:
namespace:
type: string
secretKey:
type: string
secretName:
type: string
type: object
type: object
type: object
x-kubernetes-preserve-unknown-fields: true

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,39 @@
v1:
openAPIV3Schema:
properties:
spec:
properties:
details:
format: byte
type: string
type:
type: string
type: object
type: object
x-kubernetes-preserve-unknown-fields: true
v1alpha:
openAPIV3Schema:
properties:
spec:
properties:
details:
format: byte
type: string
type:
type: string
type: object
type: object
x-kubernetes-preserve-unknown-fields: true
v2alpha1:
openAPIV3Schema:
properties:
spec:
properties:
details:
format: byte
type: string
type:
type: string
type: object
type: object
x-kubernetes-preserve-unknown-fields: true

View file

@ -0,0 +1,7 @@
v1alpha1:
openAPIV3Schema:
properties:
spec:
type: object
type: object
x-kubernetes-preserve-unknown-fields: true

View file

@ -0,0 +1,7 @@
v1alpha1:
openAPIV3Schema:
properties:
spec:
type: object
type: object
x-kubernetes-preserve-unknown-fields: true

View file

@ -0,0 +1,7 @@
v1alpha1:
openAPIV3Schema:
properties:
spec:
type: object
type: object
x-kubernetes-preserve-unknown-fields: true

View file

@ -0,0 +1,7 @@
v1alpha1:
openAPIV3Schema:
properties:
spec:
type: object
type: object
x-kubernetes-preserve-unknown-fields: true

View file

@ -0,0 +1,334 @@
v1:
openAPIV3Schema:
properties:
spec:
properties:
cancellation:
description: Cancellation describes what to do during cancellation process.
properties:
ensureInSync:
description: |-
EnsureInSync if it is true then during cancellation process data consistency is required.
Default value is true.
type: boolean
sourceReadOnly:
description: |-
SourceReadOnly if it true then after cancellation source data center should be in read-only mode.
Default value is false.
type: boolean
type: object
destination:
properties:
auth:
description: Authentication holds settings needed to authentication
at the syncmaster.
properties:
keyfileSecretName:
description: |-
KeyfileSecretName holds the name of a Secret containing a client authentication
certificate formatted at keyfile in a `tls.keyfile` field.
If `userSecretName` has not been set,
the client authentication certificate found in the secret with this name is also used to configure
the synchronization and fetch the synchronization status.
type: string
userSecretName:
description: |-
UserSecretName holds the name of a Secret containing a `username` & `password`
field used for basic authentication.
The user identified by the username must have write access in the `_system` database
of the ArangoDB cluster at the endpoint.
type: string
type: object
deploymentName:
description: |-
DeploymentName holds the name of an ArangoDeployment resource.
If set, this provides default values for masterEndpoint, auth & tls.
type: string
masterEndpoint:
description: |-
MasterEndpoint holds a list of URLs used to reach the syncmaster(s)
Use this setting if the source cluster is not running inside a Kubernetes cluster
that is reachable from the Kubernetes cluster the `ArangoDeploymentReplication` resource is deployed in.
Specifying this setting and `deploymentName` at the same time is not allowed.
items:
type: string
type: array
tls:
description: TLS holds settings needed to verify the TLS connection
to the syncmaster.
properties:
caSecretName:
description: |-
CASecretName holds the name of a Secret containing a ca.crt public key for TLS validation.
This setting is required, unless `deploymentName` has been set.
type: string
type: object
type: object
source:
properties:
auth:
description: Authentication holds settings needed to authentication
at the syncmaster.
properties:
keyfileSecretName:
description: |-
KeyfileSecretName holds the name of a Secret containing a client authentication
certificate formatted at keyfile in a `tls.keyfile` field.
If `userSecretName` has not been set,
the client authentication certificate found in the secret with this name is also used to configure
the synchronization and fetch the synchronization status.
type: string
userSecretName:
description: |-
UserSecretName holds the name of a Secret containing a `username` & `password`
field used for basic authentication.
The user identified by the username must have write access in the `_system` database
of the ArangoDB cluster at the endpoint.
type: string
type: object
deploymentName:
description: |-
DeploymentName holds the name of an ArangoDeployment resource.
If set, this provides default values for masterEndpoint, auth & tls.
type: string
masterEndpoint:
description: |-
MasterEndpoint holds a list of URLs used to reach the syncmaster(s)
Use this setting if the source cluster is not running inside a Kubernetes cluster
that is reachable from the Kubernetes cluster the `ArangoDeploymentReplication` resource is deployed in.
Specifying this setting and `deploymentName` at the same time is not allowed.
items:
type: string
type: array
tls:
description: TLS holds settings needed to verify the TLS connection
to the syncmaster.
properties:
caSecretName:
description: |-
CASecretName holds the name of a Secret containing a ca.crt public key for TLS validation.
This setting is required, unless `deploymentName` has been set.
type: string
type: object
type: object
type: object
type: object
x-kubernetes-preserve-unknown-fields: true
v1alpha:
openAPIV3Schema:
properties:
spec:
properties:
cancellation:
description: Cancellation describes what to do during cancellation process.
properties:
ensureInSync:
description: |-
EnsureInSync if it is true then during cancellation process data consistency is required.
Default value is true.
type: boolean
sourceReadOnly:
description: |-
SourceReadOnly if it true then after cancellation source data center should be in read-only mode.
Default value is false.
type: boolean
type: object
destination:
properties:
auth:
description: Authentication holds settings needed to authentication
at the syncmaster.
properties:
keyfileSecretName:
description: |-
KeyfileSecretName holds the name of a Secret containing a client authentication
certificate formatted at keyfile in a `tls.keyfile` field.
If `userSecretName` has not been set,
the client authentication certificate found in the secret with this name is also used to configure
the synchronization and fetch the synchronization status.
type: string
userSecretName:
description: |-
UserSecretName holds the name of a Secret containing a `username` & `password`
field used for basic authentication.
The user identified by the username must have write access in the `_system` database
of the ArangoDB cluster at the endpoint.
type: string
type: object
deploymentName:
description: |-
DeploymentName holds the name of an ArangoDeployment resource.
If set, this provides default values for masterEndpoint, auth & tls.
type: string
masterEndpoint:
description: |-
MasterEndpoint holds a list of URLs used to reach the syncmaster(s)
Use this setting if the source cluster is not running inside a Kubernetes cluster
that is reachable from the Kubernetes cluster the `ArangoDeploymentReplication` resource is deployed in.
Specifying this setting and `deploymentName` at the same time is not allowed.
items:
type: string
type: array
tls:
description: TLS holds settings needed to verify the TLS connection
to the syncmaster.
properties:
caSecretName:
description: |-
CASecretName holds the name of a Secret containing a ca.crt public key for TLS validation.
This setting is required, unless `deploymentName` has been set.
type: string
type: object
type: object
source:
properties:
auth:
description: Authentication holds settings needed to authentication
at the syncmaster.
properties:
keyfileSecretName:
description: |-
KeyfileSecretName holds the name of a Secret containing a client authentication
certificate formatted at keyfile in a `tls.keyfile` field.
If `userSecretName` has not been set,
the client authentication certificate found in the secret with this name is also used to configure
the synchronization and fetch the synchronization status.
type: string
userSecretName:
description: |-
UserSecretName holds the name of a Secret containing a `username` & `password`
field used for basic authentication.
The user identified by the username must have write access in the `_system` database
of the ArangoDB cluster at the endpoint.
type: string
type: object
deploymentName:
description: |-
DeploymentName holds the name of an ArangoDeployment resource.
If set, this provides default values for masterEndpoint, auth & tls.
type: string
masterEndpoint:
description: |-
MasterEndpoint holds a list of URLs used to reach the syncmaster(s)
Use this setting if the source cluster is not running inside a Kubernetes cluster
that is reachable from the Kubernetes cluster the `ArangoDeploymentReplication` resource is deployed in.
Specifying this setting and `deploymentName` at the same time is not allowed.
items:
type: string
type: array
tls:
description: TLS holds settings needed to verify the TLS connection
to the syncmaster.
properties:
caSecretName:
description: |-
CASecretName holds the name of a Secret containing a ca.crt public key for TLS validation.
This setting is required, unless `deploymentName` has been set.
type: string
type: object
type: object
type: object
type: object
x-kubernetes-preserve-unknown-fields: true
v2alpha1:
openAPIV3Schema:
properties:
spec:
properties:
cancellation:
description: Cancellation describes what to do during cancellation process.
properties:
ensureInSync:
description: |-
EnsureInSync if it is true then during cancellation process data consistency is required.
Default value is true.
type: boolean
sourceReadOnly:
description: |-
SourceReadOnly if it true then after cancellation source data center should be in read-only mode.
Default value is false.
type: boolean
type: object
destination:
properties:
auth:
description: Authentication holds settings needed to authentication
at the syncmaster.
properties:
keyfileSecretName:
description: |-
KeyfileSecretName holds the name of a Secret containing a client authentication
certificate formatted at keyfile in a `tls.keyfile` field.
type: string
userSecretName:
description: |-
UserSecretName holds the name of a Secret containing a `username` & `password`
field used for basic authentication.
The user identified by the username must have write access in the `_system` database
of the ArangoDB cluster at the endpoint.
type: string
type: object
deploymentName:
description: |-
DeploymentName holds the name of an ArangoDeployment resource.
If set this provides default values for masterEndpoint, auth & tls.
type: string
masterEndpoint:
description: MasterEndpoint holds a list of URLs used to reach the
syncmaster(s).
items:
type: string
type: array
tls:
description: TLS holds settings needed to verify the TLS connection
to the syncmaster.
properties:
caSecretName:
description: CASecretName holds the name of a Secret containing
a ca.crt public key for TLS validation.
type: string
type: object
type: object
source:
properties:
auth:
description: Authentication holds settings needed to authentication
at the syncmaster.
properties:
keyfileSecretName:
description: |-
KeyfileSecretName holds the name of a Secret containing a client authentication
certificate formatted at keyfile in a `tls.keyfile` field.
type: string
userSecretName:
description: |-
UserSecretName holds the name of a Secret containing a `username` & `password`
field used for basic authentication.
The user identified by the username must have write access in the `_system` database
of the ArangoDB cluster at the endpoint.
type: string
type: object
deploymentName:
description: |-
DeploymentName holds the name of an ArangoDeployment resource.
If set this provides default values for masterEndpoint, auth & tls.
type: string
masterEndpoint:
description: MasterEndpoint holds a list of URLs used to reach the
syncmaster(s).
items:
type: string
type: array
tls:
description: TLS holds settings needed to verify the TLS connection
to the syncmaster.
properties:
caSecretName:
description: CASecretName holds the name of a Secret containing
a ca.crt public key for TLS validation.
type: string
type: object
type: object
type: object
type: object
x-kubernetes-preserve-unknown-fields: true

View file

@ -0,0 +1,69 @@
v1alpha:
openAPIV3Schema:
properties:
spec:
properties:
localPath:
description: LocalPath setting specifies one or more local directories
(on the nodes) used to create persistent volumes in.
items:
type: string
type: array
nodeSelector:
additionalProperties:
type: string
description: NodeSelector setting specifies which nodes the operator will
provision persistent volumes on.
type: object
podCustomization:
properties:
priority:
description: Priority if defined, sets the priority for pods of storage
provisioner
format: int32
type: integer
type: object
privileged:
description: Privileged if set, passes Privileged flag to SecurityContext
for pods of storage provisioner
type: boolean
storageClass:
properties:
isDefault:
description: |-
IsDefault setting specifies if the created `StorageClass` will
be marked as default storage class.
type: boolean
name:
description: |-
Name setting specifies the name of the storage class that
created `PersistentVolume` will use.
If empty, this field defaults to the name of the `ArangoLocalStorage` object.
If a `StorageClass` with given name does not yet exist, it will be created.
type: string
reclaimPolicy:
description: ReclaimPolicy defines what happens to a persistent volume
when released from its claim.
type: string
type: object
tolerations:
description: Tolerations specifies the tolerations added to pods of storage
provisioner
items:
properties:
effect:
type: string
key:
type: string
operator:
type: string
tolerationSeconds:
format: int64
type: integer
value:
type: string
type: object
type: array
type: object
type: object
x-kubernetes-preserve-unknown-fields: true