Skip to content

Commit f426cf0

Browse files
authored
[API] Add v2alpha1 Version (#665)
1 parent 6b7451a commit f426cf0

File tree

121 files changed

+12531
-5
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

121 files changed

+12531
-5
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# Change Log
22

33
## [master](https://github.com/arangodb/kube-arangodb/tree/master) (N/A)
4+
- Add v2alpha1 API for ArangoDeployment and ArangoDeploymentReplication
45

56
## [1.1.2](https://github.com/arangodb/kube-arangodb/tree/1.1.2) (2020-11-11)
67
- Fix Bootstrap phase and move it under Plan

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ update-generated:
239239
"all" \
240240
"github.com/arangodb/kube-arangodb/pkg/generated" \
241241
"github.com/arangodb/kube-arangodb/pkg/apis" \
242-
"deployment:v1 replication:v1 storage:v1alpha backup:v1" \
242+
"deployment:v1 replication:v1 storage:v1alpha backup:v1 deployment:v2alpha1 replication:v2alpha1" \
243243
--go-header-file "./tools/codegen/boilerplate.go.txt" \
244244
$(VERIFYARGS)
245245
GOPATH=$(GOBUILDDIR) $(VENDORDIR)/k8s.io/code-generator/generate-groups.sh \
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
//
2+
// DISCLAIMER
3+
//
4+
// Copyright 2020 ArangoDB GmbH, Cologne, Germany
5+
//
6+
// Licensed under the Apache License, Version 2.0 (the "License");
7+
// you may not use this file except in compliance with the License.
8+
// You may obtain a copy of the License at
9+
//
10+
// http://www.apache.org/licenses/LICENSE-2.0
11+
//
12+
// Unless required by applicable law or agreed to in writing, software
13+
// distributed under the License is distributed on an "AS IS" BASIS,
14+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
// See the License for the specific language governing permissions and
16+
// limitations under the License.
17+
//
18+
// Copyright holder is ArangoDB GmbH, Cologne, Germany
19+
//
20+
// Author Ewout Prangsma
21+
//
22+
23+
package v2alpha1
24+
25+
import (
26+
"github.com/pkg/errors"
27+
28+
"github.com/arangodb/kube-arangodb/pkg/util"
29+
"github.com/arangodb/kube-arangodb/pkg/util/k8sutil"
30+
)
31+
32+
// AuthenticationSpec holds authentication specific configuration settings
33+
type AuthenticationSpec struct {
34+
JWTSecretName *string `json:"jwtSecretName,omitempty"`
35+
}
36+
37+
const (
38+
// JWTSecretNameDisabled is the value of JWTSecretName to use for disabling authentication.
39+
JWTSecretNameDisabled = "None"
40+
)
41+
42+
// GetJWTSecretName returns the value of jwtSecretName.
43+
func (s AuthenticationSpec) GetJWTSecretName() string {
44+
return util.StringOrDefault(s.JWTSecretName)
45+
}
46+
47+
// IsAuthenticated returns true if authentication is enabled.
48+
// Returns false other (when JWTSecretName == "None").
49+
func (s AuthenticationSpec) IsAuthenticated() bool {
50+
return s.GetJWTSecretName() != JWTSecretNameDisabled
51+
}
52+
53+
// Validate the given spec
54+
func (s AuthenticationSpec) Validate(required bool) error {
55+
if required && !s.IsAuthenticated() {
56+
return maskAny(errors.Wrap(ValidationError, "JWT secret is required"))
57+
}
58+
if s.IsAuthenticated() {
59+
if err := k8sutil.ValidateResourceName(s.GetJWTSecretName()); err != nil {
60+
return maskAny(err)
61+
}
62+
}
63+
return nil
64+
}
65+
66+
// SetDefaults fills in missing defaults
67+
func (s *AuthenticationSpec) SetDefaults(defaultJWTSecretName string) {
68+
if s.GetJWTSecretName() == "" {
69+
// Note that we don't check for nil here, since even a specified, but empty
70+
// string should result in the default value.
71+
s.JWTSecretName = util.NewString(defaultJWTSecretName)
72+
}
73+
}
74+
75+
// SetDefaultsFrom fills unspecified fields with a value from given source spec.
76+
func (s *AuthenticationSpec) SetDefaultsFrom(source AuthenticationSpec) {
77+
if s.JWTSecretName == nil {
78+
s.JWTSecretName = util.NewStringOrNil(source.JWTSecretName)
79+
}
80+
}
81+
82+
// ResetImmutableFields replaces all immutable fields in the given target with values from the source spec.
83+
// It returns a list of fields that have been reset.
84+
// Field names are relative to given field prefix.
85+
func (s AuthenticationSpec) ResetImmutableFields(fieldPrefix string, target *AuthenticationSpec) []string {
86+
var resetFields []string
87+
if s.IsAuthenticated() != target.IsAuthenticated() {
88+
// Note: You can change the name, but not from empty to non-empty (or reverse).
89+
target.JWTSecretName = util.NewStringOrNil(s.JWTSecretName)
90+
resetFields = append(resetFields, fieldPrefix+".jwtSecretName")
91+
}
92+
return resetFields
93+
}
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
//
2+
// DISCLAIMER
3+
//
4+
// Copyright 2020 ArangoDB GmbH, Cologne, Germany
5+
//
6+
// Licensed under the Apache License, Version 2.0 (the "License");
7+
// you may not use this file except in compliance with the License.
8+
// You may obtain a copy of the License at
9+
//
10+
// http://www.apache.org/licenses/LICENSE-2.0
11+
//
12+
// Unless required by applicable law or agreed to in writing, software
13+
// distributed under the License is distributed on an "AS IS" BASIS,
14+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
// See the License for the specific language governing permissions and
16+
// limitations under the License.
17+
//
18+
// Copyright holder is ArangoDB GmbH, Cologne, Germany
19+
//
20+
// Author Ewout Prangsma
21+
//
22+
23+
package v2alpha1
24+
25+
import (
26+
"testing"
27+
28+
"github.com/arangodb/kube-arangodb/pkg/util"
29+
"github.com/stretchr/testify/assert"
30+
)
31+
32+
func TestAuthenticationSpecValidate(t *testing.T) {
33+
// Valid
34+
assert.Nil(t, AuthenticationSpec{JWTSecretName: util.NewString("None")}.Validate(false))
35+
assert.Nil(t, AuthenticationSpec{JWTSecretName: util.NewString("foo")}.Validate(false))
36+
assert.Nil(t, AuthenticationSpec{JWTSecretName: util.NewString("foo")}.Validate(true))
37+
38+
// Not valid
39+
assert.Error(t, AuthenticationSpec{JWTSecretName: util.NewString("Foo")}.Validate(false))
40+
}
41+
42+
func TestAuthenticationSpecIsAuthenticated(t *testing.T) {
43+
assert.False(t, AuthenticationSpec{JWTSecretName: util.NewString("None")}.IsAuthenticated())
44+
assert.True(t, AuthenticationSpec{JWTSecretName: util.NewString("foo")}.IsAuthenticated())
45+
assert.True(t, AuthenticationSpec{JWTSecretName: util.NewString("")}.IsAuthenticated())
46+
}
47+
48+
func TestAuthenticationSpecSetDefaults(t *testing.T) {
49+
def := func(spec AuthenticationSpec) AuthenticationSpec {
50+
spec.SetDefaults("test-jwt")
51+
return spec
52+
}
53+
54+
assert.Equal(t, "test-jwt", def(AuthenticationSpec{}).GetJWTSecretName())
55+
assert.Equal(t, "foo", def(AuthenticationSpec{JWTSecretName: util.NewString("foo")}).GetJWTSecretName())
56+
}
57+
58+
func TestAuthenticationSpecResetImmutableFields(t *testing.T) {
59+
tests := []struct {
60+
Original AuthenticationSpec
61+
Target AuthenticationSpec
62+
Expected AuthenticationSpec
63+
Result []string
64+
}{
65+
// Valid "changes"
66+
{
67+
AuthenticationSpec{JWTSecretName: util.NewString("None")},
68+
AuthenticationSpec{JWTSecretName: util.NewString("None")},
69+
AuthenticationSpec{JWTSecretName: util.NewString("None")},
70+
nil,
71+
},
72+
{
73+
AuthenticationSpec{JWTSecretName: util.NewString("foo")},
74+
AuthenticationSpec{JWTSecretName: util.NewString("foo")},
75+
AuthenticationSpec{JWTSecretName: util.NewString("foo")},
76+
nil,
77+
},
78+
{
79+
AuthenticationSpec{JWTSecretName: util.NewString("foo")},
80+
AuthenticationSpec{JWTSecretName: util.NewString("foo2")},
81+
AuthenticationSpec{JWTSecretName: util.NewString("foo2")},
82+
nil,
83+
},
84+
85+
// Invalid changes
86+
{
87+
AuthenticationSpec{JWTSecretName: util.NewString("foo")},
88+
AuthenticationSpec{JWTSecretName: util.NewString("None")},
89+
AuthenticationSpec{JWTSecretName: util.NewString("foo")},
90+
[]string{"test.jwtSecretName"},
91+
},
92+
{
93+
AuthenticationSpec{JWTSecretName: util.NewString("None")},
94+
AuthenticationSpec{JWTSecretName: util.NewString("foo")},
95+
AuthenticationSpec{JWTSecretName: util.NewString("None")},
96+
[]string{"test.jwtSecretName"},
97+
},
98+
}
99+
100+
for _, test := range tests {
101+
result := test.Original.ResetImmutableFields("test", &test.Target)
102+
assert.Equal(t, test.Result, result)
103+
assert.Equal(t, test.Expected, test.Target)
104+
}
105+
}
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
//
2+
// DISCLAIMER
3+
//
4+
// Copyright 2020 ArangoDB GmbH, Cologne, Germany
5+
//
6+
// Licensed under the Apache License, Version 2.0 (the "License");
7+
// you may not use this file except in compliance with the License.
8+
// You may obtain a copy of the License at
9+
//
10+
// http://www.apache.org/licenses/LICENSE-2.0
11+
//
12+
// Unless required by applicable law or agreed to in writing, software
13+
// distributed under the License is distributed on an "AS IS" BASIS,
14+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
// See the License for the specific language governing permissions and
16+
// limitations under the License.
17+
//
18+
// Copyright holder is ArangoDB GmbH, Cologne, Germany
19+
//
20+
21+
package v2alpha1
22+
23+
import (
24+
"fmt"
25+
26+
"github.com/arangodb/kube-arangodb/pkg/util/k8sutil"
27+
)
28+
29+
const (
30+
// UserNameRoot root user name
31+
UserNameRoot = "root"
32+
)
33+
34+
// PasswordSecretName contains user password secret name
35+
type PasswordSecretName string
36+
37+
func (p PasswordSecretName) Get() string {
38+
return string(p)
39+
}
40+
41+
const (
42+
// PasswordSecretNameNone is magic value for no action
43+
PasswordSecretNameNone PasswordSecretName = "None"
44+
// PasswordSecretNameAuto is magic value for autogenerate name
45+
PasswordSecretNameAuto PasswordSecretName = "Auto"
46+
)
47+
48+
// PasswordSecretNameList is a map from username to secretnames
49+
type PasswordSecretNameList map[string]PasswordSecretName
50+
51+
// BootstrapSpec contains information for cluster bootstrapping
52+
type BootstrapSpec struct {
53+
// PasswordSecretNames contains a map of username to password-secret-name
54+
PasswordSecretNames PasswordSecretNameList `json:"passwordSecretNames,omitempty"`
55+
}
56+
57+
// IsNone returns true if p is None or p is empty
58+
func (p PasswordSecretName) IsNone() bool {
59+
return p == PasswordSecretNameNone || p == ""
60+
}
61+
62+
// IsAuto returns true if p is Auto
63+
func (p PasswordSecretName) IsAuto() bool {
64+
return p == PasswordSecretNameAuto
65+
}
66+
67+
// GetSecretName returns the secret name given by the specs. Or None if not set.
68+
func (s PasswordSecretNameList) GetSecretName(user string) PasswordSecretName {
69+
if s != nil {
70+
if secretname, ok := s[user]; ok {
71+
return secretname
72+
}
73+
}
74+
return PasswordSecretNameNone
75+
}
76+
77+
// getSecretNameForUserPassword returns the default secret name for the given user
78+
func getSecretNameForUserPassword(deploymentname, username string) PasswordSecretName {
79+
return PasswordSecretName(k8sutil.FixupResourceName(deploymentname + "-" + username + "-password"))
80+
}
81+
82+
// Validate the specification.
83+
func (b *BootstrapSpec) Validate() error {
84+
for username, secretname := range b.PasswordSecretNames {
85+
// Remove this restriction as soon as we can bootstrap databases
86+
if username != UserNameRoot {
87+
return fmt.Errorf("only username `root` allowed in passwordSecretNames")
88+
}
89+
90+
if secretname.IsNone() {
91+
if username != UserNameRoot {
92+
return fmt.Errorf("magic value None not allowed for %s", username)
93+
}
94+
} else {
95+
if err := k8sutil.ValidateResourceName(string(secretname)); err != nil {
96+
return maskAny(err)
97+
}
98+
}
99+
}
100+
101+
return nil
102+
}
103+
104+
// SetDefaults fills in default values when a field is not specified.
105+
func (b *BootstrapSpec) SetDefaults(deploymentname string) {
106+
if b.PasswordSecretNames == nil {
107+
b.PasswordSecretNames = make(map[string]PasswordSecretName)
108+
}
109+
110+
// If root is not set init with Auto
111+
if _, ok := b.PasswordSecretNames[UserNameRoot]; !ok {
112+
b.PasswordSecretNames[UserNameRoot] = PasswordSecretNameNone
113+
}
114+
115+
// Replace Auto with generated secret name
116+
for user, secretname := range b.PasswordSecretNames {
117+
if secretname.IsAuto() {
118+
b.PasswordSecretNames[user] = getSecretNameForUserPassword(deploymentname, user)
119+
}
120+
}
121+
}
122+
123+
// NewPasswordSecretNameListOrNil returns nil if input is nil, otherwise returns a clone of the given value.
124+
func NewPasswordSecretNameListOrNil(list PasswordSecretNameList) PasswordSecretNameList {
125+
if list == nil {
126+
return nil
127+
}
128+
var newList = make(PasswordSecretNameList)
129+
for k, v := range list {
130+
newList[k] = v
131+
}
132+
return newList
133+
}
134+
135+
// SetDefaultsFrom fills unspecified fields with a value from given source spec.
136+
func (b *BootstrapSpec) SetDefaultsFrom(source BootstrapSpec) {
137+
if b.PasswordSecretNames == nil {
138+
b.PasswordSecretNames = NewPasswordSecretNameListOrNil(source.PasswordSecretNames)
139+
}
140+
}

0 commit comments

Comments
 (0)