Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
273702f
Add MySQLCluster v1beta2
d-kuro Nov 24, 2021
0db2d21
Generate manifests
d-kuro Nov 24, 2021
a53e138
Set maxDescLen=30
d-kuro Nov 30, 2021
7ae9b8b
Set maxDescLen=0
d-kuro Nov 30, 2021
1c274d9
Use MySQLCluster v1beta2
d-kuro Dec 5, 2021
eb0e306
Generate conversion codes
d-kuro Dec 5, 2021
d8bb804
Add replicaServiceTemplate tests
d-kuro Dec 7, 2021
1e2c6f2
Support conversion webhook in Helm chart
d-kuro Dec 7, 2021
a9fb411
Add Helm chart update note
d-kuro Dec 7, 2021
7a4a056
Update PROJECT
d-kuro Dec 8, 2021
63c1df5
Fix kubebulder comments.
d-kuro Dec 14, 2021
a94e04a
Move conversion logic form v1beta2 -> v1beta1
d-kuro Dec 15, 2021
2733404
Add comment for generate manifests.
d-kuro Dec 15, 2021
9253b81
Fix linter Warnings
d-kuro Dec 21, 2021
4b44ff8
Generate docs
d-kuro Dec 21, 2021
42da610
Add admisson webhook for MySQLCluster v1beta2
d-kuro Dec 22, 2021
c7988e3
Remove validate and mutate webhooks from v1beta1 MySQLCluster.
d-kuro Dec 28, 2021
e6e44e6
Add comments
d-kuro Dec 28, 2021
4f5c0ae
Convert jobConfig.
d-kuro Dec 28, 2021
6e11466
Fix Makefile format.
d-kuro Dec 28, 2021
d0fa6af
Add BackupPolicy v1beta2
d-kuro Jan 8, 2022
7c02683
Use BackupPolicy v1beta2
d-kuro Jan 8, 2022
4cc80be
Add conversion webhook for BackupPolicy
d-kuro Jan 9, 2022
e2400d9
Add BackupPolicy v1beta2 docs
d-kuro Jan 16, 2022
3a55e6b
Remove old api docs
d-kuro Jan 16, 2022
05700b9
Fix testing package name
d-kuro Jan 16, 2022
fcbc2a5
Upgrade apiVersion for example and docs.
d-kuro Jan 16, 2022
6625785
Update serviceTemplate usage docs.
d-kuro Jan 16, 2022
e354449
Update docs/reconcile.md
ymmt2005 Jan 17, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 14 additions & 5 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Tool versions
CTRL_TOOLS_VERSION=0.7.0
CTRL_RUNTIME_VERSION := $(shell awk '/sigs.k8s.io\/controller-runtime/ {print substr($$2, 2)}' go.mod)
CODE_GENERATOR_VERSION := $(shell awk '/k8s.io\/client-go/ {print substr($$2, 2)}' go.mod)
KUSTOMIZE_VERSION = 4.4.1
HELM_VERSION = 3.7.1
CRD_TO_MARKDOWN_VERSION = 0.0.3
Expand All @@ -27,7 +28,7 @@ SHELL = /bin/bash
.SHELLFLAGS = -e -o pipefail -c

# Produce CRDs that work back to Kubernetes 1.11 (no version conversion)
CRD_OPTIONS = "crd:crdVersions=v1,maxDescLen=220"
CRD_OPTIONS = "crd:crdVersions=v1,maxDescLen=0"

# for Go
GOOS = $(shell go env GOOS)
Expand Down Expand Up @@ -59,17 +60,21 @@ help: ## Display this help.
.PHONY: manifests
manifests: controller-gen kustomize ## Generate WebhookConfiguration, ClusterRole and CustomResourceDefinition objects.
$(CONTROLLER_GEN) $(CRD_OPTIONS) rbac:roleName=manager-role webhook paths="./..." output:crd:artifacts:config=config/crd/bases
$(KUSTOMIZE) build config/kustomize-to-helm/overlays/crds -o charts/moco/crds
$(KUSTOMIZE) build config/crd -o config/crd/tests # Outputs static CRDs with conversion webhook enabled for use with Envtest.
$(KUSTOMIZE) build config/kustomize-to-helm/overlays/crds -o charts/moco/templates/generated/crds
$(KUSTOMIZE) build config/kustomize-to-helm/overlays/templates > charts/moco/templates/generated/generated.yaml

