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           Data.Text.Prettyprint.Doc (Pretty)
import           GHC.Generics              (Generic)


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
  { Swagger -> Map ModelName Definition
definitions :: Map ModelName Definition
  } deriving ((forall x. Swagger -> Rep Swagger x)
-> (forall x. Rep Swagger x -> Swagger) -> Generic Swagger
forall x. Rep Swagger x -> Swagger
forall x. Swagger -> Rep Swagger x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep Swagger x -> Swagger
$cfrom :: forall x. Swagger -> Rep Swagger x
Generic, Int -> Swagger -> ShowS
[Swagger] -> ShowS
Swagger -> String
(Int -> Swagger -> ShowS)
-> (Swagger -> String) -> ([Swagger] -> ShowS) -> Show Swagger
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Swagger] -> ShowS
$cshowList :: [Swagger] -> ShowS
show :: Swagger -> String
$cshow :: Swagger -> String
showsPrec :: Int -> Swagger -> ShowS
$cshowsPrec :: Int -> Swagger -> ShowS
Show)

instance FromJSON Swagger


data Definition = Definition
  { Definition -> Maybe Text
typ              :: Maybe Text
  , Definition -> Maybe Ref
ref              :: Maybe Ref
  , Definition -> Maybe Text
format           :: Maybe Text
  , Definition -> Maybe Scientific
minimum_         :: Maybe Scientific -- Avoid shadowing with Prelude.minimum
  , Definition -> Maybe Bool
exclusiveMinimum :: Maybe Bool
  , Definition -> Maybe Text
description      :: Maybe Text
  , Definition -> Maybe Definition
items            :: Maybe Definition
  , Definition -> Maybe (Map ModelName Definition)
properties       :: Maybe (Map ModelName Definition)
  , Definition -> Maybe (Set FieldName)
required         :: Maybe (Set FieldName)
  , Definition -> Maybe BaseData
baseData         :: Maybe BaseData
  , Definition -> Maybe Bool
intOrString      :: Maybe Bool
  } deriving ((forall x. Definition -> Rep Definition x)
-> (forall x. Rep Definition x -> Definition) -> Generic Definition
forall x. Rep Definition x -> Definition
forall x. Definition -> Rep Definition x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep Definition x -> Definition
$cfrom :: forall x. Definition -> Rep Definition x
Generic, Int -> Definition -> ShowS
[Definition] -> ShowS
Definition -> String
(Int -> Definition -> ShowS)
-> (Definition -> String)
-> ([Definition] -> ShowS)
-> Show Definition
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Definition] -> ShowS
$cshowList :: [Definition] -> ShowS
show :: Definition -> String
$cshow :: Definition -> String
showsPrec :: Int -> Definition -> ShowS
$cshowsPrec :: Int -> Definition -> ShowS
Show, Definition -> Definition -> Bool
(Definition -> Definition -> Bool)
-> (Definition -> Definition -> Bool) -> Eq Definition
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Definition -> Definition -> Bool
$c/= :: Definition -> Definition -> Bool
== :: Definition -> Definition -> Bool
$c== :: Definition -> Definition -> Bool
Eq)

instance FromJSON Definition where
  parseJSON :: Value -> Parser Definition
parseJSON = String
-> (Object -> Parser Definition) -> Value -> Parser Definition
forall a. String -> (Object -> Parser a) -> Value -> Parser a
withObject String
"definition" ((Object -> Parser Definition) -> Value -> Parser Definition)
-> (Object -> Parser Definition) -> Value -> Parser Definition
forall a b. (a -> b) -> a -> b
$ \Object
o -> do
    Maybe Text
typ              <- Object
o Object -> Text -> Parser (Maybe Text)
forall a. FromJSON a => Object -> Text -> Parser (Maybe a)
.:? Text
"type"
    Maybe Ref
ref              <- Object
o Object -> Text -> Parser (Maybe Ref)
forall a. FromJSON a => Object -> Text -> Parser (Maybe a)
.:? Text
"$ref"
    Maybe Text
format           <- Object
o Object -> Text -> Parser (Maybe Text)
forall a. FromJSON a => Object -> Text -> Parser (Maybe a)
.:? Text
"format"
    Maybe Scientific
