diff options
| -rw-r--r-- | README.md | 61 | ||||
| -rw-r--r-- | lib/oxidized/hook/githubrepo.rb | 13 | ||||
| -rw-r--r-- | lib/oxidized/node.rb | 12 | ||||
| -rw-r--r-- | spec/githubrepo_spec.rb | 109 | ||||
| -rw-r--r-- | spec/node_spec.rb | 46 | 
5 files changed, 218 insertions, 23 deletions
| @@ -375,13 +375,40 @@ output:  This uses the rugged/libgit2 interface. So you should remember that normal Git hooks will not be executed. + +For a single repositories for all devices: + +``` yaml +output: +  default: git +  git: +    user: Oxidized +    email: o@example.com +    repo: "/var/lib/oxidized/devices.git"  ``` + +And for groups repositories: + +``` yaml  output:    default: git    git:      user: Oxidized      email: o@example.com +    repo: +      first: "/var/lib/oxidized/first.git" +      second: "/var/lib/oxidized/second.git" +``` + +If you would like to use groups and a single repository, you can force this with the `single_repo` config. + +``` yaml +output: +  default: git +  git: +    single_repo: true      repo: "/var/lib/oxidized/devices.git" +  ```  ### Output: Http @@ -559,6 +586,40 @@ hooks:      timeout: 120  ``` +### githubrepo + +This hook configures the repository `remote` and _push_ the code when the specified event is triggerd. If the `username` and `password` are not provided, the `Rugged::Credentials::SshKeyFromAgent` will be used. + +`githubrepo` hook recognizes following configuration keys: + +  * `remote_repo`: the remote repository to be pushed to. +  * `username`: username for repository auth. +  * `password`: password for repository auth. + +When using groups repositories, each group must have its own `remote` in the `remote_repo` config. + +``` yaml +hooks: +  push_to_remote: +    remote_repo: +      routers: git@git.intranet:oxidized/routers.git +      switches: git@git.intranet:oxidized/switches.git +      firewalls: git@git.intranet:oxidized/firewalls.git +``` + + +## Hook configuration example + +``` yaml +hooks: +  push_to_remote: +    type: githubrepo +    events: [node_success, post_store] +    remote_repo: git@git.intranet:oxidized/test.git +    username: user +    password: pass +``` +  # Ruby API  The following objects exist in Oxidized. diff --git a/lib/oxidized/hook/githubrepo.rb b/lib/oxidized/hook/githubrepo.rb index d10b51e..7fc6677 100644 --- a/lib/oxidized/hook/githubrepo.rb +++ b/lib/oxidized/hook/githubrepo.rb @@ -1,12 +1,12 @@  class GithubRepo < Oxidized::Hook    def validate_cfg! -    cfg.has_key?('remote_repo') or raise KeyError, 'remote_repo is required' +    raise KeyError, 'hook.remote_repo is required' unless cfg.has_key?('remote_repo')    end    def run_hook(ctx) -    repo = Rugged::Repository.new(Oxidized.config.output.git.repo) +    repo = Rugged::Repository.new(ctx.node.repo)      log "Pushing local repository(#{repo.path})..." -    remote = repo.remotes['origin'] || repo.remotes.create('origin', cfg.remote_repo) +    remote = repo.remotes['origin'] || repo.remotes.create('origin', remote_repo(ctx.node))      log "to remote: #{remote.url}"      fetch_and_merge_remote(repo) @@ -54,4 +54,11 @@ class GithubRepo < Oxidized::Hook      end    end +  def remote_repo(node) +    if node.group.nil? || cfg.remote_repo.is_a?(String) +      cfg.remote_repo +    else +      cfg.remote_repo[node.group] +    end +  end  end diff --git a/lib/oxidized/node.rb b/lib/oxidized/node.rb index 7a278a9..35bcad9 100644 --- a/lib/oxidized/node.rb +++ b/lib/oxidized/node.rb @@ -24,7 +24,7 @@ module Oxidized        @vars           = opt[:vars]        @stats          = Stats.new        @retry          = 0 -      @repo           = Oxidized.config.output.git.repo +      @repo           = resolve_repo        # model instance needs to access node instance        @model.node = self @@ -170,5 +170,15 @@ module Oxidized        Oxidized.mgr.model[model].new      end +    def resolve_repo +      remote_repo = Oxidized.config.output.git.repo + +      if Oxidized.config.output.git.single_repo? || @group.nil? || remote_repo.is_a?(String) +        remote_repo +      else +        remote_repo[@group] +      end +    end +    end  end diff --git a/spec/githubrepo_spec.rb b/spec/githubrepo_spec.rb index 9ad43e9..ab5e251 100644 --- a/spec/githubrepo_spec.rb +++ b/spec/githubrepo_spec.rb @@ -2,19 +2,32 @@ require 'spec_helper'  require 'rugged'  require 'oxidized/hook/githubrepo' -describe Oxidized::Node do +describe GithubRepo do    let(:credentials) { mock() }    let(:remote) { mock() } +  let(:remotes) { mock() }    let(:repo_head) { mock() }    let(:repo) { mock() }    let(:gr) { GithubRepo.new }    before(:each) do      Oxidized.asetus = Asetus.new -    Oxidized.config.output.git.repo = 'foo.git' +    Oxidized.config.log = '/dev/null'      Oxidized.setup_logger    end +  describe '#validate_cfg!' do +    before do +      gr.expects(:respond_to?).with(:validate_cfg!).returns(false) # `cfg=` call +    end + +    it 'raise a error when `remote_repo` is not configured' do +      Oxidized.config.hooks.github_repo_hook = { type: 'githubrepo' } +      gr.cfg = Oxidized.config.hooks.github_repo_hook +      proc { gr.validate_cfg! }.must_raise(KeyError) +    end +  end +    describe "#fetch_and_merge_remote" do      before(:each) do        Oxidized.config.hooks.github_repo_hook.remote_repo = 'git@github.com:username/foo.git' @@ -68,31 +81,89 @@ describe Oxidized::Node do    end    describe "#run_hook" do -    before(:each) do -      remote.expects(:url).returns('https://github.com/username/foo.git') -      remote.expects(:push).with(['refs/heads/master'], credentials: credentials).returns(true) +    let(:group) { nil } +    let(:ctx) { OpenStruct.new(node: node) } +    let(:node) do +      Oxidized::Node.new(ip: '127.0.0.1', group: group, model: 'junos', output: 'output') +    end + +    before do        repo_head.expects(:name).twice.returns('refs/heads/master')        repo.expects(:head).twice.returns(repo_head)        repo.expects(:path).returns('foo.git') -      repo.expects(:remotes).returns({'origin' => remote})        repo.expects(:fetch).with('origin', ['refs/heads/master'], credentials: credentials).returns(Hash.new(0)) -      Rugged::Repository.expects(:new).with('foo.git').returns(repo)      end -    it "will push to the remote repository using https" do -      Oxidized.config.hooks.github_repo_hook.remote_repo = 'https://github.com/username/foo.git' -      Oxidized.config.hooks.github_repo_hook.username = 'username' -      Oxidized.config.hooks.github_repo_hook.password = 'password' -      Rugged::Credentials::UserPassword.expects(:new).with(username: 'username', password: 'password').returns(credentials) -      gr.cfg = Oxidized.config.hooks.github_repo_hook -      gr.run_hook(nil).must_equal true +    describe 'when there is only one repository and no groups' do +      before do +        Oxidized.config.output.git.repo = 'foo.git' +        remote.expects(:url).returns('https://github.com/username/foo.git') +        remote.expects(:push).with(['refs/heads/master'], credentials: credentials).returns(true) +        repo.expects(:remotes).returns({'origin' => remote}) +        Rugged::Repository.expects(:new).with('foo.git').returns(repo) +      end + +      it "will push to the remote repository using https" do +        Oxidized.config.hooks.github_repo_hook.remote_repo = 'https://github.com/username/foo.git' +        Oxidized.config.hooks.github_repo_hook.username = 'username' +        Oxidized.config.hooks.github_repo_hook.password = 'password' +        Rugged::Credentials::UserPassword.expects(:new).with(username: 'username', password: 'password').returns(credentials) +        gr.cfg = Oxidized.config.hooks.github_repo_hook +        gr.run_hook(ctx).must_equal true +      end + +      it "will push to the remote repository using ssh" do +        Oxidized.config.hooks.github_repo_hook.remote_repo = 'git@github.com:username/foo.git' +        Rugged::Credentials::SshKeyFromAgent.expects(:new).with(username: 'git').returns(credentials) +        gr.cfg = Oxidized.config.hooks.github_repo_hook +        gr.run_hook(ctx).must_equal true +      end      end -    it "will push to the remote repository using ssh" do -      Oxidized.config.hooks.github_repo_hook.remote_repo = 'git@github.com:username/foo.git' -      Rugged::Credentials::SshKeyFromAgent.expects(:new).with(username: 'git').returns(credentials) -      gr.cfg = Oxidized.config.hooks.github_repo_hook -      gr.run_hook(nil).must_equal true +    describe "when there are groups" do +      let(:group) { 'ggrroouupp' } + +      before do +        Rugged::Credentials::SshKeyFromAgent.expects(:new).with(username: 'git').returns(credentials) +        Rugged::Repository.expects(:new).with(repository).returns(repo) + +        repo.expects(:remotes).twice.returns(remotes) +        remotes.expects(:[]).with('origin').returns(nil) +        remotes.expects(:create).with('origin', create_remote).returns(remote) +        remote.expects(:url).returns('url') +        remote.expects(:push).with(['refs/heads/master'], credentials: credentials).returns(true) +      end + +      describe 'and there are several repositories' do +        let(:create_remote) { 'ggrroouupp#remote_repo' } +        let(:repository) { './ggrroouupp.git' } + +        before do +          Oxidized.config.output.git.repo.ggrroouupp = repository +          Oxidized.config.hooks.github_repo_hook.remote_repo.ggrroouupp = 'ggrroouupp#remote_repo' +        end + +        it 'will push to the node group repository' do +          gr.cfg = Oxidized.config.hooks.github_repo_hook +          gr.run_hook(ctx).must_equal true +        end +      end + +      describe 'and has a single repository' do +        let(:create_remote) { 'github_repo_hook#remote_repo' } +        let(:repository) { 'foo.git' } + +        before do +          Oxidized.config.output.git.repo = repository +          Oxidized.config.hooks.github_repo_hook.remote_repo = 'github_repo_hook#remote_repo' +          Oxidized.config.output.git.single_repo = true +        end + +        it 'will push to the correct repository' do +          gr.cfg = Oxidized.config.hooks.github_repo_hook +          gr.run_hook(ctx).must_equal true +        end +      end      end    end  end diff --git a/spec/node_spec.rb b/spec/node_spec.rb index c568463..21c6e34 100644 --- a/spec/node_spec.rb +++ b/spec/node_spec.rb @@ -41,4 +41,50 @@ describe Oxidized::Node do        status.must_equal :success      end    end + +  describe '#repo' do +    let(:group) { nil } +    let(:node) do +      Oxidized::Node.new({ +        ip: '127.0.0.1', group: group, model: 'junos' +      }) +    end + +    it 'when there are no groups' do +      Oxidized.config.output.git.repo = '/tmp/repository.git' +      node.repo.must_equal '/tmp/repository.git' +    end + +    describe 'when there are groups' do +      let(:group) { 'ggrroouupp' } + +      before do +        Oxidized.config.output.git.single_repo = single_repo +      end + +      describe 'with only one repository' do +        let(:single_repo) { true } + +        before do +          Oxidized.config.output.git.repo = '/tmp/repository.git' +        end + +        it 'should use the correct remote' do +          node.repo.must_equal '/tmp/repository.git' +        end +      end + +      describe 'with more than one repository' do +        let(:single_repo) { nil } + +        before do +          Oxidized.config.output.git.repo.ggrroouupp = '/tmp/ggrroouupp.git' +        end + +        it 'should use the correct remote' do +          node.repo.must_equal '/tmp/ggrroouupp.git' +        end +      end +    end +  end  end | 
