Compare commits

...

3 Commits

Author SHA1 Message Date
nikhilmantri0902
dff443f68c chore: added tests 2026-07-21 20:21:55 +05:30
nikhilmantri0902
dadec2acc4 chore: using the type directly instead of a middle variable 2026-07-21 19:49:04 +05:30
nikhilmantri0902
51edea502d chore: strong typing added for meta map 2026-07-21 19:30:59 +05:30
37 changed files with 1222 additions and 343 deletions

View File

@@ -4247,6 +4247,15 @@ components:
- missingOptionalMetrics
- missingRequiredAttributes
type: object
InframonitoringtypesClusterMeta:
additionalProperties:
type: string
properties:
k8s.cluster.name:
type: string
required:
- k8s.cluster.name
type: object
InframonitoringtypesClusterRecord:
properties:
clusterCPU:
@@ -4292,10 +4301,7 @@ components:
- statefulSets
type: object
meta:
additionalProperties:
type: string
nullable: true
type: object
$ref: '#/components/schemas/InframonitoringtypesClusterMeta'
nodeCountsByReadiness:
$ref: '#/components/schemas/InframonitoringtypesNodeCountsByReadiness'
podCountsByPhase:
@@ -4387,6 +4393,51 @@ components:
- containerCannotRun
- unknown
type: object
InframonitoringtypesContainerMeta:
additionalProperties:
type: string
properties:
container.image.name:
type: string
container.image.tag:
type: string
k8s.cluster.name:
type: string
k8s.container.name:
type: string
k8s.cronjob.name:
type: string
k8s.daemonset.name:
type: string
k8s.deployment.name:
type: string
k8s.job.name:
type: string
k8s.namespace.name:
type: string
k8s.node.name:
type: string
k8s.pod.name:
type: string
k8s.pod.uid:
type: string
k8s.statefulset.name:
type: string
required:
- k8s.pod.uid
- k8s.container.name
- k8s.pod.name
- container.image.name
- container.image.tag
- k8s.namespace.name
- k8s.node.name
- k8s.deployment.name
- k8s.statefulset.name
- k8s.daemonset.name
- k8s.job.name
- k8s.cronjob.name
- k8s.cluster.name
type: object
InframonitoringtypesContainerReady:
enum:
- ready
@@ -4420,10 +4471,7 @@ components:
format: double
type: number
meta:
additionalProperties:
type: string
nullable: true
type: object
$ref: '#/components/schemas/InframonitoringtypesContainerMeta'
podUID:
type: string
ready:
@@ -4486,6 +4534,21 @@ components:
- total
- endTimeBeforeRetention
type: object
InframonitoringtypesDaemonSetMeta:
additionalProperties:
type: string
properties:
k8s.cluster.name:
type: string
k8s.daemonset.name:
type: string
k8s.namespace.name:
type: string
required:
- k8s.daemonset.name
- k8s.namespace.name
- k8s.cluster.name
type: object
InframonitoringtypesDaemonSetRecord:
properties:
currentNodes:
@@ -4513,10 +4576,7 @@ components:
desiredNodes:
type: integer
meta:
additionalProperties:
type: string
nullable: true
type: object
$ref: '#/components/schemas/InframonitoringtypesDaemonSetMeta'
misscheduledNodes:
type: integer
podCountsByPhase:
@@ -4561,6 +4621,21 @@ components:
- total
- endTimeBeforeRetention
type: object
InframonitoringtypesDeploymentMeta:
additionalProperties:
type: string
properties:
k8s.cluster.name:
type: string
k8s.deployment.name:
type: string
k8s.namespace.name:
type: string
required:
- k8s.deployment.name
- k8s.namespace.name
- k8s.cluster.name
type: object
InframonitoringtypesDeploymentRecord:
properties:
availablePods:
@@ -4588,10 +4663,7 @@ components:
desiredPods:
type: integer
meta:
additionalProperties:
type: string
nullable: true
type: object
$ref: '#/components/schemas/InframonitoringtypesDeploymentMeta'
podCountsByPhase:
$ref: '#/components/schemas/InframonitoringtypesPodCountsByPhase'
podCountsByStatus:
@@ -4637,6 +4709,18 @@ components:
filterByStatus:
$ref: '#/components/schemas/InframonitoringtypesHostStatus'
type: object
InframonitoringtypesHostMeta:
additionalProperties:
type: string
properties:
host.name:
type: string
os.type:
type: string
required:
- os.type
- host.name
type: object
InframonitoringtypesHostRecord:
properties:
activeHostCount:
@@ -4658,10 +4742,7 @@ components:
format: double
type: number
meta:
additionalProperties:
type: string
nullable: true
type: object
$ref: '#/components/schemas/InframonitoringtypesHostMeta'
status:
$ref: '#/components/schemas/InframonitoringtypesHostStatus'
wait:
@@ -4705,6 +4786,21 @@ components:
- total
- endTimeBeforeRetention
type: object
InframonitoringtypesJobMeta:
additionalProperties:
type: string
properties:
k8s.cluster.name:
type: string
k8s.job.name:
type: string
k8s.namespace.name:
type: string
required:
- k8s.job.name
- k8s.namespace.name
- k8s.cluster.name
type: object
InframonitoringtypesJobRecord:
properties:
activePods:
@@ -4734,10 +4830,7 @@ components:
jobName:
type: string
meta:
additionalProperties:
type: string
nullable: true
type: object
$ref: '#/components/schemas/InframonitoringtypesJobMeta'
podCountsByPhase:
$ref: '#/components/schemas/InframonitoringtypesPodCountsByPhase'
podCountsByStatus:
@@ -4831,6 +4924,18 @@ components:
- message
- documentationLink
type: object
InframonitoringtypesNamespaceMeta:
additionalProperties:
type: string
properties:
k8s.cluster.name:
type: string
k8s.namespace.name:
type: string
required:
- k8s.namespace.name
- k8s.cluster.name
type: object
InframonitoringtypesNamespaceRecord:
properties:
counts:
@@ -4854,10 +4959,7 @@ components:
- statefulSets
type: object
meta:
additionalProperties:
type: string
nullable: true
type: object
$ref: '#/components/schemas/InframonitoringtypesNamespaceMeta'
namespaceCPU:
format: double
type: number
@@ -4915,15 +5017,27 @@ components:
- ready
- notReady
type: object
InframonitoringtypesNodeMeta:
additionalProperties:
type: string
properties:
k8s.cluster.name:
type: string
k8s.node.name:
type: string
k8s.node.uid:
type: string
required:
- k8s.node.uid
- k8s.cluster.name
- k8s.node.name
type: object
InframonitoringtypesNodeRecord:
properties:
condition:
$ref: '#/components/schemas/InframonitoringtypesNodeCondition'
meta:
additionalProperties:
type: string
nullable: true
type: object
$ref: '#/components/schemas/InframonitoringtypesNodeMeta'
nodeCPU:
format: double
type: number
@@ -5053,6 +5167,45 @@ components:
- shutdown
- unexpectedAdmissionError
type: object
InframonitoringtypesPodMeta:
additionalProperties:
type: string
properties:
k8s.cluster.name:
type: string
k8s.cronjob.name:
type: string
k8s.daemonset.name:
type: string
k8s.deployment.name:
type: string
k8s.job.name:
type: string
k8s.namespace.name:
type: string
k8s.node.name:
type: string
k8s.pod.name:
type: string
k8s.pod.start_time:
type: string
k8s.pod.uid:
type: string
k8s.statefulset.name:
type: string
required:
- k8s.pod.uid
- k8s.pod.name
- k8s.namespace.name
- k8s.node.name
- k8s.deployment.name
- k8s.statefulset.name
- k8s.daemonset.name
- k8s.job.name
- k8s.cronjob.name
- k8s.cluster.name
- k8s.pod.start_time
type: object
InframonitoringtypesPodPhase:
enum:
- pending
@@ -5065,10 +5218,7 @@ components:
InframonitoringtypesPodRecord:
properties:
meta:
additionalProperties:
type: string
nullable: true
type: object
$ref: '#/components/schemas/InframonitoringtypesPodMeta'
podAge:
format: int64
type: integer
@@ -5452,6 +5602,21 @@ components:
- list
- grouped_list
type: string
InframonitoringtypesStatefulSetMeta:
additionalProperties:
type: string
properties:
k8s.cluster.name:
type: string
k8s.namespace.name:
type: string
k8s.statefulset.name:
type: string
required:
- k8s.statefulset.name
- k8s.namespace.name
- k8s.cluster.name
type: object
InframonitoringtypesStatefulSetRecord:
properties:
currentPods:
@@ -5459,10 +5624,7 @@ components:
desiredPods:
type: integer
meta:
additionalProperties:
type: string
nullable: true
type: object
$ref: '#/components/schemas/InframonitoringtypesStatefulSetMeta'
podCountsByPhase:
$ref: '#/components/schemas/InframonitoringtypesPodCountsByPhase'
podCountsByStatus:
@@ -5521,13 +5683,37 @@ components:
- total
- endTimeBeforeRetention
type: object
InframonitoringtypesVolumeMeta:
additionalProperties:
type: string
properties:
k8s.cluster.name:
type: string
k8s.namespace.name:
type: string
k8s.node.name:
type: string
k8s.persistentvolumeclaim.name:
type: string
k8s.pod.name:
type: string
k8s.pod.uid:
type: string
k8s.statefulset.name:
type: string
required:
- k8s.persistentvolumeclaim.name
- k8s.pod.uid
- k8s.pod.name
- k8s.namespace.name
- k8s.node.name
- k8s.statefulset.name
- k8s.cluster.name
type: object
InframonitoringtypesVolumeRecord:
properties:
meta:
additionalProperties:
type: string
nullable: true
type: object
$ref: '#/components/schemas/InframonitoringtypesVolumeMeta'
persistentVolumeClaimName:
type: string
volumeAvailable:

View File

