-
Notifications
You must be signed in to change notification settings - Fork 475
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
Add multiple namespaces in the operator #673
Add multiple namespaces in the operator #673
Conversation
b2b02ac
to
090ab11
Compare
Adding support for multiple namespaces in the operator as per: openfaas#616 Signed-off-by: Martin Dekov <[email protected]>
090ab11
to
b2600e2
Compare
@martindekov i just went through a manual test of the operator and i think i found a bug with secrets Install this branch $ kind create cluster
$ kubectl create namespace extras
$ kubectl create namespace openfaas
$ kubectl create namespace openfaas-fn
$ cd chart
$ helm upgrade --install openfaas ./openfaas --namespace openfaas --values ./openfaas/values.yaml --set operator.create=true --set openfaasImagePullPolicy=Always --set operator.image=martindekov/faas-netes:asd-3 --set clusterRole=true --set gateway.directFunctions=true --set faasnetes.imagePullPolicy=Always --set basic_auth=false Deploy a test function to the default namespace and to a new namespace $ cat << EOF > stack.yml
provider:
name: openfaas
gateway: http://127.0.0.1:8080
functions:
stronghash:
skip_build: true
image: functions/alpine:latest
fprocess: "sha512sum"
EOF
$ faas-cli deploy
$ faas-cli deploy --namespace=extras
$ kubectl -n extras get function
NAME AGE
stronghash 13s
$ kubectl -n extras get deploy stronghash
NAME READY UP-TO-DATE AVAILABLE AGE
stronghash 1/1 1 1 7s
$ faas-cli invoke stronghash --namespace=extras <<< "foo"
0cf9180a764aba863a67b6d72f0918bc131c6772642cb2dce5a34f0a702f9470ddc2bf125c12198b1995c233c34b4afd346c54a2334c350a948a51b6e8b4e6b6 Reset $ faas-cli remove
$ faas-cli remove --namespace=extras Test secrets namespace $ faas-cli secret create password --from-literal=secret_hash
Creating secret: password
Created: 202 Accepted
$ cat << EOF > stack.yml
provider:
name: openfaas
gateway: http://127.0.0.1:8080
functions:
stronghash:
skip_build: true
image: functions/alpine:latest
fprocess: "sha512sum"
secrets:
- password
EOF
$ faas-cli deploy
$ kubectl get function -n openfaas-fn
NAME AGE
stronghash 13s
$ kubectl -n openfaas-fn get deploy stronghash
NAME READY UP-TO-DATE AVAILABLE AGE
stronghash 1/1 1 1 7s
$ faas-cli invoke stronghash <<< "foo"
0cf9180a764aba863a67b6d72f0918bc131c6772642cb2dce5a34f0a702f9470ddc2bf125c12198b1995c233c34b4afd346c54a2334c350a948a51b6e8b4e6b6
$ faas-cli secret create --namespace=extras password --from-literal=secret_hash
Creating secret: password
server returned unexpected status code: 400 - Unfortunately, the operator is not printing any logs after i send that request. I do see the request in the gateway logs though kubectl -n=openfaas logs deploy/gateway gateway -f
#...
2020/08/02 13:12:49 Forwarded [POST] to /system/secrets - [400] - 0.009358s seconds
2020/08/02 13:12:50 Forwarded [POST] to /system/secrets - [400] - 0.010448s seconds kubectl -n=openfaas logs deploy/gateway operator -f
#... I don't see any obvious change that would cause this. I am still debugging. |
Yeah Lucas you get that if secret already exists, or you are trying to access non existing/annotated namespace. In general believe we can return better or more verbose response. Did you remove all secrets before creating one? I couldn't replicate the error. It shows only if I am trying to deploy function in non annotated/existing namespace or if a secret already exists in the namespace. |
@martindekov the issue is that the secret does not exist yet in the |
Why? |
@alexellis Because of the error I included in my original test. My expectation is that faas-cli secret create --namespace=extras password --from-literal="super secret value" in my test should work. @martindekov indicated that the error is because the secret may already exist, but I verified that the namespace was completely empty and had no existing secret. |
That seems odd. Is there a secret in openfaas-fn with the same name? This should work, and only depends on the REST / HTTP implementation, rather than the CRD side of it. kubectl create ns extras
faas-cli secret create --namespace=extras password --from-literal="super secret value" |
Yes i had created the same secret in the default namespace already. I was testing that I can deploy copies of a function to different namespaces, e.g. dev, stg, prod |
return func(w http.ResponseWriter, r *http.Request) { | ||
res := handlers.ListNamespaces(defaultNamespace, clientset) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where did defer r.Body.Close()
go ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well this function is literally taken from handlers.MakeNamespacesLister
which does not have defer r.Body.Close()
.
On another note I could have just reuse handlers.MakeNamespacesLister
instead of copy pasting, but this followed how the other handlers are implemented for the operator logic and bigger refactoring should take place as per Lucas's comment from the previous review
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add it at the top, for belt-and-braces
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point, will add in both places
@LucasRoesler you did not annotate the extras namespace with |
@martindekov that makes sense. Unfortunately I can't test it right now. My laptop is unavailable for most of this week It seems like a good approach to limit via labels/annotations , but I don't recall where it is enforced. It can't be in the gateway because it is agnostic and doesn't really know about namespaces |
Yep, Lucas, thanks again for taking a look at this. Opened issue for the problem: #679 it is in both here and in |
@martindekov make sense, it otherwise seemed to work. I am going to re-test it today and give a final 👍 👎 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@martindekov i re-tested (with the correct annotations) and now everything is working as expected. I left one comment about an ignored error. Once we log that error, I will give a 👍
defer r.Body.Close() | ||
|
||
res, _ := json.Marshal([]string{defaultNamespace}) | ||
out, _ := json.Marshal(res) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please catch and at least log the error here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed, even if it's the same elsewhere
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I delayed the response here, I also agree
@@ -81,7 +103,7 @@ func makeReplicaHandler(namespace string, kube kubernetes.Interface) http.Handle | |||
} | |||
|
|||
opts := metav1.GetOptions{} | |||
dep, err := kube.AppsV1().Deployments(namespace).Get(context.TODO(), functionName, opts) | |||
dep, err := kube.AppsV1().Deployments(lookupNamespace).Get(context.TODO(), functionName, opts) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we should probably pass the r.Context()
here, but we should open a second PR for this kind of improvement
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will try work out those in #679
@LucasRoesler is there anything else outstanding as far as your'e concerned? Have you had another chance to test since recent changes were made? |
@@ -103,10 +103,15 @@ func main() { | |||
// auto-scaling is does via the HTTP API that acts on the deployment Spec.Replicas | |||
defaultResync := time.Minute * 5 | |||
|
|||
kubeInformerOpt := kubeinformers.WithNamespace(config.DefaultFunctionNamespace) | |||
namespaceScope := config.DefaultFunctionNamespace | |||
if operator && config.ClusterRole { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given that we have shared code now, would it make sense to have that namespaceScope set even when we're not using the operator?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did this as precaution for the feature, otherwise we can merge those, I would need to test the case before doing this though
@@ -49,6 +49,7 @@ func (ReadConfig) Read(hasEnv ftypes.HasEnv) (BootstrapConfig, error) { | |||
|
|||
cfg.DefaultFunctionNamespace = ftypes.ParseString(hasEnv.Getenv("function_namespace"), "default") | |||
cfg.ProfilesNamespace = ftypes.ParseString(hasEnv.Getenv("profiles_namespace"), cfg.DefaultFunctionNamespace) | |||
cfg.ClusterRole = ftypes.ParseBoolValue(hasEnv.Getenv("cluster_role"), false) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we want to think about this internal as "cluster role" or something else, like multiple_namespaces, single_namespace?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Internally would make sense to rename the variable for more friendly experience for the developer, on the other hand this code revolves around kubernetes so I believe developers should be aware of what ClusterRole is
@@ -22,7 +22,7 @@ func MakeNamespacesLister(defaultNamespace string, clientset kubernetes.Interfac | |||
return func(w http.ResponseWriter, r *http.Request) { | |||
log.Println("Query namespaces") | |||
|
|||
res := list(defaultNamespace, clientset) | |||
res := ListNamespaces(defaultNamespace, clientset) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did this go to being a public function (capital letter) so that it could be used elsewhere?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I use it in the makeNamespace
handler of the operator, though as per Lucas's feedback we don't really need exposing this, we can just reuse the namespace resolver from the faas-netes handlers and just delete pkg/server/namespace.go
package as faas-netes and operator resolve namespaces available to the framework the same way
@@ -1,89 +0,0 @@ | |||
package server |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where did this file go and why?
Does this cover both REST and the CRD? |
Per my review comment, #673 (review), I have re-teseted and just the one comment about the dropped error remains. Everything else looked reasonable or expected to me, given previous zoom discussions. |
Great. I am restarting the build. Perhaps one of us can tidy up the review comments after merging the change from Martin? |
This is part of the review from PR #673 and means that if any type fails to marshal to JSON, that we have a log line available. Signed-off-by: Alex Ellis (OpenFaaS Ltd) <[email protected]>
@martindekov please create a PR for the additional comments. |
This is part of the review from PR #673 and means that if any type fails to marshal to JSON, that we have a log line available. Signed-off-by: Alex Ellis (OpenFaaS Ltd) <[email protected]>
Refering feedback from the review openfaas#673 which adds multiple namespaces functionality which includes the following: * Extend operator readme to mention how to enable the feature * Remove mentioning that the operator does not support the feature * Replacing TODO context with the context from the request * Deferring the closing of the body of the namespaces handler * Merging the cluster role configuration so it is used in faas-netes * Reusing the logic of namespaces and secrets handling present in faas-netes in the operator. Removing the custom implementations as they are no longer used Signed-off-by: Martin Dekov <[email protected]>
Refering feedback from the review #673 which adds multiple namespaces functionality which includes the following: * Extend operator readme to mention how to enable the feature * Remove mentioning that the operator does not support the feature * Replacing TODO context with the context from the request * Deferring the closing of the body of the namespaces handler * Merging the cluster role configuration so it is used in faas-netes * Reusing the logic of namespaces and secrets handling present in faas-netes in the operator. Removing the custom implementations as they are no longer used Signed-off-by: Martin Dekov <[email protected]>
Adding support for multiple namespaces in the operator
as per:
#616
Signed-off-by: Martin Dekov [email protected]
Description
This PR fully covers Issue #616 as opposed to the draft #668 which covered only function object creation. This change is e2e. This is a working change, did not include any major refactoring of the code as proposed by Lucas in the draft, but can revisit.
Motivation and Context
Closes #616
How Has This Been Tested?
Built change in this image:
martindekov/faas-netes:asd-3
and deployed operator with the local chart:Tested default behavior (no namespace specified and function is deployed in default
openfaas-fn
namespace) and when specifying-n
flag with functions from store as this change does not involve cli specific logicTested in default and custom ns:
Tested secrets creation across default and custom namespace:
Tested logs in default and custom namespace:
Also tested default crd in
extras
namespace:Types of changes
Checklist:
git commit -s