minimum_         <- Object
o Object -> Text -> Parser (Maybe Scientific)
forall a. FromJSON a => Object -> Text -> Parser (Maybe a)
.:? Text
"minimum"
    Maybe Bool
exclusiveMinimum <- Object
o Object -> Text -> Parser (Maybe Bool)
forall a. FromJSON a => Object -> Text -> Parser (Maybe a)
.:? Text
"exclusiveMinimum"
    Maybe (Map ModelName Definition)
properties       <- Object
o Object -> Text -> Parser (Maybe (Map ModelName Definition))
forall a. FromJSON a => Object -> Text -> Parser (Maybe a)
.:? Text
"properties"
    Maybe (Set FieldName)
required         <- Object
o Object -> Text -> Parser (Maybe (Set FieldName))
forall a. FromJSON a => Object -> Text -> Parser (Maybe a)
.:? Text
"required"
    Maybe Definition
items            <- Object
o Object -> Text -> Parser (Maybe Definition)
forall a. FromJSON a => Object -> Text -> Parser (Maybe a)
.:? Text
"items"
    Maybe Text
description      <- Object
o Object -> Text -> Parser (Maybe Text)
forall a. FromJSON a => Object -> Text -> Parser (Maybe a)
.:? Text
"description"
    Maybe BaseData
baseData         <- (Maybe (Maybe BaseData) -> Maybe BaseData)
-> Parser (Maybe (Maybe BaseData)) -> Parser (Maybe BaseData)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Maybe (Maybe BaseData) -> Maybe BaseData
forall (m :: * -> *) a. Monad m => m (m a) -> m a
join (Parser (Maybe (Maybe BaseData)) -> Parser (Maybe BaseData))
-> Parser (Maybe (Maybe BaseData)) -> Parser (Maybe BaseData)
forall a b. (a -> b) -> a -> b
$ Parser (Maybe BaseData) -> Parser (Maybe (Maybe BaseData))
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional (Object
o Object -> Text -> Parser (Maybe BaseData)
forall a. FromJSON a => Object -> Text -> Parser (Maybe a)
.:? Text
"x-kubernetes-group-version-kind")
    Maybe Bool
intOrString      <- Object
o Object -> Text -> Parser (Maybe Bool)
forall a. FromJSON a => Object -> Text -> Parser (Maybe a)
.:? Text
"x-kubernetes-int-or-string"
    pure Definition :: Maybe Text
-> Maybe Ref
-> Maybe Text
-> Maybe Scientific
-> Maybe Bool
-> Maybe Text
-> Maybe Definition
-> Maybe (Map ModelName Definition)
-> Maybe (Set FieldName)
-> Maybe BaseData
-> Maybe Bool
-> Definition
Definition{Maybe Bool
Maybe Scientific
Maybe Text
Maybe (Map ModelName Definition)
Maybe (Set FieldName)
Maybe BaseData
Maybe Ref
Maybe Definition
intOrString :: Maybe Bool
baseData :: Maybe BaseData
description :: Maybe Text
items :: Maybe Definition
required :: Maybe (Set FieldName)
properties :: Maybe (Map ModelName Definition)
exclusiveMinimum :: Maybe Bool
minimum_ :: Maybe Scientific
format :: Maybe Text
ref :: Maybe Ref
typ :: Maybe Text
$sel:intOrString:Definition :: Maybe Bool
$sel:baseData:Definition :: Maybe BaseData
$sel:required:Definition :: Maybe (Set FieldName)
$sel:properties:Definition :: Maybe (Map ModelName Definition)
$sel:items:Definition :: Maybe Definition
$sel:description:Definition :: Maybe Text
$sel:exclusiveMinimum:Definition :: Maybe Bool
$sel:minimum_:Definition :: Maybe Scientific
$sel:format:Definition :: Maybe Text
$sel:ref:Definition :: Maybe Ref
$sel:typ:Definition :: Maybe Text
..}


