module Dhall.Kubernetes.Types where import qualified Data.Text as Text import qualified Data.Vector as Vector import qualified Dhall.Core as Dhall import qualified Dhall.Parser as Dhall import Control.Applicative (optional) import Control.Monad (join) import Data.Aeson import Data.Map (Map) import Data.Scientific (Scientific) import Data.Set (Set) import Data.Text (Text) import GHC.Generics (Generic) import Prettyprinter (Pretty) type Expr = Dhall.Expr Dhall.Src Dhall.Import type DuplicateHandler = (Text, [ModelName]) -> Maybe ModelName type Prefix = Text type ModelHierarchy = [ModelName] {-| Type for the Swagger specification. There is such a type defined in the `swagger2` package, but Kubernetes' OpenAPI file doesn't conform to that, so here we implement a small version of that tailored to our needs. -} data Swagger = Swagger { definitions :: Map ModelName Definition } deriving (Generic, Show) instance FromJSON Swagger data Definition = Definition { typ :: Maybe Text , ref :: Maybe Ref , format :: Maybe Text , minimum_ :: Maybe Scientific -- Avoid shadowing with Prelude.minimum , exclusiveMinimum :: Maybe Bool , maximum_ :: Maybe Scientific -- Avoid shadowing with Prelude.maximum , exclusiveMaximum :: Maybe Bool , description :: Maybe Text , items :: Maybe Definition , properties :: Maybe (Map ModelName Definition) , additionalProperties :: Maybe Definition , required :: Maybe (Set FieldName) , baseData :: Maybe BaseData , intOrString :: Maybe Bool } deriving (Generic, Show, Eq) instance FromJSON Definition where parseJSON = withObject "definition" $ \o -> do typ <- o .:? "type" ref <- o .:? "$ref" format <- o .:? "format" minimum_ <- o .:? "minimum" exclusiveMinimum <- o .:? "exclusiveMinimum" maximum_ <- o .:? "maximum" exclusiveMaximum <- o .:? "exclusiveMaximum" properties <- o .:? "properties" additionalProperties <- o .:? "additionalProperties" required <- o .:? "required" items <- o .:? "items" description <- o .:? "description" baseData <- fmap join $ optional (o .:? "x-kubernetes-group-version-kind") intOrString <- o .:? "x-kubernetes-int-or-string" pure Definition{..} newtype Ref = Ref { unRef :: Text } deriving (Generic, Show, FromJSON, Eq) newtype ModelName = ModelName { unModelName :: Text } deriving (Generic, Show, Ord, FromJSONKey, Eq, Pretty) newtype FieldName = FieldName { unFieldName :: Text } deriving (Generic, Show, FromJSON, FromJSONKey, Ord, Eq, Pretty) {-| This contains the static data that a Model might have This applies only to kubernetes resources where ``kind`` and ``apiVersion`` are statically determined by the resource. See the `Kubernetes OpenAPI Spec Readme`: https://github.com/kubernetes/kubernetes/blob/master/api/openapi-spec/README.md#x-kubernetes-group-version-kind For example for a v1 Deployment we have { kind = "Deployment" , apiVersion = "apps/v1" } -} data BaseData = BaseData { kind :: Text , apiVersion :: Text } deriving (Generic, Show, Eq) instance FromJSON BaseData where parseJSON = withArray "array of values" $ \arr -> withObject "baseData" (\o -> do group <- o .:? "group" .!= "" kind <- o .: "kind" version <- o .: "version" let apiVersion = (if Text.null group then "" else group <> "/") <> version pure BaseData{..}) (head $ Vector.toList arr)