Skip to content

Commit

Permalink
Rename OperatorVersion CRs from name-<operatorVersion> to `name-<ap…
Browse files Browse the repository at this point in the history
…pVersion>-<operatorVersion>` (#1684)

* Changed the generated name for OperatorVersion CRDs
* NO automatic migration - but the OperatTaskDependency Lookup now iterates over the OVs to find a match
* Created a bit more framework for future migrations

Co-authored-by: Aleksey Dukhovniy <alex.dukhovniy@googlemail.com>
Signed-off-by: Andreas Neumann <aneumann@mesosphere.com>
  • Loading branch information
ANeumann82 and zen-dog committed Oct 9, 2020
1 parent 7eefce1 commit 5e7546b
Show file tree
Hide file tree
Showing 36 changed files with 491 additions and 111 deletions.
1 change: 1 addition & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,7 @@ github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/u
github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68=
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jstemmer/go-junit-report v0.9.1 h1:6QPYqodiu3GuPL+7mfx+NwDdp2eTkp9IfEUpgAwUN0o=
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a h1:FaWFmfWdAUKbSCtOU2QjDaorUexogfaMgbipgYATUMU=
github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a/go.mod h1:UJSiEoRfvx3hP73CvoARgeLjaIOjybY9vj8PUPPFGeU=
Expand Down
2 changes: 1 addition & 1 deletion hack/run-operator-tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ docker build . \
-t "kudobuilder/controller:$KUDO_VERSION"

rm -rf operators
git clone https://github.com/kudobuilder/operators
git clone --branch "an/rename-operatorversions" https://github.com/kudobuilder/operators
mkdir operators/bin/
cp ./bin/kubectl-kudo operators/bin/
sed "s/%version%/$KUDO_VERSION/" operators/kudo-test.yaml.tmpl > operators/kudo-test.yaml
Expand Down
43 changes: 40 additions & 3 deletions pkg/apis/kudo/v1beta1/operatorversion_types_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,37 @@ import (

"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/client"

"github.com/kudobuilder/kudo/pkg/util/kudo"
)

func OperatorInstanceName(operatorName string) string {
return fmt.Sprintf("%s-instance", operatorName)
}

func OperatorVersionName(operatorName, version string) string {
return fmt.Sprintf("%s-%s", operatorName, version)
func OperatorVersionName(operatorName, appVersion, opVersion string) string {
if appVersion == "" {
return fmt.Sprintf("%s-%s", operatorName, opVersion)
}
return fmt.Sprintf("%s-%s-%s", operatorName, appVersion, opVersion)
}

func (ov *OperatorVersion) FullyQualifiedName() string {
return fmt.Sprintf("%s-%s", ov.Name, ov.Spec.AppVersion)
return OperatorVersionName(ov.Spec.Operator.Name, ov.Spec.AppVersion, ov.Spec.Version)
}

func (ov *OperatorVersion) EqualOperatorVersion(other *OperatorVersion) bool {
return ov.FullyQualifiedName() == other.FullyQualifiedName()
}

func ListOperatorVersions(ns string, c client.Reader) (l *OperatorVersionList, err error) {
l = &OperatorVersionList{}
if err := c.List(context.TODO(), l, client.InNamespace(ns)); err != nil {
return nil, err
}
return l, nil
}

func GetOperatorVersionByName(name, ns string, c client.Reader) (ov *OperatorVersion, err error) {
ov = &OperatorVersion{}
err = c.Get(context.TODO(), types.NamespacedName{Name: name, Namespace: ns}, ov)
Expand All @@ -32,3 +45,27 @@ func GetOperatorVersionByName(name, ns string, c client.Reader) (ov *OperatorVer
}
return ov, nil
}

// Sortable Operator implements functionality to correctly sort OVs by name, appVersion and operatorVersion
var _ kudo.SortableOperator = &OperatorVersion{}

func (ov *OperatorVersion) OperatorName() string {
return ov.Spec.Operator.Name
}

func (ov *OperatorVersion) OperatorVersion() string {
return ov.Spec.Version
}

func (ov *OperatorVersion) AppVersion() string {
return ov.Spec.AppVersion
}

func ToSortableOperatorList(ovList []OperatorVersion) kudo.SortableOperatorList {
l := kudo.SortableOperatorList{}
for _, ov := range ovList {
ov := ov
l = append(l, &ov)
}
return l
}
2 changes: 1 addition & 1 deletion pkg/controller/instance/resolver_incluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ type InClusterResolver struct {
}

func (r InClusterResolver) Resolve(name string, appVersion string, operatorVersion string) (*packages.Package, error) {
ovn := kudoapi.OperatorVersionName(name, operatorVersion)
ovn := kudoapi.OperatorVersionName(name, appVersion, operatorVersion)

ov, err := kudoapi.GetOperatorVersionByName(ovn, r.ns, r.c)
if err != nil {
Expand Down
3 changes: 2 additions & 1 deletion pkg/engine/task/task_kudo_operator.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ func (kt KudoOperatorTask) Run(ctx Context) (bool, error) {
namespace := ctx.Meta.InstanceNamespace
operatorName := kt.OperatorName
operatorVersion := kt.OperatorVersion
operatorVersionName := kudoapi.OperatorVersionName(operatorName, operatorVersion)
appVersion := kt.AppVersion
operatorVersionName := kudoapi.OperatorVersionName(operatorName, appVersion, operatorVersion)
instanceName := dependencyInstanceName(ctx.Meta.InstanceName, kt.InstanceName, operatorName)

// 1. - Expand parameter file if exists -
Expand Down
1 change: 1 addition & 0 deletions pkg/kudoctl/cmd/verify/verify.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ func (VersionVerifier) Verify(pf *packages.Files) verifier.Result {
return res
}
verifySemVer(pf.Operator.OperatorVersion, "operatorVersion", &res, true)
verifySemVer(pf.Operator.AppVersion, "appVersion", &res, false)
verifySemVer(pf.Operator.KubernetesVersion, "kubernetesVersion", &res, true)
verifySemVer(pf.Operator.KUDOVersion, "kudoVersion", &res, false)
return res
Expand Down
7 changes: 7 additions & 0 deletions pkg/kudoctl/kube/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"k8s.io/client-go/tools/clientcmd"
"sigs.k8s.io/controller-runtime/pkg/client"

"github.com/kudobuilder/kudo/pkg/client/clientset/versioned"
"github.com/kudobuilder/kudo/pkg/kudoctl/clog"
)

Expand All @@ -19,6 +20,7 @@ type Client struct {
ExtClient apiextensionsclient.Interface
DynamicClient dynamic.Interface
CtrlClient client.Client
KudoClient versioned.Interface
}

// GetConfig returns a Kubernetes client config for a given kubeconfig.
Expand Down Expand Up @@ -70,11 +72,16 @@ func GetKubeClientForConfig(config *rest.Config) (*Client, error) {
if err != nil {
return nil, fmt.Errorf("could not create Controller Runtime client: %s", err)
}
kudoClient, err := versioned.NewForConfig(config)
if err != nil {
return nil, fmt.Errorf("could not create KUDO client: %v", err)
}

return &Client{
KubeClient: kubeClient,
ExtClient: extClient,
DynamicClient: dynamicClient,
CtrlClient: ctrlClient,
KudoClient: kudoClient,
}, nil
}
12 changes: 8 additions & 4 deletions pkg/kudoctl/kudoinit/migration/migration.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
package migration

import "github.com/kudobuilder/kudo/pkg/kudoctl/kube"

// Migrater is the base interface for migrations.
type Migrater interface {
CanMigrate(client *kube.Client) error
Migrate(client *kube.Client) error
// CanMigrate checks if there are any conditions that would prevent this migration to run
// This function should only return an error if it is sure that the migration can not be executed
CanMigrate() error

// Migrate executes the migration. The call must be idempotent and ignore already migrated resources
// It can be called multiple times on the same cluster and encounter migrated and unmigrated resources.
Migrate() error
}
56 changes: 56 additions & 0 deletions pkg/kudoctl/kudoinit/migration/migration_helper.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// This package contains helper functions that can be reused by all migrations
package migration

import (
"context"
"fmt"

v1 "k8s.io/apimachinery/pkg/apis/meta/v1"

kudoapi "github.com/kudobuilder/kudo/pkg/apis/kudo/v1beta1"
"github.com/kudobuilder/kudo/pkg/kudoctl/kube"
)

// ForEachNamespace calls the given function for all namespaces in the cluster
func ForEachNamespace(client *kube.Client, f func(ns string) error) error {
l, err := client.KubeClient.CoreV1().Namespaces().List(context.TODO(), v1.ListOptions{})
if err != nil {
return fmt.Errorf("failed to fetch namespaces: %v", err)
}
for _, ns := range l.Items {
if err := f(ns.Name); err != nil {
return fmt.Errorf("failed to run function for namespace %q: %v", ns.Name, err)
}
}
return nil
}

// ForEachOperatorVersion calls the given function for all operatorversions in the given namespace
func ForEachOperatorVersion(client *kube.Client, ns string, f func(ov *kudoapi.OperatorVersion) error) error {
l, err := client.KudoClient.KudoV1beta1().OperatorVersions(ns).List(context.TODO(), v1.ListOptions{})
if err != nil {
return fmt.Errorf("failed to fetch OperatorVersions from namespace %q: %v", ns, err)
}
for _, ov := range l.Items {
ov := ov
if err := f(&ov); err != nil {
return fmt.Errorf("failed to run function for OperatorVersion \"%s/%s\": %v", ov.Namespace, ov.Name, err)
}
}
return nil
}

// ForEachInstance calls the given function for all instances in the given namespace
func ForEachInstance(client *kube.Client, ns string, f func(ov *kudoapi.Instance) error) error {
l, err := client.KudoClient.KudoV1beta1().Instances(ns).List(context.TODO(), v1.ListOptions{})
if err != nil {
return fmt.Errorf("failed to fetch Instances from namespace %q: %v", ns, err)
}
for _, i := range l.Items {
i := i
if err := f(&i); err != nil {
return fmt.Errorf("failed to run function for Instance \"%s/%s\": %v", i.Namespace, i.Name, err)
}
}
return nil
}
20 changes: 10 additions & 10 deletions pkg/kudoctl/kudoinit/setup/setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,9 @@ func (i *Installer) VerifyInstallation(client *kube.Client, result *verifier.Res
return nil
}

func requiredMigrations() []migration.Migrater {

func requiredMigrations(client *kube.Client, dryRun bool) []migration.Migrater {
// Determine which migrations to run
return []migration.Migrater{
// Implement actual migrations
}
return []migration.Migrater{}
}

func (i *Installer) PreUpgradeVerify(client *kube.Client, result *verifier.Result) error {
Expand All @@ -88,13 +85,16 @@ func (i *Installer) PreUpgradeVerify(client *kube.Client, result *verifier.Resul
return nil
}

// Step 2 - Verify that any migration is possible
migrations := requiredMigrations()
// Step 2 - Verify that all migrations can run (with dryRun)
migrations := requiredMigrations(client, true)
clog.V(1).Printf("Verify that %d required migrations can be applied", len(migrations))
for _, m := range migrations {
if err := m.CanMigrate(client); err != nil {
if err := m.CanMigrate(); err != nil {
result.AddErrors(fmt.Errorf("migration %s failed install check: %v", m, err).Error())
}
if err := m.Migrate(); err != nil {
result.AddErrors(fmt.Errorf("migration %s failed dry-run: %v", m, err).Error())
}
}

// TODO: Verify existing operators and instances?
Expand All @@ -117,10 +117,10 @@ func (i *Installer) Upgrade(client *kube.Client) error {
}

// Step 5 - Execute Migrations
migrations := requiredMigrations()
migrations := requiredMigrations(client, false)
clog.Printf("Run %d migrations", len(migrations))
for _, m := range migrations {
if err := m.Migrate(client); err != nil {
if err := m.Migrate(); err != nil {
return fmt.Errorf("migration %s failed to execute: %v", m, err)
}
}
Expand Down
8 changes: 4 additions & 4 deletions pkg/kudoctl/packages/convert/resources.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ func FilesToResources(files *packages.Files) (*packages.Resources, error) {
APIVersion: packages.APIVersion,
},
ObjectMeta: metav1.ObjectMeta{
Name: kudoapi.OperatorVersionName(files.Operator.Name, files.Operator.OperatorVersion),
Name: kudoapi.OperatorVersionName(files.Operator.Name, files.Operator.AppVersion, files.Operator.OperatorVersion),
},
Spec: kudoapi.OperatorVersionSpec{
Operator: corev1.ObjectReference{
Expand All @@ -78,7 +78,7 @@ func FilesToResources(files *packages.Files) (*packages.Resources, error) {
Status: kudoapi.OperatorVersionStatus{},
}

instance := BuildInstanceResource(files.Operator.Name, files.Operator.OperatorVersion)
instance := BuildInstanceResource(files.Operator.Name, files.Operator.AppVersion, files.Operator.OperatorVersion)

return &packages.Resources{
Operator: operator,
Expand All @@ -87,7 +87,7 @@ func FilesToResources(files *packages.Files) (*packages.Resources, error) {
}, nil
}

func BuildInstanceResource(operatorName, operatorVersion string) *kudoapi.Instance {
func BuildInstanceResource(operatorName, appVersion, operatorVersion string) *kudoapi.Instance {
return &kudoapi.Instance{
TypeMeta: metav1.TypeMeta{
Kind: "Instance",
Expand All @@ -99,7 +99,7 @@ func BuildInstanceResource(operatorName, operatorVersion string) *kudoapi.Instan
},
Spec: kudoapi.InstanceSpec{
OperatorVersion: corev1.ObjectReference{
Name: kudoapi.OperatorVersionName(operatorName, operatorVersion),
Name: kudoapi.OperatorVersionName(operatorName, appVersion, operatorVersion),
},
},
Status: kudoapi.InstanceStatus{},
Expand Down
Loading

0 comments on commit 5e7546b

Please sign in to comment.