Skip to content

Commit

Permalink
add {enable,disable,is}_object_legal_hold[_enabled] APIs
Browse files Browse the repository at this point in the history
  • Loading branch information
balamurugana committed Oct 19, 2020
1 parent 1009b2c commit 71fe622
Show file tree
Hide file tree
Showing 8 changed files with 330 additions and 16 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

check:
@pip install --user --upgrade pylint
@if python --version | grep -qi 'python 3'; then pylint --reports=no --score=no --disable=R0401 minio/*py; fi
@if python --version | grep -qi 'python 3'; then pylint --reports=no --score=no --disable=R0401,R0801 minio/*py; fi
@if python --version | grep -qi 'python 3'; then pylint --reports=no --score=no minio/credentials minio/select tests/functional; fi

@isort --diff --recursive .
Expand Down
90 changes: 75 additions & 15 deletions docs/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,21 +30,21 @@ s3Client = Minio(
)
```

| Bucket operations | Object operations | Presigned operations | Bucket policy/notification/encryption operations |
|:----------------------------------------------------------|:--------------------------------------------------|:--------------------------------------------------|:--------------------------------------------------------------------|
| [`make_bucket`](#make_bucket) | [`get_object`](#get_object) | [`presigned_get_object`](#presigned_get_object) | [`get_bucket_policy`](#get_bucket_policy) |
| [`list_buckets`](#list_buckets) | [`put_object`](#put_object) | [`presigned_put_object`](#presigned_put_object) | [`set_bucket_policy`](#set_bucket_policy) |
| [`bucket_exists`](#bucket_exists) | [`copy_object`](#copy_object) | [`presigned_post_policy`](#presigned_post_policy) | [`delete_bucket_policy`](#delete_bucket_policy) |
| [`remove_bucket`](#remove_bucket) | [`stat_object`](#stat_object) | | [`get_bucket_notification`](#get_bucket_notification) |
| [`list_objects`](#list_objects) | [`remove_object`](#remove_object) | | [`set_bucket_notification`](#set_bucket_notification) |
| [`get_bucket_versioning`](#get_bucket_versioning) | [`remove_objects`](#remove_objects) | | [`remove_all_bucket_notification`](#remove_all_bucket_notification) |
| [`set_bucket_versioning`](#set_bucket_versioning) | [`fput_object`](#fput_object) | | [`listen_bucket_notification`](#listen_bucket_notification) |
| [`delete_bucket_replication`](#delete_bucket_replication) | [`fget_object`](#fget_object) | | [`get_bucket_encryption`](#get_bucket_encryption) |
| [`get_bucket_replication`](#get_bucket_replication) | [`select_object_content`](#select_object_content) | | [`remove_all_bucket_notification`](#remove_all_bucket_notification) |
| [`set_bucket_replication`](#set_bucket_replication) | | | [`put_bucket_encryption`](#put_bucket_encryption) |
| [`delete_bucket_lifecycle`](#delete_bucket_lifecycle) | | | [`delete_bucket_encryption`](#delete_bucket_encryption) |
| [`get_bucket_lifecycle`](#get_bucket_lifecycle) | | | |
| [`set_bucket_lifecycle`](#set_bucket_lifecycle) | | | |
| Bucket operations | Object operations | Presigned operations | Bucket policy/notification/encryption operations |
|:----------------------------------------------------------|:----------------------------------------------------------------|:--------------------------------------------------|:--------------------------------------------------------------------|
| [`make_bucket`](#make_bucket) | [`get_object`](#get_object) | [`presigned_get_object`](#presigned_get_object) | [`get_bucket_policy`](#get_bucket_policy) |
| [`list_buckets`](#list_buckets) | [`put_object`](#put_object) | [`presigned_put_object`](#presigned_put_object) | [`set_bucket_policy`](#set_bucket_policy) |
| [`bucket_exists`](#bucket_exists) | [`copy_object`](#copy_object) | [`presigned_post_policy`](#presigned_post_policy) | [`delete_bucket_policy`](#delete_bucket_policy) |
| [`remove_bucket`](#remove_bucket) | [`stat_object`](#stat_object) | | [`get_bucket_notification`](#get_bucket_notification) |
| [`list_objects`](#list_objects) | [`remove_object`](#remove_object) | | [`set_bucket_notification`](#set_bucket_notification) |
| [`get_bucket_versioning`](#get_bucket_versioning) | [`remove_objects`](#remove_objects) | | [`remove_all_bucket_notification`](#remove_all_bucket_notification) |
| [`set_bucket_versioning`](#set_bucket_versioning) | [`fput_object`](#fput_object) | | [`listen_bucket_notification`](#listen_bucket_notification) |
| [`delete_bucket_replication`](#delete_bucket_replication) | [`fget_object`](#fget_object) | | [`get_bucket_encryption`](#get_bucket_encryption) |
| [`get_bucket_replication`](#get_bucket_replication) | [`select_object_content`](#select_object_content) | | [`remove_all_bucket_notification`](#remove_all_bucket_notification) |
| [`set_bucket_replication`](#set_bucket_replication) | [`enable_object_legal_hold`](#enable_object_legal_hold) | | [`put_bucket_encryption`](#put_bucket_encryption) |
| [`delete_bucket_lifecycle`](#delete_bucket_lifecycle) | [`disable_object_legal_hold`](#disable_object_legal_hold) | | [`delete_bucket_encryption`](#delete_bucket_encryption) |
| [`get_bucket_lifecycle`](#get_bucket_lifecycle) | [`is_object_legal_hold_enabled`](#is_object_legal_hold_enabled) | | |
| [`set_bucket_lifecycle`](#set_bucket_lifecycle) | | | |

## 1. Constructor

Expand Down Expand Up @@ -1112,6 +1112,66 @@ minio.remove_objects(
)
```

<a name="enable_object_legal_hold"></a>

### enable_object_legal_hold(bucket_name, object_name, version_id=None)

Enable legal hold on an object.

__Parameters__

| Param | Type | Description |
|:--------------|:------|:---------------------------|
| `bucket_name` | _str_ | Name of the bucket. |
| `object_name` | _str_ | Object name in the bucket. |
| `version_id` | _str_ | Version ID of the object. |

__Example__

```py
minio.enable_object_legal_hold("my-bucketname", "my-objectname")
```

<a name="disable_object_legal_hold"></a>

### disable_object_legal_hold(bucket_name, object_name, version_id=None)

Disable legal hold on an object.

__Parameters__

| Param | Type | Description |
|:--------------|:------|:---------------------------|
| `bucket_name` | _str_ | Name of the bucket. |
| `object_name` | _str_ | Object name in the bucket. |
| `version_id` | _str_ | Version ID of the object. |

__Example__

```py
minio.disable_object_legal_hold("my-bucketname", "my-objectname")
```

<a name="is_object_legal_hold_enabled"></a>

### is_object_legal_hold_enabled(bucket_name, object_name, version_id=None)

Returns true if legal hold is enabled on an object.

__Parameters__

| Param | Type | Description |
|:--------------|:------|:---------------------------|
| `bucket_name` | _str_ | Name of the bucket. |
| `object_name` | _str_ | Object name in the bucket. |
| `version_id` | _str_ | Version ID of the object. |

__Example__

```py
minio.is_object_legal_hold_enabled("my-bucketname", "my-objectname")
```

## 4. Presigned operations

<a name="presigned_get_object"></a>
Expand Down
28 changes: 28 additions & 0 deletions examples/disable_object_legal_hold.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# -*- coding: utf-8 -*-
# MinIO Python Library for Amazon S3 Compatible Cloud Storage.
# Copyright (C) 2020 MinIO, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# Note: YOUR-ACCESSKEYID, YOUR-SECRETACCESSKEY and my-bucketname are
# dummy values, please replace them with original values.

from minio import Minio

client = Minio(
"play.min.io",
access_key="Q3AM3UQ867SPQQA43P2F",
secret_key="zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG",
)

client.disable_object_legal_hold("my-bucketname", "my-objectname")
28 changes: 28 additions & 0 deletions examples/enable_object_legal_hold.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# -*- coding: utf-8 -*-
# MinIO Python Library for Amazon S3 Compatible Cloud Storage.
# Copyright (C) 2020 MinIO, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# Note: YOUR-ACCESSKEYID, YOUR-SECRETACCESSKEY and my-bucketname are
# dummy values, please replace them with original values.

from minio import Minio

client = Minio(
"play.min.io",
access_key="Q3AM3UQ867SPQQA43P2F",
secret_key="zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG",
)

client.enable_object_legal_hold("my-bucketname", "my-objectname")
28 changes: 28 additions & 0 deletions examples/is_object_legal_hold_enabled.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# -*- coding: utf-8 -*-
# MinIO Python Library for Amazon S3 Compatible Cloud Storage.
# Copyright (C) 2020 MinIO, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# Note: YOUR-ACCESSKEYID, YOUR-SECRETACCESSKEY and my-bucketname are
# dummy values, please replace them with original values.

from minio import Minio

client = Minio(
"play.min.io",
access_key="Q3AM3UQ867SPQQA43P2F",
secret_key="zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG",
)

status = client.is_object_legal_hold_enabled("my-bucketname", "my-objectname")
88 changes: 88 additions & 0 deletions minio/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
is_supported_header, is_valid_notification_config,
is_valid_policy_type, makedirs, md5sum_hash, quote,
read_part_data, sha256_hash, strptime_rfc3339)
from .legalhold import LegalHold
from .lifecycleconfig import LifecycleConfig
from .parsers import (parse_error_response, parse_get_bucket_notification,
parse_list_buckets, parse_list_multipart_uploads,
Expand Down Expand Up @@ -1924,6 +1925,93 @@ def set_bucket_lifecycle(self, bucket_name, config):
query_params={"lifecycle": ""},
)

def enable_object_legal_hold(
self, bucket_name, object_name, version_id=None,
):
"""
Enable legal hold on an object.
:param bucket_name: Name of the bucket.
:param object_name: Object name in the bucket.
:param version_id: Version ID of the object.
Example::
minio.enable_object_legal_hold("my-bucketname", "my-objectname")
"""
check_bucket_name(bucket_name)
check_non_empty_string(object_name)
body = marshal(LegalHold(True))
query_params = {"versionId", version_id} if version_id else {}
query_params["legal-hold"] = ""
self._execute(
"PUT",
bucket_name,
object_name=object_name,
body=body,
headers={"Content-MD5": md5sum_hash(body)},
query_params=query_params,
)

def disable_object_legal_hold(
self, bucket_name, object_name, version_id=None,
):
"""
Disable legal hold on an object.
:param bucket_name: Name of the bucket.
:param object_name: Object name in the bucket.
:param version_id: Version ID of the object.
Example::
minio.disable_object_legal_hold("my-bucketname", "my-objectname")
"""
check_bucket_name(bucket_name)
check_non_empty_string(object_name)
body = marshal(LegalHold(False))
query_params = {"versionId", version_id} if version_id else {}
query_params["legal-hold"] = ""
self._execute(
"PUT",
bucket_name,
object_name=object_name,
body=body,
headers={"Content-MD5": md5sum_hash(body)},
query_params=query_params,
)

def is_object_legal_hold_enabled(
self, bucket_name, object_name, version_id=None,
):
"""
Returns true if legal hold is enabled on an object.
:param bucket_name: Name of the bucket.
:param object_name: Object name in the bucket.
:param version_id: Version ID of the object.
Example::
status = minio.is_object_legal_hold_enabled(
"my-bucketname", "my-objectname",
)
"""
check_bucket_name(bucket_name)
check_non_empty_string(object_name)
query_params = {"versionId", version_id} if version_id else {}
query_params["legal-hold"] = ""
try:
response = self._execute(
"GET",
bucket_name,
object_name=object_name,
query_params=query_params,
)
legal_hold = unmarshal(LegalHold, response.data.decode())
return legal_hold.status
except S3Error as exc:
if exc.code != "NoSuchObjectLockConfiguration":
raise
return False

def _list_objects( # pylint: disable=too-many-arguments,too-many-branches
self,
bucket_name,
Expand Down
45 changes: 45 additions & 0 deletions minio/legalhold.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# -*- coding: utf-8 -*-
# MinIO Python Library for Amazon S3 Compatible Cloud Storage, (C)
# 2020 MinIO, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Request/response of PutObjectLegalHold and GetObjectLegalHold S3 APIs."""

from __future__ import absolute_import

from .xml import Element, SubElement, findtext


class LegalHold:
"""Legal hold configuration."""

def __init__(self, status=False):
self._status = status

@property
def status(self):
"""Get status."""
return self._status

@classmethod
def fromxml(cls, element):
"""Create new object with values from XML element."""
status = findtext(element, "Status")
return cls(status == "ON")

def toxml(self, element):
"""Convert to XML."""
element = Element("LegalHold")
SubElement(element, "Status", "ON" if self._status is True else "OFF")
return element
37 changes: 37 additions & 0 deletions tests/unit/legelhold.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# -*- coding: utf-8 -*-
# MinIO Python Library for Amazon S3 Compatible Cloud Storage,
# (C) 2020 MinIO, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from unittest import TestCase

from nose.tools import eq_

from minio import xml
from minio.legalhold import LegalHold


class LegalHoldTest(TestCase):
def test_status(self):
config = LegalHold(True)
xml.marshal(config)

config = xml.unmarshal(
LegalHold,
"""<LegalHold xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<Status>OFF</Status>
</LegalHold>""",
)
xml.marshal(config)
eq_(config.status, False)

0 comments on commit 71fe622

Please sign in to comment.