@@ -5681,6 +5681,14 @@ export interface InframonitoringtypesChecksDTO {
type: InframonitoringtypesCheckTypeDTO;
}
export interface InframonitoringtypesClusterMetaDTO {
/**
* @type string
*/
'k8s.cluster.name': string;
[key: string]: string;
}
export type InframonitoringtypesClusterRecordDTOCounts = {
/**
* @type integer
@@ -5714,16 +5722,6 @@ export type InframonitoringtypesClusterRecordDTOCounts = {
statefulSets: number;
};
export type InframonitoringtypesClusterRecordDTOMetaAnyOf = {
[key: string]: string;
};
/**
* @nullable
*/
export type InframonitoringtypesClusterRecordDTOMeta =
InframonitoringtypesClusterRecordDTOMetaAnyOf | null;
export interface InframonitoringtypesNodeCountsByReadinessDTO {
/**
* @type integer
@@ -5862,10 +5860,7 @@ export interface InframonitoringtypesClusterRecordDTO {
* @type object
*/
counts: InframonitoringtypesClusterRecordDTOCounts;
/**
* @type object,null
*/
meta: InframonitoringtypesClusterRecordDTOMeta;
meta: InframonitoringtypesClusterMetaDTO;
nodeCountsByReadiness: InframonitoringtypesNodeCountsByReadinessDTO;
podCountsByPhase: InframonitoringtypesPodCountsByPhaseDTO;
podCountsByStatus: InframonitoringtypesPodCountsByStatusDTO;
@@ -5980,21 +5975,67 @@ export interface InframonitoringtypesContainerCountsByStatusDTO {
waiting: number;
}
export interface InframonitoringtypesContainerMetaDTO {
/**
* @type string
*/
'container.image.name': string;
/**
* @type string
*/
'container.image.tag': string;
/**
* @type string
*/
'k8s.cluster.name': string;
/**
* @type string
*/
'k8s.container.name': string;
/**
* @type string
*/
'k8s.cronjob.name': string;
/**
* @type string
*/
'k8s.daemonset.name': string;
/**
* @type string
*/
'k8s.deployment.name': string;
/**
* @type string
*/
'k8s.job.name': string;
/**
* @type string
*/
'k8s.namespace.name': string;
/**
* @type string
*/
'k8s.node.name': string;
/**
* @type string
*/
'k8s.pod.name': string;
/**
* @type string
*/
'k8s.pod.uid': string;
/**
* @type string
*/
'k8s.statefulset.name': string;
[key: string]: string;
}
export enum InframonitoringtypesContainerReadyDTO {
ready = 'ready',
not_ready = 'not_ready',
no_data = 'no_data',
}
export type InframonitoringtypesContainerRecordDTOMetaAnyOf = {
[key: string]: string;
};
/**
* @nullable
*/
export type InframonitoringtypesContainerRecordDTOMeta =
InframonitoringtypesContainerRecordDTOMetaAnyOf | null;
export enum InframonitoringtypesContainerStatusDTO {
running = 'running',
waiting = 'waiting',
@@ -6048,10 +6089,7 @@ export interface InframonitoringtypesContainerRecordDTO {
* @format double
*/
memoryRequestUtilization: number;
/**
* @type object,null
*/
meta: InframonitoringtypesContainerRecordDTOMeta;
meta: InframonitoringtypesContainerMetaDTO;
/**
* @type string
*/
@@ -6082,15 +6120,21 @@ export interface InframonitoringtypesContainersDTO {
warning?: Querybuildertypesv5QueryWarnDataDTO;
}
export type InframonitoringtypesDaemonSetRecordDTOMetaAnyOf = {
export interface InframonitoringtypesDaemonSetMetaDTO {
/**
* @type string
*/
'k8s.cluster.name': string;
/**
* @type string
*/
'k8s.daemonset.name': string;
/**
* @type string
*/
'k8s.namespace.name': string;
[key: string]: string;
};
/**
* @nullable
*/
export type InframonitoringtypesDaemonSetRecordDTOMeta =
InframonitoringtypesDaemonSetRecordDTOMetaAnyOf | null;
}
export interface InframonitoringtypesDaemonSetRecordDTO {
/**
@@ -6135,10 +6179,7 @@ export interface InframonitoringtypesDaemonSetRecordDTO {
* @type integer
*/
desiredNodes: number;
/**
* @type object,null
*/
meta: InframonitoringtypesDaemonSetRecordDTOMeta;
meta: InframonitoringtypesDaemonSetMetaDTO;
/**
* @type integer
*/
@@ -6168,15 +6209,21 @@ export interface InframonitoringtypesDaemonSetsDTO {
warning?: Querybuildertypesv5QueryWarnDataDTO;
}
export type InframonitoringtypesDeploymentRecordDTOMetaAnyOf = {
export interface InframonitoringtypesDeploymentMetaDTO {
/**
* @type string
*/
'k8s.cluster.name': string;
/**
* @type string
*/
'k8s.deployment.name': string;
/**
* @type string
*/
'k8s.namespace.name': string;
[key: string]: string;
};
/**
* @nullable
*/
export type InframonitoringtypesDeploymentRecordDTOMeta =
InframonitoringtypesDeploymentRecordDTOMetaAnyOf | null;
}
export interface InframonitoringtypesDeploymentRecordDTO {
/**
@@ -6221,10 +6268,7 @@ export interface InframonitoringtypesDeploymentRecordDTO {
* @type integer
*/
desiredPods: number;
/**
* @type object,null
*/
meta: InframonitoringtypesDeploymentRecordDTOMeta;
meta: InframonitoringtypesDeploymentMetaDTO;
podCountsByPhase: InframonitoringtypesPodCountsByPhaseDTO;
podCountsByStatus: InframonitoringtypesPodCountsByStatusDTO;
}
@@ -6259,15 +6303,17 @@ export interface InframonitoringtypesHostFilterDTO {
filterByStatus?: InframonitoringtypesHostStatusDTO;
}
export type InframonitoringtypesHostRecordDTOMetaAnyOf = {
export interface InframonitoringtypesHostMetaDTO {
/**
* @type string
*/
'host.name': string;
/**
* @type string
*/
'os.type': string;
[key: string]: string;
};
/**
* @nullable
*/
export type InframonitoringtypesHostRecordDTOMeta =
InframonitoringtypesHostRecordDTOMetaAnyOf | null;
}
export interface InframonitoringtypesHostRecordDTO {
/**
@@ -6302,10 +6348,7 @@ export interface InframonitoringtypesHostRecordDTO {
* @format double
*/
memory: number;
/**
* @type object,null
*/
meta: InframonitoringtypesHostRecordDTOMeta;
meta: InframonitoringtypesHostMetaDTO;
status: InframonitoringtypesHostStatusDTO;
/**
* @type number
@@ -6331,15 +6374,21 @@ export interface InframonitoringtypesHostsDTO {
warning?: Querybuildertypesv5QueryWarnDataDTO;
}
export type InframonitoringtypesJobRecordDTOMetaAnyOf = {
export interface InframonitoringtypesJobMetaDTO {
/**
* @type string
*/
'k8s.cluster.name': string;
/**
* @type string
*/
'k8s.job.name': string;
/**
* @type string
*/
'k8s.namespace.name': string;
[key: string]: string;
};
/**
* @nullable
*/
export type InframonitoringtypesJobRecordDTOMeta =
InframonitoringtypesJobRecordDTOMetaAnyOf | null;
}
export interface InframonitoringtypesJobRecordDTO {
/**
@@ -6388,10 +6437,7 @@ export interface InframonitoringtypesJobRecordDTO {
* @type string
*/
jobName: string;
/**
* @type object,null
*/
meta: InframonitoringtypesJobRecordDTOMeta;
meta: InframonitoringtypesJobMetaDTO;
podCountsByPhase: InframonitoringtypesPodCountsByPhaseDTO;
podCountsByStatus: InframonitoringtypesPodCountsByStatusDTO;
/**
@@ -6417,6 +6463,18 @@ export interface InframonitoringtypesJobsDTO {
warning?: Querybuildertypesv5QueryWarnDataDTO;
}
export interface InframonitoringtypesNamespaceMetaDTO {
/**
* @type string
*/
'k8s.cluster.name': string;
/**
* @type string
*/
'k8s.namespace.name': string;
[key: string]: string;
}
export type InframonitoringtypesNamespaceRecordDTOCounts = {
/**
* @type integer
@@ -6440,25 +6498,12 @@ export type InframonitoringtypesNamespaceRecordDTOCounts = {
statefulSets: number;
};
export type InframonitoringtypesNamespaceRecordDTOMetaAnyOf = {
[key: string]: string;
};
/**
* @nullable
*/
export type InframonitoringtypesNamespaceRecordDTOMeta =
InframonitoringtypesNamespaceRecordDTOMetaAnyOf | null;
export interface InframonitoringtypesNamespaceRecordDTO {
/**
* @type object
*/
counts: InframonitoringtypesNamespaceRecordDTOCounts;
/**
* @type object,null
*/
meta: InframonitoringtypesNamespaceRecordDTOMeta;
meta: InframonitoringtypesNamespaceMetaDTO;
/**
* @type number
* @format double
@@ -6499,22 +6544,25 @@ export enum InframonitoringtypesNodeConditionDTO {
not_ready = 'not_ready',
no_data = 'no_data',
}
export type InframonitoringtypesNodeRecordDTOMetaAnyOf = {
export interface InframonitoringtypesNodeMetaDTO {
/**
* @type string
*/
'k8s.cluster.name': string;
/**
* @type string
*/
'k8s.node.name': string;
/**
* @type string
*/
'k8s.node.uid': string;
[key: string]: string;
};
/**
* @nullable
*/
export type InframonitoringtypesNodeRecordDTOMeta =
InframonitoringtypesNodeRecordDTOMetaAnyOf | null;
}
export interface InframonitoringtypesNodeRecordDTO {
condition: InframonitoringtypesNodeConditionDTO;
/**
* @type object,null
*/
meta: InframonitoringtypesNodeRecordDTOMeta;
meta: InframonitoringtypesNodeMetaDTO;
/**
* @type number
* @format double
@@ -6561,6 +6609,54 @@ export interface InframonitoringtypesNodesDTO {
warning?: Querybuildertypesv5QueryWarnDataDTO;
}
export interface InframonitoringtypesPodMetaDTO {
/**
* @type string
*/
'k8s.cluster.name': string;
/**
* @type string
*/
'k8s.cronjob.name': string;
/**
* @type string
*/
'k8s.daemonset.name': string;
/**
* @type string
*/
'k8s.deployment.name': string;
/**
* @type string
*/
'k8s.job.name': string;
/**
* @type string
*/
'k8s.namespace.name': string;
/**
* @type string
*/
'k8s.node.name': string;
/**
* @type string
*/
'k8s.pod.name': string;
/**
* @type string
*/
'k8s.pod.start_time': string;
/**
* @type string
*/
'k8s.pod.uid': string;
/**
* @type string
*/
'k8s.statefulset.name': string;
[key: string]: string;
}
export enum InframonitoringtypesPodPhaseDTO {
pending = 'pending',
running = 'running',
@@ -6569,16 +6665,6 @@ export enum InframonitoringtypesPodPhaseDTO {
unknown = 'unknown',
no_data = 'no_data',
}
export type InframonitoringtypesPodRecordDTOMetaAnyOf = {
[key: string]: string;
};
/**
* @nullable
*/
export type InframonitoringtypesPodRecordDTOMeta =
InframonitoringtypesPodRecordDTOMetaAnyOf | null;
export enum InframonitoringtypesPodStatusDTO {
pending = 'pending',
running = 'running',
@@ -6601,10 +6687,7 @@ export enum InframonitoringtypesPodStatusDTO {
no_data = 'no_data',
}
export interface InframonitoringtypesPodRecordDTO {
/**
* @type object,null
*/
meta: InframonitoringtypesPodRecordDTOMeta;
meta: InframonitoringtypesPodMetaDTO;
/**
* @type integer
* @format int64
@@ -6969,15 +7052,21 @@ export interface InframonitoringtypesPostableVolumesDTO {
start: number;
}
export type InframonitoringtypesStatefulSetRecordDTOMetaAnyOf = {
export interface InframonitoringtypesStatefulSetMetaDTO {
/**
* @type string
*/
'k8s.cluster.name': string;
/**
* @type string
*/
'k8s.namespace.name': string;
/**
* @type string
*/
'k8s.statefulset.name': string;
[key: string]: string;
};
/**
* @nullable
*/
export type InframonitoringtypesStatefulSetRecordDTOMeta =
InframonitoringtypesStatefulSetRecordDTOMetaAnyOf | null;
}
export interface InframonitoringtypesStatefulSetRecordDTO {
/**
@@ -6988,10 +7077,7 @@ export interface InframonitoringtypesStatefulSetRecordDTO {
* @type integer
*/
desiredPods: number;
/**
* @type object,null
*/
meta: InframonitoringtypesStatefulSetRecordDTOMeta;
meta: InframonitoringtypesStatefulSetMetaDTO;
podCountsByPhase: InframonitoringtypesPodCountsByPhaseDTO;
podCountsByStatus: InframonitoringtypesPodCountsByStatusDTO;
/**
@@ -7047,21 +7133,40 @@ export interface InframonitoringtypesStatefulSetsDTO {
warning?: Querybuildertypesv5QueryWarnDataDTO;
}
export type InframonitoringtypesVolumeRecordDTOMetaAnyOf = {
export interface InframonitoringtypesVolumeMetaDTO {
/**
* @type string
*/
'k8s.cluster.name': string;
/**
* @type string
*/
'k8s.namespace.name': string;
/**
* @type string
*/
'k8s.node.name': string;
/**
* @type string
*/
'k8s.persistentvolumeclaim.name': string;
/**
* @type string
*/
'k8s.pod.name': string;
/**
* @type string
*/
'k8s.pod.uid': string;
/**
* @type string
*/
'k8s.statefulset.name': string;
[key: string]: string;
};
/**
* @nullable
*/
export type InframonitoringtypesVolumeRecordDTOMeta =
InframonitoringtypesVolumeRecordDTOMetaAnyOf | null;
}
export interface InframonitoringtypesVolumeRecordDTO {
/**
* @type object,null
*/
meta: InframonitoringtypesVolumeRecordDTOMeta;
meta: InframonitoringtypesVolumeMetaDTO;
/**
* @type string
*/

View File

@@ -36,7 +36,7 @@ func buildClusterRecords(
ClusterCPUAllocatable: -1,
ClusterMemory: -1,
ClusterMemoryAllocatable: -1,
Meta: map[string]string{},
Meta: inframonitoringtypes.NewClusterMeta(nil),
}
if metrics, ok := metricsMap[compositeKey]; ok {
@@ -85,9 +85,7 @@ func buildClusterRecords(
}
if attrs, ok := metadataMap[compositeKey]; ok {
for k, v := range attrs {
record.Meta[k] = v
}
record.Meta = inframonitoringtypes.NewClusterMeta(attrs)
}
records = append(records, record)
@@ -149,7 +147,7 @@ func (m *module) getTopClusterGroups(
func (m *module) getClustersTableMetadata(ctx context.Context, orgID valuer.UUID, req *inframonitoringtypes.PostableClusters) (map[string]map[string]string, error) {
var nonGroupByAttrs []string
for _, key := range clusterAttrKeysForMetadata {
for _, key := range inframonitoringtypes.ClusterMetaKeys {
if !isKeyInGroupByAttrs(req.GroupBy, key) {
nonGroupByAttrs = append(nonGroupByAttrs, key)
}

View File

@@ -31,10 +31,6 @@ var clustersTableMetricNamesList = []string{
"k8s.container.status.reason",
}
var clusterAttrKeysForMetadata = []string{
"k8s.cluster.name",
}
// clusterCountAttrKeys are the resource attributes whose distinct values are
// counted per cluster. Node name is read from the node metric universe, while
// namespace + workload names come from the pod metric universe — both unioned

View File

@@ -48,7 +48,7 @@ func buildContainerRecords(
Memory: -1,
MemoryRequestUtilization: -1,
MemoryLimitUtilization: -1,
Meta: map[string]string{},
Meta: inframonitoringtypes.NewContainerMeta(nil),
}
if metrics, ok := metricsMap[compositeKey]; ok {
@@ -128,9 +128,7 @@ func buildContainerRecords(
}
if attrs, ok := metadataMap[compositeKey]; ok {
for k, v := range attrs {
record.Meta[k] = v
}
record.Meta = inframonitoringtypes.NewContainerMeta(attrs)
}
records = append(records, record)
@@ -192,7 +190,7 @@ func (m *module) getTopContainerGroups(
func (m *module) getContainersTableMetadata(ctx context.Context, orgID valuer.UUID, req *inframonitoringtypes.PostableContainers) (map[string]map[string]string, error) {
var nonGroupByAttrs []string
for _, key := range containerAttrKeysForMetadata {
for _, key := range inframonitoringtypes.ContainerMetaKeys {
if !isKeyInGroupByAttrs(req.GroupBy, key) {
nonGroupByAttrs = append(nonGroupByAttrs, key)
}

View File

@@ -58,22 +58,6 @@ var containersTableMetricNamesList = []string{
"k8s.container.status.state",
}
var containerAttrKeysForMetadata = []string{
"k8s.pod.uid",
"k8s.container.name",
"k8s.pod.name",
"container.image.name",
"container.image.tag",
"k8s.namespace.name",
"k8s.node.name",
"k8s.deployment.name",
"k8s.statefulset.name",
"k8s.daemonset.name",
"k8s.job.name",
"k8s.cronjob.name",
"k8s.cluster.name",
}
var orderByToContainersQueryNames = map[string][]string{
inframonitoringtypes.ContainersOrderByCPU: {"A"},
inframonitoringtypes.ContainersOrderByCPURequest: {"B"},

View File

@@ -40,7 +40,7 @@ func buildDaemonSetRecords(
CurrentNodes: -1,
ReadyNodes: -1,
MisscheduledNodes: -1,
Meta: map[string]string{},
Meta: inframonitoringtypes.NewDaemonSetMeta(nil),
}
if metrics, ok := metricsMap[compositeKey]; ok {
@@ -91,9 +91,7 @@ func buildDaemonSetRecords(
}
if attrs, ok := metadataMap[compositeKey]; ok {
for k, v := range attrs {
record.Meta[k] = v
}
record.Meta = inframonitoringtypes.NewDaemonSetMeta(attrs)
}
records = append(records, record)
@@ -155,7 +153,7 @@ func (m *module) getTopDaemonSetGroups(
func (m *module) getDaemonSetsTableMetadata(ctx context.Context, orgID valuer.UUID, req *inframonitoringtypes.PostableDaemonSets) (map[string]map[string]string, error) {
var nonGroupByAttrs []string
for _, key := range daemonSetAttrKeysForMetadata {
for _, key := range inframonitoringtypes.DaemonSetMetaKeys {
if !isKeyInGroupByAttrs(req.GroupBy, key) {
nonGroupByAttrs = append(nonGroupByAttrs, key)
}

View File

@@ -39,11 +39,6 @@ var daemonSetsTableMetricNamesList = []string{
// Carried forward from v1 daemonSetAttrsToEnrich
// (pkg/query-service/app/inframetrics/daemonsets.go:29-33).
var daemonSetAttrKeysForMetadata = []string{
"k8s.daemonset.name",
"k8s.namespace.name",
"k8s.cluster.name",
}
// orderByToDaemonSetsQueryNames maps the orderBy column to the query name
// used for ranking daemonset groups. v2 B/C/E/F are direct metrics, no

View File

@@ -38,7 +38,7 @@ func buildDeploymentRecords(
DeploymentMemoryLimit: -1,
DesiredPods: -1,
AvailablePods: -1,
Meta: map[string]string{},
Meta: inframonitoringtypes.NewDeploymentMeta(nil),
}
if metrics, ok := metricsMap[compositeKey]; ok {
@@ -83,9 +83,7 @@ func buildDeploymentRecords(
}
if attrs, ok := metadataMap[compositeKey]; ok {
for k, v := range attrs {
record.Meta[k] = v
}
record.Meta = inframonitoringtypes.NewDeploymentMeta(attrs)
}
records = append(records, record)
@@ -147,7 +145,7 @@ func (m *module) getTopDeploymentGroups(
func (m *module) getDeploymentsTableMetadata(ctx context.Context, orgID valuer.UUID, req *inframonitoringtypes.PostableDeployments) (map[string]map[string]string, error) {
var nonGroupByAttrs []string
for _, key := range deploymentAttrKeysForMetadata {
for _, key := range inframonitoringtypes.DeploymentMetaKeys {
if !isKeyInGroupByAttrs(req.GroupBy, key) {
nonGroupByAttrs = append(nonGroupByAttrs, key)
}

View File

@@ -37,11 +37,6 @@ var deploymentsTableMetricNamesList = []string{
// Carried forward from v1 deploymentAttrsToEnrich
// (pkg/query-service/app/inframetrics/deployments.go:29-33).
var deploymentAttrKeysForMetadata = []string{
"k8s.deployment.name",
"k8s.namespace.name",
"k8s.cluster.name",
}
// orderByToDeploymentsQueryNames maps the orderBy column to the query name
// used for ranking deployment groups. v2 B/C/E/F are direct metrics, no

View File

@@ -216,7 +216,7 @@ func buildHostRecords(
Wait: -1,
Load15: -1,
DiskUsage: -1,
Meta: map[string]string{},
Meta: inframonitoringtypes.NewHostMeta(nil),
}
if metrics, ok := metricsMap[compositeKey]; ok {
@@ -238,9 +238,7 @@ func buildHostRecords(
}
if attrs, ok := metadataMap[compositeKey]; ok {
for k, v := range attrs {
record.Meta[k] = v
}
record.Meta = inframonitoringtypes.NewHostMeta(attrs)
}
records = append(records, record)
@@ -333,7 +331,7 @@ func (m *module) applyHostsActiveStatusFilter(req *inframonitoringtypes.Postable
func (m *module) getHostsTableMetadata(ctx context.Context, orgID valuer.UUID, req *inframonitoringtypes.PostableHosts) (map[string]map[string]string, error) {
var nonGroupByAttrs []string
for _, key := range hostAttrKeysForMetadata {
for _, key := range inframonitoringtypes.HostMetaKeys {
if !isKeyInGroupByAttrs(req.GroupBy, key) {
nonGroupByAttrs = append(nonGroupByAttrs, key)
}

View File

@@ -23,10 +23,6 @@ var hostsTableMetricNamesList = []string{
"system.filesystem.usage",
}
var hostAttrKeysForMetadata = []string{
"os.type",
}
// orderByToHostsQueryNames maps the orderBy column to the query/formula names
// from HostsTableListQuery used for ranking host groups.
var orderByToHostsQueryNames = map[string][]string{

View File

@@ -40,7 +40,7 @@ func buildJobRecords(
ActivePods: -1,
FailedPods: -1,
SuccessfulPods: -1,
Meta: map[string]string{},
Meta: inframonitoringtypes.NewJobMeta(nil),
}
if metrics, ok := metricsMap[compositeKey]; ok {
@@ -91,9 +91,7 @@ func buildJobRecords(
}
if attrs, ok := metadataMap[compositeKey]; ok {
for k, v := range attrs {
record.Meta[k] = v
}
record.Meta = inframonitoringtypes.NewJobMeta(attrs)
}
records = append(records, record)
@@ -155,7 +153,7 @@ func (m *module) getTopJobGroups(
func (m *module) getJobsTableMetadata(ctx context.Context, orgID valuer.UUID, req *inframonitoringtypes.PostableJobs) (map[string]map[string]string, error) {
var nonGroupByAttrs []string
for _, key := range jobAttrKeysForMetadata {
for _, key := range inframonitoringtypes.JobMetaKeys {
if !isKeyInGroupByAttrs(req.GroupBy, key) {
nonGroupByAttrs = append(nonGroupByAttrs, key)
}

View File

@@ -39,11 +39,6 @@ var jobsTableMetricNamesList = []string{
// Carried forward from v1 jobAttrsToEnrich
// (pkg/query-service/app/inframetrics/jobs.go:31-35).
var jobAttrKeysForMetadata = []string{
"k8s.job.name",
"k8s.namespace.name",
"k8s.cluster.name",
}
// orderByToJobsQueryNames maps the orderBy column to the query name
// used for ranking job groups. v2 B/C/E/F are direct metrics, no

View File

@@ -32,7 +32,7 @@ func buildNamespaceRecords(
NamespaceName: namespaceName,
NamespaceCPU: -1,
NamespaceMemory: -1,
Meta: map[string]string{},
Meta: inframonitoringtypes.NewNamespaceMeta(nil),
}
if metrics, ok := metricsMap[compositeKey]; ok {
@@ -66,9 +66,7 @@ func buildNamespaceRecords(
}
if attrs, ok := metadataMap[compositeKey]; ok {
for k, v := range attrs {
record.Meta[k] = v
}
record.Meta = inframonitoringtypes.NewNamespaceMeta(attrs)
}
records = append(records, record)
@@ -130,7 +128,7 @@ func (m *module) getTopNamespaceGroups(
func (m *module) getNamespacesTableMetadata(ctx context.Context, orgID valuer.UUID, req *inframonitoringtypes.PostableNamespaces) (map[string]map[string]string, error) {
var nonGroupByAttrs []string
for _, key := range namespaceAttrKeysForMetadata {
for _, key := range inframonitoringtypes.NamespaceMetaKeys {
if !isKeyInGroupByAttrs(req.GroupBy, key) {
nonGroupByAttrs = append(nonGroupByAttrs, key)
}

View File

@@ -59,11 +59,6 @@ var namespacesMetricNamesListForCounts = []string{
"k8s.pod.status_reason",
}
var namespaceAttrKeysForMetadata = []string{
"k8s.namespace.name",
"k8s.cluster.name",
}
// namespaceCountAttrKeys are the workload resource attributes whose distinct
// values are counted per namespace. They are read from the pod metric universe,
// which carries the owner workload names for each pod series.

View File

@@ -42,7 +42,7 @@ func buildNodeRecords(
NodeCPUAllocatable: -1,
NodeMemory: -1,
NodeMemoryAllocatable: -1,
Meta: map[string]string{},
Meta: inframonitoringtypes.NewNodeMeta(nil),
}
if metrics, ok := metricsMap[compositeKey]; ok {
@@ -92,9 +92,7 @@ func buildNodeRecords(
}
if attrs, ok := metadataMap[compositeKey]; ok {
for k, v := range attrs {
record.Meta[k] = v
}
record.Meta = inframonitoringtypes.NewNodeMeta(attrs)
}
records = append(records, record)
@@ -156,7 +154,7 @@ func (m *module) getTopNodeGroups(
func (m *module) getNodesTableMetadata(ctx context.Context, orgID valuer.UUID, req *inframonitoringtypes.PostableNodes) (map[string]map[string]string, error) {
var nonGroupByAttrs []string
for _, key := range nodeAttrKeysForMetadata {
for _, key := range inframonitoringtypes.NodeMetaKeys {
if !isKeyInGroupByAttrs(req.GroupBy, key) {
nonGroupByAttrs = append(nonGroupByAttrs, key)
}

View File

@@ -30,11 +30,6 @@ var nodesTableMetricNamesList = []string{
"k8s.container.status.reason",
}
var nodeAttrKeysForMetadata = []string{
"k8s.node.uid",
"k8s.cluster.name",
}
var orderByToNodesQueryNames = map[string][]string{
inframonitoringtypes.NodesOrderByCPU: {"A"},
inframonitoringtypes.NodesOrderByCPUAllocatable: {"B"},

View File

@@ -49,7 +49,7 @@ func buildPodRecords(
PodMemoryRequest: -1,
PodMemoryLimit: -1,
PodAge: -1,
Meta: map[string]string{},
Meta: inframonitoringtypes.NewPodMeta(nil),
}
if metrics, ok := metricsMap[compositeKey]; ok {
@@ -163,9 +163,7 @@ func buildPodRecords(
}
}
}
for k, v := range attrs {
record.Meta[k] = v
}
record.Meta = inframonitoringtypes.NewPodMeta(attrs)
}
records = append(records, record)
@@ -227,7 +225,7 @@ func (m *module) getTopPodGroups(
func (m *module) getPodsTableMetadata(ctx context.Context, orgID valuer.UUID, req *inframonitoringtypes.PostablePods) (map[string]map[string]string, error) {
var nonGroupByAttrs []string
for _, key := range podAttrKeysForMetadata {
for _, key := range inframonitoringtypes.PodMetaKeys {
if !isKeyInGroupByAttrs(req.GroupBy, key) {
nonGroupByAttrs = append(nonGroupByAttrs, key)
}

View File

@@ -45,20 +45,6 @@ var podsTableMetricNamesList = []string{
// "k8s.container.restarts",
}
var podAttrKeysForMetadata = []string{
"k8s.pod.uid",
"k8s.pod.name",
"k8s.namespace.name",
"k8s.node.name",
"k8s.deployment.name",
"k8s.statefulset.name",
"k8s.daemonset.name",
"k8s.job.name",
"k8s.cronjob.name",
"k8s.cluster.name",
"k8s.pod.start_time",
}
var orderByToPodsQueryNames = map[string][]string{
inframonitoringtypes.PodsOrderByCPU: {"A"},
inframonitoringtypes.PodsOrderByCPURequest: {"B"},

View File

@@ -38,7 +38,7 @@ func buildStatefulSetRecords(
StatefulSetMemoryLimit: -1,
DesiredPods: -1,
CurrentPods: -1,
Meta: map[string]string{},
Meta: inframonitoringtypes.NewStatefulSetMeta(nil),
}
if metrics, ok := metricsMap[compositeKey]; ok {
@@ -83,9 +83,7 @@ func buildStatefulSetRecords(
}
if attrs, ok := metadataMap[compositeKey]; ok {
for k, v := range attrs {
record.Meta[k] = v
}
record.Meta = inframonitoringtypes.NewStatefulSetMeta(attrs)
}
records = append(records, record)
@@ -147,7 +145,7 @@ func (m *module) getTopStatefulSetGroups(
func (m *module) getStatefulSetsTableMetadata(ctx context.Context, orgID valuer.UUID, req *inframonitoringtypes.PostableStatefulSets) (map[string]map[string]string, error) {
var nonGroupByAttrs []string
for _, key := range statefulSetAttrKeysForMetadata {
for _, key := range inframonitoringtypes.StatefulSetMetaKeys {
if !isKeyInGroupByAttrs(req.GroupBy, key) {
nonGroupByAttrs = append(nonGroupByAttrs, key)
}

View File

@@ -37,11 +37,6 @@ var statefulSetsTableMetricNamesList = []string{
// Carried forward from v1 statefulSetAttrsToEnrich
// (pkg/query-service/app/inframetrics/statefulsets.go:29-33).
var statefulSetAttrKeysForMetadata = []string{
"k8s.statefulset.name",
"k8s.namespace.name",
"k8s.cluster.name",
}
// orderByToStatefulSetsQueryNames maps the orderBy column to the query name
// used for ranking statefulset groups. v2 B/C/E/F are direct metrics, no

View File

@@ -33,7 +33,7 @@ func buildVolumeRecords(
VolumeInodes: -1,
VolumeInodesFree: -1,
VolumeInodesUsed: -1,
Meta: map[string]string{},
Meta: inframonitoringtypes.NewVolumeMeta(nil),
}
if metrics, ok := metricsMap[compositeKey]; ok {
@@ -58,9 +58,7 @@ func buildVolumeRecords(
}
if attrs, ok := metadataMap[compositeKey]; ok {
for k, v := range attrs {
record.Meta[k] = v
}
record.Meta = inframonitoringtypes.NewVolumeMeta(attrs)
}
records = append(records, record)
@@ -122,7 +120,7 @@ func (m *module) getTopVolumeGroups(
func (m *module) getVolumesTableMetadata(ctx context.Context, orgID valuer.UUID, req *inframonitoringtypes.PostableVolumes) (map[string]map[string]string, error) {
var nonGroupByAttrs []string
for _, key := range volumeAttrKeysForMetadata {
for _, key := range inframonitoringtypes.VolumeMetaKeys {
if !isKeyInGroupByAttrs(req.GroupBy, key) {
nonGroupByAttrs = append(nonGroupByAttrs, key)
}

View File

@@ -28,15 +28,6 @@ var volumesTableMetricNamesList = []string{
// Carried forward from v1 volumeAttrsToEnrich
// (pkg/query-service/app/inframetrics/pvcs.go:23-31).
var volumeAttrKeysForMetadata = []string{
"k8s.persistentvolumeclaim.name",
"k8s.pod.uid",
"k8s.pod.name",
"k8s.namespace.name",
"k8s.node.name",
"k8s.statefulset.name",
"k8s.cluster.name",
}
// orderByToVolumesQueryNames maps the orderBy column to the query/formula names
// from newVolumesTableListQuery used for ranking volume groups. For "usage",

View File

@@ -6,6 +6,8 @@ import (
"github.com/SigNoz/signoz/pkg/errors"
qbtypes "github.com/SigNoz/signoz/pkg/types/querybuildertypes/querybuildertypesv5"
"github.com/swaggest/jsonschema-go"
)
type Clusters struct {
@@ -36,7 +38,7 @@ type ClusterRecord struct {
Jobs int64 `json:"jobs" required:"true"`
StatefulSets int64 `json:"statefulSets" required:"true"`
} `json:"counts" required:"true"`
Meta map[string]string `json:"meta" required:"true"`
Meta ClusterMeta `json:"meta" required:"true"`
}
// PostableClusters is the request body for the v2 clusters list API.
@@ -114,3 +116,36 @@ func (req *PostableClusters) UnmarshalJSON(data []byte) error {
*req = PostableClusters(decoded)
return req.Validate()
}
// ClusterMeta carries the guaranteed cluster metadata keys as typed fields plus
// any dynamic group-by keys in Extra.
type ClusterMeta struct {
ClusterName string `json:"k8s.cluster.name" required:"true"`
Extra map[string]string `json:"-"`
}
var ClusterMetaKeys = getMetaKeys(&ClusterMeta{})
func NewClusterMeta(attrs map[string]string) ClusterMeta {
var m ClusterMeta
m.Extra = populateMeta(&m, attrs)
return m
}
func (m ClusterMeta) MarshalJSON() ([]byte, error) {
return marshalMeta(&m, m.Extra)
}
func (m *ClusterMeta) UnmarshalJSON(data []byte) error {
raw, err := splitMeta(data)
if err != nil {
return err
}
m.Extra = populateMeta(m, raw)
return nil
}
func (ClusterMeta) PrepareJSONSchema(s *jsonschema.Schema) error {
addStringAdditionalProps(s)
return nil
}

View File

@@ -6,6 +6,8 @@ import (
"github.com/SigNoz/signoz/pkg/errors"
qbtypes "github.com/SigNoz/signoz/pkg/types/querybuildertypes/querybuildertypesv5"
"github.com/swaggest/jsonschema-go"
)
type Containers struct {
@@ -68,7 +70,7 @@ type ContainerRecord struct {
MemoryRequestUtilization float64 `json:"memoryRequestUtilization" required:"true"` // k8s.container.memory_request_utilization
MemoryLimitUtilization float64 `json:"memoryLimitUtilization" required:"true"` // k8s.container.memory_limit_utilization
Meta map[string]string `json:"meta" required:"true"`
Meta ContainerMeta `json:"meta" required:"true"`
}
// PostableContainers is the request body for the v2 containers list API.
@@ -146,3 +148,48 @@ func (req *PostableContainers) UnmarshalJSON(data []byte) error {
*req = PostableContainers(decoded)
return req.Validate()
}
// ContainerMeta carries the guaranteed container metadata keys as typed fields
// plus any dynamic group-by keys in Extra.
type ContainerMeta struct {
PodUID string `json:"k8s.pod.uid" required:"true"`
ContainerName string `json:"k8s.container.name" required:"true"`
PodName string `json:"k8s.pod.name" required:"true"`
ImageName string `json:"container.image.name" required:"true"`
ImageTag string `json:"container.image.tag" required:"true"`
NamespaceName string `json:"k8s.namespace.name" required:"true"`
NodeName string `json:"k8s.node.name" required:"true"`
DeploymentName string `json:"k8s.deployment.name" required:"true"`
StatefulSetName string `json:"k8s.statefulset.name" required:"true"`
DaemonSetName string `json:"k8s.daemonset.name" required:"true"`
JobName string `json:"k8s.job.name" required:"true"`
CronJobName string `json:"k8s.cronjob.name" required:"true"`
ClusterName string `json:"k8s.cluster.name" required:"true"`
Extra map[string]string `json:"-"`
}
var ContainerMetaKeys = getMetaKeys(&ContainerMeta{})
func NewContainerMeta(attrs map[string]string) ContainerMeta {
var m ContainerMeta
m.Extra = populateMeta(&m, attrs)
return m
}
func (m ContainerMeta) MarshalJSON() ([]byte, error) {
return marshalMeta(&m, m.Extra)
}
func (m *ContainerMeta) UnmarshalJSON(data []byte) error {
raw, err := splitMeta(data)
if err != nil {
return err
}
m.Extra = populateMeta(m, raw)
return nil
}
func (ContainerMeta) PrepareJSONSchema(s *jsonschema.Schema) error {
addStringAdditionalProps(s)
return nil
}

View File

@@ -6,6 +6,8 @@ import (
"github.com/SigNoz/signoz/pkg/errors"
qbtypes "github.com/SigNoz/signoz/pkg/types/querybuildertypes/querybuildertypesv5"
"github.com/swaggest/jsonschema-go"
)
type DaemonSets struct {
@@ -30,7 +32,7 @@ type DaemonSetRecord struct {
MisscheduledNodes int `json:"misscheduledNodes" required:"true"`
PodCountsByPhase PodCountsByPhase `json:"podCountsByPhase" required:"true"`
PodCountsByStatus PodCountsByStatus `json:"podCountsByStatus" required:"true"`
Meta map[string]string `json:"meta" required:"true"`
Meta DaemonSetMeta `json:"meta" required:"true"`
}
// PostableDaemonSets is the request body for the v2 daemonsets list API.
@@ -108,3 +110,38 @@ func (req *PostableDaemonSets) UnmarshalJSON(data []byte) error {
*req = PostableDaemonSets(decoded)
return req.Validate()
}
// DaemonSetMeta carries the guaranteed daemonset metadata keys as typed fields
// plus any dynamic group-by keys in Extra.
type DaemonSetMeta struct {
DaemonSetName string `json:"k8s.daemonset.name" required:"true"`
NamespaceName string `json:"k8s.namespace.name" required:"true"`
ClusterName string `json:"k8s.cluster.name" required:"true"`
Extra map[string]string `json:"-"`
}
var DaemonSetMetaKeys = getMetaKeys(&DaemonSetMeta{})
func NewDaemonSetMeta(attrs map[string]string) DaemonSetMeta {
var m DaemonSetMeta
m.Extra = populateMeta(&m, attrs)
return m
}
func (m DaemonSetMeta) MarshalJSON() ([]byte, error) {
return marshalMeta(&m, m.Extra)
}
func (m *DaemonSetMeta) UnmarshalJSON(data []byte) error {
raw, err := splitMeta(data)
if err != nil {
return err
}
m.Extra = populateMeta(m, raw)
return nil
}
func (DaemonSetMeta) PrepareJSONSchema(s *jsonschema.Schema) error {
addStringAdditionalProps(s)
return nil
}

View File

@@ -6,6 +6,8 @@ import (
"github.com/SigNoz/signoz/pkg/errors"
qbtypes "github.com/SigNoz/signoz/pkg/types/querybuildertypes/querybuildertypesv5"
"github.com/swaggest/jsonschema-go"
)
type Deployments struct {
@@ -28,7 +30,7 @@ type DeploymentRecord struct {
AvailablePods int `json:"availablePods" required:"true"`
PodCountsByPhase PodCountsByPhase `json:"podCountsByPhase" required:"true"`
PodCountsByStatus PodCountsByStatus `json:"podCountsByStatus" required:"true"`
Meta map[string]string `json:"meta" required:"true"`
Meta DeploymentMeta `json:"meta" required:"true"`
}
// PostableDeployments is the request body for the v2 deployments list API.
@@ -106,3 +108,38 @@ func (req *PostableDeployments) UnmarshalJSON(data []byte) error {
*req = PostableDeployments(decoded)
return req.Validate()
}
// DeploymentMeta carries the guaranteed deployment metadata keys as typed fields
// plus any dynamic group-by keys in Extra.
type DeploymentMeta struct {
DeploymentName string `json:"k8s.deployment.name" required:"true"`
NamespaceName string `json:"k8s.namespace.name" required:"true"`
ClusterName string `json:"k8s.cluster.name" required:"true"`
Extra map[string]string `json:"-"`
}
var DeploymentMetaKeys = getMetaKeys(&DeploymentMeta{})
func NewDeploymentMeta(attrs map[string]string) DeploymentMeta {
var m DeploymentMeta
m.Extra = populateMeta(&m, attrs)
return m
}
func (m DeploymentMeta) MarshalJSON() ([]byte, error) {
return marshalMeta(&m, m.Extra)
}
func (m *DeploymentMeta) UnmarshalJSON(data []byte) error {
raw, err := splitMeta(data)
if err != nil {
return err
}
m.Extra = populateMeta(m, raw)
return nil
}
func (DeploymentMeta) PrepareJSONSchema(s *jsonschema.Schema) error {
addStringAdditionalProps(s)
return nil
}

View File

@@ -6,6 +6,8 @@ import (
"github.com/SigNoz/signoz/pkg/errors"
qbtypes "github.com/SigNoz/signoz/pkg/types/querybuildertypes/querybuildertypesv5"
"github.com/swaggest/jsonschema-go"
)
type Hosts struct {
@@ -17,16 +19,16 @@ type Hosts struct {
}
type HostRecord struct {
HostName string `json:"hostName" required:"true"`
Status HostStatus `json:"status" required:"true"`
ActiveHostCount int `json:"activeHostCount" required:"true"`
InactiveHostCount int `json:"inactiveHostCount" required:"true"`
CPU float64 `json:"cpu" required:"true"`
Memory float64 `json:"memory" required:"true"`
Wait float64 `json:"wait" required:"true"`
Load15 float64 `json:"load15" required:"true"`
DiskUsage float64 `json:"diskUsage" required:"true"`
Meta map[string]string `json:"meta" required:"true"`
HostName string `json:"hostName" required:"true"`
Status HostStatus `json:"status" required:"true"`
ActiveHostCount int `json:"activeHostCount" required:"true"`
InactiveHostCount int `json:"inactiveHostCount" required:"true"`
CPU float64 `json:"cpu" required:"true"`
Memory float64 `json:"memory" required:"true"`
Wait float64 `json:"wait" required:"true"`
Load15 float64 `json:"load15" required:"true"`
DiskUsage float64 `json:"diskUsage" required:"true"`
Meta HostMeta `json:"meta" required:"true"`
}
type PostableHosts struct {
@@ -113,3 +115,37 @@ func (req *PostableHosts) UnmarshalJSON(data []byte) error {
*req = PostableHosts(decoded)
return req.Validate()
}
// HostMeta carries the guaranteed host metadata keys as typed fields plus any
// dynamic group-by keys in Extra.
type HostMeta struct {
OSType string `json:"os.type" required:"true"`
HostName string `json:"host.name" required:"true"`
Extra map[string]string `json:"-"`
}
var HostMetaKeys = getMetaKeys(&HostMeta{})
func NewHostMeta(attrs map[string]string) HostMeta {
var m HostMeta
m.Extra = populateMeta(&m, attrs)
return m
}
func (m HostMeta) MarshalJSON() ([]byte, error) {
return marshalMeta(&m, m.Extra)
}
func (m *HostMeta) UnmarshalJSON(data []byte) error {
raw, err := splitMeta(data)
if err != nil {
return err
}
m.Extra = populateMeta(m, raw)
return nil
}
func (HostMeta) PrepareJSONSchema(s *jsonschema.Schema) error {
addStringAdditionalProps(s)
return nil
}

View File

@@ -6,6 +6,8 @@ import (
"github.com/SigNoz/signoz/pkg/errors"
qbtypes "github.com/SigNoz/signoz/pkg/types/querybuildertypes/querybuildertypesv5"
"github.com/swaggest/jsonschema-go"
)
type Jobs struct {
@@ -30,7 +32,7 @@ type JobRecord struct {
SuccessfulPods int `json:"successfulPods" required:"true"`
PodCountsByPhase PodCountsByPhase `json:"podCountsByPhase" required:"true"`
PodCountsByStatus PodCountsByStatus `json:"podCountsByStatus" required:"true"`
Meta map[string]string `json:"meta" required:"true"`
Meta JobMeta `json:"meta" required:"true"`
}
// PostableJobs is the request body for the v2 jobs list API.
@@ -108,3 +110,38 @@ func (req *PostableJobs) UnmarshalJSON(data []byte) error {
*req = PostableJobs(decoded)
return req.Validate()
}
// JobMeta carries the guaranteed job metadata keys as typed fields plus any
// dynamic group-by keys in Extra.
type JobMeta struct {
JobName string `json:"k8s.job.name" required:"true"`
NamespaceName string `json:"k8s.namespace.name" required:"true"`
ClusterName string `json:"k8s.cluster.name" required:"true"`
Extra map[string]string `json:"-"`
}
var JobMetaKeys = getMetaKeys(&JobMeta{})
func NewJobMeta(attrs map[string]string) JobMeta {
var m JobMeta
m.Extra = populateMeta(&m, attrs)
return m
}
func (m JobMeta) MarshalJSON() ([]byte, error) {
return marshalMeta(&m, m.Extra)
}
func (m *JobMeta) UnmarshalJSON(data []byte) error {
raw, err := splitMeta(data)
if err != nil {
return err
}
m.Extra = populateMeta(m, raw)
return nil
}
func (JobMeta) PrepareJSONSchema(s *jsonschema.Schema) error {
addStringAdditionalProps(s)
return nil
}

View File

@@ -0,0 +1,112 @@
package inframonitoringtypes
import (
"encoding/json"
"maps"
"reflect"
"strings"
"github.com/swaggest/jsonschema-go"
)
// The meta field on every infra-monitoring v2 record carries a fixed set of
// guaranteed keys (surfaced as strongly-typed struct fields) plus any dynamic
// keys the caller introduces via group-by (kept in Extra). Each entity defines
// its own XMeta type; the helpers below give them a shared, wire-stable
// marshaling and schema contract:
//
// - MarshalJSON -> flattenMeta: known + Extra collapse into one flat object.
// - UnmarshalJSON -> splitMeta: decode the flat object, route known keys to
// fields (via the entity's NewXMeta), the rest to Extra.
// - PrepareJSONSchema -> addStringAdditionalProps: keep the reflected known
// properties and mark the object as an open map of string values.
//
// flattenMeta merges the guaranteed known keys and the open Extra map into a
// single flat JSON object, preserving the historical wire shape. known wins on
// collision. The output map is always non-nil, so an empty meta serializes as
// {} rather than null.
func flattenMeta(extra map[string]string, known map[string]string) ([]byte, error) {
out := make(map[string]string, len(extra)+len(known))
maps.Copy(out, extra)
maps.Copy(out, known)
return json.Marshal(out)
}
// splitMeta decodes a flat meta object into its raw string map. Callers pull
// their known keys out of the returned map; whatever remains becomes Extra.
func splitMeta(data []byte) (map[string]string, error) {
raw := map[string]string{}
if err := json.Unmarshal(data, &raw); err != nil {
return nil, err
}
return raw, nil
}
// metaField is one guaranteed meta key discovered from an XMeta struct's json
// tags (json:"-" fields like Extra are skipped).
type metaField struct {
index int
key string
}
// metaFieldsOf reflects the string fields of an XMeta struct (skipping json:"-"
// fields like Extra).
func metaFieldsOf(t reflect.Type) []metaField {
fields := make([]metaField, 0, t.NumField())
for i := range t.NumField() {
f := t.Field(i)
key, _, _ := strings.Cut(f.Tag.Get("json"), ",")
if key == "" || key == "-" {
continue
}
fields = append(fields, metaField{index: i, key: key})
}
return fields
}
// populateMeta routes src into the guaranteed fields of the XMeta pointed to by
// m (empty string when a key is absent) and returns the leftover keys (dynamic
// group-by keys) as Extra.
func populateMeta(m any, src map[string]string) map[string]string {
extra := map[string]string{}
maps.Copy(extra, src)
rv := reflect.ValueOf(m).Elem()
for _, f := range metaFieldsOf(rv.Type()) {
rv.Field(f.index).SetString(src[f.key])
delete(extra, f.key)
}
return extra
}
// marshalMeta flattens the guaranteed fields of the XMeta pointed to by m plus
// its Extra map into a single flat JSON object.
func marshalMeta(m any, extra map[string]string) ([]byte, error) {
rv := reflect.ValueOf(m).Elem()
known := make(map[string]string)
for _, f := range metaFieldsOf(rv.Type()) {
known[f.key] = rv.Field(f.index).String()
}
return flattenMeta(extra, known)
}
// getMetaKeys returns the guaranteed keys of an XMeta, in struct-field order. Used
// by implinframonitoring as the metadata fetch column list, keeping the key set
// defined once (on the struct).
func getMetaKeys(m any) []string {
rv := reflect.ValueOf(m).Elem()
fields := metaFieldsOf(rv.Type())
keys := make([]string, 0, len(fields))
for _, f := range fields {
keys = append(keys, f.key)
}
return keys
}
// addStringAdditionalProps marks an already-reflected meta object schema as an
// open map of string values. The known properties and their required list come
// from struct-tag reflection (this runs after, via the Preparer hook); this
// only attaches additionalProperties:{type:string} so callers may add arbitrary
// group-by keys.
func addStringAdditionalProps(s *jsonschema.Schema) {
s.WithAdditionalProperties(jsonschema.String.ToSchemaOrBool())
}

View File

@@ -0,0 +1,150 @@
package inframonitoringtypes
import (
"encoding/json"
"reflect"
"testing"
"github.com/stretchr/testify/require"
"github.com/swaggest/jsonschema-go"
)
// fullPodAttrs is a metadata map with every guaranteed pod key plus a dynamic
// group-by key, used across the round-trip cases.
func fullPodAttrs() map[string]string {
return map[string]string{
"k8s.pod.uid": "uid-1",
"k8s.pod.name": "pod-1",
"k8s.namespace.name": "ns-1",
"k8s.node.name": "node-1",
"k8s.deployment.name": "dep-1",
"k8s.statefulset.name": "",
"k8s.daemonset.name": "",
"k8s.job.name": "",
"k8s.cronjob.name": "",
"k8s.cluster.name": "cluster-1",
"k8s.pod.start_time": "2024-01-01T00:00:00Z",
"custom.groupby": "gv",
}
}
func TestPodMeta_RoundTripAndRouting(t *testing.T) {
attrs := fullPodAttrs()
m := NewPodMeta(attrs)
// known keys route to typed fields
require.Equal(t, "uid-1", m.PodUID)
require.Equal(t, "cluster-1", m.ClusterName)
require.Equal(t, "2024-01-01T00:00:00Z", m.PodStartTime)
// dynamic key routes to Extra, guaranteed keys do not
require.Equal(t, map[string]string{"custom.groupby": "gv"}, m.Extra)
// marshals to a single flat object equal to the input map
b, err := json.Marshal(m)
require.NoError(t, err)
var flat map[string]string
require.NoError(t, json.Unmarshal(b, &flat))
require.Equal(t, attrs, flat)
require.NotContains(t, string(b), "Extra")
// round-trip back into the struct is stable
var back PodMeta
require.NoError(t, json.Unmarshal(b, &back))
require.Equal(t, m, back)
}
func TestMeta_EmptyMarshalsToObjectNotNull(t *testing.T) {
b, err := json.Marshal(NewClusterMeta(nil))
require.NoError(t, err)
require.JSONEq(t, `{"k8s.cluster.name":""}`, string(b))
// a nil-Extra zero value still marshals its guaranteed keys, never null
b, err = json.Marshal(ClusterMeta{})
require.NoError(t, err)
require.JSONEq(t, `{"k8s.cluster.name":""}`, string(b))
}
func TestMeta_AbsentGuaranteedKeyEmitsEmptyString(t *testing.T) {
// os.type absent from attrs -> still present as "" (accepted behavior)
m := NewHostMeta(map[string]string{"host.name": "h1"})
require.Equal(t, "", m.OSType)
b, err := json.Marshal(m)
require.NoError(t, err)
require.JSONEq(t, `{"host.name":"h1","os.type":""}`, string(b))
}
func TestMeta_DynamicKeyDoesNotDuplicateKnownKey(t *testing.T) {
// a dynamic key colliding with a known key must not double-emit; the typed
// field wins and there is exactly one occurrence on the wire.
m := NewClusterMeta(map[string]string{"k8s.cluster.name": "c1"})
require.Empty(t, m.Extra)
require.Equal(t, "c1", m.ClusterName)
b, err := json.Marshal(m)
require.NoError(t, err)
require.JSONEq(t, `{"k8s.cluster.name":"c1"}`, string(b))
}
func TestMetaKeys_ExpectedSetAndOrder(t *testing.T) {
require.Equal(t, []string{"os.type", "host.name"}, HostMetaKeys)
require.Equal(t, []string{"k8s.node.uid", "k8s.cluster.name", "k8s.node.name"}, NodeMetaKeys)
require.Equal(t, []string{
"k8s.pod.uid", "k8s.pod.name", "k8s.namespace.name", "k8s.node.name",
"k8s.deployment.name", "k8s.statefulset.name", "k8s.daemonset.name",
"k8s.job.name", "k8s.cronjob.name", "k8s.cluster.name", "k8s.pod.start_time",
}, PodMetaKeys)
}
// TestMetaKeys_MatchStructTags guards against a field rename/reorder silently
// changing the fetch column list: every key must correspond to a json tag on
// the struct, and the two must be in the same order.
func TestMetaKeys_MatchStructTags(t *testing.T) {
cases := []struct {
keys []string
typ reflect.Type
}{
{HostMetaKeys, reflect.TypeOf(HostMeta{})},
{PodMetaKeys, reflect.TypeOf(PodMeta{})},
{ContainerMetaKeys, reflect.TypeOf(ContainerMeta{})},
{NodeMetaKeys, reflect.TypeOf(NodeMeta{})},
{NamespaceMetaKeys, reflect.TypeOf(NamespaceMeta{})},
{ClusterMetaKeys, reflect.TypeOf(ClusterMeta{})},
{DeploymentMetaKeys, reflect.TypeOf(DeploymentMeta{})},
{DaemonSetMetaKeys, reflect.TypeOf(DaemonSetMeta{})},
{StatefulSetMetaKeys, reflect.TypeOf(StatefulSetMeta{})},
{JobMetaKeys, reflect.TypeOf(JobMeta{})},
{VolumeMetaKeys, reflect.TypeOf(VolumeMeta{})},
}
for _, c := range cases {
t.Run(c.typ.Name(), func(t *testing.T) {
var tagKeys []string
for i := range c.typ.NumField() {
tag := c.typ.Field(i).Tag.Get("json")
if tag == "" || tag == "-" {
continue
}
tagKeys = append(tagKeys, tag)
}
require.Equal(t, tagKeys, c.keys)
})
}
}
// TestMeta_SchemaShape locks the OpenAPI contract the frontend depends on: known
// keys as properties + all required + additionalProperties:{type:string}.
func TestMeta_SchemaShape(t *testing.T) {
r := jsonschema.Reflector{}
s, err := r.Reflect(PodMeta{})
require.NoError(t, err)
require.Equal(t, PodMetaKeys, s.Required)
require.Len(t, s.Properties, len(PodMetaKeys))
for _, k := range PodMetaKeys {
prop, ok := s.Properties[k]
require.True(t, ok, "missing property %s", k)
require.NotNil(t, prop.TypeObject)
require.Equal(t, jsonschema.String.Type(), *prop.TypeObject.Type)
}
require.NotNil(t, s.AdditionalProperties)
require.NotNil(t, s.AdditionalProperties.TypeObject)
require.Equal(t, jsonschema.String.Type(), *s.AdditionalProperties.TypeObject.Type)
}

View File

@@ -6,6 +6,8 @@ import (
"github.com/SigNoz/signoz/pkg/errors"
qbtypes "github.com/SigNoz/signoz/pkg/types/querybuildertypes/querybuildertypesv5"
"github.com/swaggest/jsonschema-go"
)
type Namespaces struct {
@@ -28,7 +30,7 @@ type NamespaceRecord struct {
Jobs int64 `json:"jobs" required:"true"`
StatefulSets int64 `json:"statefulSets" required:"true"`
} `json:"counts" required:"true"`
Meta map[string]string `json:"meta" required:"true"`
Meta NamespaceMeta `json:"meta" required:"true"`
}
// PostableNamespaces is the request body for the v2 namespaces list API.
@@ -106,3 +108,37 @@ func (req *PostableNamespaces) UnmarshalJSON(data []byte) error {
*req = PostableNamespaces(decoded)
return req.Validate()
}
// NamespaceMeta carries the guaranteed namespace metadata keys as typed fields
// plus any dynamic group-by keys in Extra.
type NamespaceMeta struct {
NamespaceName string `json:"k8s.namespace.name" required:"true"`
ClusterName string `json:"k8s.cluster.name" required:"true"`
Extra map[string]string `json:"-"`
}
var NamespaceMetaKeys = getMetaKeys(&NamespaceMeta{})
func NewNamespaceMeta(attrs map[string]string) NamespaceMeta {
var m NamespaceMeta
m.Extra = populateMeta(&m, attrs)
return m
}
func (m NamespaceMeta) MarshalJSON() ([]byte, error) {
return marshalMeta(&m, m.Extra)
}
func (m *NamespaceMeta) UnmarshalJSON(data []byte) error {
raw, err := splitMeta(data)
if err != nil {
return err
}
m.Extra = populateMeta(m, raw)
return nil
}
func (NamespaceMeta) PrepareJSONSchema(s *jsonschema.Schema) error {
addStringAdditionalProps(s)
return nil
}

View File

@@ -6,6 +6,8 @@ import (
"github.com/SigNoz/signoz/pkg/errors"
qbtypes "github.com/SigNoz/signoz/pkg/types/querybuildertypes/querybuildertypesv5"
"github.com/swaggest/jsonschema-go"
)
type Nodes struct {
@@ -33,7 +35,7 @@ type NodeRecord struct {
NodeCPUAllocatable float64 `json:"nodeCPUAllocatable" required:"true"`
NodeMemory float64 `json:"nodeMemory" required:"true"`
NodeMemoryAllocatable float64 `json:"nodeMemoryAllocatable" required:"true"`
Meta map[string]string `json:"meta" required:"true"`
Meta NodeMeta `json:"meta" required:"true"`
}
// PostableNodes is the request body for the v2 nodes list API.
@@ -111,3 +113,38 @@ func (req *PostableNodes) UnmarshalJSON(data []byte) error {
*req = PostableNodes(decoded)
return req.Validate()
}
// NodeMeta carries the guaranteed node metadata keys as typed fields plus any
// dynamic group-by keys in Extra.
type NodeMeta struct {
NodeUID string `json:"k8s.node.uid" required:"true"`
ClusterName string `json:"k8s.cluster.name" required:"true"`
NodeName string `json:"k8s.node.name" required:"true"`
Extra map[string]string `json:"-"`
}
var NodeMetaKeys = getMetaKeys(&NodeMeta{})
func NewNodeMeta(attrs map[string]string) NodeMeta {
var m NodeMeta
m.Extra = populateMeta(&m, attrs)
return m
}
func (m NodeMeta) MarshalJSON() ([]byte, error) {
return marshalMeta(&m, m.Extra)
}
func (m *NodeMeta) UnmarshalJSON(data []byte) error {
raw, err := splitMeta(data)
if err != nil {
return err
}
m.Extra = populateMeta(m, raw)
return nil
}
func (NodeMeta) PrepareJSONSchema(s *jsonschema.Schema) error {
addStringAdditionalProps(s)
return nil
}

View File

@@ -6,6 +6,8 @@ import (
"github.com/SigNoz/signoz/pkg/errors"
qbtypes "github.com/SigNoz/signoz/pkg/types/querybuildertypes/querybuildertypesv5"
"github.com/swaggest/jsonschema-go"
)
type Pods struct {
@@ -68,7 +70,7 @@ type PodRecord struct {
PodCountsByStatus PodCountsByStatus `json:"podCountsByStatus" required:"true"`
PodRestarts int64 `json:"podRestarts" required:"true"`
PodAge int64 `json:"podAge" required:"true"`
Meta map[string]string `json:"meta" required:"true"`
Meta PodMeta `json:"meta" required:"true"`
}
// PostablePods is the request body for the v2 pods list API.
@@ -146,3 +148,46 @@ func (req *PostablePods) UnmarshalJSON(data []byte) error {
*req = PostablePods(decoded)
return req.Validate()
}
// PodMeta carries the guaranteed pod metadata keys as typed fields plus any
// dynamic group-by keys in Extra.
type PodMeta struct {
PodUID string `json:"k8s.pod.uid" required:"true"`
PodName string `json:"k8s.pod.name" required:"true"`
NamespaceName string `json:"k8s.namespace.name" required:"true"`
NodeName string `json:"k8s.node.name" required:"true"`
DeploymentName string `json:"k8s.deployment.name" required:"true"`
StatefulSetName string `json:"k8s.statefulset.name" required:"true"`
DaemonSetName string `json:"k8s.daemonset.name" required:"true"`
JobName string `json:"k8s.job.name" required:"true"`
CronJobName string `json:"k8s.cronjob.name" required:"true"`
ClusterName string `json:"k8s.cluster.name" required:"true"`
PodStartTime string `json:"k8s.pod.start_time" required:"true"`
Extra map[string]string `json:"-"`
}
var PodMetaKeys = getMetaKeys(&PodMeta{})
func NewPodMeta(attrs map[string]string) PodMeta {
var m PodMeta
m.Extra = populateMeta(&m, attrs)
return m
}
func (m PodMeta) MarshalJSON() ([]byte, error) {
return marshalMeta(&m, m.Extra)
}
func (m *PodMeta) UnmarshalJSON(data []byte) error {
raw, err := splitMeta(data)
if err != nil {
return err
}
m.Extra = populateMeta(m, raw)
return nil
}
func (PodMeta) PrepareJSONSchema(s *jsonschema.Schema) error {
addStringAdditionalProps(s)
return nil
}

View File

@@ -6,6 +6,8 @@ import (
"github.com/SigNoz/signoz/pkg/errors"
qbtypes "github.com/SigNoz/signoz/pkg/types/querybuildertypes/querybuildertypesv5"
"github.com/swaggest/jsonschema-go"
)
type StatefulSets struct {
@@ -28,7 +30,7 @@ type StatefulSetRecord struct {
CurrentPods int `json:"currentPods" required:"true"`
PodCountsByPhase PodCountsByPhase `json:"podCountsByPhase" required:"true"`
PodCountsByStatus PodCountsByStatus `json:"podCountsByStatus" required:"true"`
Meta map[string]string `json:"meta" required:"true"`
Meta StatefulSetMeta `json:"meta" required:"true"`
}
// PostableStatefulSets is the request body for the v2 statefulsets list API.
@@ -106,3 +108,38 @@ func (req *PostableStatefulSets) UnmarshalJSON(data []byte) error {
*req = PostableStatefulSets(decoded)
return req.Validate()
}
// StatefulSetMeta carries the guaranteed statefulset metadata keys as typed
// fields plus any dynamic group-by keys in Extra.
type StatefulSetMeta struct {
StatefulSetName string `json:"k8s.statefulset.name" required:"true"`
NamespaceName string `json:"k8s.namespace.name" required:"true"`
ClusterName string `json:"k8s.cluster.name" required:"true"`
Extra map[string]string `json:"-"`
}
var StatefulSetMetaKeys = getMetaKeys(&StatefulSetMeta{})
func NewStatefulSetMeta(attrs map[string]string) StatefulSetMeta {
var m StatefulSetMeta
m.Extra = populateMeta(&m, attrs)
return m
}
func (m StatefulSetMeta) MarshalJSON() ([]byte, error) {
return marshalMeta(&m, m.Extra)
}
func (m *StatefulSetMeta) UnmarshalJSON(data []byte) error {
raw, err := splitMeta(data)
if err != nil {
return err
}
m.Extra = populateMeta(m, raw)
return nil
}
func (StatefulSetMeta) PrepareJSONSchema(s *jsonschema.Schema) error {
addStringAdditionalProps(s)
return nil
}

View File

@@ -6,6 +6,8 @@ import (
"github.com/SigNoz/signoz/pkg/errors"
qbtypes "github.com/SigNoz/signoz/pkg/types/querybuildertypes/querybuildertypesv5"
"github.com/swaggest/jsonschema-go"
)
type Volumes struct {
@@ -17,14 +19,14 @@ type Volumes struct {
}
type VolumeRecord struct {
PersistentVolumeClaimName string `json:"persistentVolumeClaimName" required:"true"`
VolumeAvailable float64 `json:"volumeAvailable" required:"true"`
VolumeCapacity float64 `json:"volumeCapacity" required:"true"`
VolumeUsage float64 `json:"volumeUsage" required:"true"`
VolumeInodes float64 `json:"volumeInodes" required:"true"`
VolumeInodesFree float64 `json:"volumeInodesFree" required:"true"`
VolumeInodesUsed float64 `json:"volumeInodesUsed" required:"true"`
Meta map[string]string `json:"meta" required:"true"`
PersistentVolumeClaimName string `json:"persistentVolumeClaimName" required:"true"`
VolumeAvailable float64 `json:"volumeAvailable" required:"true"`
VolumeCapacity float64 `json:"volumeCapacity" required:"true"`
VolumeUsage float64 `json:"volumeUsage" required:"true"`
VolumeInodes float64 `json:"volumeInodes" required:"true"`
VolumeInodesFree float64 `json:"volumeInodesFree" required:"true"`
VolumeInodesUsed float64 `json:"volumeInodesUsed" required:"true"`
Meta VolumeMeta `json:"meta" required:"true"`
}
// PostableVolumes is the request body for the v2 volumes (PVCs) list API.
@@ -102,3 +104,42 @@ func (req *PostableVolumes) UnmarshalJSON(data []byte) error {
*req = PostableVolumes(decoded)
return req.Validate()
}
// VolumeMeta carries the guaranteed volume (PVC) metadata keys as typed fields
// plus any dynamic group-by keys in Extra.
type VolumeMeta struct {
PVCName string `json:"k8s.persistentvolumeclaim.name" required:"true"`
PodUID string `json:"k8s.pod.uid" required:"true"`
PodName string `json:"k8s.pod.name" required:"true"`
NamespaceName string `json:"k8s.namespace.name" required:"true"`
NodeName string `json:"k8s.node.name" required:"true"`
StatefulSetName string `json:"k8s.statefulset.name" required:"true"`
ClusterName string `json:"k8s.cluster.name" required:"true"`
Extra map[string]string `json:"-"`
}
var VolumeMetaKeys = getMetaKeys(&VolumeMeta{})
func NewVolumeMeta(attrs map[string]string) VolumeMeta {
var m VolumeMeta
m.Extra = populateMeta(&m, attrs)
return m
}
func (m VolumeMeta) MarshalJSON() ([]byte, error) {
return marshalMeta(&m, m.Extra)
}
func (m *VolumeMeta) UnmarshalJSON(data []byte) error {
raw, err := splitMeta(data)
if err != nil {
return err
}
m.Extra = populateMeta(m, raw)
return nil
}
func (VolumeMeta) PrepareJSONSchema(s *jsonschema.Schema) error {
addStringAdditionalProps(s)
return nil
}