Browse Source

Fix merge conflicts; revise KubeModel

Niko Kovacevic 5 tháng trước cách đây
mục cha
commit
0710c2e385

+ 11 - 3
core/pkg/model/kubemodel/cluster.go

@@ -1,6 +1,7 @@
 package kubemodel
 
 import (
+	"errors"
 	"time"
 )
 
@@ -14,13 +15,20 @@ type Cluster struct {
 	End      time.Time `json:"end"`      // @bingen:field[version=1]
 }
 
-func (kms *KubeModelSet) RegisterCluster(uid string) {
+func (kms *KubeModelSet) RegisterCluster(uid string) error {
 	if uid == "" {
-		kms.RegisterError("RegisterCluster: uid is nil for Cluster")
-		return
+		err := errors.New("RegisterCluster: uid is nil")
+		kms.Error(err)
+		return err
 	}
 
 	if kms.Cluster == nil {
 		kms.Cluster = &Cluster{UID: uid}
+	} else if uid != kms.Cluster.UID {
+		kms.Warnf("RegisterCluster(%s): attempting to change cluster UID from %s to %s", uid, kms.Cluster.UID, uid)
+	} else {
+		kms.Debugf("RegisterCluster(%s): cluster already registered", uid)
 	}
+
+	return nil
 }

+ 23 - 1
core/pkg/model/kubemodel/container.go

@@ -1,6 +1,9 @@
 package kubemodel
 
-import "time"
+import (
+	"fmt"
+	"time"
+)
 
 // @bingen:generate:Container
 type Container struct {
@@ -21,3 +24,22 @@ type Container struct {
 	StorageByteUsageAverage             uint64    `json:"storageByteUsageAverage"`             // @bingen:field[version=1]
 	StorageByteUsageMax                 uint64    `json:"storageByteUsageMax"`                 // @bingen:field[version=1]
 }
+
+func (kms *KubeModelSet) RegisterContainer(uid, name, podUID string) error {
+	if uid == "" {
+		err := fmt.Errorf("UID is nil for Container '%s'", name)
+		kms.Error(err)
+		return err
+	}
+
+	if _, ok := kms.Containers[uid]; !ok {
+		kms.Containers[uid] = &Container{
+			PodUID: podUID,
+			Name:   name,
+		}
+
+		kms.Metadata.ObjectCount++
+	}
+
+	return nil
+}

+ 160 - 11
core/pkg/model/kubemodel/diagnostic.go

@@ -1,14 +1,163 @@
 package kubemodel
 
-import "time"
-
-// @bingen:generate:DiagnosticResult
-type DiagnosticResult struct {
-	UID         string            `json:"uid"`               // @bingen:field[version=1]
-	Name        string            `json:"name"`              // @bingen:field[version=1]
-	Description string            `json:"description"`       // @bingen:field[version=1]
-	Category    string            `json:"category"`          // @bingen:field[version=1]
-	Timestamp   time.Time         `json:"timestamp"`         // @bingen:field[version=1]
-	Error       string            `json:"error,omitempty"`   // @bingen:field[version=1]
-	Details     map[string]string `json:"details,omitempty"` // @bingen:field[version=1]
+import (
+	"fmt"
+	"time"
+)
+
+// @bingen:generate:DiagnosticLevel
+type DiagnosticLevel int
+
+const (
+	DiagnosticLevelTrace DiagnosticLevel = iota
+	DiagnosticLevelDebug
+	DiagnosticLevelInfo
+	DiagnosticLevelWarning
+	DiagnosticLevelError
+)
+
+const DefaultDiagnosticLevel = DiagnosticLevelInfo
+
+// @bingen:generate:Diagnostic
+type Diagnostic struct {
+	Timestamp time.Time         `json:"timestamp"`         // @bingen:field[version=1]
+	Level     DiagnosticLevel   `json:"level"`             // @bingen:field[version=1]
+	Message   string            `json:"message"`           // @bingen:field[version=1]
+	Details   map[string]string `json:"details,omitempty"` // @bingen:field[version=1]
+}
+
+func (kms *KubeModelSet) RegisterDiagnostic(d Diagnostic) {
+	kms.Metadata.Diagnostics = append(kms.Metadata.Diagnostics, d)
+}
+
+func (kms *KubeModelSet) GetErrors() []Diagnostic {
+	ds := []Diagnostic{}
+
+	for _, d := range kms.Metadata.Diagnostics {
+		if d.Level == DiagnosticLevelError {
+			ds = append(ds, d)
+		}
+	}
+
+	return ds
+}
+
+func (kms *KubeModelSet) Error(err error) {
+	kms.RegisterDiagnostic(Diagnostic{
+		Timestamp: time.Now().UTC(),
+		Level:     DiagnosticLevelError,
+		Message:   err.Error(),
+	})
+}
+
+func (kms *KubeModelSet) GetWarnings() []Diagnostic {
+	ds := []Diagnostic{}
+
+	for _, d := range kms.Metadata.Diagnostics {
+		if d.Level == DiagnosticLevelWarning {
+			ds = append(ds, d)
+		}
+	}
+
+	return ds
+}
+
+func (kms *KubeModelSet) Warnf(msg string, a ...any) {
+	kms.Warn(fmt.Sprintf(msg, a...))
+}
+
+func (kms *KubeModelSet) Warn(msg string, a ...any) {
+	if kms.Metadata.DiagnosticLevel > DiagnosticLevelWarning {
+		return
+	}
+
+	kms.RegisterDiagnostic(Diagnostic{
+		Timestamp: time.Now().UTC(),
+		Level:     DiagnosticLevelWarning,
+		Message:   msg,
+	})
+}
+
+func (kms *KubeModelSet) GetInfos() []Diagnostic {
+	ds := []Diagnostic{}
+
+	for _, d := range kms.Metadata.Diagnostics {
+		if d.Level == DiagnosticLevelInfo {
+			ds = append(ds, d)
+		}
+	}
+
+	return ds
+}
+
+func (kms *KubeModelSet) Infof(msg string, a ...any) {
+	kms.Info(fmt.Sprintf(msg, a...))
+}
+
+func (kms *KubeModelSet) Info(msg string) {
+	if kms.Metadata.DiagnosticLevel > DiagnosticLevelInfo {
+		return
+	}
+
+	kms.RegisterDiagnostic(Diagnostic{
+		Timestamp: time.Now().UTC(),
+		Level:     DiagnosticLevelInfo,
+		Message:   msg,
+	})
+}
+
+func (kms *KubeModelSet) GetDebugs() []Diagnostic {
+	ds := []Diagnostic{}
+
+	for _, d := range kms.Metadata.Diagnostics {
+		if d.Level == DiagnosticLevelDebug {
+			ds = append(ds, d)
+		}
+	}
+
+	return ds
+}
+
+func (kms *KubeModelSet) Debugf(msg string, a ...any) {
+	kms.Debug(fmt.Sprintf(msg, a...))
+}
+
+func (kms *KubeModelSet) Debug(msg string) {
+	if kms.Metadata.DiagnosticLevel > DiagnosticLevelDebug {
+		return
+	}
+
+	kms.RegisterDiagnostic(Diagnostic{
+		Timestamp: time.Now().UTC(),
+		Level:     DiagnosticLevelDebug,
+		Message:   msg,
+	})
+}
+
+func (kms *KubeModelSet) GetTraces() []Diagnostic {
+	ds := []Diagnostic{}
+
+	for _, d := range kms.Metadata.Diagnostics {
+		if d.Level == DiagnosticLevelTrace {
+			ds = append(ds, d)
+		}
+	}
+
+	return ds
+}
+
+func (kms *KubeModelSet) Tracef(msg string, a ...any) {
+	kms.Trace(fmt.Sprintf(msg, a...))
+}
+
+func (kms *KubeModelSet) Trace(msg string) {
+	if kms.Metadata.DiagnosticLevel > DiagnosticLevelTrace {
+		return
+	}
+
+	kms.RegisterDiagnostic(Diagnostic{
+		Timestamp: time.Now().UTC(),
+		Level:     DiagnosticLevelTrace,
+		Message:   msg,
+	})
 }

+ 15 - 10
core/pkg/model/kubemodel/kubemodel.go

@@ -8,11 +8,15 @@ import (
 
 // @bingen:generate[stringtable]:KubeModelSet
 type KubeModelSet struct {
-	Metadata       *Metadata                 `json:"meta"`           // @bingen:field[version=1]
-	Window         Window                    `json:"window"`         // @bingen:field[version=1]
-	Cluster        *Cluster                  `json:"cluster"`        // @bingen:field[version=1]
-	Namespaces     map[string]*Namespace     `json:"namespaces"`     // @bingen:field[version=1]
-	ResourceQuotas map[string]*ResourceQuota `json:"resourceQuotas"` // @bingen:field[version=1]
+	Metadata       *Metadata                 `json:"meta"`                 // @bingen:field[version=1]
+	Window         Window                    `json:"window"`               // @bingen:field[version=1]
+	Cluster        *Cluster                  `json:"cluster"`              // @bingen:field[version=1]
+	Containers     map[string]*Container     `json:"containers,omitempty"` // @bingen:field[version=1]
+	Owners         map[string]*Owner         `json:"owners,omitempty"`     // @bingen:field[version=1]
+	Namespaces     map[string]*Namespace     `json:"namespaces"`           // @bingen:field[version=1]
+	Nodes          map[string]*Node          `json:"nodes,omitempty"`      // @bingen:field[version=1]
+	Pods           map[string]*Pod           `json:"pods,omitempty"`       // @bingen:field[version=1]
+	ResourceQuotas map[string]*ResourceQuota `json:"resourceQuotas"`       // @bingen:field[version=1]
 	idx            *index                    // @bingen:field[ignore]
 }
 
@@ -23,22 +27,23 @@ func NewKubeModelSet(start, end time.Time) *KubeModelSet {
 
 	return &KubeModelSet{
 		Metadata: &Metadata{
-			CreatedAt: time.Now().UTC(),
+			CreatedAt:       time.Now().UTC(),
+			DiagnosticLevel: DefaultDiagnosticLevel,
 		},
 		Window: Window{
 			Start: start,
 			End:   end,
 		},
+		Containers:     map[string]*Container{},
+		Owners:         map[string]*Owner{},
 		Namespaces:     map[string]*Namespace{},
+		Nodes:          map[string]*Node{},
+		Pods:           map[string]*Pod{},
 		ResourceQuotas: map[string]*ResourceQuota{},
 		idx:            index,
 	}
 }
 
-func (kms *KubeModelSet) RegisterError(str string) {
-	kms.Metadata.Errors = append(kms.Metadata.Errors, str)
-}
-
 func (kms *KubeModelSet) IsEmpty() bool {
 	return kms == nil || kms.Cluster == nil || kms.Metadata.ObjectCount == 0
 }

+ 444 - 918
core/pkg/model/kubemodel/kubemodel_codecs.go

@@ -46,7 +46,7 @@ const (
 var typeMap map[string]reflect.Type = map[string]reflect.Type{
 	"Cluster":                 reflect.TypeOf((*Cluster)(nil)).Elem(),
 	"Container":               reflect.TypeOf((*Container)(nil)).Elem(),
-	"DiagnosticResult":        reflect.TypeOf((*DiagnosticResult)(nil)).Elem(),
+	"Diagnostic":              reflect.TypeOf((*Diagnostic)(nil)).Elem(),
 	"KubeModelSet":            reflect.TypeOf((*KubeModelSet)(nil)).Elem(),
 	"Metadata":                reflect.TypeOf((*Metadata)(nil)).Elem(),
 	"Namespace":               reflect.TypeOf((*Namespace)(nil)).Elem(),
@@ -59,8 +59,6 @@ var typeMap map[string]reflect.Type = map[string]reflect.Type{
 	"ResourceQuotaSpecHard":   reflect.TypeOf((*ResourceQuotaSpecHard)(nil)).Elem(),
 	"ResourceQuotaStatus":     reflect.TypeOf((*ResourceQuotaStatus)(nil)).Elem(),
 	"ResourceQuotaStatusUsed": reflect.TypeOf((*ResourceQuotaStatusUsed)(nil)).Elem(),
-	"Service":                 reflect.TypeOf((*Service)(nil)).Elem(),
-	"ServicePort":             reflect.TypeOf((*ServicePort)(nil)).Elem(),
 	"Window":                  reflect.TypeOf((*Window)(nil)).Elem(),
 }
 
@@ -799,12 +797,12 @@ func (target *Container) UnmarshalBinaryWithContext(ctx *DecodingContext) (err e
 }
 
 //--------------------------------------------------------------------------
-//  DiagnosticResult
+//  Diagnostic
 //--------------------------------------------------------------------------
 
-// MarshalBinary serializes the internal properties of this DiagnosticResult instance
+// MarshalBinary serializes the internal properties of this Diagnostic instance
 // into a byte array
-func (target *DiagnosticResult) MarshalBinary() (data []byte, err error) {
+func (target *Diagnostic) MarshalBinary() (data []byte, err error) {
 	ctx := &EncodingContext{
 		Buffer: util.NewBuffer(),
 		Table:  nil,
@@ -819,9 +817,9 @@ func (target *DiagnosticResult) MarshalBinary() (data []byte, err error) {
 	return encBytes, nil
 }
 
-// MarshalBinaryWithContext serializes the internal properties of this DiagnosticResult instance
+// MarshalBinaryWithContext serializes the internal properties of this Diagnostic instance
 // into a byte array leveraging a predefined context.
-func (target *DiagnosticResult) MarshalBinaryWithContext(ctx *EncodingContext) (err error) {
+func (target *Diagnostic) MarshalBinaryWithContext(ctx *EncodingContext) (err error) {
 	// panics are recovered and propagated as errors
 	defer func() {
 		if r := recover(); r != nil {
@@ -838,44 +836,24 @@ func (target *DiagnosticResult) MarshalBinaryWithContext(ctx *EncodingContext) (
 	buff := ctx.Buffer
 	buff.WriteUInt8(DefaultCodecVersion) // version
 
-	if ctx.IsStringTable() {
-		a := ctx.Table.AddOrGet(target.UID)
-		buff.WriteInt(a) // write table index
-	} else {
-		buff.WriteString(target.UID) // write string
-	}
-	if ctx.IsStringTable() {
-		b := ctx.Table.AddOrGet(target.Name)
-		buff.WriteInt(b) // write table index
-	} else {
-		buff.WriteString(target.Name) // write string
-	}
-	if ctx.IsStringTable() {
-		c := ctx.Table.AddOrGet(target.Description)
-		buff.WriteInt(c) // write table index
-	} else {
-		buff.WriteString(target.Description) // write string
-	}
-	if ctx.IsStringTable() {
-		d := ctx.Table.AddOrGet(target.Category)
-		buff.WriteInt(d) // write table index
-	} else {
-		buff.WriteString(target.Category) // write string
-	}
 	// --- [begin][write][reference](time.Time) ---
-	e, errA := target.Timestamp.MarshalBinary()
+	a, errA := target.Timestamp.MarshalBinary()
 	if errA != nil {
 		return errA
 	}
-	buff.WriteInt(len(e))
-	buff.WriteBytes(e)
+	buff.WriteInt(len(a))
+	buff.WriteBytes(a)
 	// --- [end][write][reference](time.Time) ---
 
+	// --- [begin][write][alias](DiagnosticLevel) ---
+	buff.WriteInt(int(target.Level)) // write int
+	// --- [end][write][alias](DiagnosticLevel) ---
+
 	if ctx.IsStringTable() {
-		f := ctx.Table.AddOrGet(target.Error)
-		buff.WriteInt(f) // write table index
+		b := ctx.Table.AddOrGet(target.Message)
+		buff.WriteInt(b) // write table index
 	} else {
-		buff.WriteString(target.Error) // write string
+		buff.WriteString(target.Message) // write string
 	}
 	if target.Details == nil {
 		buff.WriteUInt8(uint8(0)) // write nil byte
@@ -886,14 +864,14 @@ func (target *DiagnosticResult) MarshalBinaryWithContext(ctx *EncodingContext) (
 		buff.WriteInt(len(target.Details)) // map length
 		for v, z := range target.Details {
 			if ctx.IsStringTable() {
-				g := ctx.Table.AddOrGet(v)
-				buff.WriteInt(g) // write table index
+				c := ctx.Table.AddOrGet(v)
+				buff.WriteInt(c) // write table index
 			} else {
 				buff.WriteString(v) // write string
 			}
 			if ctx.IsStringTable() {
-				h := ctx.Table.AddOrGet(z)
-				buff.WriteInt(h) // write table index
+				d := ctx.Table.AddOrGet(z)
+				buff.WriteInt(d) // write table index
 			} else {
 				buff.WriteString(z) // write string
 			}
@@ -905,8 +883,8 @@ func (target *DiagnosticResult) MarshalBinaryWithContext(ctx *EncodingContext) (
 }
 
 // UnmarshalBinary uses the data passed byte array to set all the internal properties of
-// the DiagnosticResult type
-func (target *DiagnosticResult) UnmarshalBinary(data []byte) error {
+// the Diagnostic type
+func (target *Diagnostic) UnmarshalBinary(data []byte) error {
 	var table []string
 	buff := util.NewBufferFromBytes(data)
 
@@ -936,8 +914,8 @@ func (target *DiagnosticResult) UnmarshalBinary(data []byte) error {
 }
 
 // UnmarshalBinaryWithContext uses the context containing a string table and binary buffer to set all the internal properties of
-// the DiagnosticResult type
-func (target *DiagnosticResult) UnmarshalBinaryWithContext(ctx *DecodingContext) (err error) {
+// the Diagnostic type
+func (target *Diagnostic) UnmarshalBinaryWithContext(ctx *DecodingContext) (err error) {
 	// panics are recovered and propagated as errors
 	defer func() {
 		if r := recover(); r != nil {
@@ -955,103 +933,52 @@ func (target *DiagnosticResult) UnmarshalBinaryWithContext(ctx *DecodingContext)
 	version := buff.ReadUInt8()
 
 	if version > DefaultCodecVersion {
-		return fmt.Errorf("Invalid Version Unmarshaling DiagnosticResult. Expected %d or less, got %d", DefaultCodecVersion, version)
-	}
-
-	// field version check
-	if uint8(1) <= version {
-		var b string
-		if ctx.IsStringTable() {
-			c := buff.ReadInt() // read string index
-			b = ctx.Table[c]
-		} else {
-			b = buff.ReadString() // read string
-		}
-		a := b
-		target.UID = a
-
-	} else {
-		target.UID = "" // default
-	}
-
-	// field version check
-	if uint8(1) <= version {
-		var e string
-		if ctx.IsStringTable() {
-			f := buff.ReadInt() // read string index
-			e = ctx.Table[f]
-		} else {
-			e = buff.ReadString() // read string
-		}
-		d := e
-		target.Name = d
-
-	} else {
-		target.Name = "" // default
+		return fmt.Errorf("Invalid Version Unmarshaling Diagnostic. Expected %d or less, got %d", DefaultCodecVersion, version)
 	}
 
 	// field version check
 	if uint8(1) <= version {
-		var h string
-		if ctx.IsStringTable() {
-			k := buff.ReadInt() // read string index
-			h = ctx.Table[k]
-		} else {
-			h = buff.ReadString() // read string
+		// --- [begin][read][reference](time.Time) ---
+		a := &time.Time{}
+		b := buff.ReadInt()    // byte array length
+		c := buff.ReadBytes(b) // byte array
+		errA := a.UnmarshalBinary(c)
+		if errA != nil {
+			return errA
 		}
-		g := h
-		target.Description = g
+		target.Timestamp = *a
+		// --- [end][read][reference](time.Time) ---
 
 	} else {
-		target.Description = "" // default
 	}
 
 	// field version check
 	if uint8(1) <= version {
-		var m string
-		if ctx.IsStringTable() {
-			n := buff.ReadInt() // read string index
-			m = ctx.Table[n]
-		} else {
-			m = buff.ReadString() // read string
-		}
-		l := m
-		target.Category = l
-
-	} else {
-		target.Category = "" // default
-	}
+		// --- [begin][read][alias](DiagnosticLevel) ---
+		var d int
+		e := buff.ReadInt() // read int
+		d = e
 
-	// field version check
-	if uint8(1) <= version {
-		// --- [begin][read][reference](time.Time) ---
-		o := &time.Time{}
-		p := buff.ReadInt()    // byte array length
-		q := buff.ReadBytes(p) // byte array
-		errA := o.UnmarshalBinary(q)
-		if errA != nil {
-			return errA
-		}
-		target.Timestamp = *o
-		// --- [end][read][reference](time.Time) ---
+		target.Level = DiagnosticLevel(d)
+		// --- [end][read][alias](DiagnosticLevel) ---
 
 	} else {
 	}
 
 	// field version check
 	if uint8(1) <= version {
-		var s string
+		var g string
 		if ctx.IsStringTable() {
-			t := buff.ReadInt() // read string index
-			s = ctx.Table[t]
+			h := buff.ReadInt() // read string index
+			g = ctx.Table[h]
 		} else {
-			s = buff.ReadString() // read string
+			g = buff.ReadString() // read string
 		}
-		r := s
-		target.Error = r
+		f := g
+		target.Message = f
 
 	} else {
-		target.Error = "" // default
+		target.Message = "" // default
 	}
 
 	// field version check
@@ -1060,34 +987,34 @@ func (target *DiagnosticResult) UnmarshalBinaryWithContext(ctx *DecodingContext)
 			target.Details = nil
 		} else {
 			// --- [begin][read][map](map[string]string) ---
-			w := buff.ReadInt() // map len
-			u := make(map[string]string, w)
-			for i := 0; i < w; i++ {
+			l := buff.ReadInt() // map len
+			k := make(map[string]string, l)
+			for i := 0; i < l; i++ {
 				var v string
-				var y string
+				var n string
 				if ctx.IsStringTable() {
-					aa := buff.ReadInt() // read string index
-					y = ctx.Table[aa]
+					o := buff.ReadInt() // read string index
+					n = ctx.Table[o]
 				} else {
-					y = buff.ReadString() // read string
+					n = buff.ReadString() // read string
 				}
-				x := y
-				v = x
+				m := n
+				v = m
 
 				var z string
-				var cc string
+				var q string
 				if ctx.IsStringTable() {
-					dd := buff.ReadInt() // read string index
-					cc = ctx.Table[dd]
+					r := buff.ReadInt() // read string index
+					q = ctx.Table[r]
 				} else {
-					cc = buff.ReadString() // read string
+					q = buff.ReadString() // read string
 				}
-				bb := cc
-				z = bb
+				p := q
+				z = p
 
-				u[v] = z
+				k[v] = z
 			}
-			target.Details = u
+			target.Details = k
 			// --- [end][read][map](map[string]string) ---
 
 		}
@@ -1177,14 +1104,14 @@ func (target *KubeModelSet) MarshalBinaryWithContext(ctx *EncodingContext) (err
 		// --- [end][write][struct](Cluster) ---
 
 	}
-	if target.Namespaces == nil {
+	if target.Containers == nil {
 		buff.WriteUInt8(uint8(0)) // write nil byte
 	} else {
 		buff.WriteUInt8(uint8(1)) // write non-nil byte
 
-		// --- [begin][write][map](map[string]*Namespace) ---
-		buff.WriteInt(len(target.Namespaces)) // map length
-		for v, z := range target.Namespaces {
+		// --- [begin][write][map](map[string]*Container) ---
+		buff.WriteInt(len(target.Containers)) // map length
+		for v, z := range target.Containers {
 			if ctx.IsStringTable() {
 				a := ctx.Table.AddOrGet(v)
 				buff.WriteInt(a) // write table index
@@ -1196,27 +1123,27 @@ func (target *KubeModelSet) MarshalBinaryWithContext(ctx *EncodingContext) (err
 			} else {
 				buff.WriteUInt8(uint8(1)) // write non-nil byte
 
-				// --- [begin][write][struct](Namespace) ---
+				// --- [begin][write][struct](Container) ---
 				buff.WriteInt(0) // [compatibility, unused]
 				errD := z.MarshalBinaryWithContext(ctx)
 				if errD != nil {
 					return errD
 				}
-				// --- [end][write][struct](Namespace) ---
+				// --- [end][write][struct](Container) ---
 
 			}
 		}
-		// --- [end][write][map](map[string]*Namespace) ---
+		// --- [end][write][map](map[string]*Container) ---
 
 	}
-	if target.ResourceQuotas == nil {
+	if target.Owners == nil {
 		buff.WriteUInt8(uint8(0)) // write nil byte
 	} else {
 		buff.WriteUInt8(uint8(1)) // write non-nil byte
 
-		// --- [begin][write][map](map[string]*ResourceQuota) ---
-		buff.WriteInt(len(target.ResourceQuotas)) // map length
-		for vv, zz := range target.ResourceQuotas {
+		// --- [begin][write][map](map[string]*Owner) ---
+		buff.WriteInt(len(target.Owners)) // map length
+		for vv, zz := range target.Owners {
 			if ctx.IsStringTable() {
 				b := ctx.Table.AddOrGet(vv)
 				buff.WriteInt(b) // write table index
@@ -1228,12 +1155,140 @@ func (target *KubeModelSet) MarshalBinaryWithContext(ctx *EncodingContext) (err
 			} else {
 				buff.WriteUInt8(uint8(1)) // write non-nil byte
 
-				// --- [begin][write][struct](ResourceQuota) ---
+				// --- [begin][write][struct](Owner) ---
 				buff.WriteInt(0) // [compatibility, unused]
 				errE := zz.MarshalBinaryWithContext(ctx)
 				if errE != nil {
 					return errE
 				}
+				// --- [end][write][struct](Owner) ---
+
+			}
+		}
+		// --- [end][write][map](map[string]*Owner) ---
+
+	}
+	if target.Namespaces == nil {
+		buff.WriteUInt8(uint8(0)) // write nil byte
+	} else {
+		buff.WriteUInt8(uint8(1)) // write non-nil byte
+
+		// --- [begin][write][map](map[string]*Namespace) ---
+		buff.WriteInt(len(target.Namespaces)) // map length
+		for vvv, zzz := range target.Namespaces {
+			if ctx.IsStringTable() {
+				c := ctx.Table.AddOrGet(vvv)
+				buff.WriteInt(c) // write table index
+			} else {
+				buff.WriteString(vvv) // write string
+			}
+			if zzz == nil {
+				buff.WriteUInt8(uint8(0)) // write nil byte
+			} else {
+				buff.WriteUInt8(uint8(1)) // write non-nil byte
+
+				// --- [begin][write][struct](Namespace) ---
+				buff.WriteInt(0) // [compatibility, unused]
+				errF := zzz.MarshalBinaryWithContext(ctx)
+				if errF != nil {
+					return errF
+				}
+				// --- [end][write][struct](Namespace) ---
+
+			}
+		}
+		// --- [end][write][map](map[string]*Namespace) ---
+
+	}
+	if target.Nodes == nil {
+		buff.WriteUInt8(uint8(0)) // write nil byte
+	} else {
+		buff.WriteUInt8(uint8(1)) // write non-nil byte
+
+		// --- [begin][write][map](map[string]*Node) ---
+		buff.WriteInt(len(target.Nodes)) // map length
+		for vvvv, zzzz := range target.Nodes {
+			if ctx.IsStringTable() {
+				d := ctx.Table.AddOrGet(vvvv)
+				buff.WriteInt(d) // write table index
+			} else {
+				buff.WriteString(vvvv) // write string
+			}
+			if zzzz == nil {
+				buff.WriteUInt8(uint8(0)) // write nil byte
+			} else {
+				buff.WriteUInt8(uint8(1)) // write non-nil byte
+
+				// --- [begin][write][struct](Node) ---
+				buff.WriteInt(0) // [compatibility, unused]
+				errG := zzzz.MarshalBinaryWithContext(ctx)
+				if errG != nil {
+					return errG
+				}
+				// --- [end][write][struct](Node) ---
+
+			}
+		}
+		// --- [end][write][map](map[string]*Node) ---
+
+	}
+	if target.Pods == nil {
+		buff.WriteUInt8(uint8(0)) // write nil byte
+	} else {
+		buff.WriteUInt8(uint8(1)) // write non-nil byte
+
+		// --- [begin][write][map](map[string]*Pod) ---
+		buff.WriteInt(len(target.Pods)) // map length
+		for vvvvv, zzzzz := range target.Pods {
+			if ctx.IsStringTable() {
+				e := ctx.Table.AddOrGet(vvvvv)
+				buff.WriteInt(e) // write table index
+			} else {
+				buff.WriteString(vvvvv) // write string
+			}
+			if zzzzz == nil {
+				buff.WriteUInt8(uint8(0)) // write nil byte
+			} else {
+				buff.WriteUInt8(uint8(1)) // write non-nil byte
+
+				// --- [begin][write][struct](Pod) ---
+				buff.WriteInt(0) // [compatibility, unused]
+				errH := zzzzz.MarshalBinaryWithContext(ctx)
+				if errH != nil {
+					return errH
+				}
+				// --- [end][write][struct](Pod) ---
+
+			}
+		}
+		// --- [end][write][map](map[string]*Pod) ---
+
+	}
+	if target.ResourceQuotas == nil {
+		buff.WriteUInt8(uint8(0)) // write nil byte
+	} else {
+		buff.WriteUInt8(uint8(1)) // write non-nil byte
+
+		// --- [begin][write][map](map[string]*ResourceQuota) ---
+		buff.WriteInt(len(target.ResourceQuotas)) // map length
+		for vvvvvv, zzzzzz := range target.ResourceQuotas {
+			if ctx.IsStringTable() {
+				f := ctx.Table.AddOrGet(vvvvvv)
+				buff.WriteInt(f) // write table index
+			} else {
+				buff.WriteString(vvvvvv) // write string
+			}
+			if zzzzzz == nil {
+				buff.WriteUInt8(uint8(0)) // write nil byte
+			} else {
+				buff.WriteUInt8(uint8(1)) // write non-nil byte
+
+				// --- [begin][write][struct](ResourceQuota) ---
+				buff.WriteInt(0) // [compatibility, unused]
+				errI := zzzzzz.MarshalBinaryWithContext(ctx)
+				if errI != nil {
+					return errI
+				}
 				// --- [end][write][struct](ResourceQuota) ---
 
 			}
@@ -1358,11 +1413,11 @@ func (target *KubeModelSet) UnmarshalBinaryWithContext(ctx *DecodingContext) (er
 	// field version check
 	if uint8(1) <= version {
 		if buff.ReadUInt8() == uint8(0) {
-			target.Namespaces = nil
+			target.Containers = nil
 		} else {
-			// --- [begin][read][map](map[string]*Namespace) ---
+			// --- [begin][read][map](map[string]*Container) ---
 			e := buff.ReadInt() // map len
-			d := make(map[string]*Namespace, e)
+			d := make(map[string]*Container, e)
 			for i := 0; i < e; i++ {
 				var v string
 				var g string
@@ -1375,40 +1430,40 @@ func (target *KubeModelSet) UnmarshalBinaryWithContext(ctx *DecodingContext) (er
 				f := g
 				v = f
 
-				var z *Namespace
+				var z *Container
 				if buff.ReadUInt8() == uint8(0) {
 					z = nil
 				} else {
-					// --- [begin][read][struct](Namespace) ---
-					k := &Namespace{}
+					// --- [begin][read][struct](Container) ---
+					k := &Container{}
 					buff.ReadInt() // [compatibility, unused]
 					errD := k.UnmarshalBinaryWithContext(ctx)
 					if errD != nil {
 						return errD
 					}
 					z = k
-					// --- [end][read][struct](Namespace) ---
+					// --- [end][read][struct](Container) ---
 
 				}
 				d[v] = z
 			}
-			target.Namespaces = d
-			// --- [end][read][map](map[string]*Namespace) ---
+			target.Containers = d
+			// --- [end][read][map](map[string]*Container) ---
 
 		}
 	} else {
-		target.Namespaces = nil
+		target.Containers = nil
 
 	}
 
 	// field version check
 	if uint8(1) <= version {
 		if buff.ReadUInt8() == uint8(0) {
-			target.ResourceQuotas = nil
+			target.Owners = nil
 		} else {
-			// --- [begin][read][map](map[string]*ResourceQuota) ---
+			// --- [begin][read][map](map[string]*Owner) ---
 			m := buff.ReadInt() // map len
-			l := make(map[string]*ResourceQuota, m)
+			l := make(map[string]*Owner, m)
 			for j := 0; j < m; j++ {
 				var vv string
 				var o string
@@ -1421,45 +1476,229 @@ func (target *KubeModelSet) UnmarshalBinaryWithContext(ctx *DecodingContext) (er
 				n := o
 				vv = n
 
-				var zz *ResourceQuota
+				var zz *Owner
 				if buff.ReadUInt8() == uint8(0) {
 					zz = nil
 				} else {
-					// --- [begin][read][struct](ResourceQuota) ---
-					q := &ResourceQuota{}
+					// --- [begin][read][struct](Owner) ---
+					q := &Owner{}
 					buff.ReadInt() // [compatibility, unused]
 					errE := q.UnmarshalBinaryWithContext(ctx)
 					if errE != nil {
 						return errE
 					}
 					zz = q
-					// --- [end][read][struct](ResourceQuota) ---
+					// --- [end][read][struct](Owner) ---
 
 				}
 				l[vv] = zz
 			}
-			target.ResourceQuotas = l
-			// --- [end][read][map](map[string]*ResourceQuota) ---
+			target.Owners = l
+			// --- [end][read][map](map[string]*Owner) ---
 
 		}
 	} else {
-		target.ResourceQuotas = nil
+		target.Owners = nil
 
 	}
 
-	return nil
-}
+	// field version check
+	if uint8(1) <= version {
+		if buff.ReadUInt8() == uint8(0) {
+			target.Namespaces = nil
+		} else {
+			// --- [begin][read][map](map[string]*Namespace) ---
+			s := buff.ReadInt() // map len
+			r := make(map[string]*Namespace, s)
+			for ii := 0; ii < s; ii++ {
+				var vvv string
+				var u string
+				if ctx.IsStringTable() {
+					w := buff.ReadInt() // read string index
+					u = ctx.Table[w]
+				} else {
+					u = buff.ReadString() // read string
+				}
+				t := u
+				vvv = t
 
-//--------------------------------------------------------------------------
-//  Metadata
-//--------------------------------------------------------------------------
+				var zzz *Namespace
+				if buff.ReadUInt8() == uint8(0) {
+					zzz = nil
+				} else {
+					// --- [begin][read][struct](Namespace) ---
+					x := &Namespace{}
+					buff.ReadInt() // [compatibility, unused]
+					errF := x.UnmarshalBinaryWithContext(ctx)
+					if errF != nil {
+						return errF
+					}
+					zzz = x
+					// --- [end][read][struct](Namespace) ---
 
-// MarshalBinary serializes the internal properties of this Metadata instance
-// into a byte array
-func (target *Metadata) MarshalBinary() (data []byte, err error) {
-	ctx := &EncodingContext{
-		Buffer: util.NewBuffer(),
-		Table:  nil,
+				}
+				r[vvv] = zzz
+			}
+			target.Namespaces = r
+			// --- [end][read][map](map[string]*Namespace) ---
+
+		}
+	} else {
+		target.Namespaces = nil
+
+	}
+
+	// field version check
+	if uint8(1) <= version {
+		if buff.ReadUInt8() == uint8(0) {
+			target.Nodes = nil
+		} else {
+			// --- [begin][read][map](map[string]*Node) ---
+			aa := buff.ReadInt() // map len
+			y := make(map[string]*Node, aa)
+			for jj := 0; jj < aa; jj++ {
+				var vvvv string
+				var cc string
+				if ctx.IsStringTable() {
+					dd := buff.ReadInt() // read string index
+					cc = ctx.Table[dd]
+				} else {
+					cc = buff.ReadString() // read string
+				}
+				bb := cc
+				vvvv = bb
+
+				var zzzz *Node
+				if buff.ReadUInt8() == uint8(0) {
+					zzzz = nil
+				} else {
+					// --- [begin][read][struct](Node) ---
+					ee := &Node{}
+					buff.ReadInt() // [compatibility, unused]
+					errG := ee.UnmarshalBinaryWithContext(ctx)
+					if errG != nil {
+						return errG
+					}
+					zzzz = ee
+					// --- [end][read][struct](Node) ---
+
+				}
+				y[vvvv] = zzzz
+			}
+			target.Nodes = y
+			// --- [end][read][map](map[string]*Node) ---
+
+		}
+	} else {
+		target.Nodes = nil
+
+	}
+
+	// field version check
+	if uint8(1) <= version {
+		if buff.ReadUInt8() == uint8(0) {
+			target.Pods = nil
+		} else {
+			// --- [begin][read][map](map[string]*Pod) ---
+			gg := buff.ReadInt() // map len
+			ff := make(map[string]*Pod, gg)
+			for iii := 0; iii < gg; iii++ {
+				var vvvvv string
+				var kk string
+				if ctx.IsStringTable() {
+					ll := buff.ReadInt() // read string index
+					kk = ctx.Table[ll]
+				} else {
+					kk = buff.ReadString() // read string
+				}
+				hh := kk
+				vvvvv = hh
+
+				var zzzzz *Pod
+				if buff.ReadUInt8() == uint8(0) {
+					zzzzz = nil
+				} else {
+					// --- [begin][read][struct](Pod) ---
+					mm := &Pod{}
+					buff.ReadInt() // [compatibility, unused]
+					errH := mm.UnmarshalBinaryWithContext(ctx)
+					if errH != nil {
+						return errH
+					}
+					zzzzz = mm
+					// --- [end][read][struct](Pod) ---
+
+				}
+				ff[vvvvv] = zzzzz
+			}
+			target.Pods = ff
+			// --- [end][read][map](map[string]*Pod) ---
+
+		}
+	} else {
+		target.Pods = nil
+
+	}
+
+	// field version check
+	if uint8(1) <= version {
+		if buff.ReadUInt8() == uint8(0) {
+			target.ResourceQuotas = nil
+		} else {
+			// --- [begin][read][map](map[string]*ResourceQuota) ---
+			oo := buff.ReadInt() // map len
+			nn := make(map[string]*ResourceQuota, oo)
+			for jjj := 0; jjj < oo; jjj++ {
+				var vvvvvv string
+				var qq string
+				if ctx.IsStringTable() {
+					rr := buff.ReadInt() // read string index
+					qq = ctx.Table[rr]
+				} else {
+					qq = buff.ReadString() // read string
+				}
+				pp := qq
+				vvvvvv = pp
+
+				var zzzzzz *ResourceQuota
+				if buff.ReadUInt8() == uint8(0) {
+					zzzzzz = nil
+				} else {
+					// --- [begin][read][struct](ResourceQuota) ---
+					ss := &ResourceQuota{}
+					buff.ReadInt() // [compatibility, unused]
+					errI := ss.UnmarshalBinaryWithContext(ctx)
+					if errI != nil {
+						return errI
+					}
+					zzzzzz = ss
+					// --- [end][read][struct](ResourceQuota) ---
+
+				}
+				nn[vvvvvv] = zzzzzz
+			}
+			target.ResourceQuotas = nn
+			// --- [end][read][map](map[string]*ResourceQuota) ---
+
+		}
+	} else {
+		target.ResourceQuotas = nil
+
+	}
+
+	return nil
+}
+
+//--------------------------------------------------------------------------
+//  Metadata
+//--------------------------------------------------------------------------
+
+// MarshalBinary serializes the internal properties of this Metadata instance
+// into a byte array
+func (target *Metadata) MarshalBinary() (data []byte, err error) {
+	ctx := &EncodingContext{
+		Buffer: util.NewBuffer(),
+		Table:  nil,
 	}
 
 	e := target.MarshalBinaryWithContext(ctx)
@@ -1509,40 +1748,24 @@ func (target *Metadata) MarshalBinaryWithContext(ctx *EncodingContext) (err erro
 	// --- [end][write][reference](time.Time) ---
 
 	buff.WriteInt(target.ObjectCount) // write int
-	if target.Errors == nil {
+	if target.Diagnostics == nil {
 		buff.WriteUInt8(uint8(0)) // write nil byte
 	} else {
 		buff.WriteUInt8(uint8(1)) // write non-nil byte
 
-		// --- [begin][write][slice]([]string) ---
-		buff.WriteInt(len(target.Errors)) // array length
-		for i := 0; i < len(target.Errors); i++ {
-			if ctx.IsStringTable() {
-				c := ctx.Table.AddOrGet(target.Errors[i])
-				buff.WriteInt(c) // write table index
-			} else {
-				buff.WriteString(target.Errors[i]) // write string
+		// --- [begin][write][slice]([]Diagnostic) ---
+		buff.WriteInt(len(target.Diagnostics)) // array length
+		for i := 0; i < len(target.Diagnostics); i++ {
+			// --- [begin][write][struct](Diagnostic) ---
+			buff.WriteInt(0) // [compatibility, unused]
+			errC := target.Diagnostics[i].MarshalBinaryWithContext(ctx)
+			if errC != nil {
+				return errC
 			}
-		}
-		// --- [end][write][slice]([]string) ---
-
-	}
-	if target.Warnings == nil {
-		buff.WriteUInt8(uint8(0)) // write nil byte
-	} else {
-		buff.WriteUInt8(uint8(1)) // write non-nil byte
+			// --- [end][write][struct](Diagnostic) ---
 
-		// --- [begin][write][slice]([]string) ---
-		buff.WriteInt(len(target.Warnings)) // array length
-		for j := 0; j < len(target.Warnings); j++ {
-			if ctx.IsStringTable() {
-				d := ctx.Table.AddOrGet(target.Warnings[j])
-				buff.WriteInt(d) // write table index
-			} else {
-				buff.WriteString(target.Warnings[j]) // write string
-			}
 		}
-		// --- [end][write][slice]([]string) ---
+		// --- [end][write][slice]([]Diagnostic) ---
 
 	}
 	return nil
@@ -1646,62 +1869,30 @@ func (target *Metadata) UnmarshalBinaryWithContext(ctx *DecodingContext) (err er
 	// field version check
 	if uint8(1) <= version {
 		if buff.ReadUInt8() == uint8(0) {
-			target.Errors = nil
+			target.Diagnostics = nil
 		} else {
-			// --- [begin][read][slice]([]string) ---
+			// --- [begin][read][slice]([]Diagnostic) ---
 			k := buff.ReadInt() // array len
-			h := make([]string, k)
+			h := make([]Diagnostic, k)
 			for i := 0; i < k; i++ {
-				var l string
-				var n string
-				if ctx.IsStringTable() {
-					o := buff.ReadInt() // read string index
-					n = ctx.Table[o]
-				} else {
-					n = buff.ReadString() // read string
+				// --- [begin][read][struct](Diagnostic) ---
+				m := &Diagnostic{}
+				buff.ReadInt() // [compatibility, unused]
+				errC := m.UnmarshalBinaryWithContext(ctx)
+				if errC != nil {
+					return errC
 				}
-				m := n
-				l = m
+				l := *m
+				// --- [end][read][struct](Diagnostic) ---
 
 				h[i] = l
 			}
-			target.Errors = h
-			// --- [end][read][slice]([]string) ---
-
-		}
-	} else {
-		target.Errors = nil
-
-	}
-
-	// field version check
-	if uint8(1) <= version {
-		if buff.ReadUInt8() == uint8(0) {
-			target.Warnings = nil
-		} else {
-			// --- [begin][read][slice]([]string) ---
-			q := buff.ReadInt() // array len
-			p := make([]string, q)
-			for j := 0; j < q; j++ {
-				var r string
-				var t string
-				if ctx.IsStringTable() {
-					u := buff.ReadInt() // read string index
-					t = ctx.Table[u]
-				} else {
-					t = buff.ReadString() // read string
-				}
-				s := t
-				r = s
-
-				p[j] = r
-			}
-			target.Warnings = p
-			// --- [end][read][slice]([]string) ---
+			target.Diagnostics = h
+			// --- [end][read][slice]([]Diagnostic) ---
 
 		}
 	} else {
-		target.Warnings = nil
+		target.Diagnostics = nil
 
 	}
 
@@ -4616,671 +4807,6 @@ func (target *ResourceQuotaStatusUsed) UnmarshalBinaryWithContext(ctx *DecodingC
 	return nil
 }
 
-//--------------------------------------------------------------------------
-//  Service
-//--------------------------------------------------------------------------
-
-// MarshalBinary serializes the internal properties of this Service instance
-// into a byte array
-func (target *Service) MarshalBinary() (data []byte, err error) {
-	ctx := &EncodingContext{
-		Buffer: util.NewBuffer(),
-		Table:  nil,
-	}
-
-	e := target.MarshalBinaryWithContext(ctx)
-	if e != nil {
-		return nil, e
-	}
-
-	encBytes := ctx.Buffer.Bytes()
-	return encBytes, nil
-}
-
-// MarshalBinaryWithContext serializes the internal properties of this Service instance
-// into a byte array leveraging a predefined context.
-func (target *Service) MarshalBinaryWithContext(ctx *EncodingContext) (err error) {
-	// panics are recovered and propagated as errors
-	defer func() {
-		if r := recover(); r != nil {
-			if e, ok := r.(error); ok {
-				err = e
-			} else if s, ok := r.(string); ok {
-				err = fmt.Errorf("Unexpected panic: %s", s)
-			} else {
-				err = fmt.Errorf("Unexpected panic: %+v", r)
-			}
-		}
-	}()
-
-	buff := ctx.Buffer
-	buff.WriteUInt8(DefaultCodecVersion) // version
-
-	if ctx.IsStringTable() {
-		a := ctx.Table.AddOrGet(target.UID)
-		buff.WriteInt(a) // write table index
-	} else {
-		buff.WriteString(target.UID) // write string
-	}
-	if ctx.IsStringTable() {
-		b := ctx.Table.AddOrGet(target.ClusterUID)
-		buff.WriteInt(b) // write table index
-	} else {
-		buff.WriteString(target.ClusterUID) // write string
-	}
-	if ctx.IsStringTable() {
-		c := ctx.Table.AddOrGet(target.NamespaceUID)
-		buff.WriteInt(c) // write table index
-	} else {
-		buff.WriteString(target.NamespaceUID) // write string
-	}
-	if ctx.IsStringTable() {
-		d := ctx.Table.AddOrGet(target.Name)
-		buff.WriteInt(d) // write table index
-	} else {
-		buff.WriteString(target.Name) // write string
-	}
-	// --- [begin][write][alias](ServiceType) ---
-	if ctx.IsStringTable() {
-		e := ctx.Table.AddOrGet(string(target.Type))
-		buff.WriteInt(e) // write table index
-	} else {
-		buff.WriteString(string(target.Type)) // write string
-	}
-	// --- [end][write][alias](ServiceType) ---
-
-	if ctx.IsStringTable() {
-		f := ctx.Table.AddOrGet(target.Hostname)
-		buff.WriteInt(f) // write table index
-	} else {
-		buff.WriteString(target.Hostname) // write string
-	}
-	if target.Labels == nil {
-		buff.WriteUInt8(uint8(0)) // write nil byte
-	} else {
-		buff.WriteUInt8(uint8(1)) // write non-nil byte
-
-		// --- [begin][write][map](map[string]string) ---
-		buff.WriteInt(len(target.Labels)) // map length
-		for v, z := range target.Labels {
-			if ctx.IsStringTable() {
-				g := ctx.Table.AddOrGet(v)
-				buff.WriteInt(g) // write table index
-			} else {
-				buff.WriteString(v) // write string
-			}
-			if ctx.IsStringTable() {
-				h := ctx.Table.AddOrGet(z)
-				buff.WriteInt(h) // write table index
-			} else {
-				buff.WriteString(z) // write string
-			}
-		}
-		// --- [end][write][map](map[string]string) ---
-
-	}
-	if target.Annotations == nil {
-		buff.WriteUInt8(uint8(0)) // write nil byte
-	} else {
-		buff.WriteUInt8(uint8(1)) // write non-nil byte
-
-		// --- [begin][write][map](map[string]string) ---
-		buff.WriteInt(len(target.Annotations)) // map length
-		for vv, zz := range target.Annotations {
-			if ctx.IsStringTable() {
-				k := ctx.Table.AddOrGet(vv)
-				buff.WriteInt(k) // write table index
-			} else {
-				buff.WriteString(vv) // write string
-			}
-			if ctx.IsStringTable() {
-				l := ctx.Table.AddOrGet(zz)
-				buff.WriteInt(l) // write table index
-			} else {
-				buff.WriteString(zz) // write string
-			}
-		}
-		// --- [end][write][map](map[string]string) ---
-
-	}
-	if target.Ports == nil {
-		buff.WriteUInt8(uint8(0)) // write nil byte
-	} else {
-		buff.WriteUInt8(uint8(1)) // write non-nil byte
-
-		// --- [begin][write][slice]([]ServicePort) ---
-		buff.WriteInt(len(target.Ports)) // array length
-		for i := 0; i < len(target.Ports); i++ {
-			// --- [begin][write][struct](ServicePort) ---
-			buff.WriteInt(0) // [compatibility, unused]
-			errA := target.Ports[i].MarshalBinaryWithContext(ctx)
-			if errA != nil {
-				return errA
-			}
-			// --- [end][write][struct](ServicePort) ---
-
-		}
-		// --- [end][write][slice]([]ServicePort) ---
-
-	}
-	// --- [begin][write][reference](time.Time) ---
-	m, errB := target.Start.MarshalBinary()
-	if errB != nil {
-		return errB
-	}
-	buff.WriteInt(len(m))
-	buff.WriteBytes(m)
-	// --- [end][write][reference](time.Time) ---
-
-	// --- [begin][write][reference](time.Time) ---
-	n, errC := target.End.MarshalBinary()
-	if errC != nil {
-		return errC
-	}
-	buff.WriteInt(len(n))
-	buff.WriteBytes(n)
-	// --- [end][write][reference](time.Time) ---
-
-	buff.WriteUInt64(target.NetworkTransferBytes) // write uint64
-	buff.WriteUInt64(target.NetworkReceiveBytes)  // write uint64
-	return nil
-}
-
-// UnmarshalBinary uses the data passed byte array to set all the internal properties of
-// the Service type
-func (target *Service) UnmarshalBinary(data []byte) error {
-	var table []string
-	buff := util.NewBufferFromBytes(data)
-
-	// string table header validation
-	if isBinaryTag(data, BinaryTagStringTable) {
-		buff.ReadBytes(len(BinaryTagStringTable)) // strip tag length
-		tl := buff.ReadInt()                      // table length
-		if tl > 0 {
-			table = make([]string, tl, tl)
-			for i := 0; i < tl; i++ {
-				table[i] = buff.ReadString()
-			}
-		}
-	}
-
-	ctx := &DecodingContext{
-		Buffer: buff,
-		Table:  table,
-	}
-
-	err := target.UnmarshalBinaryWithContext(ctx)
-	if err != nil {
-		return err
-	}
-
-	return nil
-}
-
-// UnmarshalBinaryWithContext uses the context containing a string table and binary buffer to set all the internal properties of
-// the Service type
-func (target *Service) UnmarshalBinaryWithContext(ctx *DecodingContext) (err error) {
-	// panics are recovered and propagated as errors
-	defer func() {
-		if r := recover(); r != nil {
-			if e, ok := r.(error); ok {
-				err = e
-			} else if s, ok := r.(string); ok {
-				err = fmt.Errorf("Unexpected panic: %s", s)
-			} else {
-				err = fmt.Errorf("Unexpected panic: %+v", r)
-			}
-		}
-	}()
-
-	buff := ctx.Buffer
-	version := buff.ReadUInt8()
-
-	if version > DefaultCodecVersion {
-		return fmt.Errorf("Invalid Version Unmarshaling Service. Expected %d or less, got %d", DefaultCodecVersion, version)
-	}
-
-	// field version check
-	if uint8(1) <= version {
-		var b string
-		if ctx.IsStringTable() {
-			c := buff.ReadInt() // read string index
-			b = ctx.Table[c]
-		} else {
-			b = buff.ReadString() // read string
-		}
-		a := b
-		target.UID = a
-
-	} else {
-		target.UID = "" // default
-	}
-
-	// field version check
-	if uint8(1) <= version {
-		var e string
-		if ctx.IsStringTable() {
-			f := buff.ReadInt() // read string index
-			e = ctx.Table[f]
-		} else {
-			e = buff.ReadString() // read string
-		}
-		d := e
-		target.ClusterUID = d
-
-	} else {
-		target.ClusterUID = "" // default
-	}
-
-	// field version check
-	if uint8(1) <= version {
-		var h string
-		if ctx.IsStringTable() {
-			k := buff.ReadInt() // read string index
-			h = ctx.Table[k]
-		} else {
-			h = buff.ReadString() // read string
-		}
-		g := h
-		target.NamespaceUID = g
-
-	} else {
-		target.NamespaceUID = "" // default
-	}
-
-	// field version check
-	if uint8(1) <= version {
-		var m string
-		if ctx.IsStringTable() {
-			n := buff.ReadInt() // read string index
-			m = ctx.Table[n]
-		} else {
-			m = buff.ReadString() // read string
-		}
-		l := m
-		target.Name = l
-
-	} else {
-		target.Name = "" // default
-	}
-
-	// field version check
-	if uint8(1) <= version {
-		// --- [begin][read][alias](ServiceType) ---
-		var o string
-		var q string
-		if ctx.IsStringTable() {
-			r := buff.ReadInt() // read string index
-			q = ctx.Table[r]
-		} else {
-			q = buff.ReadString() // read string
-		}
-		p := q
-		o = p
-
-		target.Type = ServiceType(o)
-		// --- [end][read][alias](ServiceType) ---
-
-	} else {
-	}
-
-	// field version check
-	if uint8(1) <= version {
-		var t string
-		if ctx.IsStringTable() {
-			u := buff.ReadInt() // read string index
-			t = ctx.Table[u]
-		} else {
-			t = buff.ReadString() // read string
-		}
-		s := t
-		target.Hostname = s
-
-	} else {
-		target.Hostname = "" // default
-	}
-
-	// field version check
-	if uint8(1) <= version {
-		if buff.ReadUInt8() == uint8(0) {
-			target.Labels = nil
-		} else {
-			// --- [begin][read][map](map[string]string) ---
-			x := buff.ReadInt() // map len
-			w := make(map[string]string, x)
-			for i := 0; i < x; i++ {
-				var v string
-				var aa string
-				if ctx.IsStringTable() {
-					bb := buff.ReadInt() // read string index
-					aa = ctx.Table[bb]
-				} else {
-					aa = buff.ReadString() // read string
-				}
-				y := aa
-				v = y
-
-				var z string
-				var dd string
-				if ctx.IsStringTable() {
-					ee := buff.ReadInt() // read string index
-					dd = ctx.Table[ee]
-				} else {
-					dd = buff.ReadString() // read string
-				}
-				cc := dd
-				z = cc
-
-				w[v] = z
-			}
-			target.Labels = w
-			// --- [end][read][map](map[string]string) ---
-
-		}
-	} else {
-		target.Labels = nil
-
-	}
-
-	// field version check
-	if uint8(1) <= version {
-		if buff.ReadUInt8() == uint8(0) {
-			target.Annotations = nil
-		} else {
-			// --- [begin][read][map](map[string]string) ---
-			gg := buff.ReadInt() // map len
-			ff := make(map[string]string, gg)
-			for j := 0; j < gg; j++ {
-				var vv string
-				var kk string
-				if ctx.IsStringTable() {
-					ll := buff.ReadInt() // read string index
-					kk = ctx.Table[ll]
-				} else {
-					kk = buff.ReadString() // read string
-				}
-				hh := kk
-				vv = hh
-
-				var zz string
-				var nn string
-				if ctx.IsStringTable() {
-					oo := buff.ReadInt() // read string index
-					nn = ctx.Table[oo]
-				} else {
-					nn = buff.ReadString() // read string
-				}
-				mm := nn
-				zz = mm
-
-				ff[vv] = zz
-			}
-			target.Annotations = ff
-			// --- [end][read][map](map[string]string) ---
-
-		}
-	} else {
-		target.Annotations = nil
-
-	}
-
-	// field version check
-	if uint8(1) <= version {
-		if buff.ReadUInt8() == uint8(0) {
-			target.Ports = nil
-		} else {
-			// --- [begin][read][slice]([]ServicePort) ---
-			qq := buff.ReadInt() // array len
-			pp := make([]ServicePort, qq)
-			for ii := 0; ii < qq; ii++ {
-				// --- [begin][read][struct](ServicePort) ---
-				ss := &ServicePort{}
-				buff.ReadInt() // [compatibility, unused]
-				errA := ss.UnmarshalBinaryWithContext(ctx)
-				if errA != nil {
-					return errA
-				}
-				rr := *ss
-				// --- [end][read][struct](ServicePort) ---
-
-				pp[ii] = rr
-			}
-			target.Ports = pp
-			// --- [end][read][slice]([]ServicePort) ---
-
-		}
-	} else {
-		target.Ports = nil
-
-	}
-
-	// field version check
-	if uint8(1) <= version {
-		// --- [begin][read][reference](time.Time) ---
-		tt := &time.Time{}
-		uu := buff.ReadInt()     // byte array length
-		ww := buff.ReadBytes(uu) // byte array
-		errB := tt.UnmarshalBinary(ww)
-		if errB != nil {
-			return errB
-		}
-		target.Start = *tt
-		// --- [end][read][reference](time.Time) ---
-
-	} else {
-	}
-
-	// field version check
-	if uint8(1) <= version {
-		// --- [begin][read][reference](time.Time) ---
-		xx := &time.Time{}
-		yy := buff.ReadInt()      // byte array length
-		aaa := buff.ReadBytes(yy) // byte array
-		errC := xx.UnmarshalBinary(aaa)
-		if errC != nil {
-			return errC
-		}
-		target.End = *xx
-		// --- [end][read][reference](time.Time) ---
-
-	} else {
-	}
-
-	// field version check
-	if uint8(1) <= version {
-		bbb := buff.ReadUInt64() // read uint64
-		target.NetworkTransferBytes = bbb
-
-	} else {
-		target.NetworkTransferBytes = uint64(0) // default
-	}
-
-	// field version check
-	if uint8(1) <= version {
-		ccc := buff.ReadUInt64() // read uint64
-		target.NetworkReceiveBytes = ccc
-
-	} else {
-		target.NetworkReceiveBytes = uint64(0) // default
-	}
-
-	return nil
-}
-
-//--------------------------------------------------------------------------
-//  ServicePort
-//--------------------------------------------------------------------------
-
-// MarshalBinary serializes the internal properties of this ServicePort instance
-// into a byte array
-func (target *ServicePort) MarshalBinary() (data []byte, err error) {
-	ctx := &EncodingContext{
-		Buffer: util.NewBuffer(),
-		Table:  nil,
-	}
-
-	e := target.MarshalBinaryWithContext(ctx)
-	if e != nil {
-		return nil, e
-	}
-
-	encBytes := ctx.Buffer.Bytes()
-	return encBytes, nil
-}
-
-// MarshalBinaryWithContext serializes the internal properties of this ServicePort instance
-// into a byte array leveraging a predefined context.
-func (target *ServicePort) MarshalBinaryWithContext(ctx *EncodingContext) (err error) {
-	// panics are recovered and propagated as errors
-	defer func() {
-		if r := recover(); r != nil {
-			if e, ok := r.(error); ok {
-				err = e
-			} else if s, ok := r.(string); ok {
-				err = fmt.Errorf("Unexpected panic: %s", s)
-			} else {
-				err = fmt.Errorf("Unexpected panic: %+v", r)
-			}
-		}
-	}()
-
-	buff := ctx.Buffer
-	buff.WriteUInt8(DefaultCodecVersion) // version
-
-	if ctx.IsStringTable() {
-		a := ctx.Table.AddOrGet(target.Name)
-		buff.WriteInt(a) // write table index
-	} else {
-		buff.WriteString(target.Name) // write string
-	}
-	buff.WriteUInt16(target.Port)       // write uint16
-	buff.WriteUInt16(target.TargetPort) // write uint16
-	buff.WriteUInt16(target.NodePort)   // write uint16
-	if ctx.IsStringTable() {
-		b := ctx.Table.AddOrGet(target.Protocol)
-		buff.WriteInt(b) // write table index
-	} else {
-		buff.WriteString(target.Protocol) // write string
-	}
-	return nil
-}
-
-// UnmarshalBinary uses the data passed byte array to set all the internal properties of
-// the ServicePort type
-func (target *ServicePort) UnmarshalBinary(data []byte) error {
-	var table []string
-	buff := util.NewBufferFromBytes(data)
-
-	// string table header validation
-	if isBinaryTag(data, BinaryTagStringTable) {
-		buff.ReadBytes(len(BinaryTagStringTable)) // strip tag length
-		tl := buff.ReadInt()                      // table length
-		if tl > 0 {
-			table = make([]string, tl, tl)
-			for i := 0; i < tl; i++ {
-				table[i] = buff.ReadString()
-			}
-		}
-	}
-
-	ctx := &DecodingContext{
-		Buffer: buff,
-		Table:  table,
-	}
-
-	err := target.UnmarshalBinaryWithContext(ctx)
-	if err != nil {
-		return err
-	}
-
-	return nil
-}
-
-// UnmarshalBinaryWithContext uses the context containing a string table and binary buffer to set all the internal properties of
-// the ServicePort type
-func (target *ServicePort) UnmarshalBinaryWithContext(ctx *DecodingContext) (err error) {
-	// panics are recovered and propagated as errors
-	defer func() {
-		if r := recover(); r != nil {
-			if e, ok := r.(error); ok {
-				err = e
-			} else if s, ok := r.(string); ok {
-				err = fmt.Errorf("Unexpected panic: %s", s)
-			} else {
-				err = fmt.Errorf("Unexpected panic: %+v", r)
-			}
-		}
-	}()
-
-	buff := ctx.Buffer
-	version := buff.ReadUInt8()
-
-	if version > DefaultCodecVersion {
-		return fmt.Errorf("Invalid Version Unmarshaling ServicePort. Expected %d or less, got %d", DefaultCodecVersion, version)
-	}
-
-	// field version check
-	if uint8(1) <= version {
-		var b string
-		if ctx.IsStringTable() {
-			c := buff.ReadInt() // read string index
-			b = ctx.Table[c]
-		} else {
-			b = buff.ReadString() // read string
-		}
-		a := b
-		target.Name = a
-
-	} else {
-		target.Name = "" // default
-	}
-
-	// field version check
-	if uint8(1) <= version {
-		d := buff.ReadUInt16() // read uint16
-		target.Port = d
-
-	} else {
-		target.Port = uint16(0) // default
-	}
-
-	// field version check
-	if uint8(1) <= version {
-		e := buff.ReadUInt16() // read uint16
-		target.TargetPort = e
-
-	} else {
-		target.TargetPort = uint16(0) // default
-	}
-
-	// field version check
-	if uint8(1) <= version {
-		f := buff.ReadUInt16() // read uint16
-		target.NodePort = f
-
-	} else {
-		target.NodePort = uint16(0) // default
-	}
-
-	// field version check
-	if uint8(1) <= version {
-		var h string
-		if ctx.IsStringTable() {
-			k := buff.ReadInt() // read string index
-			h = ctx.Table[k]
-		} else {
-			h = buff.ReadString() // read string
-		}
-		g := h
-		target.Protocol = g
-
-	} else {
-		target.Protocol = "" // default
-	}
-
-	return nil
-}
-
 //--------------------------------------------------------------------------
 //  Window
 //--------------------------------------------------------------------------

+ 86 - 48
core/pkg/model/kubemodel/kubemodel_test.go

@@ -1,6 +1,7 @@
 package kubemodel
 
 import (
+	"errors"
 	"testing"
 	"time"
 
@@ -15,81 +16,105 @@ func TestKubeModel(t *testing.T) {
 		kms := NewKubeModelSet(start, end)
 
 		require.NotNil(t, kms.Metadata)
-		require.Len(t, kms.Metadata.Errors, 0)
+		require.Len(t, kms.GetErrors(), 0)
 
-		kms.RegisterError("test error")
-		require.Len(t, kms.Metadata.Errors, 1)
-		require.Equal(t, "test error", kms.Metadata.Errors[0])
+		kms.Error(errors.New("test error"))
+		require.Len(t, kms.GetErrors(), 1)
+		require.Equal(t, "test error", kms.GetErrors()[0].Message)
 
-		kms.RegisterError("test error 2")
-		require.Len(t, kms.Metadata.Errors, 2)
-		require.Equal(t, "test error 2", kms.Metadata.Errors[1])
+		kms.Error(errors.New("test error 2"))
+		require.Len(t, kms.GetErrors(), 2)
+		require.Equal(t, "test error 2", kms.GetErrors()[1].Message)
 	})
 
 	t.Run("RegisterCluster", func(t *testing.T) {
 		t.Run("empty cluster UID", func(t *testing.T) {
+			var err error
+
 			kms := NewKubeModelSet(start, end)
 
-			kms.RegisterCluster("")
-			require.Len(t, kms.Metadata.Errors, 1)
-			require.Equal(t, "RegisterCluster: uid is nil for Cluster", kms.Metadata.Errors[0])
+			err = kms.RegisterCluster("")
+			require.NotNil(t, err)
+
+			require.Len(t, kms.GetErrors(), 1)
+			require.Equal(t, "RegisterCluster: uid is nil", kms.GetErrors()[0].Message)
 			require.Nil(t, kms.Cluster)
 		})
 
 		t.Run("new cluster UID", func(t *testing.T) {
+			var err error
+			var clusterUID = "cluster-uid"
+
 			kms := NewKubeModelSet(start, end)
 
-			testUID := "test-uid"
-			kms.RegisterCluster(testUID)
-			require.Len(t, kms.Metadata.Errors, 0)
+			err = kms.RegisterCluster(clusterUID)
+			require.Nil(t, err)
+
+			require.Len(t, kms.GetErrors(), 0)
 			require.NotNil(t, kms.Cluster)
-			require.Equal(t, testUID, kms.Cluster.UID)
+			require.Equal(t, clusterUID, kms.Cluster.UID)
 		})
 
 		t.Run("multiple Register calls", func(t *testing.T) {
+			var err error
+			var clusterUID = "cluster-uid"
+
 			kms := NewKubeModelSet(start, end)
 
-			testUID := "test-uid"
-			kms.RegisterCluster(testUID)
-			require.Len(t, kms.Metadata.Errors, 0)
+			err = kms.RegisterCluster(clusterUID)
+			require.Nil(t, err)
+
+			require.Len(t, kms.GetErrors(), 0)
 			require.NotNil(t, kms.Cluster)
-			require.Equal(t, testUID, kms.Cluster.UID)
+			require.Equal(t, clusterUID, kms.Cluster.UID)
 
 			// Register cluster with same UID, expect no-op on second try
-			kms.RegisterCluster(testUID)
-			require.Len(t, kms.Metadata.Errors, 0)
+			err = kms.RegisterCluster(clusterUID)
+			require.Nil(t, err)
+
+			require.Len(t, kms.GetErrors(), 0)
 			require.NotNil(t, kms.Cluster)
-			require.Equal(t, testUID, kms.Cluster.UID)
+			require.Equal(t, clusterUID, kms.Cluster.UID)
 
 			// Register cluster with another UID (should not happen), expect no-op
-			kms.RegisterCluster("another-uid")
-			require.Len(t, kms.Metadata.Errors, 0)
+			err = kms.RegisterCluster("another-uid")
+			require.Nil(t, err)
+
+			require.Len(t, kms.GetWarnings(), 1)
+			require.Equal(t, "RegisterCluster(another-uid): attempting to change cluster UID from cluster-uid to another-uid", kms.GetWarnings()[0].Message)
 			require.NotNil(t, kms.Cluster)
-			require.Equal(t, testUID, kms.Cluster.UID) // original kms.Cluster is not modified
+			require.Equal(t, clusterUID, kms.Cluster.UID) // original kms.Cluster is not modified
 		})
 	})
 
 	t.Run("RegisterNamespace", func(t *testing.T) {
 		t.Run("empty namespace UID", func(t *testing.T) {
+			var err error
+
 			kms := NewKubeModelSet(start, end)
 
-			kms.RegisterNamespace("", "")
-			require.Len(t, kms.Metadata.Errors, 1)
-			require.Equal(t, "RegisterNamespace: uid is nil for Namespace ''", kms.Metadata.Errors[0])
+			err = kms.RegisterNamespace("", "")
+			require.NotNil(t, err)
+
+			require.Len(t, kms.GetErrors(), 1)
+			require.Equal(t, "UID is nil for Namespace ''", kms.GetErrors()[0].Message)
 			require.Len(t, kms.Namespaces, 0)
 		})
 
 		t.Run("register namespace on KMS w/o cluster", func(t *testing.T) {
+			var err error
+
 			kms := NewKubeModelSet(start, end)
 
 			testUID := "uid"
 			testName := "name"
 
-			kms.RegisterNamespace(testUID, testName)
-			require.Len(t, kms.Metadata.Errors, 1)
-			require.Equal(t, "RegisterNamespace(uid, name): Cluster is nil", kms.Metadata.Errors[0])
+			err = kms.RegisterNamespace(testUID, testName)
+			require.Nil(t, err)
+
+			require.Len(t, kms.GetWarnings(), 1)
+			require.Equal(t, "RegisterNamespace(uid, name): Cluster is nil", kms.GetWarnings()[0].Message)
 
-			// TODO: Confirm here whether we still want to register a Namespace if cluster is nil
 			testNamespace := &Namespace{UID: testUID, ClusterUID: "", Name: testName}
 
 			require.NotNil(t, kms.Namespaces[testUID])
@@ -100,15 +125,21 @@ func TestKubeModel(t *testing.T) {
 		})
 
 		t.Run("register namespace on KMS w/ cluster", func(t *testing.T) {
+			var err error
+
 			kms := NewKubeModelSet(start, end)
-			kms.RegisterCluster("cluster-uid")
+			err = kms.RegisterCluster("cluster-uid")
+			require.Nil(t, err)
+
 			// At this point we have a KMS with a cluster registered
 
 			testUID := "uid"
 			testName := "name"
 
-			kms.RegisterNamespace(testUID, testName)
-			require.Len(t, kms.Metadata.Errors, 0)
+			err = kms.RegisterNamespace(testUID, testName)
+			require.Nil(t, err)
+
+			require.Len(t, kms.GetErrors(), 0)
 			require.NotNil(t, kms.Namespaces[testUID])
 
 			testNamespace := &Namespace{UID: testUID, ClusterUID: "cluster-uid", Name: testName}
@@ -118,8 +149,10 @@ func TestKubeModel(t *testing.T) {
 			require.Equal(t, 1, kms.Metadata.ObjectCount)
 
 			// Register same namespace again, expect no-op on second try
-			kms.RegisterNamespace(testUID, testName)
-			require.Len(t, kms.Metadata.Errors, 0)
+			err = kms.RegisterNamespace(testUID, testName)
+			require.Nil(t, err)
+
+			require.Len(t, kms.GetErrors(), 0)
 			require.NotNil(t, kms.Namespaces[testUID])
 			require.Equal(t, testNamespace, kms.Namespaces[testUID])
 			require.Equal(t, testNamespace, kms.idx.namespaceByName[testName])
@@ -129,25 +162,30 @@ func TestKubeModel(t *testing.T) {
 
 	t.Run("RegisterResourceQuota", func(t *testing.T) {
 		t.Run("empty resourceQuota UID", func(t *testing.T) {
+			var err error
+
 			kms := NewKubeModelSet(start, end)
 
-			kms.RegisterResourceQuota("", "test", "")
-			require.Len(t, kms.Metadata.Errors, 1)
-			require.Equal(t, "RegisterResourceQuota: uid is nil for ResourceQuota 'test'", kms.Metadata.Errors[0])
+			err = kms.RegisterResourceQuota("", "test", "")
+			require.NotNil(t, err)
+			require.Len(t, kms.GetErrors(), 1)
+			require.Equal(t, "UID is nil for ResourceQuota 'test'", kms.GetErrors()[0].Message)
 			require.Len(t, kms.ResourceQuotas, 0)
 		})
 
 		t.Run("register resource quota on KMS w/o namespace", func(t *testing.T) {
+			var err error
+
 			kms := NewKubeModelSet(start, end)
 
 			testUID := "uid"
 			testName := "name"
 
-			kms.RegisterResourceQuota(testUID, testName, "unregistered-namespace")
-			require.Len(t, kms.Metadata.Errors, 1)
-			require.Equal(t, "RegisterResourceQuota(uid, name, unregistered-namespace): missing namespace", kms.Metadata.Errors[0])
+			err = kms.RegisterResourceQuota(testUID, testName, "unregistered-namespace")
+			require.Nil(t, err)
+			require.Len(t, kms.GetWarnings(), 1)
+			require.Equal(t, "RegisterResourceQuota(uid, name, unregistered-namespace): missing namespace", kms.GetWarnings()[0].Message)
 
-			// TODO: Confirm here whether we still want to register a RQ if namespace is nil
 			testRQ := &ResourceQuota{
 				UID:          "uid",
 				NamespaceUID: "",
@@ -181,14 +219,14 @@ func TestKubeModel(t *testing.T) {
 				Status:       &ResourceQuotaStatus{Used: &ResourceQuotaStatusUsed{}},
 			}
 
-			require.Len(t, kms.Metadata.Errors, 0)
+			require.Len(t, kms.GetErrors(), 0)
 			require.NotNil(t, kms.ResourceQuotas[testUID])
 			require.Equal(t, testRQ, kms.ResourceQuotas[testUID])
 			require.Equal(t, 2, kms.Metadata.ObjectCount) // 1 namespace and 1 RQ
 
 			// Register same RQ again, expect no-op on second try
 			kms.RegisterResourceQuota(testUID, testName, testNamespace)
-			require.Len(t, kms.Metadata.Errors, 0)
+			require.Len(t, kms.GetErrors(), 0)
 			require.NotNil(t, kms.ResourceQuotas[testUID])
 			require.Equal(t, testRQ, kms.ResourceQuotas[testUID])
 			require.Equal(t, 2, kms.Metadata.ObjectCount) // 1 namespace and 1 RQ
@@ -203,7 +241,7 @@ func TestKubeModel(t *testing.T) {
 			kms.RegisterResourceQuota("uid-1", "name-1", "namespace-1")
 			kms.RegisterResourceQuota("uid-2", "name-2", "namespace-2")
 
-			require.Len(t, kms.Metadata.Errors, 0)
+			require.Len(t, kms.GetErrors(), 0)
 			require.NotNil(t, kms.ResourceQuotas)
 			require.Len(t, kms.ResourceQuotas, 2)
 
@@ -229,8 +267,8 @@ func TestKubeModel(t *testing.T) {
 			// Register a third RQ with an invalid namespace
 			kms.RegisterResourceQuota("uid-3", "name-3", "namespace-3")
 
-			require.Len(t, kms.Metadata.Errors, 1)
-			require.Equal(t, "RegisterResourceQuota(uid-3, name-3, namespace-3): missing namespace", kms.Metadata.Errors[0])
+			require.Len(t, kms.GetWarnings(), 1)
+			require.Equal(t, "RegisterResourceQuota(uid-3, name-3, namespace-3): missing namespace", kms.GetWarnings()[0].Message)
 
 			testRQ3 := &ResourceQuota{
 				UID:          "uid-3",

+ 5 - 5
core/pkg/model/kubemodel/metadata.go

@@ -6,9 +6,9 @@ import (
 
 // @bingen:generate:Metadata
 type Metadata struct {
-	CreatedAt   time.Time `json:"createdAt"`   // @bingen:field[version=1]
-	CompletedAt time.Time `json:"completedAt"` // @bingen:field[version=1]
-	ObjectCount int       `json:"objectCount"` // @bingen:field[version=1]
-	Errors      []string  `json:"errors"`      // @bingen:field[version=1]
-	Warnings    []string  `json:"warnings"`    // @bingen:field[version=1]
+	CreatedAt       time.Time       `json:"createdAt"`             // @bingen:field[version=1]
+	CompletedAt     time.Time       `json:"completedAt"`           // @bingen:field[version=1]
+	ObjectCount     int             `json:"objectCount"`           // @bingen:field[version=1]
+	Diagnostics     []Diagnostic    `json:"diagnostics,omitempty"` // @bingen:field[version=1]
+	DiagnosticLevel DiagnosticLevel `json:"level"`                 // @bingen:field[version=1]
 }

+ 2 - 7
core/pkg/model/kubemodel/namespace.go

@@ -3,8 +3,6 @@ package kubemodel
 import (
 	"fmt"
 	"time"
-
-	"github.com/opencost/opencost/core/pkg/log"
 )
 
 // @bingen:generate:Namespace
@@ -21,7 +19,7 @@ type Namespace struct {
 func (kms *KubeModelSet) RegisterNamespace(uid, name string) error {
 	if uid == "" {
 		err := fmt.Errorf("UID is nil for Namespace '%s'", name)
-		kms.RegisterError(err.Error())
+		kms.Error(err)
 		return err
 	}
 
@@ -29,7 +27,7 @@ func (kms *KubeModelSet) RegisterNamespace(uid, name string) error {
 		clusterUID := ""
 
 		if kms.Cluster == nil {
-			kms.RegisterError(fmt.Sprintf("RegisterNamespace(%s, %s): Cluster is nil", uid, name))
+			kms.Warnf("RegisterNamespace(%s, %s): Cluster is nil", uid, name)
 		} else {
 			clusterUID = kms.Cluster.UID
 		}
@@ -43,9 +41,6 @@ func (kms *KubeModelSet) RegisterNamespace(uid, name string) error {
 		kms.idx.namespaceByName[name] = kms.Namespaces[uid]
 
 		kms.Metadata.ObjectCount++
-
-		// TODO remove or reduce log level
-		log.Infof("[KM] registered namespace (%s, %s)", uid, name)
 	}
 
 	return nil

+ 32 - 1
core/pkg/model/kubemodel/node.go

@@ -1,6 +1,9 @@
 package kubemodel
 
-import "time"
+import (
+	"fmt"
+	"time"
+)
 
 // @bingen:generate:Node
 type Node struct {
@@ -23,3 +26,31 @@ type Node struct {
 	RAMByteUsageAverage      uint64 `json:"ramByteUsageAverage"`      // @bingen:field[version=1]
 	RAMByteUsageMax          uint64 `json:"ramByteUsageMax"`          // @bingen:field[version=1]
 }
+
+func (kms *KubeModelSet) RegisterNode(uid, name string) error {
+	if uid == "" {
+		err := fmt.Errorf("UID is nil for Node '%s'", name)
+		kms.Error(err)
+		return err
+	}
+
+	if _, ok := kms.Nodes[uid]; !ok {
+		clusterUID := ""
+
+		if kms.Cluster == nil {
+			kms.Warnf("RegisterNode(%s, %s): Cluster is nil", uid, name)
+		} else {
+			clusterUID = kms.Cluster.UID
+		}
+
+		kms.Nodes[uid] = &Node{
+			UID:        uid,
+			ClusterUID: clusterUID,
+			Name:       name,
+		}
+
+		kms.Metadata.ObjectCount++
+	}
+
+	return nil
+}

+ 34 - 1
core/pkg/model/kubemodel/owner.go

@@ -1,6 +1,9 @@
 package kubemodel
 
-import "time"
+import (
+	"fmt"
+	"time"
+)
 
 // @bingen:generate:OwnerKind
 type OwnerKind string
@@ -27,3 +30,33 @@ type Owner struct {
 	Start       time.Time         `json:"start"`                 // @bingen:field[version=1]
 	End         time.Time         `json:"end"`                   // @bingen:field[version=1]
 }
+
+func (kms *KubeModelSet) RegisterOwner(uid, name, namespace, kind string, isController bool) error {
+	if uid == "" {
+		err := fmt.Errorf("UID is nil for Owner '%s'", name)
+		kms.Error(err)
+		return err
+	}
+
+	if _, ok := kms.Owners[uid]; !ok {
+		namespaceUID := ""
+
+		if ns, ok := kms.idx.namespaceByName[namespace]; !ok {
+			kms.Warnf("RegisterOwner(%s, %s, %s, %s, %t): missing namespace '%s'", uid, name, namespace, kind, isController, namespace)
+		} else {
+			namespaceUID = ns.UID
+		}
+
+		kms.Owners[uid] = &Owner{
+			UID:        uid,
+			Name:       name,
+			OwnerUID:   namespaceUID,
+			Kind:       OwnerKind(kind),
+			Controller: isController,
+		}
+
+		kms.Metadata.ObjectCount++
+	}
+
+	return nil
+}

+ 32 - 1
core/pkg/model/kubemodel/pod.go

@@ -1,6 +1,9 @@
 package kubemodel
 
-import "time"
+import (
+	"fmt"
+	"time"
+)
 
 // @bingen:generate:Pod
 type Pod struct {
@@ -18,3 +21,31 @@ type Pod struct {
 	NetworkTransferBytes uint64            `json:"networkTransferBytes"`  // @bingen:field[version=1]
 	NetworkReceiveBytes  uint64            `json:"networkReceiveBytes"`   // @bingen:field[version=1]
 }
+
+func (kms *KubeModelSet) RegisterPod(uid, name, namespace string) error {
+	if uid == "" {
+		err := fmt.Errorf("UID is nil for Pod '%s'", name)
+		kms.Error(err)
+		return err
+	}
+
+	if _, ok := kms.Pods[uid]; !ok {
+		namespaceUID := ""
+
+		if ns, ok := kms.idx.namespaceByName[namespace]; !ok {
+			kms.Warnf("RegisterPod(%s, %s, %s): missing namespace '%s'", uid, name, namespace, namespace)
+		} else {
+			namespaceUID = ns.UID
+		}
+
+		kms.Pods[uid] = &Pod{
+			UID:          uid,
+			Name:         name,
+			NamespaceUID: namespaceUID,
+		}
+
+		kms.Metadata.ObjectCount++
+	}
+
+	return nil
+}

+ 2 - 9
core/pkg/model/kubemodel/resourcequota.go

@@ -3,12 +3,8 @@ package kubemodel
 import (
 	"fmt"
 	"time"
-
-	"github.com/opencost/opencost/core/pkg/log"
 )
 
-// TODO: Do we need (Start, End) for these?
-
 // @bingen:generate:ResourceQuota
 type ResourceQuota struct {
 	UID          string               `json:"uid"`          // @bingen:field[version=1]
@@ -77,7 +73,7 @@ func (stat *ResourceQuotaStatusUsed) SetLimit(resource Resource, unit Unit, stat
 func (kms *KubeModelSet) RegisterResourceQuota(uid, name, namespace string) error {
 	if uid == "" {
 		err := fmt.Errorf("UID is nil for ResourceQuota '%s'", name)
-		kms.RegisterError(err.Error())
+		kms.Error(err)
 		return err
 	}
 
@@ -85,7 +81,7 @@ func (kms *KubeModelSet) RegisterResourceQuota(uid, name, namespace string) erro
 		namespaceUID := ""
 
 		if _, ok := kms.idx.namespaceByName[namespace]; !ok {
-			kms.RegisterError(fmt.Sprintf("RegisterResourceQuota(%s, %s, %s): missing namespace", uid, name, namespace))
+			kms.Warnf("RegisterResourceQuota(%s, %s, %s): missing namespace", uid, name, namespace)
 		} else {
 			namespaceUID = kms.idx.namespaceByName[namespace].UID
 		}
@@ -99,9 +95,6 @@ func (kms *KubeModelSet) RegisterResourceQuota(uid, name, namespace string) erro
 		}
 
 		kms.Metadata.ObjectCount++
-
-		// TODO remove or reduce log level
-		log.Infof("[KM] registered resource quota (%s, %s, %s)", uid, name, namespace)
 	}
 
 	return nil

+ 0 - 39
core/pkg/model/kubemodel/service.go

@@ -1,39 +0,0 @@
-package kubemodel
-
-import "time"
-
-// @bingen:generate:ServiceType
-type ServiceType string
-
-const (
-	ServiceTypeClusterIP    ServiceType = "ClusterIP"
-	ServiceTypeNodePort     ServiceType = "NodePort"
-	ServiceTypeLoadBalancer ServiceType = "LoadBalancer"
-	ServiceTypeExternalName ServiceType = "ExternalName"
-)
-
-// @bingen:generate:ServicePort
-type ServicePort struct {
-	Name       string `json:"name"`       // @bingen:field[version=1]
-	Port       uint16 `json:"port"`       // @bingen:field[version=1]
-	TargetPort uint16 `json:"targetPort"` // @bingen:field[version=1]
-	NodePort   uint16 `json:"nodePort"`   // @bingen:field[version=1]
-	Protocol   string `json:"protocol"`   // @bingen:field[version=1]
-}
-
-// @bingen:generate:Service
-type Service struct {
-	UID                  string            `json:"uid"`                   // @bingen:field[version=1]
-	ClusterUID           string            `json:"clusterUid"`            // @bingen:field[version=1]
-	NamespaceUID         string            `json:"namespaceUid"`          // @bingen:field[version=1]
-	Name                 string            `json:"name"`                  // @bingen:field[version=1]
-	Type                 ServiceType       `json:"type"`                  // @bingen:field[version=1]
-	Hostname             string            `json:"hostname,omitempty"`    // @bingen:field[version=1]
-	Labels               map[string]string `json:"labels,omitempty"`      // @bingen:field[version=1]
-	Annotations          map[string]string `json:"annotations,omitempty"` // @bingen:field[version=1]
-	Ports                []ServicePort     `json:"ports,omitempty"`       // @bingen:field[version=1]
-	Start                time.Time         `json:"start"`                 // @bingen:field[version=1]
-	End                  time.Time         `json:"end"`                   // @bingen:field[version=1]
-	NetworkTransferBytes uint64            `json:"networkTransferBytes"`  // @bingen:field[version=1]
-	NetworkReceiveBytes  uint64            `json:"networkReceiveBytes"`   // @bingen:field[version=1]
-}