// watchHandler watches w and keeps *resourceVersion up to date. func (gc *Reflector) watchHandler(w watch.Interface, resourceVersion *uint64) { for { event, ok := <-w.ResultChan() if !ok { glog.Errorf("unexpected watch close") return } if e, a := gc.expectedType, reflect.TypeOf(event.Object); e != a { glog.Errorf("expected type %v, but watch event object had type %v", e, a) continue } jsonBase, err := runtime.FindJSONBase(event.Object) if err != nil { glog.Errorf("unable to understand watch event %#v", event) continue } switch event.Type { case watch.Added: gc.store.Add(jsonBase.ID(), event.Object) case watch.Modified: gc.store.Update(jsonBase.ID(), event.Object) case watch.Deleted: // TODO: Will any consumers need access to the "last known // state", which is passed in event.Object? If so, may need // to change this. gc.store.Delete(jsonBase.ID()) default: glog.Errorf("unable to understand watch event %#v", event) } *resourceVersion = jsonBase.ResourceVersion() + 1 } }
func (r *Reflector) listAndWatch() { var resourceVersion uint64 list, err := r.listerWatcher.List() if err != nil { glog.Errorf("Failed to list %v: %v", r.expectedType, err) return } jsonBase, err := runtime.FindJSONBase(list) if err != nil { glog.Errorf("Unable to understand list result %#v", list) return } resourceVersion = jsonBase.ResourceVersion() items, err := runtime.ExtractList(list) if err != nil { glog.Errorf("Unable to understand list result %#v (%v)", list, err) return } err = r.syncWith(items) if err != nil { glog.Errorf("Unable to sync list result: %v", err) return } for { w, err := r.listerWatcher.Watch(resourceVersion) if err != nil { glog.Errorf("failed to watch %v: %v", r.expectedType, err) return } r.watchHandler(w, &resourceVersion) } }
// syncWith replaces the store's items with the given list. func (r *Reflector) syncWith(items []runtime.Object) error { found := map[string]interface{}{} for _, item := range items { jsonBase, err := runtime.FindJSONBase(item) if err != nil { return fmt.Errorf("unexpected item in list: %v", err) } found[jsonBase.ID()] = item } r.store.Replace(found) return nil }
func runTest(t *testing.T, source interface{}) { name := reflect.TypeOf(source).Elem().Name() apiObjectFuzzer.Fuzz(source) j, err := runtime.FindJSONBase(source) if err != nil { t.Fatalf("Unexpected error %v for %#v", err, source) } j.SetKind("") j.SetAPIVersion("") data, err := runtime.Encode(source) if err != nil { t.Errorf("%v: %v (%#v)", name, err, source) return } obj2, err := runtime.Decode(data) if err != nil { t.Errorf("%v: %v", name, err) return } else { if !reflect.DeepEqual(source, obj2) { t.Errorf("1: %v: diff: %v", name, objDiff(source, obj2)) return } } obj3 := reflect.New(reflect.TypeOf(source).Elem()).Interface() err = runtime.DecodeInto(data, obj3) if err != nil { t.Errorf("2: %v: %v", name, err) return } else { if !reflect.DeepEqual(source, obj3) { t.Errorf("3: %v: diff: %v", name, objDiff(source, obj3)) return } } }
func (c *KubeConfig) executeAPIRequest(method string, clients map[string]RESTClient) bool { storage, path, hasSuffix := storagePathFromArg(c.Arg(1)) validStorage := checkStorage(storage) client, ok := clients[storage] if !ok { glog.Fatalf("Unsupported storage type %s", storage) } verb := "" setBody := false var version uint64 switch method { case "get": verb = "GET" if !validStorage || !hasSuffix { glog.Fatalf("usage: kubecfg [OPTIONS] %s <%s>[/<id>]", method, prettyWireStorage()) } case "list": verb = "GET" if !validStorage || hasSuffix { glog.Fatalf("usage: kubecfg [OPTIONS] %s <%s>", method, prettyWireStorage()) } case "delete": verb = "DELETE" if !validStorage || !hasSuffix { glog.Fatalf("usage: kubecfg [OPTIONS] %s <%s>/<id>", method, prettyWireStorage()) } case "create": verb = "POST" setBody = true if !validStorage || hasSuffix { glog.Fatalf("usage: kubecfg [OPTIONS] %s <%s>", method, prettyWireStorage()) } case "update": obj, err := client.Verb("GET").Path(path).Do().Get() if err != nil { glog.Fatalf("error obtaining resource version for update: %v", err) } jsonBase, err := runtime.FindJSONBase(obj) if err != nil { glog.Fatalf("error finding json base for update: %v", err) } version = jsonBase.ResourceVersion() verb = "PUT" setBody = true if !validStorage || !hasSuffix { glog.Fatalf("usage: kubecfg [OPTIONS] %s <%s>/<id>", method, prettyWireStorage()) } default: return false } r := client.Verb(verb). Path(path). ParseSelectorParam("labels", c.Selector) if setBody { if version != 0 { data := c.readConfig(storage) obj, err := runtime.Decode(data) if err != nil { glog.Fatalf("error setting resource version: %v", err) } jsonBase, err := runtime.FindJSONBase(obj) if err != nil { glog.Fatalf("error setting resource version: %v", err) } jsonBase.SetResourceVersion(version) data, err = runtime.Encode(obj) if err != nil { glog.Fatalf("error setting resource version: %v", err) } r.Body(data) } else { r.Body(c.readConfig(storage)) } } result := r.Do() obj, err := result.Get() if err != nil { glog.Fatalf("Got request error: %v\n", err) return false } var printer kubecfg.ResourcePrinter switch { case c.JSON: printer = &kubecfg.IdentityPrinter{} case c.YAML: printer = &kubecfg.YAMLPrinter{} case len(c.TemplateFile) > 0 || len(c.TemplateStr) > 0: var data []byte if len(c.TemplateFile) > 0 { var err error data, err = ioutil.ReadFile(c.TemplateFile) if err != nil { glog.Fatalf("Error reading template %s, %v\n", c.TemplateFile, err) return false } } else { data = []byte(c.TemplateStr) } tmpl, err := template.New("output").Parse(string(data)) if err != nil { glog.Fatalf("Error parsing template %s, %v\n", string(data), err) return false } printer = &kubecfg.TemplatePrinter{ Template: tmpl, } default: printer = humanReadablePrinter() } if err = printer.PrintObj(obj, os.Stdout); err != nil { body, _ := result.Raw() glog.Fatalf("Failed to print: %v\nRaw received object:\n%#v\n\nBody received: %v", err, obj, string(body)) } fmt.Print("\n") return true }