mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-09-06 11:42:14 +00:00
Always set ?namespace in query if specified
Revise our code to only call Request.Namespace() if a namespace *should* be present. For root scoped resources, namespace should be ignored. For namespaced resources, it is an error to have Namespace=="".
This commit is contained in:
@@ -35,6 +35,8 @@ type Helper struct {
|
||||
// An interface for reading or writing the resource version of this
|
||||
// type.
|
||||
Versioner runtime.ResourceVersioner
|
||||
// True if the resource type is scoped to namespaces
|
||||
NamespaceScoped bool
|
||||
}
|
||||
|
||||
// NewHelper creates a Helper from a ResourceMapping
|
||||
@@ -44,12 +46,14 @@ func NewHelper(client RESTClient, mapping *meta.RESTMapping) *Helper {
|
||||
Resource: mapping.Resource,
|
||||
Codec: mapping.Codec,
|
||||
Versioner: mapping.MetadataAccessor,
|
||||
|
||||
NamespaceScoped: mapping.Scope.Name() == meta.RESTScopeNameNamespace,
|
||||
}
|
||||
}
|
||||
|
||||
func (m *Helper) Get(namespace, name string) (runtime.Object, error) {
|
||||
return m.RESTClient.Get().
|
||||
Namespace(namespace).
|
||||
NamespaceIfScoped(namespace, m.NamespaceScoped).
|
||||
Resource(m.Resource).
|
||||
Name(name).
|
||||
Do().
|
||||
@@ -58,7 +62,7 @@ func (m *Helper) Get(namespace, name string) (runtime.Object, error) {
|
||||
|
||||
func (m *Helper) List(namespace string, selector labels.Selector) (runtime.Object, error) {
|
||||
return m.RESTClient.Get().
|
||||
Namespace(namespace).
|
||||
NamespaceIfScoped(namespace, m.NamespaceScoped).
|
||||
Resource(m.Resource).
|
||||
SelectorParam("labels", selector).
|
||||
Do().
|
||||
@@ -68,7 +72,7 @@ func (m *Helper) List(namespace string, selector labels.Selector) (runtime.Objec
|
||||
func (m *Helper) Watch(namespace, resourceVersion string, labelSelector, fieldSelector labels.Selector) (watch.Interface, error) {
|
||||
return m.RESTClient.Get().
|
||||
Prefix("watch").
|
||||
Namespace(namespace).
|
||||
NamespaceIfScoped(namespace, m.NamespaceScoped).
|
||||
Resource(m.Resource).
|
||||
Param("resourceVersion", resourceVersion).
|
||||
SelectorParam("labels", labelSelector).
|
||||
@@ -79,7 +83,7 @@ func (m *Helper) Watch(namespace, resourceVersion string, labelSelector, fieldSe
|
||||
func (m *Helper) WatchSingle(namespace, name, resourceVersion string) (watch.Interface, error) {
|
||||
return m.RESTClient.Get().
|
||||
Prefix("watch").
|
||||
Namespace(namespace).
|
||||
NamespaceIfScoped(namespace, m.NamespaceScoped).
|
||||
Resource(m.Resource).
|
||||
Name(name).
|
||||
Param("resourceVersion", resourceVersion).
|
||||
@@ -88,7 +92,7 @@ func (m *Helper) WatchSingle(namespace, name, resourceVersion string) (watch.Int
|
||||
|
||||
func (m *Helper) Delete(namespace, name string) error {
|
||||
return m.RESTClient.Delete().
|
||||
Namespace(namespace).
|
||||
NamespaceIfScoped(namespace, m.NamespaceScoped).
|
||||
Resource(m.Resource).
|
||||
Name(name).
|
||||
Do().
|
||||
@@ -100,14 +104,14 @@ func (m *Helper) Create(namespace string, modify bool, data []byte) (runtime.Obj
|
||||
obj, err := m.Codec.Decode(data)
|
||||
if err != nil {
|
||||
// We don't know how to check a version on this object, but create it anyway
|
||||
return createResource(m.RESTClient, m.Resource, namespace, data)
|
||||
return m.createResource(m.RESTClient, m.Resource, namespace, data)
|
||||
}
|
||||
|
||||
// Attempt to version the object based on client logic.
|
||||
version, err := m.Versioner.ResourceVersion(obj)
|
||||
if err != nil {
|
||||
// We don't know how to clear the version on this object, so send it to the server as is
|
||||
return createResource(m.RESTClient, m.Resource, namespace, data)
|
||||
return m.createResource(m.RESTClient, m.Resource, namespace, data)
|
||||
}
|
||||
if version != "" {
|
||||
if err := m.Versioner.SetResourceVersion(obj, ""); err != nil {
|
||||
@@ -121,11 +125,11 @@ func (m *Helper) Create(namespace string, modify bool, data []byte) (runtime.Obj
|
||||
}
|
||||
}
|
||||
|
||||
return createResource(m.RESTClient, m.Resource, namespace, data)
|
||||
return m.createResource(m.RESTClient, m.Resource, namespace, data)
|
||||
}
|
||||
|
||||
func createResource(c RESTClient, resource, namespace string, data []byte) (runtime.Object, error) {
|
||||
return c.Post().Namespace(namespace).Resource(resource).Body(data).Do().Get()
|
||||
func (m *Helper) createResource(c RESTClient, resource, namespace string, data []byte) (runtime.Object, error) {
|
||||
return c.Post().NamespaceIfScoped(namespace, m.NamespaceScoped).Resource(resource).Body(data).Do().Get()
|
||||
}
|
||||
|
||||
func (m *Helper) Update(namespace, name string, overwrite bool, data []byte) (runtime.Object, error) {
|
||||
@@ -134,21 +138,21 @@ func (m *Helper) Update(namespace, name string, overwrite bool, data []byte) (ru
|
||||
obj, err := m.Codec.Decode(data)
|
||||
if err != nil {
|
||||
// We don't know how to handle this object, but update it anyway
|
||||
return updateResource(c, m.Resource, namespace, name, data)
|
||||
return m.updateResource(c, m.Resource, namespace, name, data)
|
||||
}
|
||||
|
||||
// Attempt to version the object based on client logic.
|
||||
version, err := m.Versioner.ResourceVersion(obj)
|
||||
if err != nil {
|
||||
// We don't know how to version this object, so send it to the server as is
|
||||
return updateResource(c, m.Resource, namespace, name, data)
|
||||
return m.updateResource(c, m.Resource, namespace, name, data)
|
||||
}
|
||||
if version == "" && overwrite {
|
||||
// Retrieve the current version of the object to overwrite the server object
|
||||
serverObj, err := c.Get().Namespace(namespace).Resource(m.Resource).Name(name).Do().Get()
|
||||
if err != nil {
|
||||
// The object does not exist, but we want it to be created
|
||||
return updateResource(c, m.Resource, namespace, name, data)
|
||||
return m.updateResource(c, m.Resource, namespace, name, data)
|
||||
}
|
||||
serverVersion, err := m.Versioner.ResourceVersion(serverObj)
|
||||
if err != nil {
|
||||
@@ -164,9 +168,9 @@ func (m *Helper) Update(namespace, name string, overwrite bool, data []byte) (ru
|
||||
data = newData
|
||||
}
|
||||
|
||||
return updateResource(c, m.Resource, namespace, name, data)
|
||||
return m.updateResource(c, m.Resource, namespace, name, data)
|
||||
}
|
||||
|
||||
func updateResource(c RESTClient, resource, namespace, name string, data []byte) (runtime.Object, error) {
|
||||
return c.Put().Namespace(namespace).Resource(resource).Name(name).Body(data).Do().Get()
|
||||
func (m *Helper) updateResource(c RESTClient, resource, namespace, name string, data []byte) (runtime.Object, error) {
|
||||
return c.Put().NamespaceIfScoped(namespace, m.NamespaceScoped).Resource(resource).Name(name).Body(data).Do().Get()
|
||||
}
|
||||
|
@@ -75,6 +75,10 @@ func TestHelperDelete(t *testing.T) {
|
||||
return false
|
||||
}
|
||||
parts := splitPath(req.URL.Path)
|
||||
if len(parts) < 3 {
|
||||
t.Errorf("expected URL path to have 3 parts: %s", req.URL.Path)
|
||||
return false
|
||||
}
|
||||
if parts[1] != "bar" {
|
||||
t.Errorf("url doesn't contain namespace: %#v", req)
|
||||
return false
|
||||
@@ -94,7 +98,8 @@ func TestHelperDelete(t *testing.T) {
|
||||
Err: test.HttpErr,
|
||||
}
|
||||
modifier := &Helper{
|
||||
RESTClient: client,
|
||||
RESTClient: client,
|
||||
NamespaceScoped: true,
|
||||
}
|
||||
err := modifier.Delete("bar", "foo")
|
||||
if (err != nil) != test.Err {
|
||||
@@ -185,9 +190,10 @@ func TestHelperCreate(t *testing.T) {
|
||||
client.Client = test.RespFunc
|
||||
}
|
||||
modifier := &Helper{
|
||||
RESTClient: client,
|
||||
Codec: testapi.Codec(),
|
||||
Versioner: testapi.MetadataAccessor(),
|
||||
RESTClient: client,
|
||||
Codec: testapi.Codec(),
|
||||
Versioner: testapi.MetadataAccessor(),
|
||||
NamespaceScoped: true,
|
||||
}
|
||||
data := []byte{}
|
||||
if test.Object != nil {
|
||||
@@ -267,7 +273,8 @@ func TestHelperGet(t *testing.T) {
|
||||
Err: test.HttpErr,
|
||||
}
|
||||
modifier := &Helper{
|
||||
RESTClient: client,
|
||||
RESTClient: client,
|
||||
NamespaceScoped: true,
|
||||
}
|
||||
obj, err := modifier.Get("bar", "foo")
|
||||
if (err != nil) != test.Err {
|
||||
@@ -337,7 +344,8 @@ func TestHelperList(t *testing.T) {
|
||||
Err: test.HttpErr,
|
||||
}
|
||||
modifier := &Helper{
|
||||
RESTClient: client,
|
||||
RESTClient: client,
|
||||
NamespaceScoped: true,
|
||||
}
|
||||
obj, err := modifier.List("bar", labels.SelectorFromSet(labels.Set{"foo": "baz"}))
|
||||
if (err != nil) != test.Err {
|
||||
@@ -440,9 +448,10 @@ func TestHelperUpdate(t *testing.T) {
|
||||
client.Client = test.RespFunc
|
||||
}
|
||||
modifier := &Helper{
|
||||
RESTClient: client,
|
||||
Codec: testapi.Codec(),
|
||||
Versioner: testapi.MetadataAccessor(),
|
||||
RESTClient: client,
|
||||
Codec: testapi.Codec(),
|
||||
Versioner: testapi.MetadataAccessor(),
|
||||
NamespaceScoped: true,
|
||||
}
|
||||
data := []byte{}
|
||||
if test.Object != nil {
|
||||
|
Reference in New Issue
Block a user