From 95815b3edd6437891e0a20f56520cf213b213711 Mon Sep 17 00:00:00 2001 From: Aditya Manthramurthy Date: Thu, 2 Mar 2017 15:45:15 +0530 Subject: [PATCH] Clean up ConnectInfo smart constructors + doc sections: (#21) * Introduce ConnectInfo and its smart constructors * Introduce the Minio monad and provide a simple example --- docs/API.md | 139 ++++++++++++++++++++++++++++++-------- src/Network/Minio.hs | 8 +-- src/Network/Minio/Data.hs | 82 +++++++++++----------- 3 files changed, 158 insertions(+), 71 deletions(-) diff --git a/docs/API.md b/docs/API.md index a5b1908..69ea1c5 100644 --- a/docs/API.md +++ b/docs/API.md @@ -2,11 +2,7 @@ ## Initialize Minio Client object. -This SDK provides helpers to connect to play.minio.io (the public -Minio Play server), the AWS S3 service, and to a locally hosted Minio -server. - -For Play, use +### Minio - for public Play server ```haskell minioPlayCI :: ConnectInfo @@ -14,7 +10,7 @@ minioPlayCI ``` -For AWS S3, use +### AWS S3 ```haskell awsCI :: ConnectInfo @@ -24,26 +20,6 @@ awsCI { connectAccesskey = "your-access-key" ``` -For a local Minio server instance running at `localhost:9000` with -"minio" and "minio123" as access key and secret key respectively, use - -``` haskell -def :: ConnectInfo -def -``` - -For a minio server instance deployed with custom configuration, use - -``` haskell -def :: ConnectInfo -def { connectHost = "host" - , connectPort = 5000 - , connectAccessKey = "access-key" - , connectSecretKey = "secret-key" - , connectIsSecure = False - } -``` - |Bucket operations|Object Operations| |:---|:---| |[`listBuckets`](#listBuckets) |[`getObject`](#getObject)| @@ -53,9 +29,116 @@ def { connectHost = "host" |[`listIncompleteUploads`](#listIncompleteUploads)|[`copyObject`](#copyObject)| ||[`removeObject`](#removeObject)| -## 1. ConnectInfo smart constructors +## 1. Connecting and running operations on the storage service - +The Haskell Minio SDK provides high-level functionality to perform +operations on a Minio server or any AWS S3-like API compatible storage +service. + +### The `ConnectInfo` type + +The `ConnectInfo` record-type contains connection information for a +particular server. It is recommended to construct the `ConnectInfo` +value using one of the several smart constructors provided by the +library, documented in the following subsections. + +The library automatically discovers the region of a bucket by +default. This is especially useful with AWS, where buckets may be in +different regions. When performing an upload, download or other +operation, the library requests the service for the location of a +bucket and caches it for subsequent requests. + +#### awsCI :: ConnectInfo + +`awsCI` is a value that provides connection information for AWS +S3. Credentials can be supplied by overriding a couple of fields like +so: + +``` haskell +awsConn = awsCI { + connectAccessKey = "my-AWS-access-key" + , connectSecretKey = "my-AWS-secret-key" + } +``` + +#### awsWithRegionCI :: Region -> Bool -> ConnectInfo + +This constructor allows to specify the initial region and a Boolean to +enable/disable the automatic region discovery behaviour. + +The parameters in the expression `awsWithRegion region autoDiscover` are: + +|Parameter|Type|Description| +|:---|:---|:---| +| `region` | _Region_ (alias for `Text`) | The region to connect to by default for all requests. | +| `autoDiscover` | _Bool_ | If `True`, region discovery will be enabled. If `False`, discovery is disabled, and all requests go the given region only.| + +#### minioPlayCI :: ConnectInfo + +This constructor provides connection and authentication information to +connect to the public Minio Play server at +`https://play.minio.io:9000/`. + +#### minioCI :: Text -> Int -> Bool -> ConnectInfo + +Use to connect to a Minio server. + +The parameters in the expression `minioCI host port isSecure` are: + +|Parameter|Type|Description| +|:---|:---|:---| +| `host` | _Text_ | Hostname of the Minio or other S3-API compatible server | +| `port` | _Int_ | Port number to connect to| +| `isSecure` | _Bool_ | Does the server use HTTPS? | + +#### The ConnectInfo fields and Default instance + +The following table shows the fields in the `ConnectInfo` record-type: + +| Field | Type | Description | +|:---|:---|:---| +| `connectHost` | _Text_ | Host name of the server. Defaults to `localhost`. | +| `connectPort` | _Int_ | Port number on which the server listens. Defaults to `9000`. | +| `connectAccessKey` | _Text_ | Access key to use in authentication. Defaults to `minio`. | +| `connectSecretkey` | _Text_ | Secret key to use in authentication. Defaults to `minio123`. | +| `connectIsSecure` | _Bool_ | Specifies if the server used TLS. Defaults to `False` | +| `connectRegion` | _Region_ (alias for `Text`) | Specifies the region to use. Defaults to 'us-east-1' | +| `connectAutoDiscoverRegion` | _Bool_ | Specifies if the library should automatically discover the region of a bucket. Defaults to `True`| + +The `def` value of type `ConnectInfo` has all the above default +values. + +### The Minio Monad + +This monad provides the required environment to perform requests +against a Minio or other S3 API compatible server. It uses the +connection information from the `ConnectInfo` value provided to it. It +performs connection pooling, bucket location caching (if enabled) and +error handling. + +The `runMinio` function performs the provided action in the `Minio` +monad and returns a `ResourceT IO (Either MinioErr a)` value: + +``` haskell +import Network.Minio + +main :: IO () +main = do + result <- runResourceT $ runMinio def $ do + buckets <- listBuckets + return $ length buckets + + case result of + Left e -> putStrLn $ "Failed operation with error: " ++ show e + Right n -> putStrLn $ show n ++ " bucket(s) found." +``` + +The above performs a `listBuckets` operation and returns the number of +buckets in the server. If there were any errors, they will be returned +as values of type `MinioErr` as a `Left` value. + +`runResourceT` takes a value from `ResourceT IO a` to `IO a`. It takes +care of running finalizers to free resources. ## 2. Bucket operations diff --git a/src/Network/Minio.hs b/src/Network/Minio.hs index fa76067..90c361c 100644 --- a/src/Network/Minio.hs +++ b/src/Network/Minio.hs @@ -3,15 +3,14 @@ module Network.Minio ConnectInfo(..) , awsCI - , awsWithRegion + , awsWithRegionCI , minioPlayCI - , minioSimple - , minioSimpleTLS - , minioWithOpts + , minioCI , Minio , runMinio , runResourceT + , def -- * Error handling ----------------------- @@ -62,6 +61,7 @@ This module exports the high-level Minio API for object storage. import Control.Monad.Trans.Resource (runResourceT) import qualified Data.Conduit as C import qualified Data.Conduit.Binary as CB +import Data.Default (def) import qualified Data.Map as Map import Lib.Prelude diff --git a/src/Network/Minio/Data.hs b/src/Network/Minio/Data.hs index b4cb8c6..8b23a7a 100644 --- a/src/Network/Minio/Data.hs +++ b/src/Network/Minio/Data.hs @@ -43,8 +43,9 @@ awsRegionMap = Map.fromList [ , ("sa-east-1", "s3-sa-east-1.amazonaws.com") ] --- | Connection Info data type. Use the Default instance to create --- connection info for your service. +-- | Connection Info data type. To create a 'ConnectInfo' value, use one +-- of the provided smart constructors or override fields of the +-- Default instance. data ConnectInfo = ConnectInfo { connectHost :: Text , connectPort :: Int @@ -55,11 +56,19 @@ data ConnectInfo = ConnectInfo { , connectAutoDiscoverRegion :: Bool } deriving (Eq, Show) +-- | Connects to a Minio server located at @localhost:9000@ with access +-- key /minio/ and secret key /minio123/. It is over __HTTP__ by +-- default. instance Default ConnectInfo where def = ConnectInfo "localhost" 9000 "minio" "minio123" False "us-east-1" True --- | --- Default aws ConnectInfo. Credentials should be supplied before use. +-- | Default AWS ConnectInfo. Connects to "us-east-1". Credentials +-- should be supplied before use, for e.g.: +-- +-- > awsCI { +-- > connectAccessKey = "my-access-key" +-- > , connectSecretKey = "my-secret-key" +-- > } awsCI :: ConnectInfo awsCI = def { connectHost = "s3.amazonaws.com" @@ -69,12 +78,19 @@ awsCI = def { , connectIsSecure = True } --- | --- aws ConnectInfo with the specified region. --- This is for users who don't want minio-hs discovering region of a --- bucket if not known. -awsWithRegion :: Region -> Bool -> ConnectInfo -awsWithRegion region autoDiscoverRegion = +-- | AWS ConnectInfo with a specified region. It can optionally +-- disable the automatic discovery of a bucket's region via the +-- Boolean argument. +-- +-- > awsWithRegionCI "us-west-1" False { +-- > connectAccessKey = "my-access-key" +-- > , connectSecretKey = "my-secret-key" +-- > } +-- +-- This restricts all operations to the "us-west-1" region and does +-- not perform any bucket location requests. +awsWithRegionCI :: Region -> Bool -> ConnectInfo +awsWithRegionCI region autoDiscoverRegion = let host = maybe "s3.amazonaws.com" identity $ Map.lookup region awsRegionMap in awsCI { @@ -84,8 +100,8 @@ awsWithRegion region autoDiscoverRegion = } --- | --- Default minio play server ConnectInfo. Credentials are already filled. +-- | +-- ConnectInfo. Credentials are already filled in. minioPlayCI :: ConnectInfo minioPlayCI = def { connectHost = "play.minio.io" @@ -93,38 +109,26 @@ minioPlayCI = def { , connectAccessKey = "Q3AM3UQ867SPQQA43P2F" , connectSecretKey = "zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG" , connectIsSecure = True + , connectAutoDiscoverRegion = False } --- | --- ConnectInfo for minio server over HTTP. -minioSimple :: Text -> Int -> ConnectInfo -minioSimple host port = def { +-- | ConnectInfo for Minio server. Takes hostname, port and a Boolean +-- to enable TLS. +-- +-- > minioCI "minio.example.com" 9000 True { +-- > connectAccessKey = "my-access-key" +-- > , connectSecretKey = "my-secret-key" +-- > } +-- +-- This connects to a Minio server at the given hostname and port over +-- HTTPS. +minioCI :: Text -> Int -> Bool -> ConnectInfo +minioCI host port isSecure = def { connectHost = host , connectPort = port , connectRegion = "us-east-1" - , connectIsSecure = False - } - --- | --- ConnectInfo for minio server over HTTPS. -minioSimpleTLS :: Text -> Int -> ConnectInfo -minioSimpleTLS host port = mSimple { - connectIsSecure = True - } - where - mSimple = minioSimple host port - --- | --- ConnectInfo for minio server with no defaults. --- This is for users who don't want minio-hs discovering region of a --- bucket if not known. -minioWithOpts :: Text -> Int -> Region -> Bool -> Bool -> ConnectInfo -minioWithOpts host port region secure autoDiscoverRegion = def { - connectHost = host - , connectPort = port - , connectRegion = region - , connectIsSecure = secure - , connectAutoDiscoverRegion = autoDiscoverRegion + , connectIsSecure = isSecure + , connectAutoDiscoverRegion = False } -- |