Skip to content

Commit

Permalink
Add spec for git sync (ManageIQ#1)
Browse files Browse the repository at this point in the history
* [draft] add spec for .create_in_provider

* Add EmbeddedTerraform Provider class

* add ensure_managers

* fixed .create_in_provider test

* Add more tests
  • Loading branch information
putmanoj authored Mar 21, 2024
1 parent dfa4fb0 commit 6a1c41d
Show file tree
Hide file tree
Showing 7 changed files with 230 additions and 0 deletions.
22 changes: 22 additions & 0 deletions app/models/manageiq/providers/embedded_terraform/provider.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
class ManageIQ::Providers::EmbeddedTerraform::Provider < Provider
include DefaultTerraformObjects

has_one :automation_manager,
:foreign_key => "provider_id",
:class_name => "ManageIQ::Providers::EmbeddedTerraform::AutomationManager",
:autosave => true

before_validation :ensure_managers

private

def ensure_managers
build_automation_manager unless automation_manager
automation_manager.name = _("%{name} Automation Manager") % {:name => name}
if zone_id_changed?
automation_manager.enabled = Zone.maintenance_zone&.id != zone_id
automation_manager.zone_id = zone_id
end
end

end
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
module ManageIQ::Providers::EmbeddedTerraform::Provider::DefaultTerraformObjects
extend ActiveSupport::Concern

TERRAFORM_OBJECT_SOURCE = "MIQ_TERRAFORM".freeze

included do
has_many :default_terraform_objects, -> { where(:source => TERRAFORM_OBJECT_SOURCE) }, :as => :resource, :dependent => :destroy, :class_name => "CustomAttribute"
end

def default_organization
get_default_terraform_object("organization")
end

def default_organization=(org)
set_default_terraform_object("organization", org)
end

private

def get_default_terraform_object(name)
default_terraform_objects.find_by(:name => name).try(:value).try(:to_i)
end

def set_default_terraform_object(name, value)
default_terraform_objects.find_or_initialize_by(:name => name).update(:value => value)
end

end
11 changes: 11 additions & 0 deletions spec/factories/authentication.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
FactoryBot.define do

factory :embedded_terraform_credential,
:parent => :embedded_automation_manager_authentication,
:class => "ManageIQ::Providers::EmbeddedTerraform::AutomationManager::Credential"

factory :embedded_terraform_scm_credential,
:parent => :embedded_terraform_credential,
:class => "ManageIQ::Providers::EmbeddedTerraform::AutomationManager::ScmCredential"

end
11 changes: 11 additions & 0 deletions spec/factories/ext_management_system.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
FactoryBot.define do
# Leaf classes for automation_manager
factory :embedded_automation_manager_terraform,
:aliases => ["manageiq/providers/embedded_terraform/automation_manager"],
:class => "ManageIQ::Providers::EmbeddedTerraform::AutomationManager",
:parent => :embedded_automation_manager do
provider do
raise "DO NOT USE! Use :provider_embedded_terraform and reference the automation_manager from that record"
end
end
end
3 changes: 3 additions & 0 deletions spec/factories/provider.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
FactoryBot.define do
factory :provider_embedded_terraform, :class => "ManageIQ::Providers::EmbeddedTerraform::Provider", :parent => :provider
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
RSpec.describe ManageIQ::Providers::EmbeddedTerraform::AutomationManager::ConfigurationScriptSource do
context "with a local repo" do
let(:manager) do
FactoryBot.create(:provider_embedded_terraform, :default_organization => 1).managers.first
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, "*")) }
let(:repo_dir_structure) { %w[hello_world.tf] }

before do
FileUtils.mkdir_p(local_repo)

repo = Spec::Support::FakeAnsibleRepo.new(local_repo, repo_dir_structure)
repo.generate
repo.git_branch_create("other_branch")

GitRepository
stub_const("GitRepository::GIT_REPO_DIRECTORY", repo_dir)

EvmSpecHelper.assign_embedded_terraform_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
it "creates a record and initializes a git repo" do
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

git_repo_dir = repo_dir.join(result.git_repository.id.to_s)
expect(files_in_repository(git_repo_dir)).to eq ["hello_world.tf"]
end
end
end

describe "git_repository interaction" do
let(:auth) { FactoryBot.create(:embedded_terraform_scm_credential) }
let(:configuration_script_source) do
described_class.create!(
:name => "foo",
:scm_url => "https://example.com/foo.git",
:authentication => auth
)
end

it "on .create" do
configuration_script_source

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 { configuration_script_source.git_repository }.to_not make_database_queries
expect(configuration_script_source.git_repository_id).to eq git_repository.id
end

it "on .new" do
configuration_script_source = described_class.new(
:name => "foo",
:scm_url => "https://example.com/foo.git",
:authentication => auth
)

expect(GitRepository.count).to eq 0

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 make_database_queries
expect(configuration_script_source.git_repository_id).to eq git_repository.id
end

it "errors when scm_url is invalid" do
expect do
configuration_script_source.update!(:scm_url => "invalid url")
end.to raise_error(ActiveRecord::RecordInvalid)
end

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!(:name => "bar")
expect(GitRepository.first.name).to eq "bar"

configuration_script_source.update!(:scm_url => "https://example.com/bar.git")
expect(GitRepository.first.url).to eq "https://example.com/bar.git"

configuration_script_source.update!(:authentication => nil)
expect(GitRepository.first.authentication).to be_nil
end

end
end
22 changes: 22 additions & 0 deletions spec/support/evm_spec_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Set env var LOG_TO_CONSOLE if you want logging to dump to the console
# e.g. LOG_TO_CONSOLE=true ruby spec/models/vm.rb
$log.logdev = STDERR if ENV['LOG_TO_CONSOLE']

# Set env var LOGLEVEL if you want custom log level during a local test
# e.g. LOG_LEVEL=debug ruby spec/models/vm.rb
env_level = Logger.const_get(ENV['LOG_LEVEL'].to_s.upcase) rescue nil if ENV['LOG_LEVEL']
env_level ||= Logger::INFO
$log.level = env_level
Rails.logger.level = env_level

module EvmSpecHelper
extend RSpec::Mocks::ExampleMethods

def self.assign_embedded_terraform_role(miq_server = nil)
MiqRegion.seed
miq_server ||= local_miq_server
role = ServerRole.find_by(:name => "embedded_terraform") || FactoryBot.create(:server_role, :name => 'embedded_ansible', :max_concurrent => 0)
miq_server.assign_role(role).update(:active => true)
end

end

0 comments on commit 6a1c41d

Please sign in to comment.