archived_remote_object 0.1.0 → 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 255eec19ca259dc36cf8fdd0bdeac77e787044de8130631c539f3363c8a5cbf1
4
- data.tar.gz: c33825094d55dce29d7f45e13fca5a2ff18ba21048140fdb12b2bf9a44b41054
3
+ metadata.gz: b0210c27f442830b091c1849865ace9a29e961fea290e953e85e3315458e774a
4
+ data.tar.gz: 3024af7b02b867cb3a56f752a4cc714a0d457965a6c9737b6edd5dd2cd880be9
5
5
  SHA512:
6
- metadata.gz: 878e44a20cccd12a454ca35d040588a38a37745c5f598646b1b4a543fa19df30c280b875feda87dd39878b5aab7701a88ac1970e804b245773961ee348a3d684
7
- data.tar.gz: 3eaaf3e07296ea1e6648dcc03d20657bca9ea6526f72c1c76ba5ff3d1f3675bdc6c7b983b584394065c3eb5af96fc2c940c868a6c6519d5eae108c1e26361397
6
+ metadata.gz: eefb9c00c28a82b6f3722f52daa39e0edb6b0aee1fe6d652a3f091c003ccb56de792efd4f7821b901f9e7b41da84c95b905570d29e06529cdfa3ba248f88b1e5
7
+ data.tar.gz: 33eacea6fee046f83957d2fb8d79dbc0bf4456173a566f4cc062b1f8e789cdcb985f00d19de3e30d34e610e8a2db0e2153fa5a4f0834129f12c7d9545e5b82a1
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2021 Aleksey Strizhak
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,25 @@
1
+ require "archived_remote_object/version"
2
+ require "archived_remote_object/configuration"
3
+ require "archived_remote_object/archive/archived_object"
4
+ require "archived_remote_object/archive/restored_object"
5
+ require "archived_remote_object/aws_s3/archived_object"
6
+ require "archived_remote_object/aws_s3/remote_object"
7
+ require "archived_remote_object/aws_s3/client"
8
+
9
+ module ArchivedRemoteObject
10
+ def self.get_object(key) # rubocop:disable Metrics/MethodLength
11
+ Archive::RestoredObject.new(
12
+ key: key,
13
+ archived_object: Archive::ArchivedObject.new(
14
+ key: key,
15
+ remote_object: AwsS3::ArchivedObject.new(
16
+ key: key,
17
+ remote_object: AwsS3::RemoteObject.new(
18
+ key: key,
19
+ remote_client: AwsS3::Client.new
20
+ )
21
+ )
22
+ )
23
+ ).call
24
+ end
25
+ end
@@ -0,0 +1,65 @@
1
+ require "archived_remote_object/aws_s3/archived_object"
2
+
3
+ module ArchivedRemoteObject
4
+ module Archive
5
+ class ArchivedObject
6
+ CantBeRestoredError = Class.new(StandardError)
7
+ CantStopArchivingOnDurationError = Class.new(StandardError)
8
+
9
+ def initialize(
10
+ key:,
11
+ remote_object: AwsS3::ArchivedObject.new(key: key)
12
+ )
13
+ self.remote_object = remote_object
14
+ end
15
+
16
+ def archived?
17
+ remote_object.archived?
18
+ end
19
+
20
+ def restore_in_progress?
21
+ return false unless archived?
22
+
23
+ remote_object.restore_in_progress?
24
+ end
25
+
26
+ def restored?
27
+ return false unless archived?
28
+
29
+ remote_object.restored?
30
+ end
31
+
32
+ def restore
33
+ raise CantBeRestoredError if available? || restore_in_progress?
34
+
35
+ remote_object.restore
36
+ end
37
+
38
+ def stop_archiving_on_duration
39
+ raise CantStopArchivingOnDurationError if !restored? || restore_in_progress?
40
+
41
+ remote_object.stop_archiving_on_duration
42
+ end
43
+
44
+ def available?
45
+ !archived? || restored?
46
+ end
47
+
48
+ def sync
49
+ tap { remote_object.sync }
50
+ end
51
+
52
+ def debug_state
53
+ {
54
+ restore_in_progress: restore_in_progress?,
55
+ restored: restored?,
56
+ **remote_object.debug_state
57
+ }
58
+ end
59
+
60
+ private
61
+
62
+ attr_accessor :remote_object
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,46 @@
1
+ require "ostruct"
2
+ require "archived_remote_object/archive/archived_object"
3
+
4
+ module ArchivedRemoteObject
5
+ module Archive
6
+ class RestoredObject
7
+ def initialize(
8
+ key:,
9
+ archived_object: Archive::ArchivedObject.new(key: key)
10
+ )
11
+ self.archived_object = archived_object
12
+ end
13
+
14
+ def call
15
+ assign_attributes
16
+
17
+ if attributes.status == :archived
18
+ archived_object.restore
19
+ attributes.status = :restoration_initiated
20
+ end
21
+
22
+ attributes
23
+ end
24
+
25
+ private
26
+
27
+ def attributes
28
+ @attributes ||= OpenStruct.new
29
+ end
30
+
31
+ def assign_attributes # rubocop:disable Metrics/AbcSize
32
+ if archived_object.available?
33
+ attributes.status = :available
34
+ elsif archived_object.restore_in_progress?
35
+ attributes.status = :in_progress
36
+ attributes.debug_state = archived_object.debug_state
37
+ else
38
+ attributes.status = :archived
39
+ attributes.debug_state = archived_object.debug_state
40
+ end
41
+ end
42
+
43
+ attr_accessor :archived_object
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,70 @@
1
+ require "archived_remote_object/aws_s3/remote_object"
2
+
3
+ module ArchivedRemoteObject
4
+ module AwsS3
5
+ class ArchivedObject
6
+ RestoreResponseChangedError = Class.new(StandardError)
7
+
8
+ def initialize(
9
+ key:,
10
+ remote_object: AwsS3::RemoteObject.new(key: key)
11
+ )
12
+ self.key = key
13
+ self.remote_object = remote_object
14
+ end
15
+
16
+ def archived?
17
+ remote_object.attributes.storage_class == "DEEP_ARCHIVE"
18
+ end
19
+
20
+ def restore_in_progress?
21
+ restore_in_progress = parse_restore_status[0]
22
+ return false unless restore_in_progress
23
+
24
+ restore_in_progress.to_s.downcase == "true"
25
+ end
26
+
27
+ def restored?
28
+ return false unless expiry_date
29
+
30
+ Time.parse(expiry_date) > Time.now
31
+ end
32
+
33
+ def restore
34
+ remote_object.restore(key: key, duration: restore_duration_days)
35
+ end
36
+
37
+ def stop_archiving_on_duration
38
+ remote_object.storage_class = 'STANDARD'
39
+ end
40
+
41
+ def sync
42
+ tap { remote_object.sync }
43
+ end
44
+
45
+ def debug_state
46
+ remote_object.debug_state
47
+ end
48
+
49
+ private
50
+
51
+ attr_accessor :key, :remote_object
52
+
53
+ def restore_duration_days
54
+ ArchivedRemoteObject.configuration.archive_restore_duration_days
55
+ end
56
+
57
+ def expiry_date
58
+ parse_restore_status[1]
59
+ end
60
+
61
+ def parse_restore_status
62
+ remote_object.attributes.restore =~ /ongoing-request="(.+?)"(, expiry-date="(.+?)")?/
63
+ last_match = Regexp.last_match
64
+ raise RestoreResponseChangedError if !remote_object.attributes.restore.nil? && !last_match
65
+
66
+ last_match&.captures || []
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,72 @@
1
+ require "aws-sdk-s3"
2
+
3
+ module ArchivedRemoteObject
4
+ module AwsS3
5
+ class Client
6
+ attr_accessor :s3_client
7
+
8
+ def initialize
9
+ self.s3_client = Aws::S3::Client.new(
10
+ stub_responses: stub_enabled?,
11
+ region: ArchivedRemoteObject.configuration.aws_region,
12
+ credentials: Aws::Credentials.new(
13
+ ArchivedRemoteObject.configuration.aws_access_key_id,
14
+ ArchivedRemoteObject.configuration.aws_secret_access_key
15
+ )
16
+ )
17
+ end
18
+
19
+ def fetch_object_data(key:, stubbed_response: {})
20
+ if stub_enabled? && !stubbed?(:head_object)
21
+ response = {
22
+ storage_class: "DEEP_ARCHIVE",
23
+ restore: nil,
24
+ **stubbed_response
25
+ }
26
+ s3_client.stub_responses(:head_object, response)
27
+ end
28
+ s3_client.head_object(bucket: bucket, key: key)
29
+ end
30
+
31
+ def restore(key:, duration:)
32
+ s3_client.stub_responses(:restore_object) if stub_enabled? && !stubbed?(:restore_object)
33
+ s3_client.restore_object(bucket: bucket, key: key, restore_request: { days: duration })
34
+ end
35
+
36
+ def assign_tag(key:, set:)
37
+ s3_client.stub_responses(:put_object_tagging) if stub_enabled? && !stubbed?(:put_object_tagging)
38
+ s3_client.put_object_tagging(bucket: bucket, key: key, tagging: { tag_set: [{ key: set[0], value: set[1] }] })
39
+ end
40
+
41
+ def assign_storage_class(key:, storage_class:)
42
+ s3_client.stub_responses(:copy_object) if stub_enabled? && !stubbed?(:copy_object)
43
+ s3_client.copy_object(bucket: bucket, key: key, copy_source: "#{bucket}/#{key}", storage_class: storage_class)
44
+ end
45
+
46
+ def delete(key:)
47
+ s3_client.stub_responses(:delete_object) if stub_enabled? && !stubbed?(:delete_object)
48
+ s3_client.delete_object(bucket: bucket, key: key)
49
+ end
50
+
51
+ def exists?(key:)
52
+ !!fetch_object_data(key: key)
53
+ rescue Aws::S3::Errors::NotFound
54
+ false
55
+ end
56
+
57
+ private
58
+
59
+ def bucket
60
+ ArchivedRemoteObject.configuration.aws_bucket
61
+ end
62
+
63
+ def stub_enabled?
64
+ ArchivedRemoteObject.configuration.stub_client_requests
65
+ end
66
+
67
+ def stubbed?(key)
68
+ !!s3_client.instance_variable_get('@stubs').fetch(key, nil)
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,61 @@
1
+ require "archived_remote_object/aws_s3/client"
2
+
3
+ module ArchivedRemoteObject
4
+ module AwsS3
5
+ class RemoteObject
6
+ attr_accessor :key, :remote_client
7
+
8
+ def initialize(
9
+ key:,
10
+ remote_client: AwsS3::Client.new
11
+ )
12
+ self.key = key
13
+ self.remote_client = remote_client
14
+ end
15
+
16
+ def attributes
17
+ return @attributes if @attributes
18
+
19
+ fetch_attributes
20
+ end
21
+
22
+ def restore(**args)
23
+ remote_client.restore(**args)
24
+ end
25
+
26
+ def assign_tag(key:, value:)
27
+ remote_client.assign_tag(key: self.key, set: [key, value])
28
+ end
29
+
30
+ def storage_class=(storage_class)
31
+ # accepts STANDARD, STANDARD_IA, ONEZONE_IA, GLACIER, INTELLIGENT_TIERING, DEEP_ARCHIVE
32
+ remote_client.assign_storage_class(key: key, storage_class: storage_class)
33
+ end
34
+
35
+ def delete
36
+ remote_client.delete(key: key)
37
+ end
38
+
39
+ def exists?
40
+ remote_client.exists?(key: key)
41
+ end
42
+
43
+ def sync
44
+ tap { fetch_attributes }
45
+ end
46
+
47
+ def debug_state
48
+ {
49
+ restore: attributes.restore,
50
+ storage_class: attributes.storage_class
51
+ }
52
+ end
53
+
54
+ private
55
+
56
+ def fetch_attributes
57
+ @attributes = remote_client.fetch_object_data(key: key)
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,13 @@
1
+ require "ostruct"
2
+
3
+ module ArchivedRemoteObject
4
+ class << self
5
+ def configuration
6
+ @configuration ||= OpenStruct.new
7
+ end
8
+
9
+ def configure
10
+ yield(configuration)
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,3 @@
1
+ module ArchivedRemoteObject
2
+ VERSION = "0.1.5".freeze
3
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: archived_remote_object
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aleksey Strizhak
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-02-07 00:00:00.000000000 Z
11
+ date: 2021-06-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: aws-sdk
@@ -73,7 +73,16 @@ email:
73
73
  executables: []
74
74
  extensions: []
75
75
  extra_rdoc_files: []
76
- files: []
76
+ files:
77
+ - LICENSE.txt
78
+ - lib/archived_remote_object.rb
79
+ - lib/archived_remote_object/archive/archived_object.rb
80
+ - lib/archived_remote_object/archive/restored_object.rb
81
+ - lib/archived_remote_object/aws_s3/archived_object.rb
82
+ - lib/archived_remote_object/aws_s3/client.rb
83
+ - lib/archived_remote_object/aws_s3/remote_object.rb
84
+ - lib/archived_remote_object/configuration.rb
85
+ - lib/archived_remote_object/version.rb
77
86
  homepage: https://github.com/Mifrill/archived_remote_object.git
78
87
  licenses:
79
88
  - MIT
@@ -95,7 +104,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
95
104
  - !ruby/object:Gem::Version
96
105
  version: '0'
97
106
  requirements: []
98
- rubygems_version: 3.0.3
107
+ rubygems_version: 3.2.16
99
108
  signing_key:
100
109
  specification_version: 4
101
110
  summary: Get archived remote object with delayed restore