.PHONY: generate
generate: controller-gen ## Generate code containing DeepCopy, DeepCopyInto, and DeepCopyObject method implementations.
generate: controller-gen conversion-gen ## Generate code containing DeepCopy, DeepCopyInto, and DeepCopyObject method implementations.
$(CONTROLLER_GEN) object:headerFile="hack/boilerplate.go.txt" paths="./..."
$(CONVERSION_GEN) -i ./api/v1beta1/ -o . -O zz_generated.conversion --go-header-file hack/boilerplate.go.txt

.PHONY: apidoc
apidoc: crd-to-markdown $(wildcard api/*/*_types.go)
$(CRD_TO_MARKDOWN) --links docs/links.csv -f api/v1beta1/mysqlcluster_types.go -f api/v1beta1/job_types.go -n MySQLCluster > docs/crd_mysqlcluster.md
$(CRD_TO_MARKDOWN) --links docs/links.csv -f api/v1beta1/backuppolicy_types.go -f api/v1beta1/job_types.go -n BackupPolicy > docs/crd_backuppolicy.md
$(CRD_TO_MARKDOWN) --links docs/links.csv -f api/v1beta1/mysqlcluster_types.go -f api/v1beta1/job_types.go -n MySQLCluster > docs/crd_mysqlcluster_v1beta1.md
$(CRD_TO_MARKDOWN) --links docs/links.csv -f api/v1beta2/mysqlcluster_types.go -f api/v1beta2/job_types.go -n MySQLCluster > docs/crd_mysqlcluster_v1beta2.md
$(CRD_TO_MARKDOWN) --links docs/links.csv -f api/v1beta1/backuppolicy_types.go -f api/v1beta1/job_types.go -n BackupPolicy > docs/crd_backuppolicy_v1beta1.md
$(CRD_TO_MARKDOWN) --links docs/links.csv -f api/v1beta2/backuppolicy_types.go -f api/v1beta2/job_types.go -n BackupPolicy > docs/crd_backuppolicy_v1beta2.md

.PHONY: book
book: mdbook
Expand Down Expand Up @@ -140,6 +145,10 @@ CONTROLLER_GEN := $(shell pwd)/bin/controller-gen
controller-gen: ## Download controller-gen locally if necessary.
$(call go-get-tool,$(CONTROLLER_GEN),sigs.k8s.io/controller-tools/cmd/controller-gen@v$(CTRL_TOOLS_VERSION))

CONVERSION_GEN := $(shell pwd)/bin/conversion-gen
conversion-gen: ## Donwload conversion-gen locally if necessary.
$(call go-get-tool,$(CONVERSION_GEN),k8s.io/code-generator/cmd/conversion-gen@v$(CODE_GENERATOR_VERSION))

SETUP_ENVTEST := $(shell pwd)/bin/setup-envtest
.PHONY: setup-envtest
setup-envtest: ## Download setup-envtest locally if necessary
Expand Down
12 changes: 12 additions & 0 deletions PROJECT
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,18 @@ resources:
kind: MySQLCluster
path: github.com/cybozu-go/moco/api/v1beta1
version: v1beta1
webhooks:
conversion: true
webhookVersion: v1
- api:
crdVersion: v1
namespaced: true
controller: false
domain: cybozu.com
group: moco
kind: MySQLCluster
path: github.com/cybozu-go/moco/api/v1beta2
version: v1beta2
webhooks:
validation: true
webhookVersion: v1
Expand Down
14 changes: 1 addition & 13 deletions api/v1beta1/backuppolicy_types.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
package v1beta1

import (
cron "github.com/robfig/cron/v3"
batchv1beta1 "k8s.io/api/batch/v1beta1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/validation/field"
)

// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
Expand Down Expand Up @@ -84,18 +82,8 @@ type BackupPolicySpec struct {
FailedJobsHistoryLimit *int32 `json:"failedJobsHistoryLimit,omitempty"`
}

func (s *BackupPolicySpec) validate() field.ErrorList {
var allErrs field.ErrorList
p := field.NewPath("spec")

if _, err := cron.ParseStandard(s.Schedule); err != nil {
allErrs = append(allErrs, field.Invalid(p.Child("schedule"), s.Schedule, err.Error()))
}

return allErrs
}

//+kubebuilder:object:root=true
//+kubebuilder:storageversion

// BackupPolicy is a namespaced resource that should be referenced from MySQLCluster.
type BackupPolicy struct {
Expand Down
145 changes: 145 additions & 0 deletions api/v1beta1/conversion.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
package v1beta1

import (
"encoding/json"
"unsafe"

"github.com/cybozu-go/moco/api/v1beta2"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
apiconversion "k8s.io/apimachinery/pkg/conversion"
"k8s.io/apimachinery/pkg/runtime"
"sigs.k8s.io/controller-runtime/pkg/conversion"
)

const (
SpecReplicaServiceTemplateAnnotation = "mysqlcluster.v1beta2.moco.cybozu.com/spec.replicaServiceTemplate"
)

var _ conversion.Convertible = &MySQLCluster{}

// ConvertTo converts this MySQLCluster to the Hub version (v1beta2).
func (src *MySQLCluster) ConvertTo(dstRaw conversion.Hub) error {
dst := dstRaw.(*v1beta2.MySQLCluster)

return Convert__MySQLCluster_To_v1beta2_MySQLCluster(src, dst, nil)
}

// ConvertFrom converts from the Hub version (v1beta2) to this version.
func (dst *MySQLCluster) ConvertFrom(srcRaw conversion.Hub) error {
src := srcRaw.(*v1beta2.MySQLCluster)

return Convert_v1beta2_MySQLCluster_To__MySQLCluster(src, dst, nil)
}

// ConvertTo converts this MySQLCluster to the Hub version (v1beta2).
func (src *BackupPolicy) ConvertTo(dstRaw conversion.Hub) error {
dst := dstRaw.(*v1beta2.BackupPolicy)

return Convert__BackupPolicy_To_v1beta2_BackupPolicy(src, dst, nil)
}

// ConvertFrom converts from the Hub version (v1beta2) to this version.
func (dst *BackupPolicy) ConvertFrom(srcRaw conversion.Hub) error {
src := srcRaw.(*v1beta2.BackupPolicy)

return Convert_v1beta2_BackupPolicy_To__BackupPolicy(src, dst, nil)
}

// Convert__MySQLCluster_To_v1beta2_MySQLCluster is an autogenerated conversion function.
func Convert__MySQLCluster_To_v1beta2_MySQLCluster(in *MySQLCluster, out *v1beta2.MySQLCluster, s apiconversion.Scope) error {
if err := autoConvert__MySQLCluster_To_v1beta2_MySQLCluster(in, out, s); err != nil {
return err
}

if _, err := unmarshalReplicaServiceTemplate(in, out); err != nil {
return err
}

return nil
}

// Convert_v1beta2_MySQLCluster_To__MySQLCluster is an autogenerated conversion function.
func Convert_v1beta2_MySQLCluster_To__MySQLCluster(in *v1beta2.MySQLCluster, out *MySQLCluster, s apiconversion.Scope) error {
if err := autoConvert_v1beta2_MySQLCluster_To__MySQLCluster(in, out, s); err != nil {
return err
}

if err := marshalReplicaServiceTemplate(&in.Spec, out); err != nil {
return err
}

return nil
}

func Convert__MySQLClusterSpec_To_v1beta2_MySQLClusterSpec(in *MySQLClusterSpec, out *v1beta2.MySQLClusterSpec, s apiconversion.Scope) error {
if err := autoConvert__MySQLClusterSpec_To_v1beta2_MySQLClusterSpec(in, out, s); err != nil {
return err
}

out.PrimaryServiceTemplate = (*v1beta2.ServiceTemplate)(unsafe.Pointer(in.ServiceTemplate))

return nil
}

func Convert_v1beta2_MySQLClusterSpec_To__MySQLClusterSpec(in *v1beta2.MySQLClusterSpec, out *MySQLClusterSpec, s apiconversion.Scope) error {
if err := autoConvert_v1beta2_MySQLClusterSpec_To__MySQLClusterSpec(in, out, s); err != nil {
return err
}

out.ServiceTemplate = (*ServiceTemplate)(unsafe.Pointer(in.PrimaryServiceTemplate))

return nil
}

// marshalReplicaServiceTemplate stores the service template as json data in the destination object annotations.
func marshalReplicaServiceTemplate(spec *v1beta2.MySQLClusterSpec, dst metav1.Object) error {
if spec.ReplicaServiceTemplate == nil {
return nil
}

u, err := runtime.DefaultUnstructuredConverter.ToUnstructured(spec.ReplicaServiceTemplate)
if err != nil {
return err
}

data, err := json.Marshal(u)
if err != nil {
return err
}

annotations := dst.GetAnnotations()
if annotations == nil {
annotations = map[string]string{}
}

annotations[SpecReplicaServiceTemplateAnnotation] = string(data)
dst.SetAnnotations(annotations)

return nil
}

// unmarshalReplicaServiceTemplate tries to retrieve the data from the annotation and unmarshal it into the service template passed as input.
func unmarshalReplicaServiceTemplate(src metav1.Object, dst *v1beta2.MySQLCluster) (bool, error) {
data, ok := src.GetAnnotations()[SpecReplicaServiceTemplateAnnotation]
if !ok {
return false, nil
}

var s *v1beta2.ServiceTemplate

if err := json.Unmarshal([]byte(data), &s); err != nil {
return false, err
}

dst.Spec.ReplicaServiceTemplate = s

dstAnnotation := dst.GetAnnotations()

delete(dstAnnotation, SpecReplicaServiceTemplateAnnotation)

if len(dstAnnotation) == 0 {
dst.SetAnnotations(nil)
}

return true, nil
}
74 changes: 74 additions & 0 deletions api/v1beta1/conversion_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package v1beta1

import (
"testing"

mocov1beta2 "github.com/cybozu-go/moco/api/v1beta2"
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
"k8s.io/apimachinery/pkg/api/apitesting/roundtrip"
"k8s.io/apimachinery/pkg/runtime"
)

func TestCompatibility(t *testing.T) {
scheme := runtime.NewScheme()
_ = AddToScheme(scheme)
_ = mocov1beta2.AddToScheme(scheme)

f := roundtrip.CompatibilityTestFuzzer(scheme, nil)
f.NilChance(0.5).NumElements(0, 3)

t.Run("MySQLCluster v1beta1 => v1beta2 => v1beta1", func(t *testing.T) {
for i := 0; i < 10000; i++ {
var oldCluster1, oldCluster2 MySQLCluster
var cluster mocov1beta2.MySQLCluster
f.Fuzz(&oldCluster1)

var tmp1, tmp2 mocov1beta2.MySQLCluster

if err := scheme.Convert(oldCluster1.DeepCopy(), &tmp1, nil); err != nil {
t.Fatal(err)
}
if err := scheme.Convert(&tmp1, &cluster, nil); err != nil {
t.Fatal(err)
}
if err := scheme.Convert(&cluster, &tmp2, nil); err != nil {
t.Fatal(err)
}
if err := scheme.Convert(&tmp2, &oldCluster2, nil); err != nil {
t.Fatal(err)
}

if diff := cmp.Diff(oldCluster1, oldCluster2, cmpopts.EquateEmpty()); diff != "" {
t.Fatalf("compatibility error case #%d (-want +got):\n%s", i, diff)
}
}
})

t.Run("BackupPolicy v1beta1 => v1beta2 => v1beta1", func(t *testing.T) {
for i := 0; i < 10000; i++ {
var oldPolicy1, oldPolicy2 BackupPolicy
var policy mocov1beta2.BackupPolicy
f.Fuzz(&oldPolicy1)

var tmp1, tmp2 mocov1beta2.BackupPolicy

if err := scheme.Convert(oldPolicy1.DeepCopy(), &tmp1, nil); err != nil {
t.Fatal(err)
}
if err := scheme.Convert(&tmp1, &policy, nil); err != nil {
t.Fatal(err)
}
if err := scheme.Convert(&policy, &tmp2, nil); err != nil {
t.Fatal(err)
}
if err := scheme.Convert(&tmp2, &oldPolicy2, nil); err != nil {
t.Fatal(err)
}

if diff := cmp.Diff(oldPolicy1, oldPolicy2, cmpopts.EquateEmpty()); diff != "" {
t.Fatalf("compatibility error case #%d (-want +got):\n%s", i, diff)
}
}
})
}
3 changes: 3 additions & 0 deletions api/v1beta1/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// Package v1beta1 contains the v1beta1 API implementation.
// +k8s:conversion-gen=github.com/cybozu-go/moco/api/v1beta2
package v1beta1
3 changes: 3 additions & 0 deletions api/v1beta1/groupversion_info.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,7 @@ var (

// AddToScheme adds the types in this group-version to the given scheme.
AddToScheme = SchemeBuilder.AddToScheme

// localSchemeBuilder will be used in the code generated by conversion-gen.
localSchemeBuilder = &SchemeBuilder.SchemeBuilder
)
Loading