backup_rake_spec.rb 6.84 KB
Newer Older
Hugo Duksis's avatar
Hugo Duksis committed
1 2 3 4 5
require 'spec_helper'
require 'rake'

describe 'gitlab:app namespace rake task' do
  before :all do
6 7 8 9
    Rake.application.rake_require 'tasks/gitlab/task_helpers'
    Rake.application.rake_require 'tasks/gitlab/backup'
    Rake.application.rake_require 'tasks/gitlab/shell'
    Rake.application.rake_require 'tasks/gitlab/db'
10

Hugo Duksis's avatar
Hugo Duksis committed
11 12
    # empty task as env is already loaded
    Rake::Task.define_task :environment
13 14 15

    # We need this directory to run `gitlab:backup:create` task
    FileUtils.mkdir_p('public/uploads')
Hugo Duksis's avatar
Hugo Duksis committed
16 17
  end

18 19 20 21 22
  def run_rake_task(task_name)
    Rake::Task[task_name].reenable
    Rake.application.invoke_task task_name
  end

23
  def reenable_backup_sub_tasks
Marin Jankovski's avatar
Marin Jankovski committed
24
    %w{db repo uploads builds artifacts lfs}.each do |subtask|
25 26 27 28
      Rake::Task["gitlab:backup:#{subtask}:create"].reenable
    end
  end

Hugo Duksis's avatar
Hugo Duksis committed
29 30 31
  describe 'backup_restore' do
    before do
      # avoid writing task output to spec progress
32
      allow($stdout).to receive :write
Hugo Duksis's avatar
Hugo Duksis committed
33 34 35 36
    end

    context 'gitlab version' do
      before do
37 38 39 40 41 42 43 44
        allow(Dir).to receive(:glob).and_return([])
        allow(Dir).to receive(:chdir)
        allow(File).to receive(:exists?).and_return(true)
        allow(Kernel).to receive(:system).and_return(true)
        allow(FileUtils).to receive(:cp_r).and_return(true)
        allow(FileUtils).to receive(:mv).and_return(true)
        allow(Rake::Task["gitlab:shell:setup"]).
          to receive(:invoke).and_return(true)
45
        ENV['force'] = 'yes'
Hugo Duksis's avatar
Hugo Duksis committed
46 47
      end

48
      let(:gitlab_version) { Gitlab::VERSION }
Hugo Duksis's avatar
Hugo Duksis committed
49

Johannes Schleifenbaum's avatar
Johannes Schleifenbaum committed
50
      it 'should fail on mismatch' do
51
        allow(YAML).to receive(:load_file).
52
          and_return({ gitlab_version: "not #{gitlab_version}" })
53 54 55

        expect { run_rake_task('gitlab:backup:restore') }.
          to raise_error(SystemExit)
Hugo Duksis's avatar
Hugo Duksis committed
56 57
      end

Marin Jankovski's avatar
Marin Jankovski committed
58
      it 'should invoke restoration on match' do
59
        allow(YAML).to receive(:load_file).
60
          and_return({ gitlab_version: gitlab_version })
61 62 63 64 65 66 67 68
        expect(Rake::Task['gitlab:db:drop_tables']).to receive(:invoke)
        expect(Rake::Task['gitlab:backup:db:restore']).to receive(:invoke)
        expect(Rake::Task['gitlab:backup:repo:restore']).to receive(:invoke)
        expect(Rake::Task['gitlab:backup:builds:restore']).to receive(:invoke)
        expect(Rake::Task['gitlab:backup:uploads:restore']).to receive(:invoke)
        expect(Rake::Task['gitlab:backup:artifacts:restore']).to receive(:invoke)
        expect(Rake::Task['gitlab:backup:lfs:restore']).to receive(:invoke)
        expect(Rake::Task['gitlab:shell:setup']).to receive(:invoke)
69
        expect { run_rake_task('gitlab:backup:restore') }.not_to raise_error
Hugo Duksis's avatar
Hugo Duksis committed
70 71 72 73
      end
    end

  end # backup_restore task
74 75 76 77 78 79

  describe 'backup_create' do
    def tars_glob
      Dir.glob(File.join(Gitlab.config.backup.path, '*_gitlab_backup.tar'))
    end

80
    def create_backup
81
      FileUtils.rm tars_glob
82 83 84 85

      # Redirect STDOUT and run the rake task
      orig_stdout = $stdout
      $stdout = StringIO.new
86
      reenable_backup_sub_tasks
87
      run_rake_task('gitlab:backup:create')
88
      reenable_backup_sub_tasks
89 90
      $stdout = orig_stdout

91
      @backup_tar = tars_glob.first
92 93
    end

94
    before do
95 96 97
      create_backup
    end

98
    after do
99 100 101
      FileUtils.rm(@backup_tar)
    end

