-
Notifications
You must be signed in to change notification settings - Fork 381
Conversation
pkg/storage/crd/storage_interface.go
Outdated
|
||
type store struct { | ||
// TODO (nilebox): review the usage of "hasNamespace" flag | ||
hasNamespace bool |
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.
in the original TPR code, if this flag is set, you wipe the namespace from the objects even if they have a namespace. I haven't copied these code blocks yet.
@arschles why do we need this?
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.
because some service-catalog resources do not have namespaces (i.e. Broker
), but all TPR instances need namespaces. This flag indicated if the TPRs created by the interface should go into the specified namespace of the default global namespace
pkg/storage/crd/storage_interface.go
Outdated
hasNamespace bool | ||
defaultNamespace string | ||
cl restclient.Interface | ||
resourcePlural 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.
resourcePlural is an alternative to singularKind
we had for TPR implementation.
pkg/storage/crd/storage_interface.go
Outdated
out runtime.Object, | ||
ttl uint64, | ||
) error { | ||
// TODO (nilebox): can't we just use meta.Accessor(obj) instead? |
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.
@arschles Can you tell why can't we extract namespace and name from the object itself instead of decoding key?
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.
The reason could be that for GET request there is only a key, and no runtime.Object
input?
So the key here is for uniform way of passing namespace and name separate from the object?
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.
iirc we could use meta.Accessor
pkg/storage/crd/storage_interface.go
Outdated
return err | ||
} | ||
|
||
req := t.cl.Post().Resource(t.resourcePlural).Namespace(ns).Name(name).Body(obj) |
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.
@arschles see this structured API call as an alternative to
req := t.cl.Post().AbsPath(
"apis",
groupName,
tprVersion,
"namespaces",
ns,
t.singularKind.URLName(),
).Body(data)
in all other places, GET
, PUT
and all other requests use the same approach.
Why didn't you use this approach for TPRs? Do you require some extra stuff at the raw level?
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 believe that setting up a REST client with the scheme supporting all Service Catalog kinds, this approach should work
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 don't think your structured API call is wrong. I just used the various functions to build up the request instead of using AbsPath
pkg/storage/crd/storage_interface.go
Outdated
glog.Errorf("initiating the raw watch (%s)", err) | ||
return nil, err | ||
} | ||
return watchIface, 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.
In the original TPR code this result is wrapped into filter: https://github.com/kubernetes-incubator/service-catalog/blob/master/pkg/storage/tpr/storage_interface.go#L249
@arschles As far as I understand, this method is essentially a "map" function (as a functional programming term) for transforming a collection of type X type into a collection of type Y?
Not sure we actually need this 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.
yes, the filter is essentially a map function
pkg/storage/crd/options.go
Outdated
) | ||
|
||
// Options is the set of options to create a new TPR storage interface | ||
type Options struct { |
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.
Will need a Validate() method to call per upstream guidance. As part should maybe call the RESTOptions.Validate() if it exists.
@arschles @MHBauer @krancour CRD support is working now, please review.
vs
By default (with |
One additional step is required for making CRDs work compared to default https://github.com/kubernetes-incubator/service-catalog/blob/master/docs/install-1.7.md:
there might be some more granular permission enough, but without this change the registration of CRDs was failing. @arschles do we have a doc for TPR support? I haven't found one. I would extend it with CRD instructions then. |
Made |
Thanks to https://github.com/liggitt/audit2rbac I've found a more granular RBAC roles and bindings to allow Service Catalog manage its CRD resources (rewrote into
|
apiextCfg, err := restclient.InClusterConfig() | ||
if err != nil { | ||
glog.Errorf("Failed to get kube client config (%s)", err) | ||
return nil, 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.
Why not return nil, fmt.Errorf("failed to get kube client config: %v", err)
? Should not log and return the error - will likely be logged up the call stack so more than once.
There are more places like that.
Update: ok, you are following existing style. Should probably be a separate cleanup PR to fix all the places.
} | ||
res := req.Do() | ||
if res.Error() != nil { | ||
glog.Errorf("executing DELETE for %s/%s (%s)", ns, name, res.Error()) |
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.
Shouldn't this be a return fmt.Errorf(....)
? Why log anything when this function can return the error?
I guess you've been following the existing style, but this is can be improved, right?
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.
Think about it - there is no way caller gets any information about this err
. This is not right.
p.s. same in other files, will not comment there.
} else { | ||
glog.Infof("Created CRD '%s'", crd.Name) | ||
|
||
// There can be a delay, so poll until it's ready to 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.
I don't understand what this polling is waiting for - it should be always be possible to instantly get after create?
It should probably check conditions to see if names have been accepted and that the resource has been established but it is not doing any of that now.
go func(crd crdv1beta1.CustomResourceDefinition, client crdclient.CustomResourceDefinitionInterface) { | ||
defer wg.Done() | ||
if _, err := cl.Create(&crd); err != nil { | ||
errMsg <- fmt.Sprintf("%s: %s", crd.Name, 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.
Add a return
here and eliminate else
nesting?
|
||
if allErrMsg != "" { | ||
glog.Errorf("Failed to create Custom Resource:\n%s", allErrMsg) | ||
return ErrCRDInstall{fmt.Sprintf("Failed to create Custom Resource: %s", allErrMsg)} |
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.
Same as in other places - either log or return an error, not both :)
var unknown runtime.Unknown | ||
if err := req.Do().Into(&unknown); err != nil { | ||
glog.Errorf("doing request (%s)", err) | ||
return nil, 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.
This drives me crazy :) How one is supposed to debug this later? Collect pieces of information from multiple lines?
"k8s.io/apimachinery/pkg/api/meta" | ||
"k8s.io/apimachinery/pkg/runtime" | ||
restclient "k8s.io/client-go/rest" | ||
"k8s.io/kubernetes/pkg/api/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.
This should be an import from client-go
?
} | ||
|
||
// getAllNamespaces uses cl to get all namespaces | ||
func getAllNamespaces(cl restclient.Interface) (*v1.NamespaceList, error) { |
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 is a typed client for namespaces - why not use it?
} | ||
|
||
func (e errCouldntGetResourceVersion) Error() string { | ||
return fmt.Sprintf("couldn't get resource version (%s)", e.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 think %s
and %v
format error
differently and %v
is the right way to do it?
} | ||
|
||
if t.hasNamespace && ns == t.defaultNamespace { | ||
// TODO nilebox: The problem with distinguishing between "-n default" and "--all-namespaces" |
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.
Sounds like an issue, a ticket should be created for this?
@ash2k I would like to leave the error logging/propagation discussion for the follow-up PRs. It was copy-pasted from TPR support code, and I suppose that you can find the same pattern in the entire codebase. |
TODO: adopt fix #1275 |
Closing as I think that we need to revisit the requirements and decide whether we want to support CRDs in Service Catalog. If anyone wants to pick up this pull request - feel free. |
I will. #1971 |
Implementing #1088
Key differences compared to current TPR implementation:
apiVersion
(crd.servicecatalog.k8s.io
) compared to API server as a workaround for API aggregator clashing (TPRs don't work with 1.7 aggregator)Please review individual commits.