mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-31 15:25:57 +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)
|
||||
Delete(name string) 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)
|
||||
}
|
||||
|
||||
@ -94,6 +95,16 @@ func (c *nodes) Update(node *api.Node) (*api.Node, error) {
|
||||
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.
|
||||
func (c *nodes) Watch(label labels.Selector, field fields.Selector, resourceVersion string) (watch.Interface, error) {
|
||||
return c.r.Get().
|
||||
|
@ -54,6 +54,11 @@ func (c *FakeNodes) Update(minion *api.Node) (*api.Node, error) {
|
||||
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) {
|
||||
c.Fake.Actions = append(c.Fake.Actions, FakeAction{Action: "watch-nodes", Value: resourceVersion})
|
||||
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 _, 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)
|
||||
return gracePeriod, lastReadyCondition, readyCondition, err
|
||||
} else {
|
||||
|
@ -56,10 +56,11 @@ type FakeNodeHandler struct {
|
||||
Existing []*api.Node
|
||||
|
||||
// Output
|
||||
CreatedNodes []*api.Node
|
||||
DeletedNodes []*api.Node
|
||||
UpdatedNodes []*api.Node
|
||||
RequestCount int
|
||||
CreatedNodes []*api.Node
|
||||
DeletedNodes []*api.Node
|
||||
UpdatedNodes []*api.Node
|
||||
UpdatedNodeStatuses []*api.Node
|
||||
RequestCount int
|
||||
}
|
||||
|
||||
func (c *FakeNodeHandler) Nodes() client.NodeInterface {
|
||||
@ -124,6 +125,13 @@ func (m *FakeNodeHandler) Update(node *api.Node) (*api.Node, error) {
|
||||
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) {
|
||||
return nil, nil
|
||||
}
|
||||
@ -1053,7 +1061,7 @@ func TestMonitorNodeStatusUpdateStatus(t *testing.T) {
|
||||
if 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],
|
||||
item.fakeNodeHandler.UpdatedNodes[0])
|
||||
}
|
||||
|
@ -1843,7 +1843,7 @@ func (kl *Kubelet) tryUpdateNodeStatus() error {
|
||||
kl.recordNodeOnlineEvent()
|
||||
}
|
||||
|
||||
_, err = kl.kubeClient.Nodes().Update(node)
|
||||
_, err = kl.kubeClient.Nodes().UpdateStatus(node)
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -3113,7 +3113,7 @@ func TestUpdateNewNodeStatus(t *testing.T) {
|
||||
if err := kubelet.updateNodeStatus(); err != nil {
|
||||
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)
|
||||
}
|
||||
updatedNode, ok := kubeClient.Actions[1].Value.(*api.Node)
|
||||
|
@ -376,7 +376,7 @@ func (m *Master) init(c *Config) {
|
||||
endpointsStorage := endpointsetcd.NewStorage(c.EtcdHelper)
|
||||
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)
|
||||
|
||||
// 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),
|
||||
"endpoints": endpointsStorage,
|
||||
"minions": nodeStorage,
|
||||
"minions/status": nodeStatusStorage,
|
||||
"nodes": nodeStorage,
|
||||
"nodes/status": nodeStatusStorage,
|
||||
"events": event.NewStorage(eventRegistry),
|
||||
|
||||
"limitRanges": limitrange.NewStorage(limitRangeRegistry),
|
||||
|
@ -34,8 +34,22 @@ type REST struct {
|
||||
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.
|
||||
func NewStorage(h tools.EtcdHelper, connection client.ConnectionInfoGetter) *REST {
|
||||
func NewStorage(h tools.EtcdHelper, connection client.ConnectionInfoGetter) (*REST, *StatusREST) {
|
||||
prefix := "/registry/minions"
|
||||
store := &etcdgeneric.Etcd{
|
||||
NewFunc: func() runtime.Object { return &api.Node{} },
|
||||
@ -58,7 +72,10 @@ func NewStorage(h tools.EtcdHelper, connection client.ConnectionInfoGetter) *RES
|
||||
Helper: h,
|
||||
}
|
||||
|
||||
return &REST{store, connection}
|
||||
statusStore := *store
|
||||
statusStore.UpdateStrategy = minion.StatusStrategy
|
||||
|
||||
return &REST{store, connection}, &StatusREST{store: &statusStore}
|
||||
}
|
||||
|
||||
// Implement Redirector.
|
||||
|
@ -55,7 +55,7 @@ func newHelper(t *testing.T) (*tools.FakeEtcdClient, tools.EtcdHelper) {
|
||||
|
||||
func newStorage(t *testing.T) (*REST, *tools.FakeEtcdClient) {
|
||||
fakeEtcdClient, h := newHelper(t)
|
||||
storage := NewStorage(h, fakeConnectionInfoGetter{})
|
||||
storage, _ := NewStorage(h, fakeConnectionInfoGetter{})
|
||||
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.
|
||||
func (nodeStrategy) PrepareForCreate(obj runtime.Object) {
|
||||
_ = 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.
|
||||
func (nodeStrategy) PrepareForUpdate(obj, old runtime.Object) {
|
||||
_ = obj.(*api.Node)
|
||||
_ = old.(*api.Node)
|
||||
// Nodes allow *all* fields, including status, to be set.
|
||||
newNode := obj.(*api.Node)
|
||||
oldNode := old.(*api.Node)
|
||||
newNode.Status = oldNode.Status
|
||||
}
|
||||
|
||||
// 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))
|
||||
}
|
||||
|
||||
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.
|
||||
type ResourceGetter interface {
|
||||
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
|
||||
// objects via the REST API.
|
||||
// TODO: Create other strategies for updating status, bindings, etc
|
||||
var Strategy = podStrategy{api.Scheme, api.SimpleNameGenerator}
|
||||
|
||||
// NamespaceScoped is true for pods.
|
||||
|
Loading…
Reference in New Issue
Block a user