backup_jenkins 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ config/config.yml
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --color
2
+ --format progress
3
+ --profile
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ ---
2
+ language: ruby
3
+ bundler_args: --without development
4
+ rvm:
5
+ - 1.9.3
data/Gemfile ADDED
@@ -0,0 +1,13 @@
1
+ source :rubygems
2
+
3
+ # Specify your gem's dependencies in backup_jenkins.gemspec
4
+ gemspec
5
+
6
+ group :test do
7
+ gem "rake"
8
+ gem "rspec"
9
+ gem "ci_reporter"
10
+ gem "simplecov"
11
+ gem "simplecov-rcov"
12
+ gem "flog"
13
+ end
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Juan C. Müller
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,32 @@
1
+ # BackupJenkins
2
+ [![Build Status](https://secure.travis-ci.org/jcmuller/jenkins_backup.png)](http://travis-ci.org/jcmuller/jenkins_backup)
3
+ [![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/jcmuller/jenkins_backup)
4
+ [![Dependency Status](https://gemnasium.com/jcmuller/jenkins_backup.png)](https://gemnasium.com/jcmuller/jenkins_backup)
5
+
6
+ TODO: Write a gem description
7
+
8
+ ## Installation
9
+
10
+ Add this line to your application's Gemfile:
11
+
12
+ gem 'backup_jenkins'
13
+
14
+ And then execute:
15
+
16
+ $ bundle
17
+
18
+ Or install it yourself as:
19
+
20
+ $ gem install backup_jenkins
21
+
22
+ ## Usage
23
+
24
+ TODO: Write usage instructions here
25
+
26
+ ## Contributing
27
+
28
+ 1. Fork it
29
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
30
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
31
+ 4. Push to the branch (`git push origin my-new-feature`)
32
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env rake
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+
4
+ require "rspec/core/rake_task"
5
+ require "backup_jenkins/version"
6
+ require "bundler/gem_tasks"
7
+
8
+ RSpec::Core::RakeTask.new(:spec) do |spec|
9
+ spec.pattern = "spec/**/*_spec.rb"
10
+ spec.rspec_opts = ["--backtrace --format CI::Reporter::RSpec"]
11
+ end
12
+
13
+ desc "Clean backup and swap files, and artifacts"
14
+ task :clean do
15
+ require "fileutils"
16
+ Dir["{pkg/*,**/*~,**/.*.sw?,coverage/**,spec/reports/**}"].each do |file|
17
+ rm_rf file
18
+ end
19
+ end
20
+
21
+ desc "Run rspec by default"
22
+ task :default => :spec
@@ -0,0 +1,23 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/backup_jenkins/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Juan C. Müller"]
6
+ gem.email = ["jcmuller@gmail.com"]
7
+ gem.description = %{Simple Jenkins config and plugin backup to S3}
8
+ gem.summary = %q{This gem allows you to get a backup instance of jenkins up and running pretty quickly}
9
+ gem.homepage = "http://github.com/jcmuller/jenkins_backup"
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = Dir["spec/**/*_spec.rb"]
14
+ gem.name = "backup_jenkins"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = BackupJenkins::VERSION
17
+
18
+ gem.add_dependency("aws-sdk")
19
+
20
+ gem.add_development_dependency("rake")
21
+ gem.add_development_dependency("pry-debugger")
22
+ gem.add_development_dependency("pry-stack_explorer")
23
+ end
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'backup_jenkins'
4
+
5
+ BackupJenkins::CLI.run
@@ -0,0 +1,12 @@
1
+ aws:
2
+ access_key: AWS_ACCESS_KEY
3
+ secret: AWS_SECRET
4
+ bucket_name: BUCKET_NAME
5
+ backup:
6
+ dir_base: PATH_TO_BACKUP_DIRECTORY
7
+ file_name_base: SOME_BASE_NAME
8
+ timestamp: "%Y%m%d_%H%M"
9
+ backups_to_keep: 2
10
+ jenkins:
11
+ home: PATH_TO_JENKINS_HOME
12
+ verbose: true
@@ -0,0 +1,11 @@
1
+ require 'rubygems'
2
+ require 'yaml'
3
+ require 'aws'
4
+
5
+ module BackupJenkins
6
+ autoload :AWS, 'backup_jenkins/aws'
7
+ autoload :Backup, 'backup_jenkins/backup'
8
+ autoload :CLI, 'backup_jenkins/cli'
9
+ autoload :Config, 'backup_jenkins/config'
10
+ autoload :Version, 'backup_jenkins/version'
11
+ end
@@ -0,0 +1,54 @@
1
+ module BackupJenkins
2
+ class AWS
3
+ def initialize(config = Config.new)
4
+ @config = config
5
+ setup_aws
6
+ end
7
+
8
+ def populate_files
9
+ @files = []
10
+ bucket.objects.with_prefix(config.backup["file_name_base"]).each{ |o| files << o }
11
+ @files.sort!{ |a, b| a.key <=> b.key }
12
+ end
13
+
14
+ # TODO change this to use a time decay algorithm
15
+ def remove_old_files
16
+ puts "Looking for old files..." if config.verbose
17
+
18
+ populate_files
19
+
20
+ files_to_remove.each do |file|
21
+ puts "Removing #{file.key}..." if config.verbose
22
+ file.delete
23
+ end
24
+
25
+ puts "Done." if config.verbose
26
+ end
27
+
28
+ def files_to_remove
29
+ files - files.last(config.backup["backups_to_keep"])
30
+ end
31
+
32
+ def upload_file(filename, file)
33
+ puts "About to upload #{filename}..." if config.verbose
34
+ new_file = bucket.objects.create(filename, file)
35
+ puts "Done" if config.verbose
36
+ raise "Error uploading" unless new_file.class == ::AWS::S3::S3Object
37
+ end
38
+
39
+ private
40
+
41
+ attr_reader :config, :bucket, :files
42
+
43
+ def setup_aws
44
+ s3 = ::AWS::S3.new(
45
+ access_key_id: config.aws["access_key"],
46
+ secret_access_key: config.aws["secret"]
47
+ )
48
+ @bucket = s3.buckets[config.aws["bucket_name"]]
49
+ @bucket = s3.buckets.create(config.aws["bucket_name"]) unless @bucket.exists?
50
+ raise "Couldn't create bucket!" unless @bucket.exists?
51
+ end
52
+
53
+ end
54
+ end
@@ -0,0 +1,96 @@
1
+ require 'fileutils'
2
+
3
+ module BackupJenkins
4
+ class Backup
5
+ def initialize(config = Config.new)
6
+ @config = config
7
+ end
8
+
9
+ def backup_directory
10
+ @backup_directory ||= "#{config.backup["dir_base"]}/#{base_file_name}_#{timestamp}"
11
+ end
12
+
13
+ def base_file_name
14
+ "#{config.backup["file_name_base"]}_#{hostname}"
15
+ end
16
+
17
+ def hostname
18
+ %x{hostname -s}.chomp
19
+ end
20
+
21
+ def create_dir_and_copy(file_names)
22
+ file_names.each do |file_name|
23
+ create_dir_and_copy_impl(file_name)
24
+ end
25
+ end
26
+
27
+ def create_dir_and_copy_impl(file_name)
28
+ raise "file '#{file_name}' does not exist" unless FileTest.file?(file_name)
29
+
30
+ new_file_name = new_file_path(file_name)
31
+ FileUtils.mkdir_p(File.dirname(new_file_name), verbose: config.verbose)
32
+ FileUtils.cp(file_name, new_file_name, verbose: config.verbose)
33
+ end
34
+
35
+ def new_file_path(file_name)
36
+ "#{backup_directory}/#{file_name.gsub(%r{#{config.jenkins["home"]}}, "")}"
37
+ end
38
+
39
+ def do_backup
40
+ raise "Backup directory already exists! (#{backup_directory})" if FileTest.directory?(backup_directory)
41
+
42
+ copy_files
43
+
44
+ create_tarball
45
+ remove_temporary_files
46
+ end
47
+
48
+ def copy_files
49
+ create_dir_and_copy(plugin_files)
50
+ create_dir_and_copy(user_content_files)
51
+ create_dir_and_copy(jobs_files)
52
+ end
53
+
54
+ def plugin_files
55
+ Dir["#{config.jenkins["home"]}/plugins/*.jpi"] +
56
+ Dir["#{config.jenkins["home"]}/plugins/*.jpi.pinned"] +
57
+ Dir["#{config.jenkins["home"]}/plugins/*.jpi.disabled"]
58
+ end
59
+
60
+ def user_content_files
61
+ Dir["#{config.jenkins["home"]}/userContent/*"]
62
+ end
63
+
64
+ def jobs_files
65
+ `find #{config.jenkins["home"]} -maxdepth 3 -name config.xml -or -name nextBuildNumber`.split(/\n/)
66
+ end
67
+
68
+ def create_tarball
69
+ Dir.chdir(backup_directory)
70
+ %x{tar #{tar_options} #{tarball_filename} .}
71
+ raise "Error creating tarball" unless FileTest.file?(tarball_filename)
72
+ end
73
+
74
+ def remove_temporary_files
75
+ FileUtils.rm_rf(backup_directory, verbose: config.verbose)
76
+ end
77
+
78
+ def tarball_filename
79
+ "#{backup_directory}.tar.bz2"
80
+ end
81
+
82
+ def tar_options
83
+ options = %w(jcf)
84
+ options.unshift('v') if config.verbose
85
+ options.join('')
86
+ end
87
+
88
+ private
89
+
90
+ attr_reader :config
91
+
92
+ def timestamp
93
+ Time.now.strftime(config.backup["timestamp"])
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,19 @@
1
+ module BackupJenkins
2
+ class CLI
3
+ class << self
4
+ def run
5
+ config = BackupJenkins::Config.new
6
+ backup = BackupJenkins::Backup.new(config)
7
+ aws = BackupJenkins::AWS.new(config)
8
+
9
+ backup.do_backup
10
+
11
+ full_filename = backup.tarball_filename
12
+ filename = File.basename(full_filename)
13
+
14
+ aws.upload_file(filename, File.open(full_filename))
15
+ aws.remove_old_files # Clean up!
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,23 @@
1
+ module BackupJenkins
2
+ class Config
3
+ attr_reader :s3
4
+
5
+ def initialize
6
+ @config = YAML.load_file("config/config.yml")
7
+ end
8
+
9
+ def method_missing(meth, *args, &block)
10
+ return config[meth.to_s] if config.has_key?(meth.to_s)
11
+ super
12
+ end
13
+
14
+ def respond_to?(meth)
15
+ config.has_key?(meth.to_s) || super
16
+ end
17
+
18
+ private
19
+
20
+ attr_reader :config
21
+
22
+ end
23
+ end
@@ -0,0 +1,3 @@
1
+ module BackupJenkins
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,4 @@
1
+ require 'spec_helper'
2
+
3
+ describe BackupJenkins::AWS do
4
+ end
@@ -0,0 +1,4 @@
1
+ require 'spec_helper'
2
+
3
+ describe BackupJenkins::Backup do
4
+ end
@@ -0,0 +1,4 @@
1
+ require 'spec_helper'
2
+
3
+ describe BackupJenkins::CLI do
4
+ end
@@ -0,0 +1,21 @@
1
+ require 'spec_helper'
2
+ require 'tempfile'
3
+
4
+ describe BackupJenkins::Config do
5
+ before do
6
+ YAML.stub(:load_file).and_return({
7
+ "aws" => {
8
+ "access_key" => "some_key",
9
+ "secret" => "some_secret"
10
+ }
11
+ })
12
+ end
13
+
14
+ it "should get from YAML and define aws_key" do
15
+ subject.aws["access_key"].should == "some_key"
16
+ end
17
+
18
+ it "should get from YAML and define secret" do
19
+ subject.aws["secret"].should == "some_secret"
20
+ end
21
+ end
@@ -0,0 +1,28 @@
1
+ # This file was generated by the `rspec --init` command. Conventionally, all
2
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3
+ # Require this file using `require "spec_helper"` to ensure that it is only
4
+ # loaded once.
5
+ #
6
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
7
+
8
+ require 'simplecov'
9
+ require 'simplecov-rcov'
10
+ SimpleCov.formatter = SimpleCov::Formatter::RcovFormatter
11
+ SimpleCov.start do
12
+ add_filter "spec"
13
+ add_filter "vendor/bundler_gems"
14
+ end
15
+
16
+ require 'backup_jenkins'
17
+
18
+ RSpec.configure do |config|
19
+ config.treat_symbols_as_metadata_keys_with_true_values = true
20
+ config.run_all_when_everything_filtered = true
21
+ config.filter_run :focus
22
+
23
+ # Run specs in random order to surface order dependencies. If you find an
24
+ # order dependency and want to debug it, you can fix the order by providing
25
+ # the seed, which is printed after each run.
26
+ # --seed 1234
27
+ config.order = 'random'
28
+ end
metadata ADDED
@@ -0,0 +1,116 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: backup_jenkins
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Juan C. Müller
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-11-07 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: aws-sdk
16
+ requirement: &28803200 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *28803200
25
+ - !ruby/object:Gem::Dependency
26
+ name: rake
27
+ requirement: &28802660 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: *28802660
36
+ - !ruby/object:Gem::Dependency
37
+ name: pry-debugger
38
+ requirement: &28802240 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ type: :development
45
+ prerelease: false
46
+ version_requirements: *28802240
47
+ - !ruby/object:Gem::Dependency
48
+ name: pry-stack_explorer
49
+ requirement: &28801720 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: *28801720
58
+ description: Simple Jenkins config and plugin backup to S3
59
+ email:
60
+ - jcmuller@gmail.com
61
+ executables:
62
+ - backup_jenkins
63
+ extensions: []
64
+ extra_rdoc_files: []
65
+ files:
66
+ - .gitignore
67
+ - .rspec
68
+ - .travis.yml
69
+ - Gemfile
70
+ - LICENSE
71
+ - README.md
72
+ - Rakefile
73
+ - backup_jenkins.gemspec
74
+ - bin/backup_jenkins
75
+ - config/config-sample.yml
76
+ - lib/backup_jenkins.rb
77
+ - lib/backup_jenkins/aws.rb
78
+ - lib/backup_jenkins/backup.rb
79
+ - lib/backup_jenkins/cli.rb
80
+ - lib/backup_jenkins/config.rb
81
+ - lib/backup_jenkins/version.rb
82
+ - spec/lib/backup_jenkins/aws_spec.rb
83
+ - spec/lib/backup_jenkins/backup_spec.rb
84
+ - spec/lib/backup_jenkins/cli_spec.rb
85
+ - spec/lib/backup_jenkins/config_spec.rb
86
+ - spec/spec_helper.rb
87
+ homepage: http://github.com/jcmuller/jenkins_backup
88
+ licenses: []
89
+ post_install_message:
90
+ rdoc_options: []
91
+ require_paths:
92
+ - lib
93
+ required_ruby_version: !ruby/object:Gem::Requirement
94
+ none: false
95
+ requirements:
96
+ - - ! '>='
97
+ - !ruby/object:Gem::Version
98
+ version: '0'
99
+ required_rubygems_version: !ruby/object:Gem::Requirement
100
+ none: false
101
+ requirements:
102
+ - - ! '>='
103
+ - !ruby/object:Gem::Version
104
+ version: '0'
105
+ requirements: []
106
+ rubyforge_project:
107
+ rubygems_version: 1.8.15
108
+ signing_key:
109
+ specification_version: 3
110
+ summary: This gem allows you to get a backup instance of jenkins up and running pretty
111
+ quickly
112
+ test_files:
113
+ - spec/lib/backup_jenkins/backup_spec.rb
114
+ - spec/lib/backup_jenkins/cli_spec.rb
115
+ - spec/lib/backup_jenkins/config_spec.rb
116
+ - spec/lib/backup_jenkins/aws_spec.rb