Merge pull request #1343 from dbcode/master

Improve error detection for URL manifests, and skip parsing if content unchanged
This commit is contained in:
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 package config
import ( import (
"bytes"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"net/http" "net/http"
@ -34,12 +35,14 @@ import (
type SourceURL struct { type SourceURL struct {
url string url string
updates chan<- interface{} updates chan<- interface{}
data []byte
} }
func NewSourceURL(url string, period time.Duration, updates chan<- interface{}) *SourceURL { func NewSourceURL(url string, period time.Duration, updates chan<- interface{}) *SourceURL {
config := &SourceURL{ config := &SourceURL{
url: url, url: url,
updates: updates, updates: updates,
data: nil,
} }
glog.Infof("Watching URL %s", url) glog.Infof("Watching URL %s", url)
go util.Forever(config.run, period) go util.Forever(config.run, period)
@ -68,6 +71,11 @@ func (s *SourceURL) extractFromURL() error {
if len(data) == 0 { if len(data) == 0 {
return fmt.Errorf("zero-length data received from %v", s.url) 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 // First try as if it's a single manifest
var manifest api.ContainerManifest var manifest api.ContainerManifest
@ -101,6 +109,13 @@ func (s *SourceURL) extractFromURL() error {
} }
} }
if multiErr == nil { 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{} pods := []kubelet.Pod{}
for i, manifest := range manifests { for i, manifest := range manifests {
pod := kubelet.Pod{Name: manifest.ID, Manifest: manifest} pod := kubelet.Pod{Name: manifest.ID, Manifest: manifest}

View File

@ -40,7 +40,7 @@ func TestURLErrorNotExistNoUpdate(t *testing.T) {
func TestExtractFromHttpBadness(t *testing.T) { func TestExtractFromHttpBadness(t *testing.T) {
ch := make(chan interface{}, 1) 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 { if err := c.extractFromURL(); err == nil {
t.Errorf("Expected error") 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 { for _, testCase := range testCases {
data, err := json.Marshal(testCase.manifests) data, err := json.Marshal(testCase.manifests)
@ -87,7 +105,7 @@ func TestExtractInvalidManifest(t *testing.T) {
} }
testServer := httptest.NewServer(&fakeHandler) testServer := httptest.NewServer(&fakeHandler)
ch := make(chan interface{}, 1) ch := make(chan interface{}, 1)
c := SourceURL{testServer.URL, ch} c := SourceURL{testServer.URL, ch, nil}
if err := c.extractFromURL(); err == nil { if err := c.extractFromURL(); err == nil {
t.Errorf("%s: Expected error", testCase.desc) t.Errorf("%s: Expected error", testCase.desc)
} }
@ -146,7 +164,7 @@ func TestExtractFromHTTP(t *testing.T) {
} }
testServer := httptest.NewServer(&fakeHandler) testServer := httptest.NewServer(&fakeHandler)
ch := make(chan interface{}, 1) ch := make(chan interface{}, 1)
c := SourceURL{testServer.URL, ch} c := SourceURL{testServer.URL, ch, nil}
if err := c.extractFromURL(); err != nil { if err := c.extractFromURL(); err != nil {
t.Errorf("%s: Unexpected error: %v", testCase.desc, err) t.Errorf("%s: Unexpected error: %v", testCase.desc, err)
} }