diff --git a/app/models/git_repository.rb b/app/models/git_repository.rb index da747afad977..6dd7f953e745 100644 --- a/app/models/git_repository.rb +++ b/app/models/git_repository.rb @@ -2,6 +2,7 @@ class GitRepository < ApplicationRecord include AuthenticationMixin + belongs_to :authentication GIT_REPO_DIRECTORY = Rails.root.join('data/git_repos') @@ -158,9 +159,9 @@ def handling_worktree_errors def worktree_params params = {:path => directory_name} params[:certificate_check] = method(:self_signed_cert_cb) if verify_ssl == OpenSSL::SSL::VERIFY_NONE - if authentications.any? - params[:username] = default_authentication.userid - params[:password] = default_authentication.password + if (auth = authentication || default_authentication) + params[:username] = auth.userid + params[:password] = auth.password end params end diff --git a/app/models/manageiq/providers/embedded_ansible/automation_manager/configuration_script_source.rb b/app/models/manageiq/providers/embedded_ansible/automation_manager/configuration_script_source.rb index c76285a64e83..a34351bd3419 100644 --- a/app/models/manageiq/providers/embedded_ansible/automation_manager/configuration_script_source.rb +++ b/app/models/manageiq/providers/embedded_ansible/automation_manager/configuration_script_source.rb @@ -8,7 +8,8 @@ class ManageIQ::Providers::EmbeddedAnsible::AutomationManager::ConfigurationScri default_value_for :scm_type, "git" default_value_for :scm_branch, "master" - belongs_to :git_repository, :dependent => :destroy + belongs_to :git_repository, :autosave => true, :dependent => :destroy + before_validation :sync_git_repository include ManageIQ::Providers::EmbeddedAnsible::CrudCommon @@ -46,14 +47,31 @@ def raw_delete_in_provider end def git_repository - super || begin - transaction do - update!(:git_repository => GitRepository.create!(:url => scm_url)) + (super || (ensure_git_repository && super)).tap { |r| sync_git_repository(r) } + end + + private def ensure_git_repository + transaction do + repo = GitRepository.create!(attrs_for_sync_git_repository) + if new_record? + self.git_repository_id = repo.id + else + update_columns(:git_repository_id => repo.id) end - super end end + private def sync_git_repository(git_repository = nil) + return unless name_changed? || scm_url_changed? || authentication_id_changed? + + git_repository ||= self.git_repository + git_repository.attributes = attrs_for_sync_git_repository + end + + private def attrs_for_sync_git_repository + {:name => name, :url => scm_url, :authentication_id => authentication_id} + end + def sync update_attributes!(:status => "running") transaction do diff --git a/spec/factories/configuration_script_source.rb b/spec/factories/configuration_script_source.rb index 90d5b56e4c52..ebed6e67bc4e 100644 --- a/spec/factories/configuration_script_source.rb +++ b/spec/factories/configuration_script_source.rb @@ -9,5 +9,7 @@ factory :embedded_ansible_configuration_script_source, :parent => :configuration_script_source, - :class => "ManageIQ::Providers::EmbeddedAnsible::AutomationManager::ConfigurationScriptSource" + :class => "ManageIQ::Providers::EmbeddedAnsible::AutomationManager::ConfigurationScriptSource" do + scm_url { "https://example.com/foo.git" } + end end diff --git a/spec/models/manageiq/providers/embedded_ansible/automation_manager/configuration_script_source_spec.rb b/spec/models/manageiq/providers/embedded_ansible/automation_manager/configuration_script_source_spec.rb index 91610bde326e..2705fa77f101 100644 --- a/spec/models/manageiq/providers/embedded_ansible/automation_manager/configuration_script_source_spec.rb +++ b/spec/models/manageiq/providers/embedded_ansible/automation_manager/configuration_script_source_spec.rb @@ -1,343 +1,415 @@ require 'rugged' describe ManageIQ::Providers::EmbeddedAnsible::AutomationManager::ConfigurationScriptSource do - let(:manager) do - FactoryBot.create(:provider_embedded_ansible, :default_organization => 1).managers.first - end + context "with a local repo" do + let(:manager) do + FactoryBot.create(:provider_embedded_ansible, :default_organization => 1).managers.first + end - let(:params) do - { - :name => "hello_world", - :scm_url => "file://#{local_repo}" - } - end + let(:params) do + { + :name => "hello_world", + :scm_url => "file://#{local_repo}" + } + end - let(:clone_dir) { Dir.mktmpdir } - let(:local_repo) { File.join(clone_dir, "hello_world_local") } - let(:repo_dir) { Pathname.new(Dir.mktmpdir) } - let(:repos) { Dir.glob(File.join(repo_dir, "*")) } - - before do - # START: Setup local repo used for this spec - FileUtils.mkdir_p(local_repo) - File.write(File.join(local_repo, "hello_world.yaml"), <<~PLAYBOOK) - - name: Hello World Sample - hosts: all - tasks: - - name: Hello Message - debug: - msg: "Hello World!" - - PLAYBOOK - - # Init new repo at local_repo - # - # $ cd /tmp/clone_dir/hello_world_local && git init . - repo = Rugged::Repository.init_at(local_repo) - index = repo.index - - # Add new files to index - # - # $ git add . - index.add_all - index.write - - # Create initial commit - # - # $ git commit -m "Initial Commit" - Rugged::Commit.create( - repo, - :message => "Initial Commit", - :parents => [], - :tree => index.write_tree(repo), - :update_ref => "HEAD" - ) - - # Create a new branch (don't checkout) - # - # $ git branch other_branch - repo.create_branch("other_branch") - # END: Setup local repo used for this spec - - GitRepository - stub_const("GitRepository::GIT_REPO_DIRECTORY", repo_dir) - - EvmSpecHelper.assign_embedded_ansible_role - end + let(:clone_dir) { Dir.mktmpdir } + let(:local_repo) { File.join(clone_dir, "hello_world_local") } + let(:repo_dir) { Pathname.new(Dir.mktmpdir) } + let(:repos) { Dir.glob(File.join(repo_dir, "*")) } + + before do + # START: Setup local repo used for this spec + FileUtils.mkdir_p(local_repo) + File.write(File.join(local_repo, "hello_world.yaml"), <<~PLAYBOOK) + - name: Hello World Sample + hosts: all + tasks: + - name: Hello Message + debug: + msg: "Hello World!" + + PLAYBOOK + + # Init new repo at local_repo + # + # $ cd /tmp/clone_dir/hello_world_local && git init . + repo = Rugged::Repository.init_at(local_repo) + index = repo.index + + # Add new files to index + # + # $ git add . + index.add_all + index.write + + # Create initial commit + # + # $ git commit -m "Initial Commit" + Rugged::Commit.create( + repo, + :message => "Initial Commit", + :parents => [], + :tree => index.write_tree(repo), + :update_ref => "HEAD" + ) - # Clean up repo dir after each spec - after do - FileUtils.rm_rf(repo_dir) - FileUtils.rm_rf(clone_dir) - end + # Create a new branch (don't checkout) + # + # $ git branch other_branch + repo.create_branch("other_branch") + # END: Setup local repo used for this spec - def files_in_repository(git_repo_dir) - repo = Rugged::Repository.new(git_repo_dir.to_s) - repo.ref("HEAD").target.target.tree.find_all.map { |f| f[:name] } - end + GitRepository + stub_const("GitRepository::GIT_REPO_DIRECTORY", repo_dir) + + EvmSpecHelper.assign_embedded_ansible_role + end + + # Clean up repo dir after each spec + after do + FileUtils.rm_rf(repo_dir) + FileUtils.rm_rf(clone_dir) + end + + def files_in_repository(git_repo_dir) + repo = Rugged::Repository.new(git_repo_dir.to_s) + repo.ref("HEAD").target.target.tree.find_all.map { |f| f[:name] } + end - describe ".create_in_provider" do - let(:notify_creation_args) { notification_args('creation') } + describe ".create_in_provider" do + let(:notify_creation_args) { notification_args('creation') } - context "with valid params" do - it "creates a record and initializes a git repo" do - expect(Notification).to receive(:create!).with(notify_creation_args) - expect(Notification).to receive(:create!).with(notification_args("syncing", {})) + context "with valid params" do + it "creates a record and initializes a git repo" do + expect(Notification).to receive(:create!).with(notify_creation_args) + expect(Notification).to receive(:create!).with(notification_args("syncing", {})) - result = described_class.create_in_provider(manager.id, params) + result = described_class.create_in_provider(manager.id, params) - expect(result).to be_an(described_class) - expect(result.scm_type).to eq("git") - expect(result.scm_branch).to eq("master") - expect(result.status).to eq("successful") - expect(result.last_updated_on).to be_an(Time) - expect(result.last_update_error).to be_nil + expect(result).to be_an(described_class) + expect(result.scm_type).to eq("git") + expect(result.scm_branch).to eq("master") + expect(result.status).to eq("successful") + expect(result.last_updated_on).to be_an(Time) + expect(result.last_update_error).to be_nil - git_repo_dir = repo_dir.join(result.git_repository.id.to_s) - expect(files_in_repository(git_repo_dir)).to eq ["hello_world.yaml"] - end + git_repo_dir = repo_dir.join(result.git_repository.id.to_s) + expect(files_in_repository(git_repo_dir)).to eq ["hello_world.yaml"] + end - # NOTE: Second `.notify` stub below prevents `.sync` from getting fired - it "sets the status to 'new' on create" do - expect(Notification).to receive(:create!).with(notify_creation_args) - expect(described_class).to receive(:notify).with(any_args).and_call_original - expect(described_class).to receive(:notify).with("syncing", any_args).and_return(true) + # NOTE: Second `.notify` stub below prevents `.sync` from getting fired + it "sets the status to 'new' on create" do + expect(Notification).to receive(:create!).with(notify_creation_args) + expect(described_class).to receive(:notify).with(any_args).and_call_original + expect(described_class).to receive(:notify).with("syncing", any_args).and_return(true) - result = described_class.create_in_provider(manager.id, params) + result = described_class.create_in_provider(manager.id, params) - expect(result).to be_an(described_class) - expect(result.scm_type).to eq("git") - expect(result.scm_branch).to eq("master") - expect(result.status).to eq("new") - expect(result.last_updated_on).to be_nil - expect(result.last_update_error).to be_nil + expect(result).to be_an(described_class) + expect(result.scm_type).to eq("git") + expect(result.scm_branch).to eq("master") + expect(result.status).to eq("new") + expect(result.last_updated_on).to be_nil + expect(result.last_update_error).to be_nil - expect(repos).to be_empty + expect(repos).to be_empty + end end - end - context "with invalid params" do - it "does not create a record and does not call git" do - params[:name] = nil - notify_creation_args[:type] = :tower_op_failure + context "with invalid params" do + it "does not create a record and does not call git" do + params[:name] = nil + notify_creation_args[:type] = :tower_op_failure - expect(AwesomeSpawn).to receive(:run!).never - expect(Notification).to receive(:create!).with(notify_creation_args) + expect(AwesomeSpawn).to receive(:run!).never + expect(Notification).to receive(:create!).with(notify_creation_args) - expect do - described_class.create_in_provider manager.id, params - end.to raise_error(ActiveRecord::RecordInvalid) + expect do + described_class.create_in_provider manager.id, params + end.to raise_error(ActiveRecord::RecordInvalid) - expect(repos).to be_empty + expect(repos).to be_empty + end end - end - context "when there is a network error fetching the repo" do - before do - sync_notification_args = notification_args("syncing", {}) - sync_notification_args[:type] = :tower_op_failure + context "when there is a network error fetching the repo" do + before do + sync_notification_args = notification_args("syncing", {}) + sync_notification_args[:type] = :tower_op_failure - expect(Notification).to receive(:create!).with(notify_creation_args) - expect(Notification).to receive(:create!).with(sync_notification_args) - expect(GitRepository).to receive(:create!).and_raise(::Rugged::NetworkError) + expect(Notification).to receive(:create!).with(notify_creation_args) + expect(Notification).to receive(:create!).with(sync_notification_args) + allow_any_instance_of(GitRepository).to receive(:with_worktree).and_raise(::Rugged::NetworkError) - expect do - described_class.create_in_provider(manager.id, params) - end.to raise_error(::Rugged::NetworkError) - end + expect do + described_class.create_in_provider(manager.id, params) + end.to raise_error(::Rugged::NetworkError) + end - it "sets the status to 'error' if syncing has a network error" do - result = described_class.last + it "sets the status to 'error' if syncing has a network error" do + result = described_class.last - expect(result).to be_an(described_class) - expect(result.scm_type).to eq("git") - expect(result.scm_branch).to eq("master") - expect(result.status).to eq("error") - expect(result.last_updated_on).to be_an(Time) - expect(result.last_update_error).to start_with("Rugged::NetworkError") + expect(result).to be_an(described_class) + expect(result.scm_type).to eq("git") + expect(result.scm_branch).to eq("master") + expect(result.status).to eq("error") + expect(result.last_updated_on).to be_an(Time) + expect(result.last_update_error).to start_with("Rugged::NetworkError") - expect(repos).to be_empty - end + expect(repos).to be_empty + end - it "clears last_update_error on re-sync" do - result = described_class.last + it "clears last_update_error on re-sync" do + result = described_class.last - expect(result.status).to eq("error") - expect(result.last_updated_on).to be_an(Time) - expect(result.last_update_error).to start_with("Rugged::NetworkError") + expect(result.status).to eq("error") + expect(result.last_updated_on).to be_an(Time) + expect(result.last_update_error).to start_with("Rugged::NetworkError") - expect(GitRepository).to receive(:create!).and_call_original + allow_any_instance_of(GitRepository).to receive(:with_worktree).and_call_original - result.sync + result.sync - expect(result.status).to eq("successful") - expect(result.last_update_error).to be_nil + expect(result.status).to eq("successful") + expect(result.last_update_error).to be_nil + end end end - end - describe ".create_in_provider_queue" do - it "creates a task and queue item" do - EvmSpecHelper.local_miq_server - task_id = described_class.create_in_provider_queue(manager.id, params) - expect(MiqTask.find(task_id)).to have_attributes(:name => "Creating #{described_class::FRIENDLY_NAME} (name=#{params[:name]})") - expect(MiqQueue.first).to have_attributes( - :args => [manager.id, params], - :class_name => described_class.name, - :method_name => "create_in_provider", - :priority => MiqQueue::HIGH_PRIORITY, - :role => "embedded_ansible", - :zone => nil - ) + describe ".create_in_provider_queue" do + it "creates a task and queue item" do + EvmSpecHelper.local_miq_server + task_id = described_class.create_in_provider_queue(manager.id, params) + expect(MiqTask.find(task_id)).to have_attributes(:name => "Creating #{described_class::FRIENDLY_NAME} (name=#{params[:name]})") + expect(MiqQueue.first).to have_attributes( + :args => [manager.id, params], + :class_name => described_class.name, + :method_name => "create_in_provider", + :priority => MiqQueue::HIGH_PRIORITY, + :role => "embedded_ansible", + :zone => nil + ) + end end - end - describe "#update_in_provider" do - let(:update_params) { { :scm_branch => "other_branch" } } - let(:notify_update_args) { notification_args('update', update_params) } + describe "#update_in_provider" do + let(:update_params) { { :scm_branch => "other_branch" } } + let(:notify_update_args) { notification_args('update', update_params) } - context "with valid params" do - it "updates the record and initializes a git repo" do - record = build_record + context "with valid params" do + it "updates the record and initializes a git repo" do + record = build_record - expect(Notification).to receive(:create!).with(notify_update_args) - expect(Notification).to receive(:create!).with(notification_args("syncing", {})) + expect(Notification).to receive(:create!).with(notify_update_args) + expect(Notification).to receive(:create!).with(notification_args("syncing", {})) - result = record.update_in_provider update_params + result = record.update_in_provider update_params - expect(result).to be_an(described_class) - expect(result.scm_branch).to eq("other_branch") + expect(result).to be_an(described_class) + expect(result.scm_branch).to eq("other_branch") - git_repo_dir = repo_dir.join(result.git_repository.id.to_s) - expect(files_in_repository(git_repo_dir)).to eq ["hello_world.yaml"] + git_repo_dir = repo_dir.join(result.git_repository.id.to_s) + expect(files_in_repository(git_repo_dir)).to eq ["hello_world.yaml"] + end end - end - context "with invalid params" do - it "does not create a record and does not call git" do - record = build_record - update_params[:scm_type] = 'svn' # oh dear god... - notify_update_args[:type] = :tower_op_failure + context "with invalid params" do + it "does not create a record and does not call git" do + record = build_record + update_params[:scm_type] = 'svn' # oh dear god... + notify_update_args[:type] = :tower_op_failure - expect(AwesomeSpawn).to receive(:run!).never - expect(Notification).to receive(:create!).with(notify_update_args) + expect(AwesomeSpawn).to receive(:run!).never + expect(Notification).to receive(:create!).with(notify_update_args) - expect do - record.update_in_provider update_params - end.to raise_error(ActiveRecord::RecordInvalid) + expect do + record.update_in_provider update_params + end.to raise_error(ActiveRecord::RecordInvalid) + end end - end - context "when there is a network error fetching the repo" do - before do - record = build_record + context "when there is a network error fetching the repo" do + before do + record = build_record - sync_notification_args = notification_args("syncing", {}) - sync_notification_args[:type] = :tower_op_failure + sync_notification_args = notification_args("syncing", {}) + sync_notification_args[:type] = :tower_op_failure - expect(Notification).to receive(:create!).with(notify_update_args) - expect(Notification).to receive(:create!).with(sync_notification_args) - expect(record.git_repository).to receive(:update_repo).and_raise(::Rugged::NetworkError) + expect(Notification).to receive(:create!).with(notify_update_args) + expect(Notification).to receive(:create!).with(sync_notification_args) + expect(record.git_repository).to receive(:update_repo).and_raise(::Rugged::NetworkError) - expect do - # described_class.last.update_in_provider update_params - record.update_in_provider update_params - end.to raise_error(::Rugged::NetworkError) - end + expect do + # described_class.last.update_in_provider update_params + record.update_in_provider update_params + end.to raise_error(::Rugged::NetworkError) + end + + it "sets the status to 'error' if syncing has a network error" do + result = described_class.last + + expect(result).to be_an(described_class) + expect(result.scm_type).to eq("git") + expect(result.scm_branch).to eq("other_branch") + expect(result.status).to eq("error") + expect(result.last_updated_on).to be_an(Time) + expect(result.last_update_error).to start_with("Rugged::NetworkError") + end + + it "clears last_update_error on re-sync" do + result = described_class.last - it "sets the status to 'error' if syncing has a network error" do - result = described_class.last + expect(result.status).to eq("error") + expect(result.last_updated_on).to be_an(Time) + expect(result.last_update_error).to start_with("Rugged::NetworkError") - expect(result).to be_an(described_class) - expect(result.scm_type).to eq("git") - expect(result.scm_branch).to eq("other_branch") - expect(result.status).to eq("error") - expect(result.last_updated_on).to be_an(Time) - expect(result.last_update_error).to start_with("Rugged::NetworkError") + expect(result.git_repository).to receive(:update_repo).and_call_original + + result.sync + + expect(result.status).to eq("successful") + expect(result.last_update_error).to be_nil + end end + end - it "clears last_update_error on re-sync" do - result = described_class.last + describe "#update_in_provider_queue" do + it "creates a task and queue item" do + record = build_record + task_id = record.update_in_provider_queue({}) + task_name = "Updating #{described_class::FRIENDLY_NAME} (name=#{record.name})" + + expect(MiqTask.find(task_id)).to have_attributes(:name => task_name) + expect(MiqQueue.first).to have_attributes( + :instance_id => record.id, + :args => [{:task_id => task_id}], + :class_name => described_class.name, + :method_name => "update_in_provider", + :priority => MiqQueue::HIGH_PRIORITY, + :role => "embedded_ansible", + :zone => nil + ) + end + end - expect(result.status).to eq("error") - expect(result.last_updated_on).to be_an(Time) - expect(result.last_update_error).to start_with("Rugged::NetworkError") + describe "#delete_in_provider" do + it "deletes the record and removes the git dir" do + record = build_record + git_repo_dir = repo_dir.join(record.git_repository.id.to_s) - expect(result.git_repository).to receive(:update_repo).and_call_original + expect(Notification).to receive(:create!).with(notification_args('deletion', {})) + record.delete_in_provider - result.sync + expect { record.reload }.to raise_error ActiveRecord::RecordNotFound - expect(result.status).to eq("successful") - expect(result.last_update_error).to be_nil + expect(git_repo_dir).to_not exist end end - end - describe "#update_in_provider_queue" do - it "creates a task and queue item" do - record = build_record - task_id = record.update_in_provider_queue({}) - task_name = "Updating #{described_class::FRIENDLY_NAME} (name=#{record.name})" - - expect(MiqTask.find(task_id)).to have_attributes(:name => task_name) - expect(MiqQueue.first).to have_attributes( - :instance_id => record.id, - :args => [{:task_id => task_id}], - :class_name => described_class.name, - :method_name => "update_in_provider", - :priority => MiqQueue::HIGH_PRIORITY, - :role => "embedded_ansible", - :zone => nil - ) + describe "#delete_in_provider_queue" do + it "creates a task and queue item" do + record = build_record + task_id = record.delete_in_provider_queue + task_name = "Deleting #{described_class::FRIENDLY_NAME} (name=#{record.name})" + + expect(MiqTask.find(task_id)).to have_attributes(:name => task_name) + expect(MiqQueue.first).to have_attributes( + :instance_id => record.id, + :args => [], + :class_name => described_class.name, + :method_name => "delete_in_provider", + :priority => MiqQueue::HIGH_PRIORITY, + :role => "embedded_ansible", + :zone => nil + ) + end + end + + def build_record + expect(Notification).to receive(:create!).with(any_args).twice + described_class.create_in_provider manager.id, params + end + + def notification_args(action, op_arg = params) + { + :type => :tower_op_success, + :options => { + :op_name => "#{described_class::FRIENDLY_NAME} #{action}", + :op_arg => "(#{op_arg.except(:name).map { |k, v| "#{k}=#{v}" }.join(', ')})", + :tower => "EMS(manager_id=#{manager.id})" + } + } end end - describe "#delete_in_provider" do - it "deletes the record and removes the git dir" do - record = build_record - git_repo_dir = repo_dir.join(record.git_repository.id.to_s) + describe "git_repository interaction" do + let(:auth) { FactoryGirl.create(:authentication) } + let(:configuration_script_source) do + described_class.create!( + :name => "foo", + :scm_url => "https://example.com/foo.git", + :authentication => auth + ) + end - expect(Notification).to receive(:create!).with(notification_args('deletion', {})) - record.delete_in_provider + it "on .create" do + configuration_script_source - expect { record.reload }.to raise_error ActiveRecord::RecordNotFound + git_repository = GitRepository.first + expect(git_repository.name).to eq "foo" + expect(git_repository.url).to eq "https://example.com/foo.git" + expect(git_repository.authentication).to eq auth - expect(git_repo_dir).to_not exist + expect { configuration_script_source.git_repository }.to_not exceed_query_limit(0) + expect(configuration_script_source.git_repository_id).to eq git_repository.id end - end - describe "#delete_in_provider_queue" do - it "creates a task and queue item" do - record = build_record - task_id = record.delete_in_provider_queue - task_name = "Deleting #{described_class::FRIENDLY_NAME} (name=#{record.name})" - - expect(MiqTask.find(task_id)).to have_attributes(:name => task_name) - expect(MiqQueue.first).to have_attributes( - :instance_id => record.id, - :args => [], - :class_name => described_class.name, - :method_name => "delete_in_provider", - :priority => MiqQueue::HIGH_PRIORITY, - :role => "embedded_ansible", - :zone => nil + it "on .new" do + configuration_script_source = described_class.new( + :name => "foo", + :scm_url => "https://example.com/foo.git", + :authentication => auth ) + + attached_git_repository = configuration_script_source.git_repository + + git_repository = GitRepository.first + expect(git_repository).to eq attached_git_repository + expect(git_repository.name).to eq "foo" + expect(git_repository.url).to eq "https://example.com/foo.git" + expect(git_repository.authentication).to eq auth + + expect { configuration_script_source.git_repository }.to_not exceed_query_limit(0) + expect(configuration_script_source.git_repository_id).to eq git_repository.id end - end - def build_record - expect(Notification).to receive(:create!).with(any_args).twice - described_class.create_in_provider manager.id, params - end + it "errors when scm_url is invalid" do + expect do + configuration_script_source.update_attributes!(:scm_url => "invalid url") + end.to raise_error(ActiveRecord::RecordInvalid) + end - def notification_args(action, op_arg = params) - { - :type => :tower_op_success, - :options => { - :op_name => "#{described_class::FRIENDLY_NAME} #{action}", - :op_arg => "(#{op_arg.except(:name).map { |k, v| "#{k}=#{v}" }.join(', ')})", - :tower => "EMS(manager_id=#{manager.id})" - } - } + it "syncs attributes down" do + configuration_script_source.name = "bar" + expect(configuration_script_source.git_repository.name).to eq "bar" + + configuration_script_source.scm_url = "https://example.com/bar.git" + expect(configuration_script_source.git_repository.url).to eq "https://example.com/bar.git" + + configuration_script_source.authentication = nil + expect(configuration_script_source.git_repository.authentication).to be_nil + end + + it "persists attributes down" do + configuration_script_source.update_attributes!(:name => "bar") + expect(GitRepository.first.name).to eq "bar" + + configuration_script_source.update_attributes!(:scm_url => "https://example.com/bar.git") + expect(GitRepository.first.url).to eq "https://example.com/bar.git" + + configuration_script_source.update_attributes!(:authentication => nil) + expect(GitRepository.first.authentication).to be_nil + end end end