Refactor and update test-kitchen suites

This provides a large collection of updates and refactoring to improve
the development environment for the cookbooks using test-kitchen.

The primary change this provides is the addition of the 'minimal' suite
which replicates what the integration test jobs run in Zuul. This is
useful for testing and debugging issues that might be found during CI
jobs.

- Switch run_list to using roles to better match how the zuul jobs work
- Update to using Ubuntu 18.04 instead of 16.04
- Move all attributes from .kitchen.yml files to environments
- Update multi-node and dokken test-kitchen
- Use MariaDB 10.1 by default as 10.0 has been deprecated upstream for
  ubuntu 18.04. Also use OSUOSL mirror as it's more stable than
  upstream
- Don't disable EPEL on RHEL systems
- Synchronize attributes (within reason) between test-kitchen files
- Update roles run_list
- Create openstack_test cookbook and update /etc/apt/sources.list to
  OSUOSL mirrors to improve stability on Ubuntu

Change-Id: Ie6d7b56a78f7fadbd28e6d27a46446a46c3c5ebd
Signed-off-by: Lance Albertson <lance@osuosl.org>
This commit is contained in:
Lance Albertson 2019-06-18 13:35:00 -07:00 committed by Jens Harbott
parent d3a307d917
commit 5280706daa
12 changed files with 149 additions and 467 deletions

2
.gitignore vendored
View File

@ -7,7 +7,7 @@
berks-cookbooks/
Berksfile.lock
clients/
cookbooks/
./cookbooks/
Gemfile.lock
nodes/
vms/

View File

@ -14,14 +14,20 @@ transport:
provisioner:
name: dokken
encrypted_data_bag_secret_key_path: .chef/encrypted_data_bag_secret
roles_path: roles
environments_path: environments
attributes:
openstack:
secret:
key_path: /opt/kitchen/encrypted_data_bag_secret
verifier:
name: inspec
platforms:
- name: ubuntu-16.04
- name: ubuntu-18.04
driver:
image: dokken/ubuntu-16.04
image: dokken/ubuntu-18.04
pid_one_command: /bin/systemd
- name: centos-7
platform: rhel
@ -49,95 +55,15 @@ suites:
- '8003'
- '8004'
run_list:
# run_list taken from roles/allinone.json
- recipe[selinux::disabled]
- recipe[openstack-common]
- recipe[openstack-common::logging]
- recipe[openstack-common::sysctl]
- recipe[openstack-common::client]
- recipe[openstack-ops-database::server]
- recipe[openstack-ops-database::openstack-db]
- recipe[openstack-ops-messaging::rabbitmq-server]
- recipe[openstack-identity::server-apache]
- recipe[openstack-identity::registration]
- recipe[openstack-identity::openrc]
- recipe[openstack-image::api]
- recipe[openstack-image::registry]
- recipe[openstack-image::identity_registration]
- recipe[openstack-network::identity_registration]
- recipe[openstack-network::ml2_core_plugin]
- recipe[openstack-network::ml2_openvswitch]
- recipe[openstack-network]
- recipe[openstack-network::openvswitch]
- recipe[openstack-network::_bridge_config_example]
- recipe[openstack-network::plugin_config]
- recipe[openstack-network::server]
- recipe[openstack-network::l3_agent]
- recipe[openstack-network::dhcp_agent]
- recipe[openstack-network::metadata_agent]
- recipe[openstack-network::openvswitch_agent]
- recipe[openstack-compute::nova-setup]
- recipe[openstack-compute::identity_registration]
- recipe[openstack-compute::conductor]
- recipe[openstack-compute::api-os-compute]
- recipe[openstack-compute::api-metadata]
- recipe[openstack-compute::placement_api]
- recipe[openstack-compute::scheduler]
- recipe[openstack-compute::vncproxy]
- recipe[openstack-compute::compute]
- recipe[openstack-compute::identity_registration]
# NOTE: block-storage, orchestration, dashboard, etc. can be installed
# but are not tested by tempest
- recipe[openstack-block-storage::api]
- recipe[openstack-block-storage::scheduler]
- recipe[openstack-block-storage::volume_driver_lvm]
- recipe[openstack-block-storage::volume]
- recipe[openstack-block-storage::backup]
- recipe[openstack-block-storage::identity_registration]
- recipe[openstack-orchestration::engine]
- recipe[openstack-orchestration::api]
- recipe[openstack-orchestration::api-cfn]
- recipe[openstack-orchestration::identity_registration]
- recipe[openstack-image::image_upload]
- recipe[openstack-dashboard::horizon]
- recipe[openstack-dashboard::neutron-lbaas-dashboard]
- recipe[openstack-integration-test::create_network]
- recipe[openstack-integration-test::setup]
- recipe[openstack-integration-test::run_tempest]
- recipe[openstack_test]
- role[allinone]
provisioner:
client_rb:
environment: allinone
verifier:
inspec_tests:
- test/tempest/default
# from environments/allinone.json
attributes:
# Attributes copied from environments/integration.json
apache:
listen: []
yum:
epel:
enabled: false
openstack:
is_release: true
apt:
update_apt_cache: true
dashboard:
server_hostname: localhost
telemetry:
conf:
DEFAULT:
meter_dispatchers: database
mq:
user: admin
network:
tun_network_bridge_interface: eth0
conf:
DEFAULT:
service_plugins: router
image:
image_upload: true
compute:
conf:
libvirt:
cpu_type: none
virt_type: qemu
secret:
key_path: /opt/kitchen/encrypted_data_bag_secret