newtype Ref = Ref { Ref -> Text
unRef :: Text }
  deriving ((forall x. Ref -> Rep Ref x)
-> (forall x. Rep Ref x -> Ref) -> Generic Ref
forall x. Rep Ref x -> Ref
forall x. Ref -> Rep Ref x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep Ref x -> Ref
$cfrom :: forall x. Ref -> Rep Ref x
Generic, Int -> Ref -> ShowS
[Ref] -> ShowS
Ref -> String
(Int -> Ref -> ShowS)
-> (Ref -> String) -> ([Ref] -> ShowS) -> Show Ref
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Ref] -> ShowS
$cshowList :: [Ref] -> ShowS
show :: Ref -> String
$cshow :: Ref -> String
showsPrec :: Int -> Ref -> ShowS
$cshowsPrec :: Int -> Ref -> ShowS
Show, Value -> Parser [Ref]
Value -> Parser Ref
(Value -> Parser Ref) -> (Value -> Parser [Ref]) -> FromJSON Ref
forall a.
(Value -> Parser a) -> (Value -> Parser [a]) -> FromJSON a
parseJSONList :: Value -> Parser [Ref]
$cparseJSONList :: Value -> Parser [Ref]
parseJSON :: Value -> Parser Ref
$cparseJSON :: Value -> Parser Ref
FromJSON, Ref -> Ref -> Bool
(Ref -> Ref -> Bool) -> (Ref -> Ref -> Bool) -> Eq Ref
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Ref -> Ref -> Bool
$c/= :: Ref -> Ref -> Bool
== :: Ref -> Ref -> Bool
$c== :: Ref -> Ref -> Bool
Eq)


newtype ModelName = ModelName { ModelName -> Text
unModelName :: Text }
  deriving ((forall x. ModelName -> Rep ModelName x)
-> (forall x. Rep ModelName x -> ModelName) -> Generic ModelName
forall x. Rep ModelName x -> ModelName
forall x. ModelName -> Rep ModelName x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep ModelName x -> ModelName
$cfrom :: forall x. ModelName -> Rep ModelName x
Generic, Int -> ModelName -> ShowS
[ModelName] -> ShowS
ModelName -> String
(Int -> ModelName -> ShowS)
-> (ModelName -> String)
-> ([ModelName] -> ShowS)
-> Show ModelName
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ModelName] -> ShowS
$cshowList :: [ModelName] -> ShowS
show :: ModelName -> String
$cshow :: ModelName -> String
showsPrec :: Int -> ModelName -> ShowS
$cshowsPrec :: Int -> ModelName -> ShowS
Show, Eq ModelName
Eq ModelName
-> (ModelName -> ModelName -> Ordering)
-> (ModelName -> ModelName -> Bool)
-> (ModelName -> ModelName -> Bool)
-> (ModelName -> ModelName -> Bool)
-> (ModelName -> ModelName -> Bool)
-> (ModelName -> ModelName -> ModelName)
-> (ModelName -> ModelName -> ModelName)
-> Ord ModelName
ModelName -> ModelName -> Bool
ModelName -> ModelName -> Ordering
ModelName -> ModelName -> ModelName
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: ModelName -> ModelName -> ModelName
$cmin :: ModelName -> ModelName -> ModelName
max :: ModelName -> ModelName -> ModelName
$cmax :: ModelName -> ModelName -> ModelName
>= :: ModelName -> ModelName -> Bool
$c>= :: ModelName -> ModelName -> Bool
> :: ModelName -> ModelName -> Bool
$c> :: ModelName -> ModelName -> Bool
<= :: ModelName -> ModelName -> Bool
$c<= :: ModelName -> ModelName -> Bool
< :: ModelName -> ModelName -> Bool
$c< :: ModelName -> ModelName -> Bool
compare :: ModelName -> ModelName -> Ordering
$ccompare :: ModelName -> ModelName -> Ordering
$cp1Ord :: Eq ModelName
Ord, FromJSONKeyFunction [ModelName]
FromJSONKeyFunction ModelName
FromJSONKeyFunction ModelName
-> FromJSONKeyFunction [ModelName] -> FromJSONKey ModelName
forall a.
FromJSONKeyFunction a -> FromJSONKeyFunction [a] -> FromJSONKey a
fromJSONKeyList :: FromJSONKeyFunction [ModelName]
$cfromJSONKeyList :: FromJSONKeyFunction [ModelName]
fromJSONKey :: FromJSONKeyFunction ModelName
$cfromJSONKey :: FromJSONKeyFunction ModelName
FromJSONKey, ModelName -> ModelName -> Bool
(ModelName -> ModelName -> Bool)
-> (ModelName -> ModelName -> Bool) -> Eq ModelName
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: ModelName -> ModelName -> Bool
$c/= :: ModelName -> ModelName -> Bool
== :: ModelName -> ModelName -> Bool
$c== :: ModelName -> ModelName -> Bool
Eq, [ModelName] -> Doc ann
ModelName -> Doc ann
(forall ann. ModelName -> Doc ann)
-> (forall ann. [ModelName] -> Doc ann) -> Pretty ModelName
forall ann. [ModelName] -> Doc ann
forall ann. ModelName -> Doc ann
forall a.
(forall ann. a -> Doc ann)
-> (forall ann. [a] -> Doc ann) -> Pretty a
prettyList :: [ModelName] -> Doc ann
$cprettyList :: forall ann. [ModelName] -> Doc ann
pretty :: ModelName -> Doc ann
$cpretty :: forall ann. ModelName -> Doc ann
Pretty)

