Merge pull request #1343 from dbcode/master

Improve error detection for URL manifests, and skip parsing if content unchanged
pull/6/head
Brendan Burns 2014-09-17 15:34:56 -07:00
commit a1439542a1
2 changed files with 36 additions and 3 deletions

View File

@ -18,6 +18,7 @@ limitations under the License.
package config
import (
"bytes"
"fmt"
"io/ioutil"
"net/http"
@ -34,12 +35,14 @@ import (
type SourceURL struct {
url string
updates chan<- interface{}
data []byte
}
func NewSourceURL(url string, period time.Duration, updates chan<- interface{}) *SourceURL {
config := &SourceURL{
url: url,
updates: updates,
data: nil,
}
glog.Infof("Watching URL %s", url)
go util.Forever(config.run, period)
@ -68,6 +71,11 @@ func (s *SourceURL) extractFromURL() error {
if len(data) == 0 {
return fmt.Errorf("zero-length data received from %v", s.url)
}
// Short circuit if the manifest has not changed since the last time it was read.
if bytes.Compare(data, s.data) == 0 {
return nil
}
s.data = data
// First try as if it's a single manifest
var manifest api.ContainerManifest
@ -101,6 +109,13 @@ func (s *SourceURL) extractFromURL() error {
}
}
if multiErr == nil {
// A single manifest that did not pass semantic validation will yield an empty
// array of manifests (and no error) when unmarshaled as such. In that case,
// if the single manifest at least had a Version, we return the single-manifest
// error (if any).
if len(manifests) == 0 && manifest.Version != "" {
return singleErr
}
pods := []kubelet.Pod{}
for i, manifest := range manifests {
pod := kubelet.Pod{Name: manifest.ID, Manifest: manifest}

View File

@ -40,7 +40,7 @@ func TestURLErrorNotExistNoUpdate(t *testing.T) {
func TestExtractFromHttpBadness(t *testing.T) {
ch := make(chan interface{}, 1)
c := SourceURL{"http://localhost:49575/_not_found_", ch}
c := SourceURL{"http://localhost:49575/_not_found_", ch, nil}
if err := c.extractFromURL(); err == nil {
t.Errorf("Expected error")
}
@ -75,6 +75,24 @@ func TestExtractInvalidManifest(t *testing.T) {
},
},
},
{
desc: "Unspecified container name",
manifests: []api.ContainerManifest{
{
Version: "v1beta1",
Containers: []api.Container{{Name: ""}},
},
},
},
{
desc: "Invalid container name",
manifests: []api.ContainerManifest{
{
Version: "v1beta1",
Containers: []api.Container{{Name: "_INVALID_"}},
},
},
},
}
for _, testCase := range testCases {
data, err := json.Marshal(testCase.manifests)
@ -87,7 +105,7 @@ func TestExtractInvalidManifest(t *testing.T) {
}
testServer := httptest.NewServer(&fakeHandler)
ch := make(chan interface{}, 1)
c := SourceURL{testServer.URL, ch}
c := SourceURL{testServer.URL, ch, nil}
if err := c.extractFromURL(); err == nil {
t.Errorf("%s: Expected error", testCase.desc)
}
@ -146,7 +164,7 @@ func TestExtractFromHTTP(t *testing.T) {
}
testServer := httptest.NewServer(&fakeHandler)
ch := make(chan interface{}, 1)
c := SourceURL{testServer.URL, ch}
c := SourceURL{testServer.URL, ch, nil}
if err := c.extractFromURL(); err != nil {
t.Errorf("%s: Unexpected error: %v", testCase.desc, err)
}