sarchive 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: c6d915b44941ebe7212bc72c45c0a0dc202f8bff
4
+ data.tar.gz: 1fb2f83e843282b2c74cfae79cff65bc553efbdc
5
+ SHA512:
6
+ metadata.gz: 54e5a22d166d5bafd6208279d18f037f818e9d5579f9b4c7ee2117c88c3e2c5071ff1a40c2116acec460fcc09f1e21b8cbdd54965410963f4b0890cdc0f38d65
7
+ data.tar.gz: 3db44f98cf39afbda4edc9cbdf50fddd95053df52e050199447420922e8ca96e8f917a3432228fb705f811577601b5a32db251c03e7bf823132a0bebc7de599c
@@ -0,0 +1,65 @@
1
+ # Created by https://www.gitignore.io
2
+
3
+ ### Intellij ###
4
+ # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm
5
+
6
+ *.iml
7
+
8
+ ## Directory-based project format:
9
+ .idea/
10
+ # if you remove the above rule, at least ignore the following:
11
+
12
+ # User-specific stuff:
13
+ # .idea/workspace.xml
14
+ # .idea/tasks.xml
15
+ # .idea/dictionaries
16
+
17
+ # Sensitive or high-churn files:
18
+ # .idea/dataSources.ids
19
+ # .idea/dataSources.xml
20
+ # .idea/sqlDataSources.xml
21
+ # .idea/dynamic.xml
22
+ # .idea/uiDesigner.xml
23
+
24
+ # Gradle:
25
+ # .idea/gradle.xml
26
+ # .idea/libraries
27
+
28
+ # Mongo Explorer plugin:
29
+ # .idea/mongoSettings.xml
30
+
31
+ ## File-based project format:
32
+ *.ipr
33
+ *.iws
34
+
35
+ ## Plugin-specific files:
36
+
37
+ # IntelliJ
38
+ /out/
39
+
40
+ # mpeltonen/sbt-idea plugin
41
+ .idea_modules/
42
+
43
+ # JIRA plugin
44
+ atlassian-ide-plugin.xml
45
+
46
+ # Crashlytics plugin (for Android Studio and IntelliJ)
47
+ com_crashlytics_export_strings.xml
48
+ crashlytics.properties
49
+ crashlytics-build.properties
50
+
51
+ # bundle gem
52
+ /.bundle/
53
+ /.yardoc
54
+ /Gemfile.lock
55
+ /_yardoc/
56
+ /coverage/
57
+ /doc/
58
+ /pkg/
59
+ /spec/reports/
60
+ /tmp/
61
+ /vender/
62
+
63
+ # sarchive
64
+ sarchive.config.yml
65
+ /log
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
@@ -0,0 +1,3 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.1.5
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in sarchive.gemspec
4
+ gemspec
@@ -0,0 +1,60 @@
1
+ Sarchive
2
+ ==========
3
+ 「さくらのクラウド」のアーカイブ作成を簡単にコンソールから実行するためのgemです。
4
+
5
+ ## 説明
6
+ このgemを使用することにより、コンソールから簡単に複数のディスクのアーカイブを作成できます。
7
+ また、アーカイブ作成時に古いアーカイブの削除を同時に行うことも可能です。
8
+ cronで定期的に実行するように設定することで、面倒なバックアップ作業を自動化できます。
9
+
10
+ ## インストール
11
+ gem install sarchive
12
+
13
+ ## 基本的な使い方
14
+ 1. 設定ファイルの生成
15
+
16
+ sarchive init [--path] (</path/to/config/sarchive.config.yml>)
17
+ デフォルトではカレントディレクトリに`sarchive.config.yml`を生成します。
18
+ 生成先を変更する場合は`--path`オプションでパスを指定してください。
19
+
20
+ 2. 設定ファイルの編集
21
+ 実行に必要となるAPIキーや、アーカイブ作成対象のディスクを指定してください。
22
+
23
+ token: # コンパネで作成したAPIキーのaccess-tokenを指定してください
24
+ secret: # コンパネで作成したAPIキーのaccess-token-secretを指定してください
25
+ disks:
26
+ tk1v: # 対象のゾーン名 (tk1a: 東京第1, is1a: 石狩第1, is1b: 石狩第2, tk1v: Sandbox)
27
+ - 999999999999 # 対象ディスクのID
28
+ - 999999999999 # 複数指定可
29
+
30
+ 3. 実行
31
+
32
+ sarchive exec [--path] (</path/to/config/sarchive.config.yml>)
33
+ デフォルトではカレントディレクトリの`sarchive.config.yml`をもとに実行します。
34
+ 読み込む設定ファイルを変更する場合は、`--path`オプションでパスを指定してください。
35
+
36
+ ## その他の機能
37
+ ### アーカイブ自動削除
38
+ アーカイブ作成と同時に古いアーカイブを削除することができます。
39
+ 以下のように設定ファイルを編集してください。
40
+
41
+ auto_delete:
42
+ enable: true # trueを指定し自動削除を有効にしてください
43
+ store: # 何を基準にアーカイブを削除するかの設定です。counts, hoursのどちらか一方を指定してください
44
+ # counts: 3
45
+ # hours : 72
46
+
47
+ - `counts`
48
+ 数を基準に削除を行います。仮に3を指定した場合、新しい順に3個残して4つ目以降を削除します。
49
+ - `hours`
50
+ 経過時間を基準に削除を行います。仮に72を指定した場合、作成から72時間より多く経過しているものを削除します。
51
+
52
+ ## 注意事項
53
+ プロダクション環境で利用する前に[Sandbox](http://cloud-news.sakura.ad.jp/sandbox/)でテストすることを推奨します。
54
+ 本プログラムを使用して損害が発生した場合も、本プログラム作成者は一切の責任を負いません。
55
+
56
+ ## TODO
57
+ - 実行結果のSlack通知機能
58
+
59
+ ## Licence
60
+ MIT
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "sarchive"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+
7
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "sarchive"
4
+
5
+ Sarchive::CLI.start
@@ -0,0 +1,6 @@
1
+ require "sarchive/version"
2
+ require "sarchive/cli"
3
+
4
+ module Sarchive
5
+ # Your code goes here...
6
+ end
@@ -0,0 +1,192 @@
1
+ require 'sarchive'
2
+ require 'sarchive/sacloud'
3
+ require 'sarchive/plogger'
4
+ require 'thor'
5
+ require 'yaml'
6
+
7
+ module Sarchive
8
+ class CLI < Thor
9
+
10
+ desc 'init', '設定ファイルを作成します'
11
+ option :path, :type => :string, :default => './sarchive.config.yml', :banner => '作成する設定ファイルのパス'
12
+ def init()
13
+ dest = File.expand_path(options[:path])
14
+
15
+ STDOUT.puts('設定ファイルを作成します')
16
+
17
+ operation = 'create'
18
+
19
+ if File.exist?(dest)
20
+ STDOUT.puts('すでに設定ファイルが存在します。上書きしますか?(y/n)')
21
+ input = STDIN.gets.chomp
22
+
23
+ case input
24
+ when /^y(es)?$/i
25
+ operation = 'overwrite'
26
+ else
27
+ operation = 'skip'
28
+ end
29
+ end
30
+
31
+ STDOUT.puts("[#{operation}] #{dest}")
32
+
33
+ unless operation == 'skip'
34
+ FileUtils.cp(File.expand_path('../sarchive.config.yml.example', __FILE__), dest)
35
+ end
36
+
37
+ exit(true)
38
+ end
39
+
40
+ desc 'exec', 'ディスクのアーカイブを作成します'
41
+ option :path, :type => :string, :default => './sarchive.config.yml', :banner => '読み込む設定ファイルのパス'
42
+ def exec()
43
+ unless File.exist?(options[:path])
44
+ STDERR.puts('設定ファイルが存在しません')
45
+ exit(false) # ログ出力できないのでここで終了する
46
+ end
47
+
48
+ config = YAML.load_file(options[:path])
49
+ token = config['token']
50
+ secret = config['secret']
51
+ disks = config['disks']
52
+ auto_delete = config['auto_delete']
53
+ log_path = config['log_path'] ? config['log_path'] : './log/sarchive.log'
54
+ err_log_path = config['err_log_path'] ? config['err_log_path'] : './log/sarchive.err.log'
55
+
56
+ logger = PLogger.new(File.expand_path(log_path), File.expand_path(err_log_path))
57
+
58
+ logger.info("Sarchive start.")
59
+
60
+ unless token and secret
61
+ fail('設定ファイルエラー: tokenまたはsecretが設定されていません')
62
+ end
63
+
64
+ if auto_delete['enable']
65
+
66
+ counts = auto_delete['store']['counts']
67
+ hours = auto_delete['store']['hours']
68
+
69
+ if counts
70
+ unless counts.is_a?(Integer) and 0 < counts
71
+ fail('設定ファイルエラー: countsには正の整数を指定してください')
72
+ end
73
+ end
74
+
75
+ if hours
76
+ unless hours.is_a?(Integer) and 0 < hours
77
+ fail('設定ファイルエラー: hoursには正の整数を指定してください')
78
+ end
79
+ end
80
+
81
+ if counts and hours
82
+ fail('設定ファイルエラー: auto_deleteのcountsとhoursはどちらか一方のみを指定してください')
83
+ end
84
+ end
85
+
86
+ sacloud = Sarchive::Sacloud.new(token, secret, logger)
87
+
88
+ disks.each do |zone, disk_ids|
89
+
90
+ unless disk_ids
91
+ next
92
+ end
93
+
94
+ sacloud.set_zone(zone)
95
+
96
+ disk_ids.each do |disk_id|
97
+
98
+ logger.info("Target zone=[#{zone}] disk_id=[#{disk_id}]")
99
+
100
+ # 作成パート
101
+ logger.info("Making...")
102
+ archive = sacloud.create_archive(disk_id)
103
+
104
+ unless archive
105
+ logger.error("Making failed. disk_id=[#{disk_id}]")
106
+ next
107
+ end
108
+
109
+ logger.info("Making success! archive_id=[#{archive.id}]")
110
+
111
+ # 削除パート
112
+ if auto_delete['enable']
113
+ archives = sacloud.find_stored_archives(disk_id)
114
+
115
+ items = []
116
+ archives.each do |a|
117
+ a.description.match(/(\d{4})\-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/) do |m|
118
+ items.push({ :archive => a, :created_at => m[1] + m[2] + m[3] + m[4] + m[5] + m[6] })
119
+ end
120
+ end
121
+
122
+ sorted_items = items.sort do |a, b|
123
+ a[:created_at] <=> b[:created_at]
124
+ end
125
+
126
+ counts = auto_delete['store']['counts']
127
+ hours = auto_delete['store']['hours']
128
+
129
+ if counts
130
+
131
+ logger.info("Removing... threshold_counts=[#{counts}]")
132
+
133
+ if counts < sorted_items.length
134
+ (sorted_items.length - counts).times do |i|
135
+ ret = sacloud.delete_archive(sorted_items[i][:archive].id)
136
+
137
+ if ret
138
+ logger.info("Removing success! archive_id=[#{sorted_items[i][:archive].id}]")
139
+ else
140
+ logger.error("Removing failed. archive_id=[#{sorted_items[i][:archive].id}]")
141
+ end
142
+ end
143
+ else
144
+ logger.info("A target doesn't exist.")
145
+ end
146
+
147
+ elsif hours
148
+
149
+ logger.info("Removing... threshold_hours=[#{hours}]")
150
+
151
+ target_items = []
152
+ sorted_items.each do |a|
153
+ at = a[:created_at]
154
+ time = Time.local(at[0, 4], at[4, 2], at[6, 2], at[8, 2], at[10, 2], at[12, 2])
155
+
156
+ # 秒に換算し加算
157
+ time += hours * 60 * 60
158
+
159
+ if time < Time.now
160
+ target_items.push(a)
161
+ end
162
+ end
163
+
164
+ if target_items.empty?
165
+ logger.info("A target doesn't exist.")
166
+ end
167
+
168
+ target_items.each do |a|
169
+ ret = sacloud.delete_archive(a[:archive].id)
170
+
171
+ if ret
172
+ logger.info("Removing success! archive_id=[#{a[:archive].id}]")
173
+ else
174
+ logger.error("Removing failed. archive_id=[#{a[:archive].id}]")
175
+ end
176
+ end
177
+ end
178
+ end
179
+ end
180
+ end
181
+
182
+ logger.info("Sarchive normal end.")
183
+ exit(true)
184
+
185
+ rescue => e
186
+ logger.error(e.message)
187
+ logger.info("Sarchive abnormal end.")
188
+ exit(false)
189
+ end
190
+ end
191
+
192
+ end
@@ -0,0 +1,31 @@
1
+ require 'logger'
2
+ require 'fileutils'
3
+
4
+ class PLogger
5
+
6
+ def initialize(log_path, err_log_path)
7
+ FileUtils.mkdir_p(File::dirname(log_path))
8
+ FileUtils.mkdir_p(File::dirname(err_log_path))
9
+
10
+ @stdout = Logger.new STDOUT
11
+ @stderr = Logger.new STDERR
12
+ @log = Logger.new(log_path, 'monthly')
13
+ @elog = Logger.new(err_log_path, 'monthly')
14
+ end
15
+
16
+ %w(debug info warn).each do |level|
17
+ define_method(level) do |*args|
18
+ [@stdout, @log].all? do |output|
19
+ output.send level, *args
20
+ end
21
+ end
22
+ end
23
+
24
+ %w(error fatal).each do |level|
25
+ define_method(level) do |*args|
26
+ [@stderr, @log, @elog].all? do |output|
27
+ output.send level, *args
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,73 @@
1
+ require 'saklient/cloud/api'
2
+
3
+ module Sarchive
4
+ class Sacloud
5
+
6
+ def initialize(token, secret, logger)
7
+ @sarchive_tag = 'sarchive_'
8
+ @api = Saklient::Cloud::API::authorize(token, secret)
9
+ @logger = logger
10
+ end
11
+
12
+ def set_zone(zone)
13
+ @api = @api.in_zone(zone)
14
+ end
15
+
16
+ def create_archive(disk_id)
17
+
18
+ disk = get_disk(disk_id)
19
+
20
+ unless disk
21
+ fail("対象のディスク[id=#{disk_id}]が見つかりません。アーカイブの作成をスキップします")
22
+ end
23
+
24
+ created_at = Time.now.strftime("%Y-%m-%d %H:%M:%S")
25
+ archive = @api.archive.create
26
+ archive.name = disk.name
27
+ archive.description = "Created by sarchive at #{created_at}"
28
+ archive.tags = [@sarchive_tag]
29
+ archive.source = disk
30
+ archive.save
31
+
32
+ unless archive.sleep_while_copying
33
+ fail("ディスク[id=#{disk.id}, name=#{disk.name}]からアーカイブへのコピーがタイムアウトまたは失敗しました。コントロールパネルでステータスを確認してください")
34
+ end
35
+
36
+ archive
37
+
38
+ rescue => e
39
+ @logger.error(e.message)
40
+ nil
41
+ end
42
+
43
+ def delete_archive(disk_id)
44
+ archive = @api.archive.get_by_id(disk_id.to_s) rescue nil
45
+
46
+ unless archive
47
+ fail("削除対象のアーカイブ[id=#{disk_id}]が見つかりません。アーカイブの削除をスキップします")
48
+ end
49
+
50
+ archive.destroy
51
+ archive
52
+
53
+ rescue => e
54
+ @logger.error(e.message)
55
+ nil
56
+ end
57
+
58
+ def find_stored_archives(disk_id)
59
+ @api.archive.
60
+ filter_by('SourceDisk.ID', disk_id.to_s).
61
+ with_tag(@sarchive_tag).
62
+ find
63
+ rescue
64
+ nil
65
+ end
66
+
67
+ private
68
+
69
+ def get_disk(disk_id)
70
+ @api.disk.get_by_id(disk_id.to_s) rescue nil
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,40 @@
1
+ # Sarchive設定ファイル
2
+ #
3
+ # [APIキー]
4
+ # token : コンパネで作成したAPIキーのaccess-tokenを指定してください
5
+ # secret: コンパネで作成したAPIキーのaccess-token-secretを指定してください
6
+ #
7
+ # [ターゲットディスク]
8
+ # disks: アーカイブを作成したい対象ディスクの設定です
9
+ # tk1v: 対象のゾーン名称をキーにします(tk1a, is1a, is1b, tk1v)
10
+ # - 999... 対象のディスクのIDを指定します
11
+ #
12
+ # [アーカイブ自動削除]
13
+ # auto_delete: アーカイブ作成と同時に古いアーカイブを削除するアーカイブ自動削除の設定です
14
+ # enable: 自動削除を有効にする場合はtrueを指定してください
15
+ # store : 何を基準にアーカイブを削除するかの設定です。counts, hoursのどちらか一方を指定してください
16
+ # counts: 数を基準に削除を行います。仮に3を指定した場合、3個残して4つ目以降を削除します
17
+ # hours : 経過時間を基準に削除を行います。仮に72を指定した場合、作成から72時間より多く経過しているものを削除します
18
+ #
19
+ # [ログ出力先]
20
+ # log_path : ログの出力先を指定してください。相対パスを指定する場合、実行場所が基準となります
21
+ # err_log_path: エラーログの出力先を指定してください。相対パスを指定する場合、実行場所が基準となります
22
+
23
+ token:
24
+ secret:
25
+ disks:
26
+ tk1v: # Sandboxゾーン
27
+ - 999999999999
28
+ - 999999999999
29
+ tk1a: # 東京第1ゾーン
30
+ is1a: # 石狩第1ゾーン
31
+ is1b: # 石狩第2ゾーン
32
+
33
+ auto_delete:
34
+ enable: false
35
+ store:
36
+ # counts: 3
37
+ # hours : 72
38
+
39
+ log_path: ./log/sarchive.log
40
+ err_log_path: ./log/sarchive.err.log
@@ -0,0 +1,3 @@
1
+ module Sarchive
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,31 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'sarchive/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "sarchive"
8
+ spec.version = Sarchive::VERSION
9
+ spec.licenses = ["MIT"]
10
+ spec.authors = ["hogesuke"]
11
+ spec.email = ["miyado@gmail.com"]
12
+
13
+ spec.summary = "「さくらのクラウド」のアーカイブ作成を簡単にコンソールから実行するためのgemです"
14
+ spec.description = "このgemを使用することにより、コンソールから簡単に複数のディスクのアーカイブを作成できます。また、アーカイブ作成時に古いアーカイブの削除を同時に行うことも可能です。cronで定期的に実行するように設定することで、面倒なバックアップ作業を自動化できます。"
15
+ spec.homepage = "https://github.com/hogesuke/sarchive"
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
18
+ spec.bindir = "exe"
19
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
+ spec.require_paths = ["lib"]
21
+
22
+ if spec.respond_to?(:metadata)
23
+ spec.metadata['allowed_push_host'] = "https://rubygems.org"
24
+ end
25
+
26
+ spec.add_development_dependency "bundler", "~> 1.9"
27
+ spec.add_development_dependency "rake", "~> 10.0"
28
+
29
+ spec.add_dependency "thor"
30
+ spec.add_dependency "saklient", "~> 0.0.2.8"
31
+ end
metadata ADDED
@@ -0,0 +1,118 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sarchive
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - hogesuke
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2015-05-31 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.9'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.9'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: thor
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: saklient
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 0.0.2.8
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 0.0.2.8
69
+ description: "このgemを使用することにより、コンソールから簡単に複数のディスクのアーカイブを作成できます。また、アーカイブ作成時に古いアーカイブの削除を同時に行うことも可能です。cronで定期的に実行するように設定することで、面倒なバックアップ作業を自動化できます。"
70
+ email:
71
+ - miyado@gmail.com
72
+ executables:
73
+ - sarchive
74
+ extensions: []
75
+ extra_rdoc_files: []
76
+ files:
77
+ - ".gitignore"
78
+ - ".rspec"
79
+ - ".travis.yml"
80
+ - Gemfile
81
+ - README.md
82
+ - Rakefile
83
+ - bin/console
84
+ - bin/setup
85
+ - exe/sarchive
86
+ - lib/sarchive.rb
87
+ - lib/sarchive/cli.rb
88
+ - lib/sarchive/plogger.rb
89
+ - lib/sarchive/sacloud.rb
90
+ - lib/sarchive/sarchive.config.yml.example
91
+ - lib/sarchive/version.rb
92
+ - sarchive.gemspec
93
+ homepage: https://github.com/hogesuke/sarchive
94
+ licenses:
95
+ - MIT
96
+ metadata:
97
+ allowed_push_host: https://rubygems.org
98
+ post_install_message:
99
+ rdoc_options: []
100
+ require_paths:
101
+ - lib
102
+ required_ruby_version: !ruby/object:Gem::Requirement
103
+ requirements:
104
+ - - ">="
105
+ - !ruby/object:Gem::Version
106
+ version: '0'
107
+ required_rubygems_version: !ruby/object:Gem::Requirement
108
+ requirements:
109
+ - - ">="
110
+ - !ruby/object:Gem::Version
111
+ version: '0'
112
+ requirements: []
113
+ rubyforge_project:
114
+ rubygems_version: 2.2.2
115
+ signing_key:
116
+ specification_version: 4
117
+ summary: "「さくらのクラウド」のアーカイブ作成を簡単にコンソールから実行するためのgemです"
118
+ test_files: []