102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
    context 'archive file permissions' do
      it 'should set correct permissions on the tar file' do
        expect(File.exist?(@backup_tar)).to be_truthy
        expect(File::Stat.new(@backup_tar).mode.to_s(8)).to eq('100600')
      end

      context 'with custom archive_permissions' do
        before do
          allow(Gitlab.config.backup).to receive(:archive_permissions).and_return(0651)
          # We created a backup in a before(:all) so it got the default permissions.
          # We now need to do some work to create a _new_ backup file using our stub.
          FileUtils.rm(@backup_tar)
          create_backup
        end

        it 'uses the custom permissions' do
          expect(File::Stat.new(@backup_tar).mode.to_s(8)).to eq('100651')
        end
      end
121 122 123 124
    end

    it 'should set correct permissions on the tar contents' do
      tar_contents, exit_status = Gitlab::Popen.popen(
Marin Jankovski's avatar
Marin Jankovski committed
125
        %W{tar -tvf #{@backup_tar} db uploads.tar.gz repositories builds.tar.gz artifacts.tar.gz lfs.tar.gz}
126 127 128
      )
      expect(exit_status).to eq(0)
      expect(tar_contents).to match('db/')
129
      expect(tar_contents).to match('uploads.tar.gz')
130
      expect(tar_contents).to match('repositories/')
131
      expect(tar_contents).to match('builds.tar.gz')
132
      expect(tar_contents).to match('artifacts.tar.gz')
Marin Jankovski's avatar
Marin Jankovski committed
133
      expect(tar_contents).to match('lfs.tar.gz')
134
      expect(tar_contents).not_to match(/^.{4,9}[rwx].* (database.sql.gz|uploads.tar.gz|repositories|builds.tar.gz|artifacts.tar.gz)\/$/)
135 136 137 138
    end

    it 'should delete temp directories' do
      temp_dirs = Dir.glob(
Marin Jankovski's avatar
Marin Jankovski committed
139
        File.join(Gitlab.config.backup.path, '{db,repositories,uploads,builds,artifacts,lfs}')
140 141 142 143 144
      )

      expect(temp_dirs).to be_empty
    end
  end # backup_create task
145 146 147 148 149 150 151 152 153

  describe "Skipping items" do
    def tars_glob
      Dir.glob(File.join(Gitlab.config.backup.path, '*_gitlab_backup.tar'))
    end

    before :all do
      @origin_cd = Dir.pwd

154
      reenable_backup_sub_tasks
155

156
      FileUtils.rm tars_glob
157 158 159 160

      # Redirect STDOUT and run the rake task
      orig_stdout = $stdout
      $stdout = StringIO.new
161
      ENV["SKIP"] = "repositories,uploads"
162 163 164
      run_rake_task('gitlab:backup:create')
      $stdout = orig_stdout

165
      @backup_tar = tars_glob.first
166 167 168 169 170 171 172 173
    end

    after :all do
      FileUtils.rm(@backup_tar)
      Dir.chdir @origin_cd
    end

    it "does not contain skipped item" do
174
      tar_contents, _exit_status = Gitlab::Popen.popen(
Marin Jankovski's avatar
Marin Jankovski committed
175
        %W{tar -tvf #{@backup_tar} db uploads.tar.gz repositories builds.tar.gz artifacts.tar.gz lfs.tar.gz}
176 177 178
      )

      expect(tar_contents).to match('db/')
179 180
      expect(tar_contents).to match('uploads.tar.gz')
      expect(tar_contents).to match('builds.tar.gz')
181
      expect(tar_contents).to match('artifacts.tar.gz')
Marin Jankovski's avatar
Marin Jankovski committed
182
      expect(tar_contents).to match('lfs.tar.gz')
183 184 185 186
      expect(tar_contents).not_to match('repositories/')
    end

    it 'does not invoke repositories restore' do
187
      allow(Rake::Task['gitlab:shell:setup']).
188
        to receive(:invoke).and_return(true)
189 190
      allow($stdout).to receive :write

191 192 193 194 195 196 197 198
      expect(Rake::Task['gitlab:db:drop_tables']).to receive :invoke
      expect(Rake::Task['gitlab:backup:db:restore']).to receive :invoke
      expect(Rake::Task['gitlab:backup:repo:restore']).not_to receive :invoke
      expect(Rake::Task['gitlab:backup:uploads:restore']).not_to receive :invoke
      expect(Rake::Task['gitlab:backup:builds:restore']).to receive :invoke
      expect(Rake::Task['gitlab:backup:artifacts:restore']).to receive :invoke
      expect(Rake::Task['gitlab:backup:lfs:restore']).to receive :invoke
      expect(Rake::Task['gitlab:shell:setup']).to receive :invoke
199
      expect { run_rake_task('gitlab:backup:restore') }.not_to raise_error
200 201
    end
  end
Hugo Duksis's avatar
Hugo Duksis committed
202
end # gitlab:app namespace