newtype FieldName = FieldName { FieldName -> Text
unFieldName :: Text }
  deriving ((forall x. FieldName -> Rep FieldName x)
-> (forall x. Rep FieldName x -> FieldName) -> Generic FieldName
forall x. Rep FieldName x -> FieldName
forall x. FieldName -> Rep FieldName x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep FieldName x -> FieldName
$cfrom :: forall x. FieldName -> Rep FieldName x
Generic, Int -> FieldName -> ShowS
[FieldName] -> ShowS
FieldName -> String
(Int -> FieldName -> ShowS)
-> (FieldName -> String)
-> ([FieldName] -> ShowS)
-> Show FieldName
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [FieldName] -> ShowS
$cshowList :: [FieldName] -> ShowS
show :: FieldName -> String
$cshow :: FieldName -> String
showsPrec :: Int -> FieldName -> ShowS
$cshowsPrec :: Int -> FieldName -> ShowS
Show, Value -> Parser [FieldName]
Value -> Parser FieldName
(Value -> Parser FieldName)
-> (Value -> Parser [FieldName]) -> FromJSON FieldName
forall a.
(Value -> Parser a) -> (Value -> Parser [a]) -> FromJSON a
parseJSONList :: Value -> Parser [FieldName]
$cparseJSONList :: Value -> Parser [FieldName]
parseJSON :: Value -> Parser FieldName
$cparseJSON :: Value -> Parser FieldName
FromJSON, FromJSONKeyFunction [FieldName]
FromJSONKeyFunction FieldName
FromJSONKeyFunction FieldName
-> FromJSONKeyFunction [FieldName] -> FromJSONKey FieldName
forall a.
FromJSONKeyFunction a -> FromJSONKeyFunction [a] -> FromJSONKey a
fromJSONKeyList :: FromJSONKeyFunction [FieldName]
$cfromJSONKeyList :: FromJSONKeyFunction [FieldName]
fromJSONKey :: FromJSONKeyFunction FieldName
$cfromJSONKey :: FromJSONKeyFunction FieldName
FromJSONKey, Eq FieldName
Eq FieldName
-> (FieldName -> FieldName -> Ordering)
-> (FieldName -> FieldName -> Bool)
-> (FieldName -> FieldName -> Bool)
-> (FieldName -> FieldName -> Bool)
-> (FieldName -> FieldName -> Bool)
-> (FieldName -> FieldName -> FieldName)
-> (FieldName -> FieldName -> FieldName)
-> Ord FieldName
FieldName -> FieldName -> Bool
FieldName -> FieldName -> Ordering
FieldName -> FieldName -> FieldName
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: FieldName -> FieldName -> FieldName
$cmin :: FieldName -> FieldName -> FieldName
max :: FieldName -> FieldName -> FieldName
$cmax :: FieldName -> FieldName -> FieldName
>= :: FieldName -> FieldName -> Bool
$c>= :: FieldName -> FieldName -> Bool
> :: FieldName -> FieldName -> Bool
$c> :: FieldName -> FieldName -> Bool
<= :: FieldName -> FieldName -> Bool
$c<= :: FieldName -> FieldName -> Bool
< :: FieldName -> FieldName -> Bool
$c< :: FieldName -> FieldName -> Bool
compare :: FieldName -> FieldName -> Ordering
$ccompare :: FieldName -> FieldName -> Ordering
$cp1Ord :: Eq FieldName
Ord, FieldName -> FieldName -> Bool
(FieldName -> FieldName -> Bool)
-> (FieldName -> FieldName -> Bool) -> Eq FieldName
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: FieldName -> FieldName -> Bool
$c/= :: FieldName -> FieldName -> Bool
== :: FieldName -> FieldName -> Bool
$c== :: FieldName -> FieldName -> Bool
Eq, [FieldName] -> Doc ann
FieldName -> Doc ann
(forall ann. FieldName -> Doc ann)
-> (forall ann. [FieldName] -> Doc ann) -> Pretty FieldName
forall ann. [FieldName] -> Doc ann
forall ann. FieldName -> Doc ann
forall a.
(forall ann. a -> Doc ann)
-> (forall ann. [a] -> Doc ann) -> Pretty a
prettyList :: [FieldName] -> Doc ann
$cprettyList :: forall ann. [FieldName] -> Doc ann
pretty :: FieldName -> Doc ann
$cpretty :: forall ann. FieldName -> Doc ann
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
  { BaseData -> Text
kind       :: Text
  , BaseData -> Text
apiVersion :: Text
  } deriving ((forall x. BaseData -> Rep BaseData x)
-> (forall x. Rep BaseData x -> BaseData) -> Generic BaseData
forall x. Rep BaseData x -> BaseData
forall x. BaseData -> Rep BaseData x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep BaseData x -> BaseData
$cfrom :: forall x. BaseData -> Rep BaseData x
Generic, Int -> BaseData -> ShowS
[BaseData] -> ShowS
BaseData -> String
(Int -> BaseData -> ShowS)
-> (BaseData -> String) -> ([BaseData] -> ShowS) -> Show BaseData
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [BaseData] -> ShowS
$cshowList :: [BaseData] -> ShowS
show :: BaseData -> String
$cshow :: BaseData -> String
showsPrec :: Int -> BaseData -> ShowS
$cshowsPrec :: Int -> BaseData -> ShowS
Show, BaseData -> BaseData -> Bool
(BaseData -> BaseData -> Bool)
-> (BaseData -> BaseData -> Bool) -> Eq BaseData
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: BaseData -> BaseData -> Bool
$c/= :: BaseData -> BaseData -> Bool
== :: BaseData -> BaseData -> Bool
$c== :: BaseData -> BaseData -> Bool
Eq)

instance FromJSON BaseData where
  parseJSON :: Value -> Parser BaseData
parseJSON = String -> (Array -> Parser BaseData) -> Value -> Parser BaseData
forall a. String -> (Array -> Parser a) -> Value -> Parser a
withArray String
"array of values" ((Array -> Parser BaseData) -> Value -> Parser BaseData)
-> (Array -> Parser BaseData) -> Value -> Parser BaseData
forall a b. (a -> b) -> a -> b
$ \Array
arr -> String -> (Object -> Parser BaseData) -> Value -> Parser BaseData
forall a. String -> (Object -> Parser a) -> Value -> Parser a
withObject String
"baseData" (\Object
o -> do
    Text
group   <- Object
o Object -> Text -> Parser (Maybe Text)
forall a. FromJSON a => Object -> Text -> Parser (Maybe a)
.:? Text
"group" Parser (Maybe Text) -> Text -> Parser Text
forall a. Parser (Maybe a) -> a -> Parser a
.!= Text
""
    Text
kind    <- Object
o Object -> Text -> Parser Text
forall a. FromJSON a => Object -> Text -> Parser a
.: Text
"kind"
    Text
version <- Object
o Object -> Text -> Parser Text
forall a. FromJSON a => Object -> Text -> Parser a
.: Text
"version"
    let apiVersion :: Text
apiVersion = (if Text -> Bool
Text.null Text
group then Text
"" else Text
group Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"/") Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
version
    BaseData -> Parser BaseData
forall (f :: * -> *) a. Applicative f => a -> f a
pure BaseData :: Text -> Text -> BaseData
BaseData{Text
apiVersion :: Text
kind :: Text
$sel:apiVersion:BaseData :: Text
$sel:kind:BaseData :: Text
..})
    ([Value] -> Value
forall a. [a] -> a
head ([Value] -> Value) -> [Value] -> Value
forall a b. (a -> b) -> a -> b
$ Array -> [Value]
forall a. Vector a -> [a]
Vector.toList Array
arr)