-
Notifications
You must be signed in to change notification settings - Fork 18
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
State support for Bundles #60
State support for Bundles #60
Conversation
bundle/executor.go
Outdated
} | ||
|
||
// NewExecutor - Creates a new Executor for running an APB. | ||
func NewExecutor() Executor { | ||
func NewExecutor(k8sClient k8.Interface, stateNS string) Executor { |
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.
not sure if this is the right approach. Feedback welcome
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 would prefer to use the clients package to get the k8s client that way. That is how most things are behaving and I have examples of how to test that.
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.
Is stateNS
different than bundle.serviceInstance.Context.Namespace
https://github.com/automationbroker/bundle-lib/blob/master/bundle/types.go#L140 ?
Not sure how to handle version checks here as state support wont be present until the following is present ansibleplaybookbundle/ansible-asb-modules#15 Does it mean a bump of the bundle / apb spec version and adding checks to the code for this version? |
Can someone point me to the genesis of this PR? IRC logs, email, or issue? Trying to get an idea what it is we're trying to solve. I think I missed or probably just forgot :) Thanks. |
@jmrodri it is the bundle-lib part of https://github.com/openshift/ansible-service-broker/blob/master/docs/proposals/apb-state-support.md the apb state support proposal Notes This is the first real thing I have done in the lib so struggled a little with understanding where the boundaries lay (ie what should be in the broker and what should be in the lib) If I am off on where the implementation of this should be, I'd be keen to know and understand more. |
runtime/state.go
Outdated
func (s *State) PrepareMount(name string) (*v1.VolumeMount, *v1.Volume, error) { | ||
mount := &v1.VolumeMount{ | ||
Name: name, | ||
MountPath: "/etc/apb/state", |
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.
set this value in PodEnv also so that it can be read by the module
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.
this is really LGTM!
I like the use of volume mounts.
@@ -38,7 +38,7 @@ func (e *executor) Bind( | |||
go func() { | |||
e.actionStarted() | |||
executionContext, err := e.executeApb( | |||
"bind", instance.Spec, instance.Context, parameters) | |||
"bind", instance, parameters) |
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.
I'm okay with it, I prefer only to pass in what is absolutely necessary but that is just a nitpick. I also understand this makes it easier to keep the signature stable as you require more things on the instance.
bundle/executor.go
Outdated
} | ||
|
||
// NewExecutor - Creates a new Executor for running an APB. | ||
func NewExecutor() Executor { | ||
func NewExecutor(k8sClient k8.Interface, stateNS string) Executor { |
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 would prefer to use the clients package to get the k8s client that way. That is how most things are behaving and I have examples of how to test that.
runtime/state.go
Outdated
|
||
// State handles the state for service bundles | ||
type State struct { | ||
Client k8.Interface |
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 would prefer this to use the clients
package.
@@ -141,8 +155,10 @@ func (e *executor) updateDescription(newDescription string) { | |||
|
|||
// executeApb - Runs an APB Action with a provided set of inputs | |||
func (e *executor) executeApb( | |||
action string, spec *Spec, context *Context, p *Parameters, | |||
action string, instance *ServiceInstance, p *Parameters, |
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.
Overall decent job. Minor change requests. Thanks for the PR.
bundle/executor.go
Outdated
PrepareMount(name string) (*v1.VolumeMount, *v1.Volume, error) | ||
StateIsPresent(name string) (bool, error) | ||
Name(instanceID string) string | ||
MasterNS() string |
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.
If NS is Namespace, I'd call the method MasterNamespace
, using ns as a variable is okay, but for the method feels better to spell it out.
@@ -38,7 +38,7 @@ func (e *executor) Bind( | |||
go func() { | |||
e.actionStarted() | |||
executionContext, err := e.executeApb( | |||
"bind", instance.Spec, instance.Context, parameters) | |||
"bind", instance, parameters) |
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'm okay with it, I prefer only to pass in what is absolutely necessary but that is just a nitpick. I also understand this makes it easier to keep the signature stable as you require more things on the instance.
bundle/bind.go
Outdated
@@ -62,6 +62,12 @@ func (e *executor) Bind( | |||
} | |||
} | |||
|
|||
// pod execution is complete so transfer state back | |||
if err := e.stateManager.CopyState(executionContext.PodName, e.stateManager.Name(instance.ID.String()), executionContext.Namespace, e.stateManager.MasterNS()); err != nil { |
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.
This is one really really long line :) can we just break it on one of the parameters?
if err := e.stateManager.CopyState(executionContext.PodName, e.stateManager.Name(instance.ID.String()),
executionContext.Namespace, e.stateManager.MasterNS()); err != nil {
e.actionFinishedWithError(err)
return
}
OR
if err := e.stateManager.CopyState(executionContext.PodName,
e.stateManager.Name(instance.ID.String()),
executionContext.Namespace,
e.stateManager.MasterNS()); err != nil {
e.actionFinishedWithError(err)
return
}
bundle/deprovision.go
Outdated
executionContext, err := e.executeApb("deprovision", instance, instance.Parameters) | ||
defer func() { | ||
if err := e.stateManager.DeleteState(e.stateManager.Name(instance.ID.String())); err != nil { | ||
log.Error("failed to delete state for instance "+instance.ID.String(), err) |
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'd use the formatted version:
log.Errorf("failed to delete state for instance %s - %v", instance.ID.String(), err)
bundle/executor.go
Outdated
@@ -31,6 +31,7 @@ import ( | |||
"github.com/pborman/uuid" | |||
log "github.com/sirupsen/logrus" | |||
"k8s.io/api/core/v1" | |||
k8 "k8s.io/client-go/kubernetes" |
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.
k8
feels weird, haven't we been doing k8s
? or k8scli
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.
removed
runtime/state.go
Outdated
|
||
// Name provides a consistent name for the state object | ||
func (s *State) Name(id string) string { | ||
return id + "-state" |
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.
this works, usually we do the return fmt.Sprintf("%s-state", id)
runtime/state.go
Outdated
log.Info("state: checking is present") | ||
if _, err := s.Client.CoreV1().ConfigMaps(s.targetNs).Get(stateName, metav1.GetOptions{}); err != nil { | ||
if kerror.IsNotFound(err) { | ||
log.Info("state: is not found ** ") |
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.
How often will this occur? Feels like this should be a debug statement not info.
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.
yep left in by accident there
runtime/state.go
Outdated
return true, nil | ||
} | ||
|
||
// PrepareMount will prepare the voume definitions and mounts |
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.
typo in comment: voume -> volume
runtime/state.go
Outdated
|
||
// DeleteState will remove the state object from the broker namespace | ||
func (s *State) DeleteState(name string) error { | ||
log.Info("state: deleting master state " + name + " in ns " + s.targetNs) |
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.
use the formatted version of info:
log.Infof("state: deleting master state %s in ns %s", name, s.targetNs)
runtime/state.go
Outdated
type State struct { | ||
Client k8.Interface | ||
// this is the namespace where the master configs will be stored | ||
targetNs string |
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 would prefer targetns
or targetNS
or even better nsTarget
@jmrodri @shawn-hurley ok thanks for feedback looks like we are happy with the approach. I will make the required changes and flesh out unit tests for the state module (didn't do this first as wanted to ensure I was heading in the right direction) |
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.
Nice job.
bundle/executor.go
Outdated
} | ||
|
||
// NewExecutor - Creates a new Executor for running an APB. | ||
func NewExecutor() Executor { | ||
func NewExecutor(k8sClient k8.Interface, stateNS string) Executor { |
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.
Is stateNS
different than bundle.serviceInstance.Context.Namespace
https://github.com/automationbroker/bundle-lib/blob/master/bundle/types.go#L140 ?
@rthallisey stateNS is the where the master copy of the state will be stored. In our case the broker namespace. So it is a different namespace |
c6f0bc9
to
a31958b
Compare
addressed all requested changes. I will add a set of tests for the state manager. Note I also added a new env var to set the BUNDLE_STATE_LOCATION for use by the module |
@maleck13 So I was re-looking through this after the changes and I actually see 1 thing that should be changed. We are trying to move all of the stuff that uses k8scli to the runtime, and therefore I think that State Manager should be moved to the runtime package, its interface embedded into the Runtime interface and the provider struct should embed a default runtime. I also think that allowing an override in the configuration should be added. Please ping me if you have any questions. Sorry I didn't catch this the first time around. |
Is the idea here that a different StateManager could be provided externally when using the lib outside of the broker but we will provide a default implementation? I am ok making the change just trying to understand the reasoning. The actual concrete implementation of the interface is already in the runtime package limiting the k8scli to the runtime package. This makes me wonder should the state type in the runtime package be exported, seems it should be internal right? |
The idea is that the only way to interact with the runtime package is through the Provider. This Provider is just an implementation of the The idea is that if we have a bunch of sane defaults, but then if someone wants to change something they can. This will allow users of bundle lib who want to implement a new runtime can. I don't envision anyone doing this right at the moment but I do see future use cases that are not too far into the future. |
c1f2d72
to
aa349d2
Compare
@shawn-hurley I believe I have made the changes you requested. Let me know if this what your were expecting. @jmrodri I believe I have addressed your feedback |
aa349d2
to
baa1351
Compare
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.
This a nit, but I would like to keep the same structure/layout that we have been using
runtime/runtime.go
Outdated
} | ||
|
||
// StateManager defines an interface for managing state created by service bundles | ||
type StateManager interface { |
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 would move this interface into the state file. this would follow the pattern that we have used for ExtractedCredential
runtime/state.go
Outdated
import ( | ||
"fmt" | ||
|
||
"github.com/apex/log" |
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 think this is a mistaken import. I believe it should be log "github.com/sirupsen/logrus"
Remove the apex log, and add the logrus UNDER the clients, like it looks below. This makes goimports happy and uses the correct logger.
import (
"fmt"
"github.com/automationbroker/bundle-lib/clients"
log "github.com/sirupsen/logrus"
"k8s.io/api/core/v1"
kerror "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
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.
@maleck13 Wrong logger used in state.go
, see the other comment above with the suggested fix. Then I will merge it tomorrow (Thursday). I validated it today. Great job.
fix import for log
84f1338
to
6fbe98e
Compare
@jmrodri Thanks. Good spot on the import. Once merged will we tag / release I will then make the needed updates to the broker |
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.
Looks great. This approach is going to make it much easier for APB developers to pass data between calls even outside of the cluster approach since it's just mounted files. Great job!
Apologies on delay with this. Here is a pass at the state support in the bundle lib. Please be brutal 😀 I have changes to the broker also but will wait until this is nailed down.
@shawn-hurley You mentioned making the PR against 0.1-release. Is that needed for this work as it is targeting the next release?