intellij-kubernetes icon indicating copy to clipboard operation
intellij-kubernetes copied to clipboard

Schema validation does not work with multi-resource documents

Open adietish opened this issue 2 years ago • 7 comments

Steps:

  1. EXEC: open the following yaml in an editor
---
apiVersion: v1
kind: Service
metadata:
  annotations:
    app.quarkus.io/build-timestamp: 2023-06-30 - 12:24:49 +0000
  labels:
    app.kubernetes.io/name: openshift-quickstart
    app.kubernetes.io/version: 1.0.0-SNAPSHOT
    app.kubernetes.io/managed-by: quarkus
  name: openshift-quickstart
spec:
  ports:
    - name: http
      port: 80
      protocol: TCP
      targetPort: 8080
    - name: https
      port: 443
      protocol: TCP
      targetPort: 8443
  selector:
    app.kubernetes.io/name: openshift-quickstart
    app.kubernetes.io/version: 1.0.0-SNAPSHOT
  type: ClusterIP
---
apiVersion: apps/v1
kind: Deployment
metadata:
  annotations:
    app.quarkus.io/build-timestamp: 2023-06-30 - 12:24:49 +0000
  labels:
    app.kubernetes.io/managed-by: quarkus
    app.kubernetes.io/version: 1.0.0-SNAPSHOT
    app.kubernetes.io/name: openshift-quickstart
  name: openshift-quickstart
spec:
  replicas: 1
  selector:
    matchLabels:
      app.kubernetes.io/version: 1.0.0-SNAPSHOT
      app.kubernetes.io/name: openshift-quickstart
  template:
    metadata:
      annotations:
        app.quarkus.io/build-timestamp: 2023-06-30 - 12:24:49 +0000
      labels:
        app.kubernetes.io/managed-by: quarkus
        app.kubernetes.io/version: 1.0.0-SNAPSHOT
        app.kubernetes.io/name: openshift-quickstart
    spec:
      containers:
        - env:
            - name: KUBERNETES_NAMESPACE
              valueFrom:
                fieldRef:
                  fieldPath: metadata.namespace
          image: adietish/openshift-quickstart:1.0.0-SNAPSHOT
          imagePullPolicy: Always
          name: openshift-quickstart
          ports:
            - containerPort: 8080
              name: http
              protocol: TCP
            - containerPort: 8443
              name: https
              protocol: TCP
  1. EXEC: put your cursor to the 2nd resource, a Deployment
  2. EXEC: inspect the schema that is applied. It is shown in the right corner of the status bar:

Result: The schema that is applied still is Service (first resource in the document) image

adietish avatar Jul 12 '23 12:07 adietish

It very much looks like the current platform schema validation framework only supports using a single schema file per editor. It seems unable to use multiple schema files per json/yaml file that is edited (multi-resource files contains multiple individual resources separated by --- and each resource should be validated against it's own schema). If this is confirmed we'd have to get away from using or extending the platform implementation.

adietish avatar Dec 19 '23 08:12 adietish

in vscode this was requested and they found a workaround indicating the schemas: https://github.com/redhat-developer/vscode-yaml/issues/702#issuecomment-1048518781

adietish avatar Dec 20 '23 15:12 adietish

I tried to provide KubernetesSchemaProviders which would return true if one of the resources in the file match the typeinfo in the schema provider:

	override fun isAvailable(file: VirtualFile): Boolean {
		return ApplicationManager.getApplication().runReadAction(
			Computable {
/*
				val psiFile = PsiManager.getInstance(project!!).findFile(file)
				if (psiFile == null) {
					false
				} else {
					val fileInfo = KubernetesTypeInfo.extractMeta(psiFile)
					info == fileInfo
				}
*/
				val fileContent = String(file.contentsToByteArray(true))
				val resources = EditorResourceSerialization.deserialize(fileContent, file.fileType, null)
				resources.any { resource ->
					info.kind == resource.kind
							&& info.apiGroup == resource.apiVersion
				}
		})
	}

But this results in no schema being considered at all.

adietish avatar Dec 20 '23 15:12 adietish

I dug into the json plugin/platform and found out that the validation is done on behalf of JsonSchemaComplianceChecker. Interestingly JsonSchemaComplianceChecker#annotate() is called 3 times for the 3 resources. The root schema is the deployment schema though. Maybe if we can provide a composite schema which holds the 3 schema would help work around it.

JsonSchemaComplianceChecker is created by JsonSchemaComplianceInspection which is declared as local inspection in the json plugin:

    <localInspection language="JSON" shortName="JsonSchemaCompliance"
                     bundle="messages.JsonBundle" key="json.schema.inspection.compliance.name" groupKey="json.inspection.group"
                     enabledByDefault="true" level="WARNING"
                     implementationClass="com.jetbrains.jsonSchema.impl.inspections.JsonSchemaComplianceInspection"/>

adietish avatar Dec 20 '23 15:12 adietish

I talked to Yann Cébron on Jetbrains Slack #intellij-platform and he told me that he'd investigate the possibilities to use several schemas to validate a single json/yaml file.

adietish avatar Dec 21 '23 09:12 adietish

I didn't hear back from Yann. I'll have to ask him again since erroneous validation errors in multi-resource documents hurt the user experience a lot. Schema validation is basically useless. I have to investigate how the jetbrains plugin handles the situation. There's nothin I can reuse though since it is not opensource.

adietish avatar Feb 10 '25 22:02 adietish