module Hocker.Types where
import Control.Applicative
import Control.Monad.Error.Class
import qualified Control.Monad.Except as Except
import Control.Monad.IO.Class
import qualified Control.Monad.Reader as Reader
import Control.Monad.Reader.Class
import qualified Crypto.Hash as Hash
import qualified Data.ByteString.Lazy
import Data.Char (toUpper)
import Data.Monoid
import Data.Text (Text)
import qualified Data.Text as Text
import qualified Network.Wreq as Wreq
import Network.Wreq.ErrorHandling
import qualified Options.Applicative as Options
import Options.Generic
import URI.ByteString
import Hocker.Types.Exceptions
import Hocker.Types.Hash ()
import Hocker.Types.ImageName
import Hocker.Types.ImageTag
import Hocker.Types.URI ()
type RegistryURI = (URIRef Absolute)
type Username = Text
type Password = Text
type Layer = Text
type StrippedDigest = Text
type Manifest = Data.ByteString.Lazy.ByteString
type ImageConfigJSON = Data.ByteString.Lazy.ByteString
type RspBS = Wreq.Response Data.ByteString.Lazy.ByteString
type Extension = String
type RepoNamePart = Text
type ImageNamePart = Text
type ConfigDigest = Base32Digest
data Options w = Options
{
registry :: w ::: Maybe RegistryURI
<?> "URI of registry, defaults to the Docker Hub registry"
, credentials :: Maybe Credentials
, out :: w ::: Maybe FilePath
<?> "Write content to location"
, imageName :: ImageName
, imageTag :: ImageTag
} deriving (Generic)
instance ParseRecord (Options Wrapped)
deriving instance Show (Options Unwrapped)
newtype Hocker a = Hocker { unHocker :: Reader.ReaderT HockerMeta (Except.ExceptT HockerException IO) a }
deriving
( Functor
, Applicative
, Monad
, MonadIO
, MonadReader HockerMeta
, MonadError HockerException
)
runHocker :: Hocker a -> HockerMeta -> IO (Either HockerException a)
runHocker (unHocker -> d) = Except.runExceptT . interceptHttpExc . Reader.runReaderT d
data HockerMeta = HockerMeta
{ dockerRegistry :: RegistryURI
, auth :: Maybe Wreq.Auth
, imageName :: ImageName
, imageTag :: ImageTag
, out :: Maybe FilePath
, outDir :: Maybe FilePath
, imageLayer :: Maybe (Hash.Digest Hash.SHA256)
} deriving (Show)
newtype Base32Digest = Base32Digest Text
deriving (Show, Read, Eq)
newtype Base16Digest = Base16Digest Text
deriving (Show, Read, Eq)
data Credentials = Basic Username Password | BearerToken Text
deriving (Show)
instance ParseField Credentials where
readField = Options.readerError "Internal, fatal error: unexpected use of readField"
parseField _ _ _ = (Basic <$> parseUsername <*> parsePassword) <|> (BearerToken <$> parseToken)
where
parseUsername = Text.pack <$>
(Options.option Options.str $
( Options.metavar "BASIC USERNAME"
<> Options.long "username"
<> Options.short 'u'
<> Options.help "Username part of a basic auth credential"
)
)
parsePassword = Text.pack <$>
(Options.option Options.str $
( Options.metavar "BASIC PASSWORD"
<> Options.long "password"
<> Options.short 'p'
<> Options.help "Password part of a basic auth credential"
)
)
parseToken = Text.pack <$>
(Options.option Options.str $
( Options.metavar "BEARER TOKEN"
<> Options.long "token"
<> Options.short 't'
<> Options.help "Bearer token retrieved from a call to `docker login` (mutually exclusive to --username and --password)"
)
)
instance ParseFields Credentials
instance ParseRecord Credentials where
parseRecord = fmap Options.Generic.getOnly parseRecord
upperFirst :: String -> String
upperFirst [] = []
upperFirst (h:t) = toUpper h : t