diff --git a/apis/core/v1alpha1/generic_resource_helpers.go b/apis/core/v1alpha1/generic_resource_helpers.go index e61c6d92d..d8203ff69 100644 --- a/apis/core/v1alpha1/generic_resource_helpers.go +++ b/apis/core/v1alpha1/generic_resource_helpers.go @@ -36,6 +36,28 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" ) +// TenantOrgID returns the org this usage is billed to, falling back to the +// deprecated namespace org id until every producer sets Tenant. +func (s GenericResourceSpec) TenantOrgID() string { + if s.Tenant != nil && s.Tenant.OrgID != "" { + return s.Tenant.OrgID + } + if s.Namespace != nil { + return s.Namespace.AceOrgID + } + return "" +} + +func (s GenericResourceSpec) TenantOrgMetadata() map[string]string { + if s.Tenant != nil && s.Tenant.OrgID != "" { + return s.Tenant.Metadata + } + if s.Namespace != nil { + return s.Namespace.AceOrgMetadata + } + return nil +} + func GetGenericResourceName(item client.Object) string { return fmt.Sprintf("%s~%s", item.GetName(), item.GetObjectKind().GroupVersionKind().GroupKind()) } diff --git a/apis/core/v1alpha1/generic_resource_types.go b/apis/core/v1alpha1/generic_resource_types.go index 69ea8aa8a..13f091f20 100644 --- a/apis/core/v1alpha1/generic_resource_types.go +++ b/apis/core/v1alpha1/generic_resource_types.go @@ -80,6 +80,7 @@ type GenericResourceSpec struct { RoleResourceRequests map[api.PodRole]ResourceList `json:"roleResourceRequests,omitempty"` Namespace *NamespaceInfo `json:"namespace,omitempty"` + Tenant *TenantInfo `json:"tenant,omitempty"` Pods []ComputeResource `json:"pods,omitempty"` Storage []StorageResource `json:"storage,omitempty"` @@ -91,12 +92,31 @@ type NamespaceInfo struct { UID types.UID `json:"uid,omitempty"` Name string `json:"name"` // +optional - CreationTimestamp metav1.Time `json:"creationTimestamp,omitempty"` - AceOrgID string `json:"aceOrgID,omitempty"` + CreationTimestamp metav1.Time `json:"creationTimestamp,omitempty"` + // Deprecated: use GenericResourceSpec.Tenant. Removed after one release. + AceOrgID string `json:"aceOrgID,omitempty"` + // Deprecated: use GenericResourceSpec.Tenant. Removed after one release. AceOrgMetadata map[string]string `json:"aceOrgMetadata,omitempty"` EnableResourceTrial bool `json:"enableResourceTrial,omitempty"` } +// +kubebuilder:validation:Enum=namespace;cluster +type TenantSource string + +const ( + TenantSourceNamespace TenantSource = "namespace" + TenantSourceCluster TenantSource = "cluster" +) + +// TenantInfo identifies the org a usage event is billed to, independent of how +// that org was discovered. +type TenantInfo struct { + OrgID string `json:"orgID,omitempty"` + // +optional + Metadata map[string]string `json:"metadata,omitempty"` + Source TenantSource `json:"source,omitempty"` +} + type ComputeResource struct { // +optional UID types.UID `json:"uid,omitempty"` diff --git a/apis/core/v1alpha1/openapi_generated.go b/apis/core/v1alpha1/openapi_generated.go index 496fe15b7..6fe628351 100644 --- a/apis/core/v1alpha1/openapi_generated.go +++ b/apis/core/v1alpha1/openapi_generated.go @@ -401,6 +401,7 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA "kmodules.xyz/resource-metadata/apis/core/v1alpha1.ResourceView": schema_resource_metadata_apis_core_v1alpha1_ResourceView(ref), "kmodules.xyz/resource-metadata/apis/core/v1alpha1.Service": schema_resource_metadata_apis_core_v1alpha1_Service(ref), "kmodules.xyz/resource-metadata/apis/core/v1alpha1.StorageResource": schema_resource_metadata_apis_core_v1alpha1_StorageResource(ref), + "kmodules.xyz/resource-metadata/apis/core/v1alpha1.TenantInfo": schema_resource_metadata_apis_core_v1alpha1_TenantInfo(ref), "kmodules.xyz/resource-metadata/apis/shared.Action": schema_kmodulesxyz_resource_metadata_apis_shared_Action(ref), "kmodules.xyz/resource-metadata/apis/shared.ActionGroup": schema_kmodulesxyz_resource_metadata_apis_shared_ActionGroup(ref), "kmodules.xyz/resource-metadata/apis/shared.ActionInfo": schema_kmodulesxyz_resource_metadata_apis_shared_ActionInfo(ref), @@ -20655,6 +20656,11 @@ func schema_resource_metadata_apis_core_v1alpha1_GenericResourceSpec(ref common. Ref: ref("kmodules.xyz/resource-metadata/apis/core/v1alpha1.NamespaceInfo"), }, }, + "tenant": { + SchemaProps: spec.SchemaProps{ + Ref: ref("kmodules.xyz/resource-metadata/apis/core/v1alpha1.TenantInfo"), + }, + }, "pods": { SchemaProps: spec.SchemaProps{ Type: []string{"array"}, @@ -20692,7 +20698,7 @@ func schema_resource_metadata_apis_core_v1alpha1_GenericResourceSpec(ref common. }, }, Dependencies: []string{ - "kmodules.xyz/client-go/api/v1.ClusterMetadata", "kmodules.xyz/client-go/api/v1.ResourceID", "kmodules.xyz/resource-metadata/apis/core/v1alpha1.ComputeResource", "kmodules.xyz/resource-metadata/apis/core/v1alpha1.GenericResourceStatus", "kmodules.xyz/resource-metadata/apis/core/v1alpha1.NamespaceInfo", "kmodules.xyz/resource-metadata/apis/core/v1alpha1.ResourceRequirements", "kmodules.xyz/resource-metadata/apis/core/v1alpha1.StorageResource"}, + "kmodules.xyz/client-go/api/v1.ClusterMetadata", "kmodules.xyz/client-go/api/v1.ResourceID", "kmodules.xyz/resource-metadata/apis/core/v1alpha1.ComputeResource", "kmodules.xyz/resource-metadata/apis/core/v1alpha1.GenericResourceStatus", "kmodules.xyz/resource-metadata/apis/core/v1alpha1.NamespaceInfo", "kmodules.xyz/resource-metadata/apis/core/v1alpha1.ResourceRequirements", "kmodules.xyz/resource-metadata/apis/core/v1alpha1.StorageResource", "kmodules.xyz/resource-metadata/apis/core/v1alpha1.TenantInfo"}, } } @@ -20785,13 +20791,15 @@ func schema_resource_metadata_apis_core_v1alpha1_NamespaceInfo(ref common.Refere }, "aceOrgID": { SchemaProps: spec.SchemaProps{ - Type: []string{"string"}, - Format: "", + Description: "Deprecated: use GenericResourceSpec.Tenant. Removed after one release.", + Type: []string{"string"}, + Format: "", }, }, "aceOrgMetadata": { SchemaProps: spec.SchemaProps{ - Type: []string{"object"}, + Description: "Deprecated: use GenericResourceSpec.Tenant. Removed after one release.", + Type: []string{"object"}, AdditionalProperties: &spec.SchemaOrBool{ Allows: true, Schema: &spec.Schema{ @@ -21453,6 +21461,46 @@ func schema_resource_metadata_apis_core_v1alpha1_StorageResource(ref common.Refe } } +func schema_resource_metadata_apis_core_v1alpha1_TenantInfo(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "TenantInfo identifies the org a usage event is billed to, independent of how that org was discovered.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "orgID": { + SchemaProps: spec.SchemaProps{ + Type: []string{"string"}, + Format: "", + }, + }, + "metadata": { + SchemaProps: spec.SchemaProps{ + Type: []string{"object"}, + AdditionalProperties: &spec.SchemaOrBool{ + Allows: true, + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + }, + }, + }, + "source": { + SchemaProps: spec.SchemaProps{ + Type: []string{"string"}, + Format: "", + }, + }, + }, + }, + }, + } +} + func schema_kmodulesxyz_resource_metadata_apis_shared_Action(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ diff --git a/apis/core/v1alpha1/zz_generated.deepcopy.go b/apis/core/v1alpha1/zz_generated.deepcopy.go index a6b4e4a9c..152e7d64b 100644 --- a/apis/core/v1alpha1/zz_generated.deepcopy.go +++ b/apis/core/v1alpha1/zz_generated.deepcopy.go @@ -506,6 +506,11 @@ func (in *GenericResourceSpec) DeepCopyInto(out *GenericResourceSpec) { *out = new(NamespaceInfo) (*in).DeepCopyInto(*out) } + if in.Tenant != nil { + in, out := &in.Tenant, &out.Tenant + *out = new(TenantInfo) + (*in).DeepCopyInto(*out) + } if in.Pods != nil { in, out := &in.Pods, &out.Pods *out = make([]ComputeResource, len(*in)) @@ -1010,3 +1015,26 @@ func (in *StorageResource) DeepCopy() *StorageResource { in.DeepCopyInto(out) return out } + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TenantInfo) DeepCopyInto(out *TenantInfo) { + *out = *in + if in.Metadata != nil { + in, out := &in.Metadata, &out.Metadata + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TenantInfo. +func (in *TenantInfo) DeepCopy() *TenantInfo { + if in == nil { + return nil + } + out := new(TenantInfo) + in.DeepCopyInto(out) + return out +} diff --git a/crds/core.k8s.appscode.com_genericresources.yaml b/crds/core.k8s.appscode.com_genericresources.yaml index d5e3be133..b90edc958 100644 --- a/crds/core.k8s.appscode.com_genericresources.yaml +++ b/crds/core.k8s.appscode.com_genericresources.yaml @@ -124,10 +124,14 @@ spec: namespace: properties: aceOrgID: + description: 'Deprecated: use GenericResourceSpec.Tenant. Removed + after one release.' type: string aceOrgMetadata: additionalProperties: type: string + description: 'Deprecated: use GenericResourceSpec.Tenant. Removed + after one release.' type: object creationTimestamp: format: date-time @@ -389,6 +393,23 @@ spec: - name type: object type: array + tenant: + description: |- + TenantInfo identifies the org a usage event is billed to, independent of how + that org was discovered. + properties: + metadata: + additionalProperties: + type: string + type: object + orgID: + type: string + source: + enum: + - namespace + - cluster + type: string + type: object totalResource: properties: limits: