Merge pull request #3664 from thockin/pull-if

Pull if
This commit is contained in:
Tim Hockin 2015-01-21 13:05:28 -08:00
commit 30219f8dfa
13 changed files with 186 additions and 17 deletions

View File

@ -15,7 +15,7 @@ All users of the cluster will have access to any private registry in the `.docke
## Preloading Images ## Preloading Images
Be default, the kubelet will try to pull each image from the specified registry. Be default, the kubelet will try to pull each image from the specified registry.
However, if the `imagePullPolicy` property of the container is set to `PullIfNotPresent` or `PullNever`, However, if the `imagePullPolicy` property of the container is set to `IfNotPresent` or `Never`,
then a local image is used (preferentially or exclusively, respectively). then a local image is used (preferentially or exclusively, respectively).
This can be used to preload certain images for speed or as an alternative to authenticating to a private registry. This can be used to preload certain images for speed or as an alternative to authenticating to a private registry.

View File

@ -131,6 +131,10 @@ var apiObjectFuzzer = fuzz.New().NilChance(.5).NumElements(1, 1).Funcs(
c.RandString(): c.RandString(), c.RandString(): c.RandString(),
} }
}, },
func(p *internal.PullPolicy, c fuzz.Continue) {
policies := []internal.PullPolicy{internal.PullAlways, internal.PullNever, internal.PullIfNotPresent}
*p = policies[c.Rand.Intn(len(policies))]
},
) )
func TestInternalRoundTrip(t *testing.T) { func TestInternalRoundTrip(t *testing.T) {

View File

@ -146,7 +146,6 @@ func fuzzerFor(t *testing.T, version string, src rand.Source) *fuzz.Fuzzer {
c.RandString(): c.RandString(), c.RandString(): c.RandString(),
} }
}, },
func(q *resource.Quantity, c fuzz.Continue) { func(q *resource.Quantity, c fuzz.Continue) {
// Real Quantity fuzz testing is done elsewhere; // Real Quantity fuzz testing is done elsewhere;
// this limited subset of functionality survives // this limited subset of functionality survives
@ -156,6 +155,10 @@ func fuzzerFor(t *testing.T, version string, src rand.Source) *fuzz.Fuzzer {
//q.Amount.SetScale(inf.Scale(-c.Intn(12))) //q.Amount.SetScale(inf.Scale(-c.Intn(12)))
q.Amount.SetUnscaled(c.Int63n(1000)) q.Amount.SetUnscaled(c.Int63n(1000))
}, },
func(p *api.PullPolicy, c fuzz.Continue) {
policies := []api.PullPolicy{api.PullAlways, api.PullNever, api.PullIfNotPresent}
*p = policies[c.Rand.Intn(len(policies))]
},
) )
return f return f
} }

View File

@ -291,11 +291,11 @@ type PullPolicy string
const ( const (
// PullAlways means that kubelet always attempts to pull the latest image. Container will fail If the pull fails. // PullAlways means that kubelet always attempts to pull the latest image. Container will fail If the pull fails.
PullAlways PullPolicy = "PullAlways" PullAlways PullPolicy = "Always"
// PullNever means that kubelet never pulls an image, but only uses a local image. Container will fail if the image isn't present // PullNever means that kubelet never pulls an image, but only uses a local image. Container will fail if the image isn't present
PullNever PullPolicy = "PullNever" PullNever PullPolicy = "Never"
// PullIfNotPresent means that kubelet pulls if the image isn't present on disk. Container will fail if the image isn't present and the pull fails. // PullIfNotPresent means that kubelet pulls if the image isn't present on disk. Container will fail if the image isn't present and the pull fails.
PullIfNotPresent PullPolicy = "PullIfNotPresent" PullIfNotPresent PullPolicy = "IfNotPresent"
) )
// Container represents a single container that is expected to be run on the host. // Container represents a single container that is expected to be run on the host.

View File

@ -707,6 +707,39 @@ func init() {
} }
return nil return nil
}, },
func(in *newer.PullPolicy, out *PullPolicy, s conversion.Scope) error {
switch *in {
case newer.PullAlways:
*out = PullAlways
case newer.PullNever:
*out = PullNever
case newer.PullIfNotPresent:
*out = PullIfNotPresent
case "":
*out = ""
default:
// Let unknown values through - they will get caught by validation
*out = PullPolicy(*in)
}
return nil
},
func(in *PullPolicy, out *newer.PullPolicy, s conversion.Scope) error {
switch *in {
case PullAlways:
*out = newer.PullAlways
case PullNever:
*out = newer.PullNever
case PullIfNotPresent:
*out = newer.PullIfNotPresent
case "":
*out = ""
default:
// Let unknown values through - they will get caught by validation
*out = newer.PullPolicy(*in)
}
return nil
},
) )
if err != nil { if err != nil {
// If one of the conversion functions is malformed, detect it immediately. // If one of the conversion functions is malformed, detect it immediately.

View File

@ -270,3 +270,49 @@ func TestServiceEmptySelector(t *testing.T) {
t.Errorf("unexpected selector: %#v", obj) t.Errorf("unexpected selector: %#v", obj)
} }
} }
func TestPullPolicyConversion(t *testing.T) {
table := []struct {
versioned current.PullPolicy
internal newer.PullPolicy
}{
{
versioned: current.PullAlways,
internal: newer.PullAlways,
}, {
versioned: current.PullNever,
internal: newer.PullNever,
}, {
versioned: current.PullIfNotPresent,
internal: newer.PullIfNotPresent,
}, {
versioned: "",
internal: "",
}, {
versioned: "invalid value",
internal: "invalid value",
},
}
for _, item := range table {
var got newer.PullPolicy
err := Convert(&item.versioned, &got)
if err != nil {
t.Errorf("Unexpected error: %v", err)
continue
}
if e, a := item.internal, got; e != a {
t.Errorf("Expected: %q, got %q", e, a)
}
}
for _, item := range table {
var got current.PullPolicy
err := Convert(&item.internal, &got)
if err != nil {
t.Errorf("Unexpected error: %v", err)
continue
}
if e, a := item.versioned, got; e != a {
t.Errorf("Expected: %q, got %q", e, a)
}
}
}

View File

@ -620,6 +620,39 @@ func init() {
} }
return nil return nil
}, },
func(in *newer.PullPolicy, out *PullPolicy, s conversion.Scope) error {
switch *in {
case newer.PullAlways:
*out = PullAlways
case newer.PullNever:
*out = PullNever
case newer.PullIfNotPresent:
*out = PullIfNotPresent
case "":
*out = ""
default:
// Let unknown values through - they will get caught by validation
*out = PullPolicy(*in)
}
return nil
},
func(in *PullPolicy, out *newer.PullPolicy, s conversion.Scope) error {
switch *in {
case PullAlways:
*out = newer.PullAlways
case PullNever:
*out = newer.PullNever
case PullIfNotPresent:
*out = newer.PullIfNotPresent
case "":
*out = ""
default:
// Let unknown values through - they will get caught by validation
*out = newer.PullPolicy(*in)
}
return nil
},
) )
if err != nil { if err != nil {
// If one of the conversion functions is malformed, detect it immediately. // If one of the conversion functions is malformed, detect it immediately.

View File

@ -100,3 +100,49 @@ func TestNodeConversion(t *testing.T) {
t.Errorf("unexpected encoding: %s - %#v", m["kind"], string(data)) t.Errorf("unexpected encoding: %s - %#v", m["kind"], string(data))
} }
} }
func TestPullPolicyConversion(t *testing.T) {
table := []struct {
versioned current.PullPolicy
internal newer.PullPolicy
}{
{
versioned: current.PullAlways,
internal: newer.PullAlways,
}, {
versioned: current.PullNever,
internal: newer.PullNever,
}, {
versioned: current.PullIfNotPresent,
internal: newer.PullIfNotPresent,
}, {
versioned: "",
internal: "",
}, {
versioned: "invalid value",
internal: "invalid value",
},
}
for _, item := range table {
var got newer.PullPolicy
err := newer.Scheme.Convert(&item.versioned, &got)
if err != nil {
t.Errorf("Unexpected error: %v", err)
continue
}
if e, a := item.internal, got; e != a {
t.Errorf("Expected: %q, got %q", e, a)
}
}
for _, item := range table {
var got current.PullPolicy
err := newer.Scheme.Convert(&item.internal, &got)
if err != nil {
t.Errorf("Unexpected error: %v", err)
continue
}
if e, a := item.versioned, got; e != a {
t.Errorf("Expected: %q, got %q", e, a)
}
}
}

View File

@ -309,11 +309,11 @@ type PullPolicy string
const ( const (
// PullAlways means that kubelet always attempts to pull the latest image. Container will fail If the pull fails. // PullAlways means that kubelet always attempts to pull the latest image. Container will fail If the pull fails.
PullAlways PullPolicy = "PullAlways" PullAlways PullPolicy = "Always"
// PullNever means that kubelet never pulls an image, but only uses a local image. Container will fail if the image isn't present // PullNever means that kubelet never pulls an image, but only uses a local image. Container will fail if the image isn't present
PullNever PullPolicy = "PullNever" PullNever PullPolicy = "Never"
// PullIfNotPresent means that kubelet pulls if the image isn't present on disk. Container will fail if the image isn't present and the pull fails. // PullIfNotPresent means that kubelet pulls if the image isn't present on disk. Container will fail if the image isn't present and the pull fails.
PullIfNotPresent PullPolicy = "PullIfNotPresent" PullIfNotPresent PullPolicy = "IfNotPresent"
) )
// Container represents a single container that is expected to be run on the host. // Container represents a single container that is expected to be run on the host.

View File

@ -118,6 +118,10 @@ var apiObjectFuzzer = fuzz.New().NilChance(.5).NumElements(1, 1).Funcs(
c.RandString(): c.RandString(), c.RandString(): c.RandString(),
} }
}, },
func(p *api.PullPolicy, c fuzz.Continue) {
policies := []api.PullPolicy{api.PullAlways, api.PullNever, api.PullIfNotPresent}
*p = policies[c.Rand.Intn(len(policies))]
},
) )
func TestLoad(t *testing.T) { func TestLoad(t *testing.T) {

View File

@ -227,27 +227,27 @@ func TestValidatePullPolicy(t *testing.T) {
} }
testCases := map[string]T{ testCases := map[string]T{
"NotPresent1": { "NotPresent1": {
api.Container{Name: "abc", Image: "image:latest", ImagePullPolicy: "PullIfNotPresent"}, api.Container{Name: "abc", Image: "image:latest", ImagePullPolicy: "IfNotPresent"},
api.PullIfNotPresent, api.PullIfNotPresent,
}, },
"NotPresent2": { "NotPresent2": {
api.Container{Name: "abc1", Image: "image", ImagePullPolicy: "PullIfNotPresent"}, api.Container{Name: "abc1", Image: "image", ImagePullPolicy: "IfNotPresent"},
api.PullIfNotPresent, api.PullIfNotPresent,
}, },
"Always1": { "Always1": {
api.Container{Name: "123", Image: "image:latest", ImagePullPolicy: "PullAlways"}, api.Container{Name: "123", Image: "image:latest", ImagePullPolicy: "Always"},
api.PullAlways, api.PullAlways,
}, },
"Always2": { "Always2": {
api.Container{Name: "1234", Image: "image", ImagePullPolicy: "PullAlways"}, api.Container{Name: "1234", Image: "image", ImagePullPolicy: "Always"},
api.PullAlways, api.PullAlways,
}, },
"Never1": { "Never1": {
api.Container{Name: "abc-123", Image: "image:latest", ImagePullPolicy: "PullNever"}, api.Container{Name: "abc-123", Image: "image:latest", ImagePullPolicy: "Never"},
api.PullNever, api.PullNever,
}, },
"Never2": { "Never2": {
api.Container{Name: "abc-1234", Image: "image", ImagePullPolicy: "PullNever"}, api.Container{Name: "abc-1234", Image: "image", ImagePullPolicy: "Never"},
api.PullNever, api.PullNever,
}, },
"DefaultToNotPresent": {api.Container{Name: "notPresent", Image: "image"}, api.PullIfNotPresent}, "DefaultToNotPresent": {api.Container{Name: "notPresent", Image: "image"}, api.PullIfNotPresent},

View File

@ -157,7 +157,7 @@ func TestExtractFromHTTP(t *testing.T) {
Name: "1", Name: "1",
Image: "foo", Image: "foo",
TerminationMessagePath: "/dev/termination-log", TerminationMessagePath: "/dev/termination-log",
ImagePullPolicy: "PullIfNotPresent"}}, ImagePullPolicy: "IfNotPresent"}},
}, },
}, },
api.BoundPod{ api.BoundPod{
@ -171,7 +171,7 @@ func TestExtractFromHTTP(t *testing.T) {
Name: "1", Name: "1",
Image: "foo", Image: "foo",
TerminationMessagePath: "/dev/termination-log", TerminationMessagePath: "/dev/termination-log",
ImagePullPolicy: "PullIfNotPresent"}}, ImagePullPolicy: "IfNotPresent"}},
}, },
}), }),
}, },

View File

@ -487,7 +487,7 @@ func TestSyncPodsCreatesNetAndContainerPullsImage(t *testing.T) {
}, },
Spec: api.PodSpec{ Spec: api.PodSpec{
Containers: []api.Container{ Containers: []api.Container{
{Name: "bar", Image: "something", ImagePullPolicy: "PullIfNotPresent"}, {Name: "bar", Image: "something", ImagePullPolicy: "IfNotPresent"},
}, },
}, },
}, },