mirror of https://github.com/k3s-io/k3s
Merge pull request #6857 from wojtek-t/fix_scheduler_nodes
Fix listing nodes in schedulerpull/6/head
commit
835a87aed2
|
@ -1579,6 +1579,8 @@ func init() {
|
|||
switch label {
|
||||
case "name":
|
||||
return "metadata.name", value, nil
|
||||
case "unschedulable":
|
||||
return "spec.unschedulable", value, nil
|
||||
default:
|
||||
return "", "", fmt.Errorf("field label not supported: %s", label)
|
||||
}
|
||||
|
|
|
@ -1504,6 +1504,8 @@ func init() {
|
|||
switch label {
|
||||
case "name":
|
||||
return "metadata.name", value, nil
|
||||
case "unschedulable":
|
||||
return "spec.unschedulable", value, nil
|
||||
default:
|
||||
return "", "", fmt.Errorf("field label not supported: %s", label)
|
||||
}
|
||||
|
|
|
@ -44,6 +44,8 @@ func init() {
|
|||
switch label {
|
||||
case "metadata.name":
|
||||
return label, value, nil
|
||||
case "spec.unschedulable":
|
||||
return label, value, nil
|
||||
default:
|
||||
return "", "", fmt.Errorf("field label not supported: %s", label)
|
||||
}
|
||||
|
|
|
@ -250,6 +250,7 @@ func (r *Request) RequestURI(uri string) *Request {
|
|||
const (
|
||||
// A constant that clients can use to refer in a field selector to the object name field.
|
||||
// Will be automatically emitted as the correct name for the API version.
|
||||
NodeUnschedulable = "spec.unschedulable"
|
||||
ObjectNameField = "metadata.name"
|
||||
PodHost = "spec.host"
|
||||
)
|
||||
|
@ -295,9 +296,11 @@ var fieldMappings = versionToResourceToFieldMapping{
|
|||
"v1beta1": resourceTypeToFieldMapping{
|
||||
"nodes": clientFieldNameToAPIVersionFieldName{
|
||||
ObjectNameField: "name",
|
||||
NodeUnschedulable: "unschedulable",
|
||||
},
|
||||
"minions": clientFieldNameToAPIVersionFieldName{
|
||||
ObjectNameField: "name",
|
||||
NodeUnschedulable: "unschedulable",
|
||||
},
|
||||
"pods": clientFieldNameToAPIVersionFieldName{
|
||||
PodHost: "DesiredState.Host",
|
||||
|
@ -306,9 +309,11 @@ var fieldMappings = versionToResourceToFieldMapping{
|
|||
"v1beta2": resourceTypeToFieldMapping{
|
||||
"nodes": clientFieldNameToAPIVersionFieldName{
|
||||
ObjectNameField: "name",
|
||||
NodeUnschedulable: "unschedulable",
|
||||
},
|
||||
"minions": clientFieldNameToAPIVersionFieldName{
|
||||
ObjectNameField: "name",
|
||||
NodeUnschedulable: "unschedulable",
|
||||
},
|
||||
"pods": clientFieldNameToAPIVersionFieldName{
|
||||
PodHost: "DesiredState.Host",
|
||||
|
@ -317,9 +322,11 @@ var fieldMappings = versionToResourceToFieldMapping{
|
|||
"v1beta3": resourceTypeToFieldMapping{
|
||||
"nodes": clientFieldNameToAPIVersionFieldName{
|
||||
ObjectNameField: "metadata.name",
|
||||
NodeUnschedulable: "spec.unschedulable",
|
||||
},
|
||||
"minions": clientFieldNameToAPIVersionFieldName{
|
||||
ObjectNameField: "metadata.name",
|
||||
NodeUnschedulable: "spec.unschedulable",
|
||||
},
|
||||
"pods": clientFieldNameToAPIVersionFieldName{
|
||||
PodHost: "spec.host",
|
||||
|
|
|
@ -108,6 +108,7 @@ type ResourceGetter interface {
|
|||
func NodeToSelectableFields(node *api.Node) fields.Set {
|
||||
return fields.Set{
|
||||
"metadata.name": node.Name,
|
||||
"spec.unschedulable": fmt.Sprint(node.Spec.Unschedulable),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -28,7 +28,6 @@ import (
|
|||
"github.com/GoogleCloudPlatform/kubernetes/pkg/client/cache"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/controller/framework"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/fields"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
|
||||
algorithm "github.com/GoogleCloudPlatform/kubernetes/pkg/scheduler"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/plugin/pkg/scheduler"
|
||||
|
@ -230,40 +229,9 @@ func (factory *ConfigFactory) createAssignedPodLW() *cache.ListWatch {
|
|||
|
||||
// createMinionLW returns a cache.ListWatch that gets all changes to minions.
|
||||
func (factory *ConfigFactory) createMinionLW() *cache.ListWatch {
|
||||
return cache.NewListWatchFromClient(factory.Client, "nodes", api.NamespaceAll, parseSelectorOrDie(""))
|
||||
}
|
||||
|
||||
// Lists all minions and filter out unhealthy ones, then returns
|
||||
// an enumerator for cache.Poller.
|
||||
func (factory *ConfigFactory) pollMinions() (cache.Enumerator, error) {
|
||||
allNodes, err := factory.Client.Nodes().List(labels.Everything(), fields.Everything())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
nodes := &api.NodeList{
|
||||
TypeMeta: allNodes.TypeMeta,
|
||||
ListMeta: allNodes.ListMeta,
|
||||
}
|
||||
for _, node := range allNodes.Items {
|
||||
conditionMap := make(map[api.NodeConditionType]*api.NodeCondition)
|
||||
for i := range node.Status.Conditions {
|
||||
cond := node.Status.Conditions[i]
|
||||
conditionMap[cond.Type] = &cond
|
||||
}
|
||||
if node.Spec.Unschedulable {
|
||||
continue
|
||||
}
|
||||
if condition, ok := conditionMap[api.NodeReady]; ok {
|
||||
if condition.Status == api.ConditionTrue {
|
||||
nodes.Items = append(nodes.Items, node)
|
||||
}
|
||||
} else {
|
||||
// If no condition is set, we get unknown node condition. In such cases,
|
||||
// do not add the node.
|
||||
glog.V(2).Infof("Minion %s is not available. Skipping", node.Name)
|
||||
}
|
||||
}
|
||||
return &nodeEnumerator{nodes}, nil
|
||||
// TODO: Filter out nodes that doesn't have NodeReady condition.
|
||||
fields := fields.Set{client.NodeUnschedulable: "false"}.AsSelector()
|
||||
return cache.NewListWatchFromClient(factory.Client, "nodes", api.NamespaceAll, fields)
|
||||
}
|
||||
|
||||
// Returns a cache.ListWatch that gets all changes to services.
|
||||
|
|
|
@ -131,168 +131,6 @@ func PriorityTwo(pod api.Pod, podLister algorithm.PodLister, minionLister algori
|
|||
return []algorithm.HostPriority{}, nil
|
||||
}
|
||||
|
||||
func TestPollMinions(t *testing.T) {
|
||||
table := []struct {
|
||||
minions []api.Node
|
||||
expectedCount int
|
||||
}{
|
||||
{
|
||||
minions: []api.Node{
|
||||
{
|
||||
ObjectMeta: api.ObjectMeta{Name: "foo"},
|
||||
Status: api.NodeStatus{
|
||||
Conditions: []api.NodeCondition{
|
||||
{Type: api.NodeReady, Status: api.ConditionTrue},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ObjectMeta: api.ObjectMeta{Name: "fiz"},
|
||||
Spec: api.NodeSpec{
|
||||
Unschedulable: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
ObjectMeta: api.ObjectMeta{Name: "baz"},
|
||||
Status: api.NodeStatus{
|
||||
Conditions: []api.NodeCondition{
|
||||
{Type: api.NodeReady, Status: api.ConditionTrue},
|
||||
{Type: api.NodeReady, Status: api.ConditionTrue},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ObjectMeta: api.ObjectMeta{Name: "fuz"},
|
||||
Status: api.NodeStatus{
|
||||
Conditions: []api.NodeCondition{
|
||||
{Type: api.NodeReady, Status: api.ConditionTrue},
|
||||
},
|
||||
},
|
||||
Spec: api.NodeSpec{
|
||||
Unschedulable: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
ObjectMeta: api.ObjectMeta{Name: "buz"},
|
||||
Status: api.NodeStatus{
|
||||
Conditions: []api.NodeCondition{
|
||||
{Type: api.NodeReady, Status: api.ConditionTrue},
|
||||
},
|
||||
},
|
||||
Spec: api.NodeSpec{
|
||||
Unschedulable: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
ObjectMeta: api.ObjectMeta{Name: "foobar"},
|
||||
Status: api.NodeStatus{
|
||||
Conditions: []api.NodeCondition{
|
||||
{Type: api.NodeReady, Status: api.ConditionFalse},
|
||||
},
|
||||
},
|
||||
Spec: api.NodeSpec{
|
||||
Unschedulable: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedCount: 3,
|
||||
},
|
||||
{
|
||||
minions: []api.Node{
|
||||
{
|
||||
ObjectMeta: api.ObjectMeta{Name: "foo"},
|
||||
Status: api.NodeStatus{
|
||||
Conditions: []api.NodeCondition{
|
||||
{Type: api.NodeReady, Status: api.ConditionTrue},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ObjectMeta: api.ObjectMeta{Name: "bar"},
|
||||
Status: api.NodeStatus{
|
||||
Conditions: []api.NodeCondition{
|
||||
{Type: api.NodeReady, Status: api.ConditionFalse},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedCount: 1,
|
||||
},
|
||||
{
|
||||
minions: []api.Node{
|
||||
{
|
||||
ObjectMeta: api.ObjectMeta{Name: "foo"},
|
||||
Spec: api.NodeSpec{
|
||||
Unschedulable: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
ObjectMeta: api.ObjectMeta{Name: "bar"},
|
||||
Spec: api.NodeSpec{
|
||||
Unschedulable: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedCount: 0,
|
||||
},
|
||||
{
|
||||
minions: []api.Node{
|
||||
{
|
||||
ObjectMeta: api.ObjectMeta{Name: "foo"},
|
||||
Status: api.NodeStatus{
|
||||
Conditions: []api.NodeCondition{
|
||||
{Type: api.NodeReady, Status: api.ConditionTrue},
|
||||
{Type: "invalidValue", Status: api.ConditionFalse}},
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedCount: 1,
|
||||
},
|
||||
{
|
||||
minions: []api.Node{
|
||||
{
|
||||
ObjectMeta: api.ObjectMeta{Name: "foo"},
|
||||
Status: api.NodeStatus{
|
||||
Conditions: []api.NodeCondition{},
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedCount: 0,
|
||||
},
|
||||
}
|
||||
|
||||
for _, item := range table {
|
||||
ml := &api.NodeList{Items: item.minions}
|
||||
handler := util.FakeHandler{
|
||||
StatusCode: 200,
|
||||
ResponseBody: runtime.EncodeOrDie(latest.Codec, ml),
|
||||
T: t,
|
||||
}
|
||||
mux := http.NewServeMux()
|
||||
// FakeHandler musn't be sent requests other than the one you want to test.
|
||||
resource := "nodes"
|
||||
if api.PreV1Beta3(testapi.Version()) {
|
||||
resource = "minions"
|
||||
}
|
||||
mux.Handle(testapi.ResourcePath(resource, api.NamespaceAll, ""), &handler)
|
||||
server := httptest.NewServer(mux)
|
||||
defer server.Close()
|
||||
client := client.NewOrDie(&client.Config{Host: server.URL, Version: testapi.Version()})
|
||||
cf := NewConfigFactory(client)
|
||||
|
||||
ce, err := cf.pollMinions()
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error: %v", err)
|
||||
continue
|
||||
}
|
||||
handler.ValidateRequest(t, testapi.ResourcePath(resource, api.NamespaceAll, ""), "GET", nil)
|
||||
|
||||
if a := ce.Len(); item.expectedCount != a {
|
||||
t.Errorf("Expected %v, got %v", item.expectedCount, a)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestDefaultErrorFunc(t *testing.T) {
|
||||
testPod := &api.Pod{
|
||||
ObjectMeta: api.ObjectMeta{Name: "foo", Namespace: "bar"},
|
||||
|
|
Loading…
Reference in New Issue