azurify-0.1.0.0: azurify.hs
{-# LANGUAGE OverloadedStrings, DeriveDataTypeable #-}
module Main where
import qualified Azure as Az
import Control.Monad.IO.Class (liftIO)
import qualified Data.ByteString as B
import qualified Data.ByteString.Char8 as B8
import qualified Data.ByteString.Lazy as L
import System.Console.CmdArgs
import System.Directory(getCurrentDirectory)
data Commands = UploadBlob { uploadBlobPath :: String
, uploadBlobStorageName :: String
, uploadBlobContainerName :: String
, uploadBlobFileName :: String
, uploadBlobContentType :: Maybe String
, uploadBlobContentEncoding :: Maybe String
, uploadBlobContentLanguage :: Maybe String
, uploadBlobContentCache :: Maybe String
}
| DeleteBlob { deleteBlobStorageName :: String
, deleteBlobContainerName :: String
, deleteBlobBlobName :: String
}
| DownloadBlob { downloadBlobStorageName :: String
, downloadBlobContainerName :: String
, downloadBlobBlobName :: String
}
| CreateContainer { createContainerStorageName :: String
, createContainerContainerName :: String
, createContainerACL :: Maybe String
}
| DeleteContainer { deleteContainerStorageName :: String
, deleteContainerContainerName :: String
, deleteContainerForce :: Maybe Bool
}
| ListContainer { listContainerStorageName :: String
, listContainerContainerName :: String
}
| BreakBlobLease { breakLeaseStorageName :: String
, breakLeaseContainerName :: String
, breakLeaseBlobName :: String
}
deriving (Show, Data, Typeable, Eq)
uploadBlob = UploadBlob { uploadBlobPath = def &= typ "file" &= argPos 0
, uploadBlobStorageName = def &= typ "accountname" &= argPos 1
, uploadBlobContainerName = def &= typ "containername" &= argPos 2
, uploadBlobFileName = def &= typ "blobname" &= argPos 3
, uploadBlobContentType = def &= name "contenttype"
, uploadBlobContentEncoding = def &= name "contentencoding"
, uploadBlobContentLanguage = def &= name "contentlanguage"
, uploadBlobContentCache = def &= name "cachecontrol"
} &= help "Upload a blob"
downloadBlob = DownloadBlob { downloadBlobStorageName = def &= typ "accountname" &= argPos 0
, downloadBlobContainerName = def &= typ "containername" &= argPos 1
, downloadBlobBlobName = def &= typ "blobname" &= argPos 2
} &= help "Download a blob"
deleteBlob = DeleteBlob { deleteBlobStorageName = def &= typ "accountname" &= argPos 0
, deleteBlobContainerName = def &= typ "containername" &= argPos 1
, deleteBlobBlobName = def &= typ "blobname" &= argPos 2
} &= help "Delete a blob"
breakBlobLease = BreakBlobLease { breakLeaseStorageName = def &= typ "accountname" &= argPos 0
, breakLeaseContainerName = def &= typ "containername" &= argPos 1
, breakLeaseBlobName = def &= typ "blobname" &= argPos 2
}
listContainer = ListContainer { listContainerStorageName = def &= typ "accountname" &= argPos 0
, listContainerContainerName = def &= typ "containername" &= argPos 1
} &= help "List all blobs in a container"
createContainer = CreateContainer { createContainerStorageName = def &= typ "accountname" &= argPos 0
, createContainerContainerName = def &= typ "containername" &= argPos 1
, createContainerACL = def &= typ "blobpublic|containerpublic|private" &= argPos 2
} &= help "Create a container with the specified access control"
deleteContainer = DeleteContainer { deleteContainerStorageName = def &= typ "accountname" &= argPos 0
, deleteContainerContainerName = def &= typ "containername" &= argPos 1
, deleteContainerForce = def &= name "force"
} &= help "Delete the container and all the blobs inside it"
mode = cmdArgsMode $ modes [uploadBlob, downloadBlob, deleteBlob, breakBlobLease, listContainer, createContainer, deleteContainer] &= help "Access the Azure blob storage" &= program "azurify" &= summary "Azurify v1.0"
main :: IO ()
main = do
m <- cmdArgsRun mode
putStrLn "Please enter your authkey:"
azureKey <- B.getLine
case m of
UploadBlob path account container name contType contEnc contLang contCache -> do
contents <- B.readFile path
res <- Az.createBlob (B8.pack account)
azureKey (B8.pack container)
(Az.BlobSettings (B8.pack name)
(B8.pack `fmap` contType)
(B8.pack `fmap` contEnc)
(B8.pack `fmap` contLang)
Nothing
(B8.pack `fmap` contCache)
Az.BlockBlob
Nothing
(Just contents)
)
case res of
Just (stat, err) -> putStrLn "error" >> print stat >> putStrLn "\n" >> print err
Nothing -> return ()
DownloadBlob account container blobname -> do -- TODO: progress indicator
pwd <- getCurrentDirectory
res <- Az.getBlob (B8.pack account) azureKey (B8.pack container) (B8.pack blobname)
let path = pwd ++ "/" ++ blobname
putStrLn path
case res of
Left (stat, err) -> putStrLn "error" >> print stat >> putStrLn "\n" >> print err
Right content -> L.writeFile path content
DeleteBlob account container blobname -> do
res <- Az.deleteBlob (B8.pack account) azureKey (B8.pack container) (B8.pack blobname)
case res of
Just (stat, err) -> putStrLn "error" >> print stat >> putStrLn "\n" >> print err
_ -> return ()
BreakBlobLease account container blobname -> do
res <- Az.breakLease (B8.pack account) azureKey (B8.pack container) (B8.pack blobname)
case res of
Just (stat, err) -> putStrLn "error" >> print stat >> putStrLn "\n" >> print err
_ -> return ()
ListContainer account container -> do -- TODO: output formatting
res <- Az.listContainer (B8.pack account) azureKey (B8.pack container)
case res of
Left (stat, err) -> putStrLn "error" >> print stat >> putStrLn "\n" >> print err
Right blobs -> mapM_ print blobs
CreateContainer account container access -> do
let acl = case access of {
Just "blobpublic" -> Az.BlobPublic;
Just "containerpublic" -> Az.ContainerPublic;
Just "private" -> Az.Private;
Nothing -> Az.Private;
_ -> error "invalid access control specified";
}
res <- Az.createContainer (B8.pack account) azureKey (B8.pack container) acl
case res of
Just (stat, err) -> putStrLn "error" >> print stat >> putStrLn "\n" >> print err
Nothing -> return ()
DeleteContainer account container force -> do
if force == (Just True) then do
res <- Az.listContainer (B8.pack account) azureKey (B8.pack container)
case res of
Left (stat, err) -> putStrLn "error listing container" >> print stat >> putStrLn "\n" >> print err
Right (x:_) -> error "Container not empty, use --force to ignore"
else do
res <- Az.deleteContainer (B8.pack account) azureKey (B8.pack container)
case res of
Just (stat, err) -> putStrLn "error" >> print stat >> putStrLn "\n" >> print err
Nothing -> return ()