{
  "description": "NodeClass is the Schema for the NodeClass API",
  "properties": {
    "apiVersion": {
      "description": "APIVersion defines the versioned schema of this representation of an object.\nServers should convert recognized schemas to the latest internal value, and\nmay reject unrecognized values.\nMore info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources",
      "type": "string"
    },
    "kind": {
      "description": "Kind is a string value representing the REST resource this object represents.\nServers may infer this from the endpoint the client submits requests to.\nCannot be updated.\nIn CamelCase.\nMore info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds",
      "type": "string"
    },
    "metadata": {
      "type": "object"
    },
    "spec": {
      "description": "NodeClassSpec is the top level specification for the AWS Karpenter Provider.\nThis will contain configuration necessary to launch instances in AWS.",
      "properties": {
        "ephemeralStorage": {
          "default": {
            "iops": 3000,
            "size": "80Gi",
            "throughput": 125
          },
          "description": "EphemeralStorage specifies the default data volume storage attached to the node",
          "properties": {
            "iops": {
              "default": 3000,
              "description": "The IOPS for ephemeral storage",
              "format": "int64",
              "maximum": 16000,
              "minimum": 3000,
              "type": "integer"
            },
            "size": {
              "default": "80Gi",
              "description": "The size of the ephemeral storage",
              "pattern": "^((?:[1-9][0-9]{0,3}|[1-4][0-9]{4}|[5][0-8][0-9]{3}|59000)Gi|(?:[1-9][0-9]{0,3}|[1-5][0-9]{4}|[6][0-3][0-9]{3}|64000)G|([1-9]||[1-5][0-7]|58)Ti|([1-9]||[1-5][0-9]|6[0-3]|64)T)$",
              "type": "string"
            },
            "throughput": {
              "default": 125,
              "description": "The throughput for ephemeral storage",
              "format": "int64",
              "maximum": 1000,
              "minimum": 125,
              "type": "integer"
            }
          },
          "type": "object",
          "additionalProperties": false
        },
        "networkPolicy": {
          "default": "DefaultAllow",
          "description": "NetworkPolicy tells the network policy agent how it should enforce network policies against pods\nBy default, the Amazon VPC CNI plugin for Kubernetes configures network policies for pods in parallel with the pod provisioning\nIn the DefaultAllow mode, until all of the policies are configured for the new pod, containers in the new pod will start with a default allow policy.\nA default allow policy means that all ingress and egress traffic is allowed to and from the new pods\nIn the DefaultDeny mode, a new pod will be blocked from Egress and Ingress connections till a qualifying Network Policy is applied\nIn this mode, you must have a network policy defined for every pod in your cluster. Host Networking pods are exempted from this requirement.",
          "enum": [
            "DefaultAllow",
            "DefaultDeny"
          ],
          "type": "string"
        },
        "networkPolicyEventLogs": {
          "default": "Disabled",
          "description": "NetworkPolicyEventLogs controls whether Network Policy event logging is enabled on the nodes.\nBy default, this value is set to Disabled. When set to Enabled, the Network Policy Agent on the node will log the outcomes of network policy decisions.",
          "enum": [
            "Enabled",
            "Disabled"
          ],
          "type": "string"
        },
        "role": {
          "description": "Role is the AWS identity that nodes use. This field is immutable.\nThis field is mutually exclusive from instanceProfile.\nMarking this field as immutable avoids concerns around terminating managed instance profiles from running instances.\nThis field may be made mutable in the future, assuming the correct garbage collection and drift handling is implemented\nfor the old instance profiles on an update.",
          "maxLength": 64,
          "type": "string",
          "x-kubernetes-validations": [
            {
              "message": "role cannot be empty",
              "rule": "self != ''"
            },
            {
              "message": "immutable field changed",
              "rule": "self == oldSelf"
            }
          ]
        },
        "securityGroupSelectorTerms": {
          "description": "SecurityGroupSelectorTerms is a list of or security group selector terms. The terms are ORed.",
          "items": {
            "description": "SecurityGroupSelectorTerm defines selection logic for a security group used by Karpenter to launch nodes.\nIf multiple fields are used for selection, the requirements are ANDed.",
            "properties": {
              "id": {
                "description": "ID is the security group id in EC2",
                "pattern": "sg-[0-9a-z]+",
                "type": "string"
              },
              "name": {
                "description": "Name is the security group name in EC2.\nThis value is the name field, which is different from the name tag.",
                "type": "string"
              },
              "tags": {
                "additionalProperties": {
                  "type": "string"
                },
                "description": "Tags is a map of key/value tags used to select subnets\nSpecifying '*' for a value selects all values for a given tag key.",
                "maxProperties": 20,
                "type": "object",
                "x-kubernetes-validations": [
                  {
                    "message": "empty tag keys or values aren't supported",
                    "rule": "self.all(k, k != '' && self[k] != '')"
                  }
                ]
              }
            },
            "type": "object",
            "additionalProperties": false
          },
          "maxItems": 30,
          "type": "array",
          "x-kubernetes-validations": [
            {
              "message": "securityGroupSelectorTerms cannot be empty",
              "rule": "self.size() != 0"
            },
            {
              "message": "expected at least one, got none, ['tags', 'id', 'name']",
              "rule": "self.all(x, has(x.tags) || has(x.id) || has(x.name))"
            },
            {
              "message": "'id' is mutually exclusive, cannot be set with a combination of other fields in securityGroupSelectorTerms",
              "rule": "!self.all(x, has(x.id) && (has(x.tags) || has(x.name)))"
            },
            {
              "message": "'name' is mutually exclusive, cannot be set with a combination of other fields in securityGroupSelectorTerms",
              "rule": "!self.all(x, has(x.name) && (has(x.tags) || has(x.id)))"
            }
          ]
        },
        "snatPolicy": {
          "default": "Random",
          "description": "SNATPolicy specifies how SNAT (Source Network Address Translation) is configured on the node\nIf SNATPolicy is set to Disabled, the SNAT iptables rule and off-VPC IP rule are not applied, and these rules are removed if they have already been applied\nDo not use SNATPolicy Disabled if you need to allow inbound communication to your pods from external VPNs, direct connections, and external VPCs,\nand your pods do not need to access the Internet directly via an Internet Gateway.\nIf SNATPolicy is set to Random, the CNI will use PRNG, meaning that --random-fully will be added to the SNAT iptables rule\nEnabling this functionality means that outbound connections will be assigned a source port that is not necessarily part of the ephemeral port range set at the OS level",
          "enum": [
            "Random",
            "Disabled"
          ],
          "type": "string"
        },
        "subnetSelectorTerms": {
          "description": "SubnetSelectorTerms is a list of or subnet selector terms. The terms are ORed.",
          "items": {
            "description": "SubnetSelectorTerm defines selection logic for a subnet used by Karpenter to launch nodes.\nIf multiple fields are used for selection, the requirements are ANDed.",
            "properties": {
              "id": {
                "description": "ID is the subnet id in EC2",
                "pattern": "subnet-[0-9a-z]+",
                "type": "string"
              },
              "tags": {
                "additionalProperties": {
                  "type": "string"
                },
                "description": "Tags is a map of key/value tags used to select subnets\nSpecifying '*' for a value selects all values for a given tag key.",
                "maxProperties": 20,
                "type": "object",
                "x-kubernetes-validations": [
                  {
                    "message": "empty tag keys or values aren't supported",
                    "rule": "self.all(k, k != '' && self[k] != '')"
                  }
                ]
              }
            },
            "type": "object",
            "additionalProperties": false
          },
          "maxItems": 30,
          "type": "array",
          "x-kubernetes-validations": [
            {
              "message": "subnetSelectorTerms cannot be empty",
              "rule": "self.size() != 0"
            },
            {
              "message": "expected at least one, got none, ['tags', 'id']",
              "rule": "self.all(x, has(x.tags) || has(x.id))"
            },
            {
              "message": "'id' is mutually exclusive, cannot be set with a combination of other fields in subnetSelectorTerms",
              "rule": "!self.all(x, has(x.id) && has(x.tags))"
            }
          ]
        },
        "tags": {
          "additionalProperties": {
            "type": "string"
          },
          "description": "Tags to be applied on ec2 resources like instances and launch templates.",
          "type": "object",
          "x-kubernetes-validations": [
            {
              "message": "empty tag keys aren't supported",
              "rule": "self.all(k, k != '')"
            },
            {
              "message": "tag contains a restricted tag matching kubernetes.io/cluster/",
              "rule": "self.all(k, !k.startsWith('kubernetes.io/cluster') )"
            },
            {
              "message": "tag contains a restricted tag matching karpenter.sh/provisioner-name",
              "rule": "self.all(k, k != 'karpenter.sh/provisioner-name')"
            },
            {
              "message": "tag contains a restricted tag matching karpenter.sh/nodepool",
              "rule": "self.all(k, k != 'karpenter.sh/nodepool')"
            },
            {
              "message": "tag contains a restricted tag matching karpenter.sh/nodeclaim",
              "rule": "self.all(k, k != 'karpenter.sh/nodeclaim')"
            },
            {
              "message": "tag contains a restricted tag matching karpenter.sh/managed-by",
              "rule": "self.all(k, k !='karpenter.sh/managed-by')"
            },
            {
              "message": "tag contains a restricted tag matching eks.amazonaws.com/nodeclass",
              "rule": "self.all(k, k !='eks.amazonaws.com/nodeclass')"
            }
          ]
        }
      },
      "required": [
        "role",
        "securityGroupSelectorTerms",
        "subnetSelectorTerms"
      ],
      "type": "object",
      "additionalProperties": false
    },
    "status": {
      "description": "NodeClassStatus contains the resolved state of the EKSNodeClass",
      "properties": {
        "conditions": {
          "items": {
            "description": "Condition aliases the upstream type and adds additional helper methods",
            "properties": {
              "lastTransitionTime": {
                "description": "lastTransitionTime is the last time the condition transitioned from one status to another.\nThis should be when the underlying condition changed.  If that is not known, then using the time when the API field changed is acceptable.",
                "format": "date-time",
                "type": "string"
              },
              "message": {
                "description": "message is a human readable message indicating details about the transition.\nThis may be an empty string.",
                "maxLength": 32768,
                "type": "string"
              },
              "observedGeneration": {
                "description": "observedGeneration represents the .metadata.generation that the condition was set based upon.\nFor instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date\nwith respect to the current state of the instance.",
                "format": "int64",
                "minimum": 0,
                "type": "integer"
              },
              "reason": {
                "description": "reason contains a programmatic identifier indicating the reason for the condition's last transition.\nProducers of specific condition types may define expected values and meanings for this field,\nand whether the values are considered a guaranteed API.\nThe value should be a CamelCase string.\nThis field may not be empty.",
                "maxLength": 1024,
                "minLength": 1,
                "pattern": "^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$",
                "type": "string"
              },
              "status": {
                "description": "status of the condition, one of True, False, Unknown.",
                "enum": [
                  "True",
                  "False",
                  "Unknown"
                ],
                "type": "string"
              },
              "type": {
                "description": "type of condition in CamelCase or in foo.example.com/CamelCase.",
                "maxLength": 316,
                "pattern": "^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$",
                "type": "string"
              }
            },
            "required": [
              "lastTransitionTime",
              "message",
              "reason",
              "status",
              "type"
            ],
            "type": "object",
            "additionalProperties": false
          },
          "type": "array"
        },
        "instanceProfile": {
          "description": "InstanceProfile contains the resolved instance profile for the role",
          "type": "string"
        },
        "securityGroups": {
          "description": "SecurityGroups contains the current Security Groups values that are available to the\ncluster under the SecurityGroups selectors.",
          "items": {
            "description": "SecurityGroup contains resolved SecurityGroup selector values utilized for node launch",
            "properties": {
              "id": {
                "description": "ID of the security group",
                "type": "string"
              },
              "name": {
                "description": "Name of the security group",
                "type": "string"
              }
            },
            "required": [
              "id"
            ],
            "type": "object",
            "additionalProperties": false
          },
          "type": "array"
        },
        "subnets": {
          "description": "Subnets contains the current Subnet values that are available to the\ncluster under the subnet selectors.",
          "items": {
            "description": "Subnet contains resolved Subnet selector values utilized for node launch",
            "properties": {
              "id": {
                "description": "ID of the subnet",
                "type": "string"
              },
              "zone": {
                "description": "The associated availability zone",
                "type": "string"
              },
              "zoneID": {
                "description": "The associated availability zone ID",
                "type": "string"
              }
            },
            "required": [
              "id",
              "zone"
            ],
            "type": "object",
            "additionalProperties": false
          },
          "type": "array"
        }
      },
      "type": "object",
      "additionalProperties": false
    }
  },
  "required": [
    "spec"
  ],
  "type": "object"
}
