Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: auto-upgrade flagd-proxy with OFO upgrades #596

Merged
merged 9 commits into from
Jan 24, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
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
8 changes: 8 additions & 0 deletions chart/open-feature-operator/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,14 @@ helm repo update
helm upgrade --install open-feature-operator openfeature/open-feature-operator
```

**Note:**
odubajDT marked this conversation as resolved.
Show resolved Hide resolved
If you have used `flagd-proxy` provider and upgrading to OFO version `v0.5.4` or higher,
`flagd-proxy` will be automatically upgraded to the lastest supported version by the `open-feature-operator`.
odubajDT marked this conversation as resolved.
Show resolved Hide resolved
This upgrade will also consider your current `FeatureFlagSource` configuration and adapt
the `flagd-proxy` Deployment accordingly.
odubajDT marked this conversation as resolved.
Show resolved Hide resolved

If you are upgrading OFO to `v0.5.3` or lower, `flagd-proxy` (if present) won't be upgraded automatically.

#### Upgrade CRDs

CRDs are not upgraded automatically with helm (https://helm.sh/docs/chart_best_practices/custom_resource_definitions/).
Expand Down
64 changes: 46 additions & 18 deletions common/flagdproxy/flagdproxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package flagdproxy
import (
"context"
"fmt"
"reflect"

"github.com/go-logr/logr"
"github.com/open-feature/open-feature-operator/common/types"
Expand All @@ -28,6 +29,7 @@ type FlagdProxyHandler struct {
Log logr.Logger
}

type CreateUpdateFunc func(ctx context.Context, obj client.Object) error
odubajDT marked this conversation as resolved.
Show resolved Hide resolved
type FlagdProxyConfiguration struct {
Port int
ManagementPort int
Expand Down Expand Up @@ -62,32 +64,44 @@ func (f *FlagdProxyHandler) Config() *FlagdProxyConfiguration {
return f.config
}

func (f *FlagdProxyHandler) CreateObject(ctx context.Context, obj client.Object) error {
return f.Client.Create(ctx, obj)
}

func (f *FlagdProxyHandler) UpdateObject(ctx context.Context, obj client.Object) error {
return f.Client.Update(ctx, obj)
}
odubajDT marked this conversation as resolved.
Show resolved Hide resolved

func (f *FlagdProxyHandler) HandleFlagdProxy(ctx context.Context) error {
Kavindu-Dodan marked this conversation as resolved.
Show resolved Hide resolved
exists, err := f.doesFlagdProxyExist(ctx)
exists, deployment, err := f.doesFlagdProxyExist(ctx)
if err != nil {
return err
}

ownerReferences := f.getOwnerReferences(ctx)
newDeployment := f.newFlagdProxyManifest(ownerReferences)
newService := f.newFlagdProxyServiceManifest(ownerReferences)

if !exists {
return f.deployFlagdProxy(ctx)
f.Log.Info("flagd-proxy Deployment does not exist, creating")
return f.deployFlagdProxy(ctx, f.CreateObject, newDeployment, newService)
}
// flagd-proxy exists, need to check if it's the right version
if !f.isFlagdProxyUpToDate(deployment, newDeployment) {
f.Log.Info("flagd-proxy Deployment changed, updating")
return f.deployFlagdProxy(ctx, f.UpdateObject, newDeployment, newService)
}
f.Log.Info("flagd-proxy Deployment up-to-date")
return nil
}

func (f *FlagdProxyHandler) deployFlagdProxy(ctx context.Context) error {
ownerReferences := []metav1.OwnerReference{}
ownerReference, err := f.getOwnerReference(ctx)
if err != nil {
f.Log.Error(err, "unable to create owner reference for open-feature-operator, not appending")
} else {
ownerReferences = append(ownerReferences, ownerReference)
}

func (f *FlagdProxyHandler) deployFlagdProxy(ctx context.Context, ff CreateUpdateFunc, deployment *appsV1.Deployment, service *corev1.Service) error {
f.Log.Info("deploying the flagd-proxy")
if err := f.Client.Create(ctx, f.newFlagdProxyManifest(ownerReferences)); err != nil && !errors.IsAlreadyExists(err) {
if err := ff(ctx, deployment); err != nil && !errors.IsAlreadyExists(err) {
odubajDT marked this conversation as resolved.
Show resolved Hide resolved
return err
}
f.Log.Info("deploying the flagd-proxy service")
if err := f.Client.Create(ctx, f.newFlagdProxyServiceManifest(ownerReferences)); err != nil && !errors.IsAlreadyExists(err) {
if err := ff(ctx, service); err != nil && !errors.IsAlreadyExists(err) {
return err
}
return nil
Expand Down Expand Up @@ -178,19 +192,22 @@ func (f *FlagdProxyHandler) newFlagdProxyManifest(ownerReferences []metav1.Owner
}
}

func (f *FlagdProxyHandler) doesFlagdProxyExist(ctx context.Context) (bool, error) {
func (f *FlagdProxyHandler) doesFlagdProxyExist(ctx context.Context) (bool, *appsV1.Deployment, error) {
d := &appsV1.Deployment{}
err := f.Client.Get(ctx, client.ObjectKey{Name: FlagdProxyDeploymentName, Namespace: f.config.Namespace}, d)
if err != nil {
if errors.IsNotFound(err) {
// does not exist, is not ready, no error
return false, nil
return false, nil, nil
}
// does not exist, is not ready, is in error
return false, err
return false, nil, err
}
// exists, at least one replica ready, no error
return true, nil
return true, d, nil
}

func (f *FlagdProxyHandler) isFlagdProxyUpToDate(old, new *appsV1.Deployment) bool {
return reflect.DeepEqual(old.Spec, new.Spec)
thisthat marked this conversation as resolved.
Show resolved Hide resolved
}

func (f *FlagdProxyHandler) getOwnerReference(ctx context.Context) (metav1.OwnerReference, error) {
Expand All @@ -206,3 +223,14 @@ func (f *FlagdProxyHandler) getOwnerReference(ctx context.Context) (metav1.Owner
}, nil

}

func (f *FlagdProxyHandler) getOwnerReferences(ctx context.Context) []metav1.OwnerReference {
odubajDT marked this conversation as resolved.
Show resolved Hide resolved
ownerReferences := []metav1.OwnerReference{}
ownerReference, err := f.getOwnerReference(ctx)
if err != nil {
f.Log.Error(err, "unable to create owner reference for open-feature-operator, not appending")
} else {
ownerReferences = append(ownerReferences, ownerReference)
}
return ownerReferences
}
46 changes: 42 additions & 4 deletions common/flagdproxy/flagdproxy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,19 +104,21 @@ func TestDoesFlagdProxyExist(t *testing.T) {

require.NotNil(t, ph)

res, err := ph.doesFlagdProxyExist(context.TODO())
res, d, err := ph.doesFlagdProxyExist(context.TODO())
require.Nil(t, err)
require.Nil(t, d)
require.False(t, res)

err = fakeClient.Create(context.TODO(), deployment)
require.Nil(t, err)

res, err = ph.doesFlagdProxyExist(context.TODO())
res, d, err = ph.doesFlagdProxyExist(context.TODO())
require.Nil(t, err)
require.NotNil(t, d)
require.True(t, res)
}

func TestFlagdProxyHandler_HandleFlagdProxy_ProxyExists(t *testing.T) {
func TestFlagdProxyHandler_HandleFlagdProxy_ProxyExistsWithBadVersion(t *testing.T) {
env := types.EnvConfig{
PodNamespace: "ns",
}
Expand Down Expand Up @@ -159,8 +161,44 @@ func TestFlagdProxyHandler_HandleFlagdProxy_ProxyExists(t *testing.T) {
require.Nil(t, err)
require.NotNil(t, deployment)

// verify that the existing deployment has been changed
require.Equal(t, "flagd-proxy", deployment.Spec.Template.Spec.Containers[0].Name)
}

func TestFlagdProxyHandler_HandleFlagdProxy_ProxyExistsWithNewestVersion(t *testing.T) {
env := types.EnvConfig{
PodNamespace: "ns",
}
kpConfig := NewFlagdProxyConfiguration(env)

require.NotNil(t, kpConfig)

fakeClient := fake.NewClientBuilder().WithObjects().Build()

ph := NewFlagdProxyHandler(kpConfig, fakeClient, testr.New(t))

require.NotNil(t, ph)

proxy := ph.newFlagdProxyManifest([]metav1.OwnerReference{})

err := fakeClient.Create(context.TODO(), proxy)
require.Nil(t, err)

err = ph.HandleFlagdProxy(context.Background())

require.Nil(t, err)

deployment := &v1.Deployment{}
err = fakeClient.Get(context.Background(), client.ObjectKey{
Namespace: env.PodNamespace,
Name: FlagdProxyDeploymentName,
}, deployment)

require.Nil(t, err)
require.NotNil(t, deployment)

// verify that the existing deployment has not been changed
require.Equal(t, "my-container", deployment.Spec.Template.Spec.Containers[0].Name)
require.Equal(t, "flagd-proxy", deployment.Spec.Template.Spec.Containers[0].Name)
}

func TestFlagdProxyHandler_HandleFlagdProxy_CreateProxy(t *testing.T) {
Expand Down
8 changes: 8 additions & 0 deletions docs/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,14 @@ helm upgrade --install openfeature openfeature/open-feature-operator
helm upgrade --install openfeature openfeature/open-feature-operator
```

