mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-04 18:00:08 +00:00
Update NodeStatus use subresources.
This commit is contained in:
parent
b12d75d0ee
commit
ccc56d3c3c
@ -35,6 +35,7 @@ type NodeInterface interface {
|
|||||||
List(selector labels.Selector) (*api.NodeList, error)
|
List(selector labels.Selector) (*api.NodeList, error)
|
||||||
Delete(name string) error
|
Delete(name string) error
|
||||||
Update(*api.Node) (*api.Node, error)
|
Update(*api.Node) (*api.Node, error)
|
||||||
|
UpdateStatus(*api.Node) (*api.Node, error)
|
||||||
Watch(label labels.Selector, field fields.Selector, resourceVersion string) (watch.Interface, error)
|
Watch(label labels.Selector, field fields.Selector, resourceVersion string) (watch.Interface, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,6 +95,16 @@ func (c *nodes) Update(node *api.Node) (*api.Node, error) {
|
|||||||
return result, err
|
return result, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *nodes) UpdateStatus(node *api.Node) (*api.Node, error) {
|
||||||
|
result := &api.Node{}
|
||||||
|
if len(node.ResourceVersion) == 0 {
|
||||||
|
err := fmt.Errorf("invalid update object, missing resource version: %v", node)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
err := c.r.Put().Resource(c.resourceName()).Name(node.Name).SubResource("status").Body(node).Do().Into(result)
|
||||||
|
return result, err
|
||||||
|
}
|
||||||
|
|
||||||
// Watch returns a watch.Interface that watches the requested nodes.
|
// Watch returns a watch.Interface that watches the requested nodes.
|
||||||
func (c *nodes) Watch(label labels.Selector, field fields.Selector, resourceVersion string) (watch.Interface, error) {
|
func (c *nodes) Watch(label labels.Selector, field fields.Selector, resourceVersion string) (watch.Interface, error) {
|
||||||
return c.r.Get().
|
return c.r.Get().
|
||||||
|
@ -54,6 +54,11 @@ func (c *FakeNodes) Update(minion *api.Node) (*api.Node, error) {
|
|||||||
return obj.(*api.Node), err
|
return obj.(*api.Node), err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *FakeNodes) UpdateStatus(minion *api.Node) (*api.Node, error) {
|
||||||
|
obj, err := c.Fake.Invokes(FakeAction{Action: "update-status-node", Value: minion}, &api.Node{})
|
||||||
|
return obj.(*api.Node), err
|
||||||
|
}
|
||||||
|
|
||||||
func (c *FakeNodes) Watch(label labels.Selector, field fields.Selector, resourceVersion string) (watch.Interface, error) {
|
func (c *FakeNodes) Watch(label labels.Selector, field fields.Selector, resourceVersion string) (watch.Interface, error) {
|
||||||
c.Fake.Actions = append(c.Fake.Actions, FakeAction{Action: "watch-nodes", Value: resourceVersion})
|
c.Fake.Actions = append(c.Fake.Actions, FakeAction{Action: "watch-nodes", Value: resourceVersion})
|
||||||
return c.Fake.Watch, c.Fake.Err
|
return c.Fake.Watch, c.Fake.Err
|
||||||
|
@ -413,7 +413,7 @@ func (nc *NodeController) tryUpdateNodeStatus(node *api.Node) (time.Duration, ap
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !api.Semantic.DeepEqual(nc.getCondition(&node.Status, api.NodeReady), lastReadyCondition) {
|
if !api.Semantic.DeepEqual(nc.getCondition(&node.Status, api.NodeReady), lastReadyCondition) {
|
||||||
if _, err = nc.kubeClient.Nodes().Update(node); err != nil {
|
if _, err = nc.kubeClient.Nodes().UpdateStatus(node); err != nil {
|
||||||
glog.Errorf("Error updating node %s: %v", node.Name, err)
|
glog.Errorf("Error updating node %s: %v", node.Name, err)
|
||||||
return gracePeriod, lastReadyCondition, readyCondition, err
|
return gracePeriod, lastReadyCondition, readyCondition, err
|
||||||
} else {
|
} else {
|
||||||
|
@ -56,10 +56,11 @@ type FakeNodeHandler struct {
|
|||||||
Existing []*api.Node
|
Existing []*api.Node
|
||||||
|
|
||||||
// Output
|
// Output
|
||||||
CreatedNodes []*api.Node
|
CreatedNodes []*api.Node
|
||||||
DeletedNodes []*api.Node
|
DeletedNodes []*api.Node
|
||||||
UpdatedNodes []*api.Node
|
UpdatedNodes []*api.Node
|
||||||
RequestCount int
|
UpdatedNodeStatuses []*api.Node
|
||||||
|
RequestCount int
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *FakeNodeHandler) Nodes() client.NodeInterface {
|
func (c *FakeNodeHandler) Nodes() client.NodeInterface {
|
||||||
@ -124,6 +125,13 @@ func (m *FakeNodeHandler) Update(node *api.Node) (*api.Node, error) {
|
|||||||
return node, nil
|
return node, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *FakeNodeHandler) UpdateStatus(node *api.Node) (*api.Node, error) {
|
||||||
|
nodeCopy := *node
|
||||||
|
m.UpdatedNodeStatuses = append(m.UpdatedNodeStatuses, &nodeCopy)
|
||||||
|
m.RequestCount++
|
||||||
|
return node, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (m *FakeNodeHandler) Watch(label labels.Selector, field fields.Selector, resourceVersion string) (watch.Interface, error) {
|
func (m *FakeNodeHandler) Watch(label labels.Selector, field fields.Selector, resourceVersion string) (watch.Interface, error) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
@ -1053,7 +1061,7 @@ func TestMonitorNodeStatusUpdateStatus(t *testing.T) {
|
|||||||
if item.expectedRequestCount != item.fakeNodeHandler.RequestCount {
|
if item.expectedRequestCount != item.fakeNodeHandler.RequestCount {
|
||||||
t.Errorf("expected %v call, but got %v.", item.expectedRequestCount, item.fakeNodeHandler.RequestCount)
|
t.Errorf("expected %v call, but got %v.", item.expectedRequestCount, item.fakeNodeHandler.RequestCount)
|
||||||
}
|
}
|
||||||
if !api.Semantic.DeepEqual(item.expectedNodes, item.fakeNodeHandler.UpdatedNodes) {
|
if len(item.fakeNodeHandler.UpdatedNodes) > 0 && !api.Semantic.DeepEqual(item.expectedNodes, item.fakeNodeHandler.UpdatedNodes) {
|
||||||
t.Errorf("expected nodes %+v, got %+v", item.expectedNodes[0],
|
t.Errorf("expected nodes %+v, got %+v", item.expectedNodes[0],
|
||||||
item.fakeNodeHandler.UpdatedNodes[0])
|
item.fakeNodeHandler.UpdatedNodes[0])
|
||||||
}
|
}
|
||||||
|
@ -1843,7 +1843,7 @@ func (kl *Kubelet) tryUpdateNodeStatus() error {
|
|||||||
kl.recordNodeOnlineEvent()
|
kl.recordNodeOnlineEvent()
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = kl.kubeClient.Nodes().Update(node)
|
_, err = kl.kubeClient.Nodes().UpdateStatus(node)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3113,7 +3113,7 @@ func TestUpdateNewNodeStatus(t *testing.T) {
|
|||||||
if err := kubelet.updateNodeStatus(); err != nil {
|
if err := kubelet.updateNodeStatus(); err != nil {
|
||||||
t.Errorf("unexpected error: %v", err)
|
t.Errorf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
if len(kubeClient.Actions) != 2 || kubeClient.Actions[1].Action != "update-node" {
|
if len(kubeClient.Actions) != 2 || kubeClient.Actions[1].Action != "update-status-node" {
|
||||||
t.Fatalf("unexpected actions: %v", kubeClient.Actions)
|
t.Fatalf("unexpected actions: %v", kubeClient.Actions)
|
||||||
}
|
}
|
||||||
updatedNode, ok := kubeClient.Actions[1].Value.(*api.Node)
|
updatedNode, ok := kubeClient.Actions[1].Value.(*api.Node)
|
||||||
|
@ -376,7 +376,7 @@ func (m *Master) init(c *Config) {
|
|||||||
endpointsStorage := endpointsetcd.NewStorage(c.EtcdHelper)
|
endpointsStorage := endpointsetcd.NewStorage(c.EtcdHelper)
|
||||||
m.endpointRegistry = endpoint.NewRegistry(endpointsStorage)
|
m.endpointRegistry = endpoint.NewRegistry(endpointsStorage)
|
||||||
|
|
||||||
nodeStorage := nodeetcd.NewStorage(c.EtcdHelper, c.KubeletClient)
|
nodeStorage, nodeStatusStorage := nodeetcd.NewStorage(c.EtcdHelper, c.KubeletClient)
|
||||||
m.nodeRegistry = minion.NewRegistry(nodeStorage)
|
m.nodeRegistry = minion.NewRegistry(nodeStorage)
|
||||||
|
|
||||||
// TODO: split me up into distinct storage registries
|
// TODO: split me up into distinct storage registries
|
||||||
@ -397,7 +397,9 @@ func (m *Master) init(c *Config) {
|
|||||||
"services": service.NewStorage(m.serviceRegistry, c.Cloud, m.nodeRegistry, m.endpointRegistry, m.portalNet, c.ClusterName),
|
"services": service.NewStorage(m.serviceRegistry, c.Cloud, m.nodeRegistry, m.endpointRegistry, m.portalNet, c.ClusterName),
|
||||||
"endpoints": endpointsStorage,
|
"endpoints": endpointsStorage,
|
||||||
"minions": nodeStorage,
|
"minions": nodeStorage,
|
||||||
|
"minions/status": nodeStatusStorage,
|
||||||
"nodes": nodeStorage,
|
"nodes": nodeStorage,
|
||||||
|
"nodes/status": nodeStatusStorage,
|
||||||
"events": event.NewStorage(eventRegistry),
|
"events": event.NewStorage(eventRegistry),
|
||||||
|
|
||||||
"limitRanges": limitrange.NewStorage(limitRangeRegistry),
|
"limitRanges": limitrange.NewStorage(limitRangeRegistry),
|
||||||
|
@ -34,8 +34,22 @@ type REST struct {
|
|||||||
connection client.ConnectionInfoGetter
|
connection client.ConnectionInfoGetter
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// StatusREST implements the REST endpoint for changing the status of a pod.
|
||||||
|
type StatusREST struct {
|
||||||
|
store *etcdgeneric.Etcd
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *StatusREST) New() runtime.Object {
|
||||||
|
return &api.Node{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update alters the status subset of an object.
|
||||||
|
func (r *StatusREST) Update(ctx api.Context, obj runtime.Object) (runtime.Object, bool, error) {
|
||||||
|
return r.store.Update(ctx, obj)
|
||||||
|
}
|
||||||
|
|
||||||
// NewStorage returns a RESTStorage object that will work against nodes.
|
// NewStorage returns a RESTStorage object that will work against nodes.
|
||||||
func NewStorage(h tools.EtcdHelper, connection client.ConnectionInfoGetter) *REST {
|
func NewStorage(h tools.EtcdHelper, connection client.ConnectionInfoGetter) (*REST, *StatusREST) {
|
||||||
prefix := "/registry/minions"
|
prefix := "/registry/minions"
|
||||||
store := &etcdgeneric.Etcd{
|
store := &etcdgeneric.Etcd{
|
||||||
NewFunc: func() runtime.Object { return &api.Node{} },
|
NewFunc: func() runtime.Object { return &api.Node{} },
|
||||||
@ -58,7 +72,10 @@ func NewStorage(h tools.EtcdHelper, connection client.ConnectionInfoGetter) *RES
|
|||||||
Helper: h,
|
Helper: h,
|
||||||
}
|
}
|
||||||
|
|
||||||
return &REST{store, connection}
|
statusStore := *store
|
||||||
|
statusStore.UpdateStrategy = minion.StatusStrategy
|
||||||
|
|
||||||
|
return &REST{store, connection}, &StatusREST{store: &statusStore}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implement Redirector.
|
// Implement Redirector.
|
||||||
|
@ -55,7 +55,7 @@ func newHelper(t *testing.T) (*tools.FakeEtcdClient, tools.EtcdHelper) {
|
|||||||
|
|
||||||
func newStorage(t *testing.T) (*REST, *tools.FakeEtcdClient) {
|
func newStorage(t *testing.T) (*REST, *tools.FakeEtcdClient) {
|
||||||
fakeEtcdClient, h := newHelper(t)
|
fakeEtcdClient, h := newHelper(t)
|
||||||
storage := NewStorage(h, fakeConnectionInfoGetter{})
|
storage, _ := NewStorage(h, fakeConnectionInfoGetter{})
|
||||||
return storage, fakeEtcdClient
|
return storage, fakeEtcdClient
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,14 +56,14 @@ func (nodeStrategy) AllowCreateOnUpdate() bool {
|
|||||||
// PrepareForCreate clears fields that are not allowed to be set by end users on creation.
|
// PrepareForCreate clears fields that are not allowed to be set by end users on creation.
|
||||||
func (nodeStrategy) PrepareForCreate(obj runtime.Object) {
|
func (nodeStrategy) PrepareForCreate(obj runtime.Object) {
|
||||||
_ = obj.(*api.Node)
|
_ = obj.(*api.Node)
|
||||||
// Nodes allow *all* fields, including status, to be set.
|
// Nodes allow *all* fields, including status, to be set on create.
|
||||||
}
|
}
|
||||||
|
|
||||||
// PrepareForUpdate clears fields that are not allowed to be set by end users on update.
|
// PrepareForUpdate clears fields that are not allowed to be set by end users on update.
|
||||||
func (nodeStrategy) PrepareForUpdate(obj, old runtime.Object) {
|
func (nodeStrategy) PrepareForUpdate(obj, old runtime.Object) {
|
||||||
_ = obj.(*api.Node)
|
newNode := obj.(*api.Node)
|
||||||
_ = old.(*api.Node)
|
oldNode := old.(*api.Node)
|
||||||
// Nodes allow *all* fields, including status, to be set.
|
newNode.Status = oldNode.Status
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate validates a new node.
|
// Validate validates a new node.
|
||||||
@ -77,6 +77,27 @@ func (nodeStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) fie
|
|||||||
return validation.ValidateMinionUpdate(old.(*api.Node), obj.(*api.Node))
|
return validation.ValidateMinionUpdate(old.(*api.Node), obj.(*api.Node))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type nodeStatusStrategy struct {
|
||||||
|
nodeStrategy
|
||||||
|
}
|
||||||
|
|
||||||
|
var StatusStrategy = nodeStatusStrategy{Strategy}
|
||||||
|
|
||||||
|
func (nodeStatusStrategy) PrepareForCreate(obj runtime.Object) {
|
||||||
|
_ = obj.(*api.Node)
|
||||||
|
// Nodes allow *all* fields, including status, to be set on create.
|
||||||
|
}
|
||||||
|
|
||||||
|
func (nodeStatusStrategy) PrepareForUpdate(obj, old runtime.Object) {
|
||||||
|
newNode := obj.(*api.Node)
|
||||||
|
oldNode := old.(*api.Node)
|
||||||
|
newNode.Spec = oldNode.Spec
|
||||||
|
}
|
||||||
|
|
||||||
|
func (nodeStatusStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) fielderrors.ValidationErrorList {
|
||||||
|
return validation.ValidateMinionUpdate(old.(*api.Node), obj.(*api.Node))
|
||||||
|
}
|
||||||
|
|
||||||
// ResourceGetter is an interface for retrieving resources by ResourceLocation.
|
// ResourceGetter is an interface for retrieving resources by ResourceLocation.
|
||||||
type ResourceGetter interface {
|
type ResourceGetter interface {
|
||||||
Get(api.Context, string) (runtime.Object, error)
|
Get(api.Context, string) (runtime.Object, error)
|
||||||
|
@ -43,7 +43,6 @@ type podStrategy struct {
|
|||||||
|
|
||||||
// Strategy is the default logic that applies when creating and updating Pod
|
// Strategy is the default logic that applies when creating and updating Pod
|
||||||
// objects via the REST API.
|
// objects via the REST API.
|
||||||
// TODO: Create other strategies for updating status, bindings, etc
|
|
||||||
var Strategy = podStrategy{api.Scheme, api.SimpleNameGenerator}
|
var Strategy = podStrategy{api.Scheme, api.SimpleNameGenerator}
|
||||||
|
|
||||||
// NamespaceScoped is true for pods.
|
// NamespaceScoped is true for pods.
|
||||||
|
Loading…
Reference in New Issue
Block a user