Azure / AKS-Edge

Welcome to the Azure Kubernetes Service (AKS) Edge repo.
MIT License
53 stars 34 forks source link

[BUG] The provided configuration file JSON Schema is invalid #143

Closed markrexwinkel closed 2 months ago

markrexwinkel commented 10 months ago

Describe the bug A JSON Schema is provided in the AksEdge installation folder that should be able to validate the JSON configuration passed into Powershell CmdLets like New-AksEdgeDeployment.

The schema is at: %ProgramFiles%\AksEdge\aksedge-dcschema.json

The Schema is not a valid JSON Schema. Some properties have invalid types (guid, int).

{
    "$id": "https://microsoft.com/aksedge-dcschema.json",
    "$schema": "https://json-schema.org/draft/2020-12/schema",
    "title": "AKS Edge Essentials Deployment Configuration",
    "type": "object",
    "properties": {
        "SchemaVersion": {
            "type": "string",
            "default": "1.8",
            "description": "Version of the schema/format of the json"
        },
        "Version": {
            "type": "string",
            "default": "1.0",
            "description": "Version of the json instance"
        },
        "DeploymentType": {
            "enum": [
                "SingleMachineCluster",
                "ScalableCluster",
                "CapiCluster"
            ],
            "$comment": "Type of the deployment found on this machine",
            "default": "SingleMachineCluster"
        },
        "Init": {
            "type": "object",
            "properties": {
                "ServiceIPRangeStart": {
                    "type": "string",
                    "format": "ipv4"
                },
                "ServiceIPRangeSize": {
                    "type": "integer",
                    "minimum" : 1,
                    "maximum" : 127
                }
            },
            "$comment": "Cluster initialization properties to provide when deploying a new cluster"
        },
        "Join": {
            "type": "object",
            "properties": {
                "ClusterJoinToken": {
                    "type": "string"
                },
                "DiscoveryTokenHash": {
                    "type": "string"
                },
                "CertificateKey": {
                    "type": "string"
                },
                "ClusterId": {
                    "type": "guid"
                }
            },
            "$comment": "The join properties are populated when generating a new scale config. When those values are populated, the end user is not supposed to change their values"
        },
        "Arc": {
            "type": "object",
            "properties": {
                "ClusterName": {
                    "type": "string"
                },
                "Location": {
                    "type": "string"
                },
                "ResourceGroupName": {
                    "type": "string"
                },
                "SubscriptionId": {
                    "type": "guid"
                },
                "TenantId": {
                    "type": "guid"
                },
                "ClientId": {
                    "type": "string"
                },
                "ClientSecret": {
                    "type": "string"
                }
            },
            "$comment": "To provide when deploying a new CAPI cluster or when connecting an existing cluster to ARC"
        },
        "Network": {
            "type": "object",
            "properties": {
                "ControlPlaneEndpointIp": {
                    "type": "string",
                    "format": "ipv4"
                },
                "NetworkPlugin": {
                    "enum": [
                        "calico",
                        "flannel"
                    ],
                    "$comment": "The default value is distribution-specific and will be set in the PS module if not explicitly specified"
                },
                "Ip4GatewayAddress": {
                    "type": "string",
                    "format": "ipv4"
                },
                "Ip4PrefixLength": {
                    "type": "integer",
                    "default": 24,
                    "minimum" : 1,
                    "maximum" : 31
                },
                "Ip4AddressPrefix": {
                    "type": "string",
                    "default": null
                },
                "DnsServers": {
                    "type": "array",
                    "items": {
                        "type": "string",
                        "format": "ipv4"
                    },
                    "minitems": 1
                },
                "InternetDisabled" : {
                    "type" : "boolean",
                    "default": false
                },
                "SkipAddressFreeCheck": {
                    "type": "boolean",
                    "default": false
                },
                "SkipDnsCheck": {
                    "type": "boolean",
                    "default": false
                },
                "Proxy": {
                    "type": "object",
                    "properties": {
                        "Http": {
                            "type": "string"
                        },
                        "Https": {
                            "type": "string"
                        },
                        "No": {
                            "type": "string"
                        }
                    }
                }
            },
            "$comment": "Cluster-wide network properties used for deploying or joining a cluster"
        },
        "User": {
            "type": "object",
            "properties": {
                "AcceptEula": {
                    "type": "boolean"
                },
                "AcceptOptionalTelemetry": {
                    "type": "boolean"
                },
                "VolumeLicense": {
                    "type": "object",
                    "properties": {
                        "EnrollmentID": {
                            "type": "string"
                        },
                        "PartNumber": {
                            "type": "string"
                        }
                    }
                }
            },
            "$comment": "Properties that apply to a single new deployment, or across a range of new CAPI based deployments"
        },
        "Machines": {
            "type": "array",
            "items": {
                "$ref": "#/$defs/MachineConfigType"
            },
            "minitems": 1,
            "$comment": "A single machine config in case of the single machine and scalable cluster and an array of machine configs for the deployment of a CAPI cluster"
        }
    },
    "$defs": {
        "MachineConfigType": {
            "type": "object",
            "properties": {
                "ArcHybridComputeMachineId": {
                    "type": "string"
                },
                "NetworkConnection": {
                    "type": "object",
                    "properties": {
                        "AdapterName": {
                            "type": "string"
                        },
                        "Mtu": {
                            "type": "integer"
                        }
                    }
                },
                "LinuxNode": { "$ref": "#/$defs/NodeConfigType" },
                "WindowsNode": { "$ref": "#/$defs/NodeConfigType" }
            },
            "$comment": "Machine-individual properties that apply to a deployment on one machine in a cluster"
        },
        "NodeConfigType": {
            "type": "object",
            "properties": {
                "ControlPlane": {
                    "type": "boolean",
                    "default": false,
                    "$comment": "For non-CAPI deployments, this is only used when joining an existing cluster and deploying a Linux node. For cluster initialization this will automatically be defaulted to true"
                },
                "CpuCount": {
                    "type": "integer",
                    "default": 4,
                    "minimum" : 2
                },
                "MemoryInMB": {
                    "type": "integer",
                    "default": 4096,
                    "multipleOf" : 2,
                    "minimum" : 2048
                },
                "DataSizeInGB": {
                    "type": "integer",
                    "default": 10,
                    "$comment": "Only used for Linux nodes so far"
                },
                "Ip4Address": {
                    "type": "string",
                    "format": "ipv4"
                },
                "MacAddress": {
                    "type": "string"
                },
                "TimeoutSeconds": {
                    "type": "int",
                    "$comment": "For the Windows node, a default of 900s is chosen whereas for the Linux node a default of 300s is chosen"
                },
                "TpmPassthrough": {
                    "type": "boolean",
                    "default": false,
                    "$comment": "For allowing nodes to access TPM on the node host, only used for Linux nodes so far"
                },
                "SecondaryNetworks": {
                    "type": "array",
                    "items": {
                        "$ref": "#/$defs/SecondaryNetworkConfigType"
                    },
                    "$comment": "For providing secondary network details during deployment. Only used for Linux nodes so far"
                }
            },
            "$comment": "Node properties that apply to a node running as part of a machine deployment."
        },
        "SecondaryNetworkConfigType": {
            "type": "object",
            "properties": {
                "VMSwitchName": {
                    "type": "string"
                },
                "Ip4Address": {
                    "type": "string",
                    "format": "ipv4"
                },
                "Ip4GatewayAddress": {
                    "type": "string",
                    "format": "ipv4"
                },
                "Ip4PrefixLength": {
                    "type": "integer",
                    "default": null,
                    "minimum" : 1,
                    "maximum" : 31
                }
            }
        }
    }
}
JSON Pointer Current value Proposed value Remarks
#/properties/Join/properties/ClusterId/type guid string additionally add a format field: "format": "guid"
#/properties/Arc/properties/SubscriptionId/type guid string additionally add a format field: "format": "guid"
#/properties/Arc/properties/TenantId/type guid string additionally add a format field: "format": "guid"
#/$defs/NodeConfigType/properties/TimeoutSeconds/type int integer

Invalid keywords:

JSON Pointer Valid keyword
#/properties/Network/properties/DnsServers/minitems minItems
#/properties/Machines/minitems minItems

To Reproduce Steps to reproduce the behavior:

  1. Try to parse the schema itself using the NuGet package JsonSchema.Net:
    
    using Json.Schema;

try { var schema = JsonSchema.FromFile(@"C:\Program Files\AksEdge\aksedge-dcschema.json"); Console.WriteLine(schema.GetTitle()); } catch(Exception ex) { Console.WriteLine(ex); }


3. An exception is thrown: `System.Text.Json.JsonException: Could not find appropriate value for guid in type SchemaValueType`

**Expected behavior**
No exception and the output: `AKS Edge Essentials Deployment Configuration`

**Environment (please complete the following information):**
 - AKS Edge Essentials Version 1.2.414.0
kvietmeier commented 9 months ago

Can we use YAML instead? It has the virtue of allowing comments in the code.

SummerSmith commented 8 months ago

We have created a bug to track progress on this (25797446) and I will provide any updates here when there are some.

scooley commented 2 months ago

Fixed in December :).