View File

@ -19,157 +19,23 @@ provisioner:
# before any recipes had a chance to run -> we cannot use a recipe to put the
# secrets file in place.
encrypted_data_bag_secret_key_path: .chef/encrypted_data_bag_secret
roles_path: roles
environments_path: environments
attributes:
# Attributes copied from environments/multinode.json
apache:
listen: []
yum:
epel:
enabled: false
openstack:
is_release: true
apt:
update_apt_cache: true
bind_service:
db:
host: '192.168.101.60'
mq:
host: '192.168.101.60'
main:
identity:
host: '0.0.0.0'
admin:
identity:
host: '0.0.0.0'
all:
block-storage:
host: '0.0.0.0'
compute-api:
host: '0.0.0.0'
compute-metadata-api:
host: '0.0.0.0'
image_api:
host: '0.0.0.0'
image_registry:
host: '0.0.0.0'
network:
host: '0.0.0.0'
orchestration-api:
host: '0.0.0.0'
orchestration-api-cfn:
host: '0.0.0.0'
placement-api:
host: '0.0.0.0'
compute:
conf:
libvirt:
cpu_type: none
virt_type: qemu
dashboard:
server_hostname: controller.example.net
endpoints:
db:
host: '192.168.101.60'
mq:
host: '192.168.101.60'
admin:
block-storage:
host: '192.168.101.60'
compute-api:
host: '192.168.101.60'
compute-metadata-api:
host: '192.168.101.60'
identity:
host: '192.168.101.60'
image_api:
host: '192.168.101.60'
image_registry:
host: '192.168.101.60'
network:
host: '192.168.101.60'
orchestration-api:
host: '192.168.101.60'
orchestration-api-cfn:
host: '192.168.101.60'
placement-api:
host: '192.168.101.60'
internal:
block-storage:
host: '192.168.101.60'
compute-api:
host: '192.168.101.60'
compute-metadata-api:
host: '192.168.101.60'
identity:
host: '192.168.101.60'
image_api:
host: '192.168.101.60'
image_registry:
host: '192.168.101.60'
network:
host: '192.168.101.60'
orchestration-api:
host: '192.168.101.60'
orchestration-api-cfn:
host: '192.168.101.60'
placement-api:
host: '192.168.101.60'
public:
block-storage:
host: '192.168.101.60'
compute-api:
host: '192.168.101.60'
compute-metadata-api:
host: '192.168.101.60'
identity:
host: '192.168.101.60'
image_api:
host: '192.168.101.60'
image_registry:
host: '192.168.101.60'
network:
host: '192.168.101.60'
orchestration-api:
host: '192.168.101.60'
orchestration-api-cfn:
host: '192.168.101.60'
placement-api:
host: '192.168.101.60'
image:
image_upload: true
memcached_servers: ['127.0.0.1:11211']
mq:
user: admin
network:
conf:
DEFAULT:
service_plugins: router
ml2:
tenant_network_types: 'vxlan'
plugins:
ml2_openvswitch:
conf:
ml2_type_vxlan:
vni_ranges: '65537:69999'
vxlan_group: '239.1.1.40'
transport_url:
rabbit_host: '192.168.101.60'
tun_network_bridge_interface: 'eth2'
secret:
key_path: /tmp/kitchen/encrypted_data_bag_secret
sysctl:
net.ipv4.ip_forward: 1
telemetry:
conf:
DEFAULT:
meter_dispatchers: database
verifier:
name: inspec
platforms:
- name: ubuntu-16.04
- name: centos-7.5
- name: ubuntu-18.04
driver:
box: bento/ubuntu-18.04
- name: centos-7
driver:
box: bento/centos-7
suites:
- name: compute1
@ -180,12 +46,12 @@ suites:
network:
- ["private_network", {ip: "192.168.100.61"}]
- ["private_network", {ip: "192.168.101.61"}]
provisioner:
client_rb:
environment: multinode
run_list:
- recipe[openstack-common]
- recipe[openstack-common::logging]
- recipe[openstack-common::sysctl]
- recipe[openstack-common::python]
- recipe[openstack-compute::compute]
- recipe[openstack_test]
- role[multinode-compute]
- name: compute2
customize:
cpus: 2
@ -194,12 +60,12 @@ suites:
network:
- ["private_network", {ip: "192.168.100.62"}]
- ["private_network", {ip: "192.168.101.62"}]
provisioner:
client_rb:
environment: multinode
run_list:
- recipe[openstack-common]
- recipe[openstack-common::logging]
- recipe[openstack-common::sysctl]
- recipe[openstack-common::python]
- recipe[openstack-compute::compute]
- recipe[openstack_test]
- role[multinode-compute]
- name: controller
customize:
cpus: 4
@ -208,60 +74,12 @@ suites:
network:
- ["private_network", {ip: "192.168.100.60"}]
- ["private_network", {ip: "192.168.101.60"}]
provisioner:
client_rb:
environment: multinode
run_list:
# run_list taken from roles/multinode-controller.json
- recipe[openstack-common]
- recipe[openstack-common::logging]
- recipe[openstack-common::sysctl]
- recipe[openstack-common::python]
- recipe[openstack-common::client]
- recipe[openstack-common::etcd]
- recipe[openstack-ops-database::server]
- recipe[openstack-ops-database::openstack-db]
- recipe[openstack-ops-messaging::rabbitmq-server]
- recipe[openstack-identity::server-apache]
- recipe[openstack-identity::registration]
- recipe[openstack-identity::openrc]
- recipe[openstack-image::api]
- recipe[openstack-image::registry]
- recipe[openstack-image::identity_registration]
- recipe[openstack-network::plugin_config]
- recipe[openstack-network::ml2_openvswitch]
- recipe[openstack-network]
- recipe[openstack-network::openvswitch]
- recipe[openstack-network::_bridge_config_example]
- recipe[openstack-network::l3_agent]
- recipe[openstack-network::dhcp_agent]
- recipe[openstack-network::metadata_agent]
- recipe[openstack-network::openvswitch_agent]
- recipe[openstack-compute::nova-setup]
- recipe[openstack-compute::identity_registration]
- recipe[openstack-compute::conductor]
- recipe[openstack-compute::api-os-compute]
- recipe[openstack-compute::api-metadata]
- recipe[openstack-compute::placement_api]
- recipe[openstack-compute::scheduler]
- recipe[openstack-compute::vncproxy]
- recipe[openstack-compute::identity_registration]
# NOTE: block-storage, orchestration, dashboard, etc. will be installed
# but are not tested by tempest
- recipe[openstack-block-storage::api]
- recipe[openstack-block-storage::scheduler]
- recipe[openstack-block-storage::volume_driver_lvm]
- recipe[openstack-block-storage::volume]
- recipe[openstack-block-storage::backup]
- recipe[openstack-block-storage::identity_registration]
- recipe[openstack-orchestration::engine]
- recipe[openstack-orchestration::api]
- recipe[openstack-orchestration::api-cfn]
- recipe[openstack-orchestration::identity_registration]
- recipe[openstack-image::image_upload]
- recipe[openstack-dashboard::horizon]
- recipe[openstack-dashboard::neutron-lbaas-dashboard]
- recipe[openstack-integration-test::create_network]
- recipe[openstack-integration-test::setup]
- recipe[openstack-integration-test::run_tempest]
- recipe[openstack_test]
- role[multinode-controller]
verifier:
inspec_tests:
- test/tempest/default

