Skip to content

Commit 99a1745

Browse files
authored
setting up for providers on the CR (#30)
* setting up for providers on the CR * setting up for providers on the CR * secret validation * secret validation
1 parent 4148243 commit 99a1745

File tree

8 files changed

+151
-11
lines changed

8 files changed

+151
-11
lines changed

README.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@
77

88
The open-feature-operator is a Kubernetes native operator that allows you to expose feature flags to your applications. It injects a [flagd](https://github.com/open-feature/flagd) sidecar into your pod and allows you to poll the flagd server for feature flags in a variety of ways.
99

10+
### Deploy the latest release
11+
12+
`kubectl apply -f https://github.com/open-feature/open-feature-operator/releases/download/v0.0.1/release.yaml`
13+
1014
### Architecture
1115

1216
As per the issue [here](https://github.com/open-feature/research/issues/1)
@@ -69,5 +73,5 @@ root@nginx:/# curl localhost:8080
6973

7074
#### Run the example
7175

72-
1. `kubectl apply -f config/samples/config_v1alpha1_featureflagconfiguration.yaml`
76+
1. `kubectl apply -f config/samples/crds/featureflagconfiguration.yaml`
7377
1. `kubectl apply -f config/samples/pod.yaml`

apis/core/v1alpha1/featureflagconfiguration_types.go

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,18 @@ import (
2929
type FeatureFlagConfigurationSpec struct {
3030
// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
3131
// Important: Run "make" to regenerate code after modifying this file
32-
33-
// Foo is an example field of FeatureFlagConfiguration. Edit featureflagconfiguration_types.go to remove/update
32+
// +optional
33+
Provider *FeatureFlagProvider `json:"provider"`
34+
// FeatureFlagSpec is the json representation of the feature flag
3435
FeatureFlagSpec string `json:"featureFlagSpec,omitempty"`
3536
}
3637

38+
type FeatureFlagProvider struct {
39+
// +kubebuilder:validation:Enum=flagD
40+
Name string `json:"name"`
41+
Credentials corev1.ObjectReference `json:"credentials"`
42+
}
43+
3744
// FeatureFlagConfigurationStatus defines the observed state of FeatureFlagConfiguration
3845
type FeatureFlagConfigurationStatus struct {
3946
// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
@@ -86,7 +93,7 @@ func GenerateFfConfigMap(name string, namespace string, references []metav1.Owne
8693
OwnerReferences: references,
8794
},
8895
Data: map[string]string{
89-
"config.yaml": spec.FeatureFlagSpec,
96+
"config.json": spec.FeatureFlagSpec,
9097
},
9198
}
9299
}

apis/core/v1alpha1/zz_generated.deepcopy.go

Lines changed: 23 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

config/crd/bases/core.openfeature.dev_featureflagconfigurations.yaml

Lines changed: 74 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,81 @@ spec:
3838
FeatureFlagConfiguration
3939
properties:
4040
featureFlagSpec:
41-
description: Foo is an example field of FeatureFlagConfiguration.
42-
Edit featureflagconfiguration_types.go to remove/update
41+
description: FeatureFlagSpec is the json representation of the feature
42+
flag
4343
type: string
44+
provider:
45+
description: 'INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
46+
Important: Run "make" to regenerate code after modifying this file'
47+
properties:
48+
credentials:
49+
description: 'ObjectReference contains enough information to let
50+
you inspect or modify the referred object. --- New uses of this
51+
type are discouraged because of difficulty describing its usage
52+
when embedded in APIs. 1. Ignored fields. It includes many
53+
fields which are not generally honored. For instance, ResourceVersion
54+
and FieldPath are both very rarely valid in actual usage. 2.
55+
Invalid usage help. It is impossible to add specific help for
56+
individual usage. In most embedded usages, there are particular
57+
restrictions like, "must refer only to types A and B" or "UID
58+
not honored" or "name must be restricted". Those cannot be well
59+
described when embedded. 3. Inconsistent validation. Because
60+
the usages are different, the validation rules are different
61+
by usage, which makes it hard for users to predict what will
62+
happen. 4. The fields are both imprecise and overly precise. Kind
63+
is not a precise mapping to a URL. This can produce ambiguity
64+
during interpretation and require a REST mapping. In most cases,
65+
the dependency is on the group,resource tuple and the version
66+
of the actual struct is irrelevant. 5. We cannot easily change
67+
it. Because this type is embedded in many locations, updates
68+
to this type will affect numerous schemas. Don''t make new
69+
APIs embed an underspecified API type they do not control. Instead
70+
of using this type, create a locally provided and used type
71+
that is well-focused on your reference. For example, ServiceReferences
72+
for admission registration: https://github.com/kubernetes/api/blob/release-1.17/admissionregistration/v1/types.go#L533
73+
.'
74+
properties:
75+
apiVersion:
76+
description: API version of the referent.
77+
type: string
78+
fieldPath:
79+
description: 'If referring to a piece of an object instead
80+
of an entire object, this string should contain a valid
81+
JSON/Go field access statement, such as desiredState.manifest.containers[2].
82+
For example, if the object reference is to a container within
83+
a pod, this would take on a value like: "spec.containers{name}"
84+
(where "name" refers to the name of the container that triggered
85+
the event) or if no container name is specified "spec.containers[2]"
86+
(container with index 2 in this pod). This syntax is chosen
87+
only to have some well-defined way of referencing a part
88+
of an object. TODO: this design is not final and this field
89+
is subject to change in the future.'
90+
type: string
91+
kind:
92+
description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
93+
type: string
94+
name:
95+
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names'
96+
type: string
97+
namespace:
98+
description: 'Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/'
99+
type: string
100+
resourceVersion:
101+
description: 'Specific resourceVersion to which this reference
102+
is made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency'
103+
type: string
104+
uid:
105+
description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids'
106+
type: string
107+
type: object
108+
name:
109+
enum:
110+
- flagD
111+
type: string
112+
required:
113+
- credentials
114+
- name
115+
type: object
44116
type: object
45117
status:
46118
description: FeatureFlagConfigurationStatus defines the observed state
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
apiVersion: core.openfeature.dev/v1alpha1
2+
kind: FeatureFlagConfiguration
3+
metadata:
4+
name: featureflagconfiguration-sample
5+
spec:
6+
provider:
7+
name: "flagD"
8+
credentials:
9+
name: "sample-provider-secret"
10+
namespace: "default"
11+
featureFlagSpec: |
12+
{}

config/samples/config_v1alpha1_featureflagconfiguration.yaml renamed to config/samples/crds/featureflagconfiguration.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@ metadata:
44
name: featureflagconfiguration-sample
55
spec:
66
featureFlagSpec: |
7-
{}
7+
{}

controllers/featureflagconfiguration_controller.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,18 @@ func (r *FeatureFlagConfigurationReconciler) Reconcile(ctx context.Context, req
104104
return r.finishReconcile(nil, false)
105105
}
106106

107+
// Check the provider on the FeatureFlagConfiguration
108+
if ffconf.Spec.Provider == nil {
109+
r.Log.Info("No provider specified for FeatureFlagConfiguration, using FlagD")
110+
ffconf.Spec.Provider = &corev1alpha1.FeatureFlagProvider{
111+
Name: "flagD",
112+
}
113+
if err := r.Update(ctx, ffconf); err != nil {
114+
r.Log.Error(err, "Failed to update FeatureFlagConfiguration Provider")
115+
return r.finishReconcile(err, false)
116+
}
117+
}
118+
107119
// Get list of configmaps
108120
configMapList := &corev1.ConfigMapList{}
109121
var ffConfigMapList []corev1.ConfigMap

webhooks/featureflagconfiguration_webhook.go

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,17 @@ package webhooks
33
import (
44
"context"
55
"encoding/json"
6-
"errors"
76
"fmt"
87
"net/http"
98
"strings"
109

10+
"k8s.io/apimachinery/pkg/api/errors"
11+
1112
"github.com/go-logr/logr"
1213
corev1alpha1 "github.com/open-feature/open-feature-operator/apis/core/v1alpha1"
1314
"github.com/open-feature/open-feature-operator/pkg/utils"
1415
"github.com/xeipuuv/gojsonschema"
16+
corev1 "k8s.io/api/core/v1"
1517
"sigs.k8s.io/controller-runtime/pkg/client"
1618
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
1719
)
@@ -45,6 +47,16 @@ func (m *FeatureFlagConfigurationValidator) Handle(ctx context.Context, req admi
4547
return admission.Denied(fmt.Sprintf("FeatureFlagSpec is not valid JSON: %s", err.Error()))
4648
}
4749
}
50+
51+
if config.Spec.Provider.Credentials.Name != "" {
52+
// Check the provider and whether it has an existing secret
53+
providerKeySecret := corev1.Secret{}
54+
if err := m.Client.Get(ctx, client.ObjectKey{Name: config.Spec.Provider.Credentials.Name,
55+
Namespace: config.Spec.Provider.Credentials.Namespace}, &providerKeySecret); errors.IsNotFound(err) {
56+
return admission.Denied("credentials secret not found")
57+
}
58+
}
59+
4860
return admission.Allowed("")
4961
}
5062

@@ -76,7 +88,7 @@ func (m *FeatureFlagConfigurationValidator) validateJSONSchema(schemaJSON string
7688
for _, desc := range result.Errors() {
7789
sb.WriteString(fmt.Sprintf("- %s\n", desc))
7890
}
79-
return errors.New(sb.String())
91+
return errors.NewBadRequest(sb.String())
8092
}
8193
return nil
8294
}

0 commit comments

Comments
 (0)