================================================================================
record-contract.ncl
================================================================================

# An illustrative (thus incomplete and maybe incorrect) contract example for a
# Kubernetes configuration.
# Schema and example derived from https://github.com/kubernetes/examples/blob/master/guestbook-go/guestbook-controller.json.

let Port | doc "A contract for a port number" = contract.from_predicate (fun value =>
  builtin.is_num value &&
  value % 1 == 0 &&
  value >= 0 &&
  value <= 65535) in

let PortElt
  | doc "A contract for a port element of a Kubernetes configuration"
  = {
    name | String,
    containerPort | Port,
  } in

let Container = {
  name | String,
  image | String,
  ports | Array PortElt,
} in

let KubernetesConfig = {
  kind | [| 'ReplicationController, 'ReplicaSet, 'Pod |]
       | doc "The kind of the element being configured."
       | default = 'Pod,

  apiVersion | String,

  metadata = {
    name | String,
    labels.app | String,
  },

  spec = {
    replicas | num.PosNat
             | doc "The number of replicas"
             | default = 1,

    selector.matchLabels.app | String,

    template = {
      metadata.labels.app | String,
      spec.containers | Array Container,
    },
  },
} in

let name_ = "myApp" in
let metadata_ = {
    name = name_,
    labels.app = name_,
  } in

{
  kind = 'ReplicationController,
  apiVersion = "1.1.0",
  metadata = metadata_,
  spec = {
    replicas = 3,
    selector = {
      app.name = name_,
      matchLabels.app = name_,
    },
    template = {
       metadata = metadata_,
       spec = {
          containers = [
            {
              name = name_,
              image = "k8s.gcr.io/%{name_}:v3",
              ports = [
                {
                  name = "http-server",
                  containerPort = 80,
                }
              ]
            }
          ]
        }
    }
  }
} | KubernetesConfig

--------------------------------------------------------------------------------

(term
  (comment)
  (comment)
  (comment)
  (uni_term
    (let_expr
      (let_in_block
        (let_binding
          (pattern
            (ident))
          (annot
            (annot_atom
              (static_string
                (chunk_literal_single
                  (str_literal)))))
          (term
            (uni_term
              (infix_expr
                (applicative
                  (applicative
                    (record_operand
                      (record_operation_chain
                        (record_operand
                          (atom
                            (ident)))
                        (ident))))
                  (record_operand
                    (atom
                      (uni_term
                        (fun_expr
                          (pattern_fun
                            (ident))
                          (term
                            (uni_term
                              (infix_expr
                                (infix_expr
                                  (infix_expr
                                    (infix_expr
                                      (applicative
                                        (applicative
                                          (record_operand
                                            (record_operation_chain
                                              (record_operand
                                                (atom
                                                  (ident)))
                                              (ident))))
                                        (record_operand
                                          (atom
                                            (ident)))))
                                    (infix_lazy_b_op_9)
                                    (infix_expr
                                      (infix_expr
                                        (infix_expr
                                          (applicative
                                            (record_operand
                                              (atom
                                                (ident)))))
                                        (infix_b_op_3)
                                        (infix_expr
                                          (applicative
                                            (record_operand
                                              (atom
                                                (num_literal))))))
                                      (infix_b_op_8)
                                      (infix_expr
                                        (applicative
                                          (record_operand
                                            (atom
                                              (num_literal)))))))
                                  (infix_lazy_b_op_9)
                                  (infix_expr
                                    (infix_expr
                                      (applicative
                                        (record_operand
                                          (atom
                                            (ident)))))
                                    (infix_b_op_7)
                                    (infix_expr
                                      (applicative
                                        (record_operand
                                          (atom
                                            (num_literal)))))))
                                (infix_lazy_b_op_9)
                                (infix_expr
                                  (infix_expr
                                    (applicative
                                      (record_operand
                                        (atom
                                          (ident)))))
                                  (infix_b_op_7)
                                  (infix_expr
                                    (applicative
                                      (record_operand
                                        (atom
                                          (num_literal)))))))))))))))))))
      (term
        (uni_term
          (let_expr
            (let_in_block
              (let_binding
                (pattern
                  (ident))
                (annot
                  (annot_atom
                    (static_string
                      (chunk_literal_single
                        (str_literal)))))
                (term
                  (uni_term
                    (infix_expr
                      (applicative
                        (record_operand
                          (atom
                            (uni_record
                              (record_field
                                (field_path
                                  (field_path_elem
                                    (ident)))
                                (annot
                                  (annot_atom
                                    (types
                                      (infix_expr
                                        (applicative
                                          (record_operand
                                            (atom
                                              (type_atom
                                                (type_builtin))))))))))
                              (record_field
                                (field_path
                                  (field_path_elem
                                    (ident)))
                                (annot
                                  (annot_atom
                                    (types
                                      (infix_expr
                                        (applicative
                                          (record_operand
                                            (atom
                                              (ident))))))))))))))))))
            (term
              (uni_term
                (let_expr
                  (let_in_block
                    (let_binding
                      (pattern
                        (ident))
                      (term
                        (uni_term
                          (infix_expr
                            (applicative
                              (record_operand
                                (atom
                                  (uni_record
                                    (record_field
                                      (field_path
                                        (field_path_elem
                                          (ident)))
                                      (annot
                                        (annot_atom
                                          (types
                                            (infix_expr
                                              (applicative
                                                (record_operand
                                                  (atom
                                                    (type_atom
                                                      (type_builtin))))))))))
                                    (record_field
                                      (field_path
                                        (field_path_elem
                                          (ident)))
                                      (annot
                                        (annot_atom
                                          (types
                                            (infix_expr
                                              (applicative
                                                (record_operand
                                                  (atom
                                                    (type_atom
                                                      (type_builtin))))))))))
                                    (record_field
                                      (field_path
                                        (field_path_elem
                                          (ident)))
                                      (annot
                                        (annot_atom
                                          (types
                                            (infix_expr
                                              (applicative
                                                (type_array
                                                  (record_operand
                                                    (atom
                                                      (ident)))))))))))))))))))
                  (term
                    (uni_term
                      (let_expr
                        (let_in_block
                          (let_binding
                            (pattern
                              (ident))
                            (term
                              (uni_term
                                (infix_expr
                                  (applicative
                                    (record_operand
                                      (atom
                                        (uni_record
                                          (record_field
                                            (field_path
                                              (field_path_elem
                                                (ident)))
                                            (annot
                                              (annot_atom
                                                (types
                                                  (infix_expr
                                                    (applicative
                                                      (record_operand
                                                        (atom
                                                          (type_atom
                                                            (enum
                                                              (enum_tag
                                                                (raw_enum_tag)))
                                                            (enum
                                                              (enum_tag
                                                                (raw_enum_tag)))
                                                            (enum
                                                              (enum_tag
                                                                (raw_enum_tag))))))))))
                                              (annot_atom
                                                (static_string
                                                  (chunk_literal_single
                                                    (str_literal))))
                                              (annot_atom))
                                            (term
                                              (uni_term
                                                (infix_expr
                                                  (applicative
                                                    (record_operand
                                                      (atom
                                                        (enum_tag
                                                          (raw_enum_tag)))))))))
                                          (record_field
                                            (field_path
                                              (field_path_elem
                                                (ident)))
                                            (annot
                                              (annot_atom
                                                (types
                                                  (infix_expr
                                                    (applicative
                                                      (record_operand
                                                        (atom
                                                          (type_atom
                                                            (type_builtin))))))))))
                                          (record_field
                                            (field_path
                                              (field_path_elem
                                                (ident)))
                                            (term
                                              (uni_term
                                                (infix_expr
                                                  (applicative
                                                    (record_operand
                                                      (atom
                                                        (uni_record
                                                          (record_field
                                                            (field_path
                                                              (field_path_elem
                                                                (ident)))
                                                            (annot
                                                              (annot_atom
                                                                (types
                                                                  (infix_expr
                                                                    (applicative
                                                                      (record_operand
                                                                        (atom
                                                                          (type_atom
                                                                            (type_builtin))))))))))
                                                          (record_field
                                                            (field_path
                                                              (field_path_elem
                                                                (ident))
                                                              (field_path_elem
                                                                (ident)))
                                                            (annot
                                                              (annot_atom
                                                                (types
                                                                  (infix_expr
                                                                    (applicative
                                                                      (record_operand
                                                                        (atom
                                                                          (type_atom
                                                                            (type_builtin))))))))))))))))))
                                          (record_field
                                            (field_path
                                              (field_path_elem
                                                (ident)))
                                            (term
                                              (uni_term
                                                (infix_expr
                                                  (applicative
                                                    (record_operand
                                                      (atom
                                                        (uni_record
                                                          (record_field
                                                            (field_path
                                                              (field_path_elem
                                                                (ident)))
                                                            (annot
                                                              (annot_atom
                                                                (types
                                                                  (infix_expr
                                                                    (applicative
                                                                      (record_operand
                                                                        (record_operation_chain
                                                                          (record_operand
                                                                            (atom
                                                                              (ident)))
                                                                          (ident)))))))
                                                              (annot_atom
                                                                (static_string
                                                                  (chunk_literal_single
                                                                    (str_literal))))
                                                              (annot_atom))
                                                            (term
                                                              (uni_term
                                                                (infix_expr
                                                                  (applicative
                                                                    (record_operand
                                                                      (atom
                                                                        (num_literal))))))))
                                                          (record_field
                                                            (field_path
                                                              (field_path_elem
                                                                (ident))
                                                              (field_path_elem
                                                                (ident))
                                                              (field_path_elem
                                                                (ident)))
                                                            (annot
                                                              (annot_atom
                                                                (types
                                                                  (infix_expr
                                                                    (applicative
                                                                      (record_operand
                                                                        (atom
                                                                          (type_atom
                                                                            (type_builtin))))))))))
                                                          (record_field
                                                            (field_path
                                                              (field_path_elem
                                                                (ident)))
                                                            (term
                                                              (uni_term
                                                                (infix_expr
                                                                  (applicative
                                                                    (record_operand
                                                                      (atom
                                                                        (uni_record
                                                                          (record_field
                                                                            (field_path
                                                                              (field_path_elem
                                                                                (ident))
                                                                              (field_path_elem
                                                                                (ident))
                                                                              (field_path_elem
                                                                                (ident)))
                                                                            (annot
                                                                              (annot_atom
                                                                                (types
                                                                                  (infix_expr
                                                                                    (applicative
                                                                                      (record_operand
                                                                                        (atom
                                                                                          (type_atom
                                                                                            (type_builtin))))))))))
                                                                          (record_field
                                                                            (field_path
                                                                              (field_path_elem
                                                                                (ident))
                                                                              (field_path_elem
                                                                                (ident)))
                                                                            (annot
                                                                              (annot_atom
                                                                                (types
                                                                                  (infix_expr
                                                                                    (applicative
                                                                                      (type_array
                                                                                        (record_operand
                                                                                          (atom
                                                                                            (ident)))))))))))))))))))))))))))))))))))
                        (term
                          (uni_term
                            (let_expr
                              (let_in_block
                                (let_binding
                                  (pattern
                                    (ident))
                                  (term
                                    (uni_term
                                      (infix_expr
                                        (applicative
                                          (record_operand
                                            (atom
                                              (str_chunks
                                                (str_chunks_single
                                                  (chunk_literal_single
                                                    (str_literal))))))))))))
                              (term
                                (uni_term
                                  (let_expr
                                    (let_in_block
                                      (let_binding
                                        (pattern
                                          (ident))
                                        (term
                                          (uni_term
                                            (infix_expr
                                              (applicative
                                                (record_operand
                                                  (atom
                                                    (uni_record
                                                      (record_field
                                                        (field_path
                                                          (field_path_elem
                                                            (ident)))
                                                        (term
                                                          (uni_term
                                                            (infix_expr
                                                              (applicative
                                                                (record_operand
                                                                  (atom
                                                                    (ident))))))))
                                                      (record_field
                                                        (field_path
                                                          (field_path_elem
                                                            (ident))
                                                          (field_path_elem
                                                            (ident)))
                                                        (term
                                                          (uni_term
                                                            (infix_expr
                                                              (applicative
                                                                (record_operand
                                                                  (atom
                                                                    (ident)))))))))))))))))
                                    (term
                                      (uni_term
                                        (annotated_infix_expr
                                          (infix_expr
                                            (applicative
                                              (record_operand
                                                (atom
                                                  (uni_record
                                                    (record_field
                                                      (field_path
                                                        (field_path_elem
                                                          (ident)))
                                                      (term
                                                        (uni_term
                                                          (infix_expr
                                                            (applicative
                                                              (record_operand
                                                                (atom
                                                                  (enum_tag
                                                                    (raw_enum_tag)))))))))
                                                    (record_field
                                                      (field_path
                                                        (field_path_elem
                                                          (ident)))
                                                      (term
                                                        (uni_term
                                                          (infix_expr
                                                            (applicative
                                                              (record_operand
                                                                (atom
                                                                  (str_chunks
                                                                    (str_chunks_single
                                                                      (chunk_literal_single
                                                                        (str_literal)))))))))))
                                                    (record_field
                                                      (field_path
                                                        (field_path_elem
                                                          (ident)))
                                                      (term
                                                        (uni_term
                                                          (infix_expr
                                                            (applicative
                                                              (record_operand
                                                                (atom
                                                                  (ident))))))))
                                                    (record_last_field
                                                      (record_field
                                                        (field_path
                                                          (field_path_elem
                                                            (ident)))
                                                        (term
                                                          (uni_term
                                                            (infix_expr
                                                              (applicative
                                                                (record_operand
                                                                  (atom
                                                                    (uni_record
                                                                      (record_field
                                                                        (field_path
                                                                          (field_path_elem
                                                                            (ident)))
                                                                        (term
                                                                          (uni_term
                                                                            (infix_expr
                                                                              (applicative
                                                                                (record_operand
                                                                                  (atom
                                                                                    (num_literal))))))))
                                                                      (record_field
                                                                        (field_path
                                                                          (field_path_elem
                                                                            (ident)))
                                                                        (term
                                                                          (uni_term
                                                                            (infix_expr
                                                                              (applicative
                                                                                (record_operand
                                                                                  (atom
                                                                                    (uni_record
                                                                                      (record_field
                                                                                        (field_path
                                                                                          (field_path_elem
                                                                                            (ident))
                                                                                          (field_path_elem
                                                                                            (ident)))
                                                                                        (term
                                                                                          (uni_term
                                                                                            (infix_expr
                                                                                              (applicative
                                                                                                (record_operand
                                                                                                  (atom
                                                                                                    (ident))))))))
                                                                                      (record_field
                                                                                        (field_path
                                                                                          (field_path_elem
                                                                                            (ident))
                                                                                          (field_path_elem
                                                                                            (ident)))
                                                                                        (term
                                                                                          (uni_term
                                                                                            (infix_expr
                                                                                              (applicative
                                                                                                (record_operand
                                                                                                  (atom
                                                                                                    (ident))))))))))))))))
                                                                      (record_last_field
                                                                        (record_field
                                                                          (field_path
                                                                            (field_path_elem
                                                                              (ident)))
                                                                          (term
                                                                            (uni_term
                                                                              (infix_expr
                                                                                (applicative
                                                                                  (record_operand
                                                                                    (atom
                                                                                      (uni_record
                                                                                        (record_field
                                                                                          (field_path
                                                                                            (field_path_elem
                                                                                              (ident)))
                                                                                          (term
                                                                                            (uni_term
                                                                                              (infix_expr
                                                                                                (applicative
                                                                                                  (record_operand
                                                                                                    (atom
                                                                                                      (ident))))))))
                                                                                        (record_last_field
                                                                                          (record_field
                                                                                            (field_path
                                                                                              (field_path_elem
                                                                                                (ident)))
                                                                                            (term
                                                                                              (uni_term
                                                                                                (infix_expr
                                                                                                  (applicative
                                                                                                    (record_operand
                                                                                                      (atom
                                                                                                        (uni_record
                                                                                                          (record_last_field
                                                                                                            (record_field
                                                                                                              (field_path
                                                                                                                (field_path_elem
                                                                                                                  (ident)))
                                                                                                              (term
                                                                                                                (uni_term
                                                                                                                  (infix_expr
                                                                                                                    (applicative
                                                                                                                      (record_operand
                                                                                                                        (atom
                                                                                                                          (term
                                                                                                                            (uni_term
                                                                                                                              (infix_expr
                                                                                                                                (applicative
                                                                                                                                  (record_operand
                                                                                                                                    (atom
                                                                                                                                      (uni_record
                                                                                                                                        (record_field
                                                                                                                                          (field_path
                                                                                                                                            (field_path_elem
                                                                                                                                              (ident)))
                                                                                                                                          (term
                                                                                                                                            (uni_term
                                                                                                                                              (infix_expr
                                                                                                                                                (applicative
                                                                                                                                                  (record_operand
                                                                                                                                                    (atom
                                                                                                                                                      (ident))))))))
                                                                                                                                        (record_field
                                                                                                                                          (field_path
                                                                                                                                            (field_path_elem
                                                                                                                                              (ident)))
                                                                                                                                          (term
                                                                                                                                            (uni_term
                                                                                                                                              (infix_expr
                                                                                                                                                (applicative
                                                                                                                                                  (record_operand
                                                                                                                                                    (atom
                                                                                                                                                      (str_chunks
                                                                                                                                                        (str_chunks_single
                                                                                                                                                          (chunk_literal_single
                                                                                                                                                            (str_literal))
                                                                                                                                                          (chunk_expr
                                                                                                                                                            (interpolation_start)
                                                                                                                                                            (term
                                                                                                                                                              (uni_term
                                                                                                                                                                (infix_expr
                                                                                                                                                                  (applicative
                                                                                                                                                                    (record_operand
                                                                                                                                                                      (atom
                                                                                                                                                                        (ident)))))))
                                                                                                                                                            (interpolation_end))
                                                                                                                                                          (chunk_literal_single
                                                                                                                                                            (str_literal)))))))))))
                                                                                                                                        (record_last_field
                                                                                                                                          (record_field
                                                                                                                                            (field_path
                                                                                                                                              (field_path_elem
                                                                                                                                                (ident)))
                                                                                                                                            (term
                                                                                                                                              (uni_term
                                                                                                                                                (infix_expr
                                                                                                                                                  (applicative
                                                                                                                                                    (record_operand
                                                                                                                                                      (atom
                                                                                                                                                        (term
                                                                                                                                                          (uni_term
                                                                                                                                                            (infix_expr
                                                                                                                                                              (applicative
                                                                                                                                                                (record_operand
                                                                                                                                                                  (atom
                                                                                                                                                                    (uni_record
                                                                                                                                                                      (record_field
                                                                                                                                                                        (field_path
                                                                                                                                                                          (field_path_elem
                                                                                                                                                                            (ident)))
                                                                                                                                                                        (term
                                                                                                                                                                          (uni_term
                                                                                                                                                                            (infix_expr
                                                                                                                                                                              (applicative
                                                                                                                                                                                (record_operand
                                                                                                                                                                                  (atom
                                                                                                                                                                                    (str_chunks
                                                                                                                                                                                      (str_chunks_single
                                                                                                                                                                                        (chunk_literal_single
                                                                                                                                                                                          (str_literal)))))))))))
                                                                                                                                                                      (record_field
                                                                                                                                                                        (field_path
                                                                                                                                                                          (field_path_elem
                                                                                                                                                                            (ident)))
                                                                                                                                                                        (term
                                                                                                                                                                          (uni_term
                                                                                                                                                                            (infix_expr
                                                                                                                                                                              (applicative
                                                                                                                                                                                (record_operand
                                                                                                                                                                                  (atom
                                                                                                                                                                                    (num_literal))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
                                          (annot
                                            (annot_atom
                                              (types
                                                (infix_expr
                                                  (applicative
                                                    (record_operand
                                                      (atom
                                                        (ident)))))))))))))))))))))))))))))