View File

@ -25,12 +25,18 @@ provisioner:
# before any recipes had a chance to run -> we cannot use a recipe to put the
# secrets file in place.
encrypted_data_bag_secret_key_path: .chef/encrypted_data_bag_secret
roles_path: roles
environments_path: environments
attributes:
openstack:
secret:
key_path: /tmp/kitchen/encrypted_data_bag_secret
verifier:
name: inspec
platforms:
- name: ubuntu-bionic
- name: ubuntu-18.04
driver:
box: bento/ubuntu-18.04
- name: centos-7
@ -40,110 +46,27 @@ platforms:
suites:
- name: default
run_list:
# run_list taken from roles/allinone.json
- recipe[openstack-common]
- recipe[openstack-common::logging]
- recipe[openstack-common::sysctl]
- recipe[openstack-common::client]
- recipe[openstack-ops-database::server]
- recipe[openstack-ops-database::openstack-db]
- recipe[openstack-ops-messaging::rabbitmq-server]
- recipe[openstack-identity::server-apache]
- recipe[openstack-identity::registration]
- recipe[openstack-identity::openrc]
- recipe[openstack-image::api]
- recipe[openstack-image::registry]
- recipe[openstack-image::identity_registration]
- recipe[openstack-network::identity_registration]
- recipe[openstack-network::ml2_core_plugin]
- recipe[openstack-network::ml2_openvswitch]
- recipe[openstack-network]
- recipe[openstack-network::openvswitch]
- recipe[openstack-network::_bridge_config_example]
- recipe[openstack-network::plugin_config]
- recipe[openstack-network::server]
- recipe[openstack-network::l3_agent]
- recipe[openstack-network::dhcp_agent]
- recipe[openstack-network::metadata_agent]
- recipe[openstack-network::openvswitch_agent]
- recipe[openstack-compute::nova-setup]
- recipe[openstack-compute::identity_registration]
- recipe[openstack-compute::conductor]
- recipe[openstack-compute::api-os-compute]
- recipe[openstack-compute::api-metadata]
- recipe[openstack-compute::placement_api]
- recipe[openstack-compute::scheduler]
- recipe[openstack-compute::vncproxy]
- recipe[openstack-compute::compute]
- recipe[openstack-compute::identity_registration]
# NOTE: block-storage, orchestration, dashboard, etc. can be installed
# but are not tested by tempest
- recipe[openstack-block-storage::api]
- recipe[openstack-block-storage::volume_driver_lvm]
- recipe[openstack-block-storage::volume]
- recipe[openstack-block-storage::scheduler]
- recipe[openstack-block-storage::backup]
- recipe[openstack-block-storage::identity_registration]
- recipe[openstack-bare-metal::api]
- recipe[openstack-bare-metal::conductor]
- recipe[openstack-bare-metal::identity_registration]
- recipe[openstack-orchestration::engine]
- recipe[openstack-orchestration::api]
- recipe[openstack-orchestration::api-cfn]
- recipe[openstack-orchestration::identity_registration]
- recipe[openstack-dns::api]
- recipe[openstack-dns::central]
- recipe[openstack-dns::sink]
- recipe[openstack-dns::identity_registration]
- recipe[openstack-image::image_upload]
- recipe[openstack-dashboard::horizon]
- recipe[openstack-dashboard::neutron-lbaas-dashboard]
- recipe[openstack-orchestration::dashboard]
- recipe[openstack-integration-test::create_network]
- recipe[openstack-integration-test::setup]
- recipe[openstack-integration-test::run_tempest]
- recipe[openstack_test]
- role[allinone]
driver_config:
network:
- ["private_network", {ip: <%= public_ip %>}]
provisioner:
client_rb:
environment: allinone
verifier:
inspec_tests:
- test/tempest/default
- name: minimal
run_list:
- recipe[openstack_test]
- role[minimal]
driver_config:
network:
- ["private_network", {ip: <%= public_ip %>}]
provisioner:
client_rb:
environment: integration
verifier:
inspec_tests:
- test/tempest/default
# from environments/allinone-ubuntu16.json, environments/allinone-centos7.json
attributes:
# Attributes copied from environments/integration-ubuntu16.json
apache:
listen: []
yum:
epel:
enabled: false
poise-python:
options:
pip_version: '18.0'
setuptools_version: '40.0.0'
wheel_version: '0.31.1'
openstack:
is_release: true
apt:
update_apt_cache: true
dashboard:
server_hostname: localhost
memcached_servers: ['127.0.0.1:11211']
telemetry:
conf:
DEFAULT:
meter_dispatchers: database
mq:
user: admin
network:
conf:
DEFAULT:
service_plugins: router
image:
image_upload: true
compute:
conf:
libvirt:
cpu_type: none
virt_type: qemu
secret:
key_path: /tmp/kitchen/encrypted_data_bag_secret

