cookbooks/aws-parallelcluster-environment/spec/unit/resources/cloudwatch_spec.rb (290 lines of code) (raw):
require 'spec_helper'
class ConvergeCloudWatch
def self.setup(chef_run)
chef_run.converge_dsl('aws-parallelcluster-environment') do
cloudwatch 'setup' do
action :setup
end
end
end
def self.configure(chef_run)
chef_run.converge_dsl('aws-parallelcluster-environment') do
cloudwatch 'configure' do
action :configure
end
end
end
end
describe 'cloudwatch:setup' do
for_all_oses do |platform, version|
context "on #{platform}#{version}" do
cached(:aws_region) { "aws_region" }
cached(:aws_domain) { "aws_domain" }
cached(:sources_dir) { "sources_dir" }
cached(:public_key_local_path) { "#{sources_dir}/amazon-cloudwatch-agent.gpg" }
cached(:s3_domain) { "https://s3.#{aws_region}.#{aws_domain}" }
cached(:package_url_prefix) { "#{s3_domain}/amazoncloudwatch-agent-#{aws_region}" }
cached(:package_extension) { platform == 'ubuntu' ? 'deb' : 'rpm' }
cached(:signature_url) { "#{package_url}.sig" }
cached(:package_path) { "#{sources_dir}/amazon-cloudwatch-agent.#{package_extension}" }
cached(:signature_path) { "#{package_path}.sig" }
context "when not on arm" do
cached(:platform_url_component) do
case platform
when 'amazon'
'amazon_linux'
when 'rocky'
'redhat'
else
platform
end
end
cached(:package_url) { "#{package_url_prefix}/#{platform_url_component}/amd64/latest/amazon-cloudwatch-agent.#{package_extension}" }
cached(:chef_run) do
runner = runner(platform: platform, version: version, step_into: ['cloudwatch']) do |node|
node.override['cluster']['sources_dir'] = sources_dir
node.override['cluster']['region'] = aws_region
node.override['cluster']['aws_domain'] = aws_domain
end
allow_any_instance_of(Object).to receive(:arm_instance?).and_return(false)
ConvergeCloudWatch.setup(runner)
end
it 'sets up cloudwatch' do
is_expected.to setup_cloudwatch('setup')
end
it 'creates source dir' do
is_expected.to create_directory("sources_dir").with_recursive(true)
end
it 'downloads cloudwatch public key' do
is_expected.to create_if_missing_remote_file(public_key_local_path).with(
source: 'https://s3.amazonaws.com/amazoncloudwatch-agent/assets/amazon-cloudwatch-agent.gpg',
retries: 3,
retry_delay: 5
)
end
it 'downloads cloudwatch package' do
is_expected.to create_if_missing_remote_file(package_path).with(
source: package_url,
retries: 3,
retry_delay: 5
)
end
it 'downloads package signature' do
is_expected.to create_if_missing_remote_file(signature_path).with(
source: signature_url,
retries: 3,
retry_delay: 5
)
end
it 'imports cloudwatch agent public key to the keyring' do
is_expected.to run_execute('import-cloudwatch-agent-key').with_command("gpg --import #{public_key_local_path}")
end
it 'verifies cloudwatch agent public key fingerprint' do
is_expected.to run_execute('verify-cloudwatch-agent-public-key-fingerprint')
.with_command('gpg --list-keys --fingerprint "Amazon CloudWatch Agent" | grep "9376 16F3 450B 7D80 6CBD 9725 D581 6730 3B78 9C72"')
end
it 'verifies cloudwatch agent package signature' do
is_expected.to run_execute('verify-cloudwatch-agent-rpm-signature')
.with_command("gpg --verify #{signature_path} #{package_path}")
end
it('installs cloudwatch package') do
if platform == 'ubuntu'
is_expected.to install_dpkg_package(package_path).with_source(package_path)
else
is_expected.to install_package(package_path)
end
end
end
context "when on arm" do
cached(:platform_url_component) do
case platform
when 'amazon'
'amazon_linux'
when 'centos', 'rocky'
'redhat'
else
platform
end
end
cached(:package_url) { "#{package_url_prefix}/#{platform_url_component}/arm64/latest/amazon-cloudwatch-agent.#{package_extension}" }
cached(:chef_run) do
runner = runner(platform: platform, version: version, step_into: ['cloudwatch']) do |node|
node.override['cluster']['sources_dir'] = sources_dir
node.override['cluster']['region'] = aws_region
node.override['cluster']['aws_domain'] = aws_domain
end
allow_any_instance_of(Object).to receive(:arm_instance?).and_return(true)
ConvergeCloudWatch.setup(runner)
end
it 'downloads cloudwatch package' do
is_expected.to create_if_missing_remote_file(package_path).with(
source: package_url,
retries: 3,
retry_delay: 5
)
end
end
end
end
end
describe 'cloudwatch:configure' do
for_all_oses do |platform, version|
context "on #{platform}#{version}" do
cached(:config_script_path) { '/usr/local/bin/write_cloudwatch_agent_json.py' }
cached(:config_schema_path) { '/usr/local/etc/cloudwatch_agent_config_schema.json' }
cached(:config_data_path) { '/usr/local/etc/cloudwatch_agent_config.json' }
cached(:validator_script_path) { '/usr/local/bin/cloudwatch_agent_config_util.py' }
cached(:common_module_path) { '/usr/local/bin/cloudwatch_agent_common_utils.py' }
cached(:cookbook_venv_path) { 'cookbook/virtual/env/path' }
cached(:log_group_name) { 'test_log_group_name' }
cached(:scheduler) { 'test_scheduler' }
cached(:node_type) { 'test_node_type' }
cached(:cluster_config_path) { 'cluster_test_config_path' }
context "when not yet configured and cloudwatch logging enabled" do
cached(:chef_run) do
runner = runner(platform: platform, version: version, step_into: ['cloudwatch']) do |node|
node.override['cluster']['log_group_name'] = log_group_name
node.override['cluster']['scheduler'] = scheduler
node.override['cluster']['node_type'] = node_type
node.override['cluster']['cluster_config_path'] = cluster_config_path
node.override['cluster']['cw_logging_enabled'] = 'true'
end
allow_any_instance_of(Object).to receive(:cookbook_virtualenv_path).and_return(cookbook_venv_path)
stub_command("/opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a status | grep status | grep running").and_return(false)
allow(File).to receive(:exist?).with('/opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json').and_return(false)
ConvergeCloudWatch.configure(runner)
end
it 'configures cloudwatch' do
is_expected.to configure_cloudwatch('configure')
end
it 'creates write_cloudwatch_agent_json.py' do
is_expected.to create_if_missing_cookbook_file('/usr/local/bin/write_cloudwatch_agent_json.py').with(
source: 'cloudwatch/write_cloudwatch_agent_json.py',
path: '/usr/local/bin/write_cloudwatch_agent_json.py',
user: 'root',
group: 'root',
mode: '0755'
)
end
it 'creates cloudwatch_agent_common_utils.py' do
is_expected.to create_if_missing_cookbook_file('/usr/local/bin/cloudwatch_agent_common_utils.py').with(
source: 'cloudwatch/cloudwatch_agent_common_utils.py',
path: '/usr/local/bin/cloudwatch_agent_common_utils.py',
user: 'root',
group: 'root',
mode: '0755'
)
end
it 'creates cloudwatch_agent_config.json' do
is_expected.to create_if_missing_cookbook_file('cloudwatch_agent_config.json').with(
source: 'cloudwatch/cloudwatch_agent_config.json',
path: config_data_path,
user: 'root',
group: 'root',
mode: '0644'
)
end
it 'creates cloudwatch_agent_config_schema.json' do
is_expected.to create_if_missing_cookbook_file('cloudwatch_agent_config_schema.json').with(
source: 'cloudwatch/cloudwatch_agent_config_schema.json',
path: config_schema_path,
user: 'root',
group: 'root',
mode: '0644'
)
end
it 'creates cloudwatch_agent_config_util.py' do
is_expected.to create_if_missing_cookbook_file('cloudwatch_agent_config_util.py').with(
source: 'cloudwatch/cloudwatch_agent_config_util.py',
path: validator_script_path,
user: 'root',
group: 'root',
mode: '0644'
)
end
it 'validates cloudwatch' do
is_expected.to run_execute('cloudwatch-config-validation').with(
user: 'root',
timeout: 300,
environment: {
'CW_LOGS_CONFIGS_SCHEMA_PATH' => config_schema_path,
'CW_LOGS_CONFIGS_PATH' => config_data_path,
},
command: "#{cookbook_venv_path}/bin/python #{validator_script_path}"
)
end
it 'creates cloudwatch config' do
is_expected.to run_execute('cloudwatch-config-creation').with(
user: 'root',
timeout: 300,
environment: {
'LOG_GROUP_NAME' => log_group_name,
'SCHEDULER' => scheduler,
'NODE_ROLE' => node_type,
'CONFIG_DATA_PATH' => config_data_path,
}
)
end
it 'starts cloudwatch agent' do
is_expected.to run_execute("cloudwatch-agent-start").with(
user: 'root',
timeout: 300,
command: "/opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a append-config -m ec2 -c file:/opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json -s || /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a fetch-config -m ec2 -c file:/opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json -s"
)
end
end
context "when cloudwatch config already exists" do
cached(:chef_run) do
runner = runner(platform: platform, version: version, step_into: ['cloudwatch']) do |node|
node.override['cluster']['log_group_name'] = log_group_name
node.override['cluster']['scheduler'] = scheduler
node.override['cluster']['node_type'] = node_type
node.override['cluster']['cluster_config_path'] = cluster_config_path
end
allow(File).to receive(:exist?).with('/opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json').and_return(true)
stub_command("/opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a status | grep status | grep running").and_return(false)
ConvergeCloudWatch.configure(runner)
end
it 'does not owerwrite cloudwatch config' do
is_expected.not_to run_execute('cloudwatch-config-creation')
end
end
context "cloudwatch logging disabled" do
cached(:chef_run) do
runner = runner(platform: platform, version: version, step_into: ['cloudwatch']) do |node|
node.override['cluster']['log_group_name'] = log_group_name
node.override['cluster']['scheduler'] = scheduler
node.override['cluster']['node_type'] = node_type
node.override['cluster']['cluster_config_path'] = cluster_config_path
node.override['cluster']['cw_logging_enabled'] = 'false'
end
stub_command("/opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a status | grep status | grep running").and_return(false)
ConvergeCloudWatch.configure(runner)
end
it 'does not start cloudwatch' do
is_expected.not_to run_execute("cloudwatch-agent-start")
end
end
context "cloudwatch agent already running" do
cached(:chef_run) do
runner = runner(platform: platform, version: version, step_into: ['cloudwatch']) do |node|
node.override['cluster']['log_group_name'] = log_group_name
node.override['cluster']['scheduler'] = scheduler
node.override['cluster']['node_type'] = node_type
node.override['cluster']['cluster_config_path'] = cluster_config_path
node.override['cluster']['cw_logging_enabled'] = 'true'
end
stub_command('/opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a status | grep status | grep running').and_return(true)
ConvergeCloudWatch.configure(runner)
end
it 'starts cloudwatch agent' do
is_expected.to run_execute("cloudwatch-agent-start").with(
user: 'root',
timeout: 300,
command: "/opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a append-config -m ec2 -c file:/opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json -s || /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a fetch-config -m ec2 -c file:/opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json -s"
)
end
end
end
end
end