defmodule GCloudex.CloudStorage.Impl do @moduledoc """ Wrapper for Google Cloud Storage API. """ defmacro __using__(:cloud_storage) do quote do use GCloudex.CloudStorage.Request @endpoint "storage.googleapis.com" @project GCloudex.get_project_id ################### ### GET Service ### ################### @doc""" Lists all the buckets in the specified project. """ @spec list_buckets() :: HTTPResponse.t def list_buckets do request_service end ##################### ### DELETE Bucket ### ##################### @doc""" Deletes and empty bucket. """ @spec delete_bucket(bucket :: binary) :: HTTPResponse.t def delete_bucket(bucket) do request :delete, bucket, [], "" end ################## ### GET Bucket ### ################## @doc""" Lists all the objects in the specified 'bucket'. """ @spec list_objects(bucket :: binary) :: HTTPResponse.t def list_objects(bucket) do request :get, bucket, [], "" end @doc""" Lists all the objects in the specified 'bucket' using the given 'query_params'. The query parameters must be passed as a list of tuples [{param_1, value_1}, {param_2, value_2}]. """ @spec list_objects(bucket :: binary, query_params :: [{binary, binary}]) :: HTTPResponse.t def list_objects(bucket, query_params) do request_query :get, bucket, [], "", "?" <> parse_query_params(query_params, "") end @doc""" Lists the specified 'bucket' ACL. """ @spec get_bucket_acl(bucket :: binary) :: HTTPResponse.t def get_bucket_acl(bucket) do request_query :get, bucket, [], "", "?acl" end @doc""" Lists the specified 'bucket' CORS configuration. """ @spec get_bucket_cors(bucket :: binary) :: HTTPResponse.t def get_bucket_cors(bucket) do request_query :get, bucket, [], "", "?cors" end @doc""" Lists the specified 'bucket' lifecycle configuration. """ @spec get_bucket_lifecycle(bucket :: binary) :: HTTPResponse.t def get_bucket_lifecycle(bucket) do request_query :get, bucket, [], "", "?lifecycle" end @doc""" Lists the specified 'bucket' location. """ @spec get_bucket_region(bucket :: binary) :: HTTPResponse.t def get_bucket_region(bucket) do request_query :get, bucket, [], "", "?location" end @doc""" Lists the specified 'bucket' logging configuration. """ @spec get_bucket_logging(bucket :: binary) :: HTTPResponse.t def get_bucket_logging(bucket) do request_query :get, bucket, [], "", "?logging" end @doc""" Lists the specified 'bucket' class. """ @spec get_bucket_class(bucket :: binary) :: HTTPResponse.t def get_bucket_class(bucket) do request_query :get, bucket, [], "", "?storageClass" end @doc""" Lists the specified 'bucket' versioning configuration. """ @spec get_bucket_versioning(bucket :: binary) :: HTTPResponse.t def get_bucket_versioning(bucket) do request_query :get, bucket, [], "", "?versioning" end @doc""" Lists the specified 'bucket' website configuration. """ @spec get_bucket_website(bucket :: binary) :: HTTPResponse.t def get_bucket_website(bucket) do request_query :get, bucket, [], "", "?website" end ################### ### HEAD Bucket ### ################### @doc""" Indicates if the specified 'bucket' exists or whether the request has READ access to it. """ @spec exists_bucket(bucket :: binary) :: HTTPResponse.t def exists_bucket(bucket) do request :head, bucket, [], "" end ################## ### PUT Bucket ### ################## @doc""" Creates a bucket with the specified 'bucket' name if available. This function will create the bucket in the default region 'US' and with the default class 'STANDARD'. """ @spec create_bucket(bucket :: binary) :: HTTPResponse.t def create_bucket(bucket) do headers = [{"x-goog-project-id", @project}] request :put, bucket, headers, "" end @doc""" Creates a bucket with the specified 'bucket' name if available and in the specified 'region'. This function will create the bucket with the default class 'STANDARD'. """ @spec create_bucket(bucket :: binary, region :: binary) :: HTTPResponse.t def create_bucket(bucket, region) do headers = [{"x-goog-project-id", @project}] body = """ #{region} """ request :put, bucket, headers, body end @doc""" Creates a bucket with the specified 'bucket' name if available and in the specified 'region' and with the specified 'class'. """ @spec create_bucket(bucket :: binary, region :: binary, class :: binary) :: HTTPResponse.t def create_bucket(bucket, region, class) do headers = [{"x-goog-project-id", @project}] body = """ #{region} #{class} """ request :put, bucket, headers, body end @doc""" Sets or modifies the existing ACL in the specified 'bucket' with the given 'acl_config' in XML format. """ @spec set_bucket_acl(bucket :: binary, acl_config :: binary) :: HTTPResponse.t def set_bucket_acl(bucket, acl_config) do request_query :put, bucket, [], acl_config, "?acl" end @doc""" Sets or modifies the existing CORS configuration in the specified 'bucket' with the given 'cors_config' in XML format. """ @spec set_bucket_cors(bucket :: binary, cors_config :: binary) :: HTTPResponse.t def set_bucket_cors(bucket, cors_config) do request_query :put, bucket, [], cors_config, "?cors" end @doc""" Sets or modifies the existing lifecyle configuration in the specified 'bucket' with the given 'lifecycle_config' in XML format. """ @spec set_bucket_lifecycle(bucket :: binary, lifecycle_config :: binary) :: HTTPResponse.t def set_bucket_lifecycle(bucket, lifecycle_config) do request_query :put, bucket, [], lifecycle_config, "?lifecycle" end @doc""" Sets or modifies the existing logging configuration in the specified 'bucket' with the given 'logging_config' in XML format. """ @spec set_bucket_logging(bucket :: binary, logging_config :: binary) :: HTTPResponse.t def set_bucket_logging(bucket, logging_config) do request_query :put, bucket, [], logging_config, "?logging" end @doc""" Sets or modifies the existing versioning configuration in the specified 'bucket' with the given 'versioning_config' in XML format. """ @spec set_bucket_versioning(bucket :: binary, versioning_config :: binary) :: HTTPResponse.t def set_bucket_versioning(bucket, versioning_config) do request_query :put, bucket, [], versioning_config, "?versioning" end @doc""" Sets or modifies the existing website configuration in the specified 'bucket' with the given 'website_config' in XML format. """ @spec set_bucket_website(bucket :: binary, website_config :: binary) :: HTTPResponse.t def set_bucket_website(bucket, website_config) do request_query :put, bucket, [], website_config, "?websiteConfig" end ##################### ### DELETE Object ### ##################### @doc""" Deletes the 'object' in the specified 'bucket'. """ @spec delete_object(bucket :: binary, object :: binary) :: HTTPResponse.t def delete_object(bucket, object) do request_query :delete, bucket, [], "", object end @doc""" Deletes the 'object' in the specified 'bucket' using the given 'query_params'. The query parameters must be passed as a list of tuples [{param_1, value_1}, {param_2, value_2}]. """ @spec delete_object(bucket :: binary, object :: binary, query_params :: [{binary, binary}]) :: HTTPResponse.t def delete_object(bucket, object, query_params) do request_query :delete, bucket, [], "", object <> "?" <> parse_query_params(query_params, "") end ################## ### GET Object ### ################## @doc""" Downloads the 'object' from the specified 'bucket'. The requester must have READ permission. """ @spec get_object(bucket :: binary, object :: binary) :: HTTPResponse.t def get_object(bucket, object) do request_query :get, bucket, [], "", object end @doc""" Downloads the 'object' from the specified 'bucket' using the given 'query_params'. The query parameters must be passed as a list of tuples [{param_1, value_1}, {param_2, value_2}]. The requester must have READ permission. """ @spec get_object(bucket :: binary, object :: binary, query_params :: [{binary, binary}]) :: HTTPResponse.t def get_object(bucket, object, query_params) do request_query :get, bucket, [], "", object <> "?" <> parse_query_params(query_params, "") end @doc""" Lists the 'object' ACL from the specified 'bucket'. The requester must have FULL_CONTROL permission. """ @spec get_object_acl(bucket :: binary, object :: binary) :: HTTPResponse.t def get_object_acl(bucket, object) do request_query :get, bucket, [], "", object <> "?acl" end ################### ### HEAD Object ### ################### @doc""" Lists metadata for the given 'object' from the specified 'bucket'. """ @spec get_object_metadata(bucket :: binary, object :: binary) :: HTTPResponse.t def get_object_metadata(bucket, object) do request_query :head, bucket, [], "", object end @doc""" Lists metadata for the given 'object' from the specified 'bucket' using the given 'query_params'. The query parameters must be passed as a list of tuples [{param_1, value_1}, {param_2, value_2}]. """ @spec get_object_metadata(bucket :: binary, object :: binary, [{binary, binary}]) :: HTTPResponse.t def get_object_metadata(bucket, object, query_params) do request_query :head, bucket, [], "", object <> "?" <> parse_query_params(query_params, "") end ################## ### PUT Object ### ################## @doc""" Uploads the file in the given 'filepath' to the specified 'bucket'. If a 'bucket_path' is specified then the filename must be included at the end: put_object "somebucket", "/home/user/Documents/this_file", "new_folder/some_other_folder/this_file" => # This will upload the file to the directory in 'bucket_path' and will create the directories if they do not exist. """ @spec put_object(bucket :: binary, filepath :: binary, bucket_path :: binary) :: HTTPResponse.t def put_object(bucket, filepath, bucket_path \\ :empty) do body = {:file, filepath} case bucket_path do :empty -> request_query :put, bucket, [], body, filepath _ -> request_query :put, bucket, [], body, bucket_path end end @doc""" Copies the specified 'source_object' into the given 'new_bucket' as 'new_object'. """ @spec copy_object(new_bucket :: binary, new_object :: binary, source_object :: binary) :: HTTPResponse.t def copy_object(new_bucket, new_object, source_object) do headers = [{"x-goog-copy-source", source_object}] request_query :put, new_bucket, headers, new_object end @doc""" Sets or modifies the 'object' from the specified 'bucket' with the provided 'acl_config' in XML format. """ @spec set_object_acl(bucket :: binary, object :: binary, acl_config :: binary) :: HTTPResponse.t def set_object_acl(bucket, object, acl_config) do request_query :put, bucket, [], acl_config, object <> "?acl" end @doc""" Sets or modifies the 'object' from the specified 'bucket' with the provided 'acl_config' in XML format and using the given 'query_params'. The query parameters must be passed as a list of tuples [{param_1, value_1}, {param_2, value_2}]. """ @spec set_object_acl(bucket :: binary, object :: binary, acl_config :: binary, [{binary, binary}]) :: HTTPResponse.t def set_object_acl(bucket, object, acl_config, query_params) do request_query :put, bucket, [], acl_config, object <> "?acl" <> "&" <> parse_query_params(query_params, "") end ######################## ### HELPER FUNCTIONS ### ######################## defp parse_query_params([], query), do: query <> "" defp parse_query_params([{param, val} = _head | []], query), do: query <> param <> "=" <> val defp parse_query_params([{param, val} = _head | tail], query) do parse_query_params tail, query <> param <> "=" <> val <> "&" end end end end