**Note:**
odubajDT marked this conversation as resolved.
Show resolved Hide resolved
If you have used `flagd-proxy` provider and upgrading to OFO version `v0.5.4` or higher,
`flagd-proxy` will be automatically upgraded to the lastest supported version by the `open-feature-operator`.
odubajDT marked this conversation as resolved.
Show resolved Hide resolved
This upgrade will also consider your current `FeatureFlagSource` configuration and adapt
the `flagd-proxy` Deployment accordingly.

If you are upgrading OFO to `v0.5.3` or lower, `flagd-proxy` (if present) won't be upgraded automatically.

#### Upgrading CRDs

CRDs are not upgraded automatically with helm (https://helm.sh/docs/chart_best_practices/custom_resource_definitions/).
Expand Down
9 changes: 7 additions & 2 deletions docs/v1beta_migration.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,5 +76,10 @@ We recommend following migration steps,
3. Install upgraded custom resources
4. Update annotation of your workloads to the latest supported version

If you have used `flagd-proxy` provider, then you have to upgrade the image used by the `flagd-proxy` deployment.
For this, please edit the deployment of `flagd-proxy` to version [v0.3.1](https://github.com/open-feature/flagd/pkgs/container/flagd-proxy/152333134?tag=v0.3.1) or above.
If you have used `flagd-proxy` provider, then you have to upgrade the image used by the `flagd-proxy` deployment.
For this, please edit the deployment of `flagd-proxy` to version [v0.3.1](https://github.com/open-feature/flagd/pkgs/container/flagd-proxy/152333134?tag=v0.3.1) or above.

**Note:**
odubajDT marked this conversation as resolved.
Show resolved Hide resolved
Since OFO version `v0.5.4`, `flagd-proxy` pod (if present) will be upgraded automatically to the
to the latest supported version by `open-feature-operator`.
For more information see the [upgrade section](./installation.md#upgrading).
Loading