Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve "constraint violation" error message. #4132

Merged
merged 3 commits into from
Feb 5, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
10 changes: 8 additions & 2 deletions pkg/constraint/constraint.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,17 @@ limitations under the License.
package constraint

import (
"fmt"

"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
)

// Allowed returns true if pods is a collection of bound pods
// which can run without conflict on a single minion.
func Allowed(pods []api.BoundPod) bool {
return !PortsConflict(pods)
func Allowed(pods []api.BoundPod) []error {
errors := []error{}
for _, port := range hostPortsConflict(pods) {
errors = append(errors, fmt.Errorf("host port %v is already in use", port))
}
return errors
}
15 changes: 8 additions & 7 deletions pkg/constraint/constraint_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ limitations under the License.
package constraint

import (
"fmt"
"testing"

"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
Expand All @@ -40,11 +41,11 @@ func podWithContainers(containers ...api.Container) api.BoundPod {

func TestAllowed(t *testing.T) {
table := []struct {
allowed bool
pods []api.BoundPod
err string
pods []api.BoundPod
}{
{
allowed: true,
err: "[]",
pods: []api.BoundPod{
podWithContainers(
containerWithHostPorts(1, 2, 3),
Expand All @@ -57,7 +58,7 @@ func TestAllowed(t *testing.T) {
},
},
{
allowed: true,
err: "[]",
pods: []api.BoundPod{
podWithContainers(
containerWithHostPorts(0, 0),
Expand All @@ -70,15 +71,15 @@ func TestAllowed(t *testing.T) {
},
},
{
allowed: false,
err: "[host port 3 is already in use]",
pods: []api.BoundPod{
podWithContainers(
containerWithHostPorts(3, 3),
),
},
},
{
allowed: false,
err: "[host port 6 is already in use]",
pods: []api.BoundPod{
podWithContainers(
containerWithHostPorts(6),
Expand All @@ -91,7 +92,7 @@ func TestAllowed(t *testing.T) {
}

for _, item := range table {
if e, a := item.allowed, Allowed(item.pods); e != a {
if e, a := item.err, Allowed(item.pods); e != fmt.Sprintf("%v", a) {
t.Errorf("Expected %v, got %v: \n%v\v", e, a, item.pods)
}
}
Expand Down
12 changes: 7 additions & 5 deletions pkg/constraint/ports.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,22 +20,24 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
)

// PortsConflict returns true iff two containers attempt to expose
// the same host port.
func PortsConflict(pods []api.BoundPod) bool {
// hostPortsConflict returns an array of host ports that at least two
// containers attempt to expose. The array is empty if no such port
// exists.
func hostPortsConflict(pods []api.BoundPod) []int {
hostPorts := map[int]struct{}{}
conflictingPorts := []int{}
for _, pod := range pods {
for _, container := range pod.Spec.Containers {
for _, port := range container.Ports {
if port.HostPort == 0 {
continue
}
if _, exists := hostPorts[port.HostPort]; exists {
return true
conflictingPorts = append(conflictingPorts, port.HostPort)
}
hostPorts[port.HostPort] = struct{}{}
}
}
}
return false
return conflictingPorts
}
4 changes: 2 additions & 2 deletions pkg/registry/etcd/etcd.go
Original file line number Diff line number Diff line change
Expand Up @@ -214,8 +214,8 @@ func (r *Registry) assignPod(ctx api.Context, podID string, machine string) erro
err = r.AtomicUpdate(contKey, &api.BoundPods{}, func(in runtime.Object) (runtime.Object, error) {
boundPodList := in.(*api.BoundPods)
boundPodList.Items = append(boundPodList.Items, *boundPod)
if !constraint.Allowed(boundPodList.Items) {
return nil, fmt.Errorf("the assignment would cause a constraint violation")
if errors := constraint.Allowed(boundPodList.Items); len(errors) > 0 {
return nil, fmt.Errorf("the assignment would cause the following constraints violation: %v", errors)
}
return boundPodList, nil
})
Expand Down