View File

@ -29,4 +29,5 @@ else
cookbook 'openstackclient', git: 'https://git.openstack.org/openstack/cookbook-openstackclient'
end
cookbook 'openstack_test', path: 'test/cookbooks/openstack_test'
cookbook 'statsd', github: 'librato/statsd-cookbook'

View File

@ -7,9 +7,12 @@
]
},
"yum": {
"epel": {
"enabled": false
"mariadb": {
"install": {
"version": "10.1"
},
"apt_repository": {
"base_url": "ftp.osuosl.org/pub/mariadb/repo"
}
}
},
@ -29,6 +32,9 @@
"dashboard": {
"server_hostname": "localhost"
},
"memcached_servers": [
"127.0.0.1:11211"
],
"mq": {
"user": "admin"
},
@ -52,4 +58,4 @@
}
}
}
}
}

View File

@ -10,6 +10,9 @@
"mariadb": {
"install": {
"version": "10.1"
},
"apt_repository": {
"base_url": "ftp.osuosl.org/pub/mariadb/repo"
}
}
},

View File

@ -5,23 +5,37 @@
"listen": [
]
},
"yum": {
"epel": {
"enabled": false
},
"mariadb": {
"install": {
"version": "10.1"
},
"apt_repository": {
"base_url": "ftp.osuosl.org/pub/mariadb/repo"
}
}
},
"override_attributes": {
"openstack": {
"is_release": true,
"apt": {
"unattended_upgrades": {
"enable": false
},
"update_apt_cache": true
},
"sysctl": {
"net.ipv4.ip_forward": 1
"telemetry": {
"conf": {
"DEFAULT": {
"meter_dispatchers": "database"
}
}
},
"integration-test": {
"conf": {
"service_available": {
"ceilometer": false,
"heat": false,
"horizon": false
}
}
},
"endpoints": {
"db": {
@ -30,42 +44,10 @@
"mq": {
"host": "192.168.101.60"
},
"admin": {
"identity": {
"host": "192.168.101.60"
},
"network": {
"host": "192.168.101.60"
},
"image_api": {
"host": "192.168.101.60"
},
"image_registry": {
"host": "192.168.101.60"
},
"block-storage": {
"host": "192.168.101.60"
},
"compute-api": {
"host": "192.168.101.60"
},
"compute-metadata-api": {
"host": "192.168.101.60"
},
"compute-novnc": {
"host": "192.168.101.60"
},
"orchestration-api": {
"host": "192.168.101.60"
},
"orchestration-api-cfn": {
"host": "192.168.101.60"
},
"placement-api": {
"host": "192.168.101.60"
}
},
"internal": {
"bare_metal": {
"host": "192.168.101.60"
},
"identity": {
"host": "192.168.101.60"
},
@ -101,6 +83,9 @@
}
},
"public": {
"bare_metal": {
"host": "192.168.101.60"
},
"identity": {
"host": "192.168.101.60"
},
@ -143,17 +128,20 @@
"mq": {
"host": "192.168.101.60"
},
"main": {
"public": {
"identity": {
"host": "0.0.0.0"
}
},
"admin": {
"internal": {
"identity": {
"host": "0.0.0.0"
}
},
"all": {
"bare_metal": {
"host": "0.0.0.0"
},
"network": {
"host": "0.0.0.0"
},
@ -187,32 +175,21 @@
}
},
"dashboard": {
"server_hostname": "localhost"
"server_hostname": "controller.example.net"
},
"memcached_servers": [
"192.168.101.60:11211"
],
"mq": {
"user": "admin"
},
"network": {
"plugins": {
"ml2_openvswitch": {
"conf": {
"ml2_type_vxlan": {
"vni_ranges": "65537:69999",
"vxlan_group": "239.1.1.40"
}
}
}
},
"tun_network_bridge_interface": "enp0s8",
"conf": {
"DEFAULT": {
"service_plugins": "router"
},
"transport_url": {
"rabbit_host": "192.168.101.60"
},
"ml2": {
"tenant_network_types": "vxlan"
}
}
},
@ -232,4 +209,4 @@
}
}
}
}
}

View File

@ -5,7 +5,6 @@
"recipe[openstack-common]",
"recipe[openstack-common::logging]",
"recipe[openstack-common::sysctl]",
"recipe[openstack-common::python]",
"recipe[openstack-common::client]",
"recipe[openstack-common::etcd]",
"recipe[openstack-ops-database::server]",
@ -40,11 +39,18 @@
"recipe[openstack-compute::compute]",
"recipe[openstack-compute::identity_registration]",
"recipe[openstack-block-storage::api]",
"recipe[openstack-block-storage::scheduler]",
"recipe[openstack-block-storage::volume_driver_lvm]",
"recipe[openstack-block-storage::volume]",
"recipe[openstack-block-storage::scheduler]",
"recipe[openstack-block-storage::backup]",
"recipe[openstack-block-storage::identity_registration]",
"recipe[openstack-bare-metal::api]",
"recipe[openstack-bare-metal::conductor]",
"recipe[openstack-bare-metal::identity_registration]",
"recipe[openstack-orchestration::engine]",
"recipe[openstack-orchestration::api]",
"recipe[openstack-orchestration::api-cfn]",
"recipe[openstack-orchestration::identity_registration]",
"recipe[openstack-dns::api]",
"recipe[openstack-dns::central]",
"recipe[openstack-dns::sink]",

View File

@ -5,7 +5,6 @@
"recipe[openstack-common]",
"recipe[openstack-common::logging]",
"recipe[openstack-common::sysctl]",
"recipe[openstack-common::python]",
"recipe[openstack-common::client]",
"recipe[openstack-common::etcd]",
"recipe[openstack-ops-database::server]",
@ -18,9 +17,14 @@
"recipe[openstack-image::registry]",
"recipe[openstack-image::identity_registration]",
"recipe[openstack-network]",
"recipe[openstack-network::server]",
"recipe[openstack-network::ml2_core_plugin]",
"recipe[openstack-network::openvswitch]",
"recipe[openstack-network::_bridge_config_example]",
"recipe[openstack-network::plugin_config]",
"recipe[openstack-network::server]",
"recipe[openstack-network::l3_agent]",
"recipe[openstack-network::dhcp_agent]",
"recipe[openstack-network::metadata_agent]",
"recipe[openstack-network::openvswitch_agent]",
"recipe[openstack-compute::nova-setup]",
"recipe[openstack-compute::identity_registration]",
"recipe[openstack-compute::conductor]",
@ -36,12 +40,21 @@
"recipe[openstack-block-storage::volume]",
"recipe[openstack-block-storage::backup]",
"recipe[openstack-block-storage::identity_registration]",
"recipe[openstack-bare-metal::api]",
"recipe[openstack-bare-metal::conductor]",
"recipe[openstack-bare-metal::identity_registration]",
"recipe[openstack-orchestration::engine]",
"recipe[openstack-orchestration::api]",
"recipe[openstack-orchestration::api-cfn]",
"recipe[openstack-orchestration::identity_registration]",
"recipe[openstack-dns::api]",
"recipe[openstack-dns::central]",
"recipe[openstack-dns::sink]",
"recipe[openstack-dns::identity_registration]",
"recipe[openstack-image::image_upload]",
"recipe[openstack-dashboard::horizon]",
"recipe[openstack-dashboard::neutron-lbaas-dashboard]"
"recipe[openstack-dashboard::neutron-lbaas-dashboard]",
"recipe[openstack-integration-test::create_network]",
"recipe[openstack-integration-test::setup]"
]
}

View File

@ -0,0 +1,2 @@
name 'openstack_test'
version '0.1.0'

View File

@ -0,0 +1,7 @@
# Use OSUOSL mirrors as they are more stable than upstream
execute 'Update /etc/apt/sources.list' do
command 'sed -i -e "s/archive.ubuntu.com/ubuntu.osuosl.org/g" /etc/apt/sources.list'
only_if { node['platform_family'] == 'debian' }
not_if 'grep -q ubuntu.osuosl.org /etc/apt/sources.list'
action :nothing
end.run_action(:run)