summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.papr.inventory3
-rw-r--r--.tito/packages/openshift-ansible2
-rw-r--r--DEPLOYMENT_TYPES.md2
-rw-r--r--README.md14
-rw-r--r--README_AWS.md200
-rw-r--r--README_GCE.md136
-rw-r--r--README_libvirt.md163
-rw-r--r--README_openstack.md87
-rw-r--r--README_vagrant.md1
-rw-r--r--bin/README.md6
-rwxr-xr-xbin/cluster424
-rw-r--r--callback_plugins/aa_version_requirement.py2
-rw-r--r--docs/proposals/README.md27
-rw-r--r--docs/proposals/playbook_consolidation.md178
-rw-r--r--docs/proposals/proposal_template.md30
-rw-r--r--docs/repo_structure.md6
-rw-r--r--filter_plugins/oo_filters.py19
-rw-r--r--filter_plugins/openshift_node.py13
-rw-r--r--filter_plugins/openshift_version.py4
-rw-r--r--images/installer/README_INVENTORY_GENERATOR.md85
-rw-r--r--images/installer/root/etc/inventory-generator-config.yaml20
-rw-r--r--images/installer/root/exports/config.json.template2
-rwxr-xr-ximages/installer/root/usr/local/bin/generate397
-rwxr-xr-ximages/installer/root/usr/local/bin/run7
-rw-r--r--inventory/README.md6
-rw-r--r--inventory/aws/hosts/ec2.ini189
-rwxr-xr-xinventory/aws/hosts/ec2.py1511
-rw-r--r--inventory/aws/hosts/hosts1
-rw-r--r--inventory/byo/hosts.origin.example74
-rw-r--r--inventory/byo/hosts.ose.example81
-rwxr-xr-xinventory/gce/hosts/gce.py477
-rw-r--r--inventory/gce/hosts/hosts1
-rw-r--r--inventory/libvirt/hosts/hosts1
-rw-r--r--inventory/libvirt/hosts/libvirt.ini20
-rwxr-xr-xinventory/libvirt/hosts/libvirt_generic.py191
-rw-r--r--inventory/openstack/hosts/hosts1
-rwxr-xr-xinventory/openstack/hosts/openstack.py247
-rw-r--r--openshift-ansible.spec194
-rw-r--r--playbooks/README.md2
-rw-r--r--playbooks/adhoc/uninstall.yml2
-rw-r--r--playbooks/aws/README.md256
-rwxr-xr-xplaybooks/aws/openshift-cluster/accept.yml53
-rw-r--r--playbooks/aws/openshift-cluster/add_nodes.yml35
-rw-r--r--playbooks/aws/openshift-cluster/build_ami.yml78
-rw-r--r--playbooks/aws/openshift-cluster/cluster_hosts.yml25
-rw-r--r--playbooks/aws/openshift-cluster/config.yml37
-rw-r--r--playbooks/aws/openshift-cluster/install.yml74
-rw-r--r--playbooks/aws/openshift-cluster/launch.yml54
-rw-r--r--playbooks/aws/openshift-cluster/library/ec2_ami_find.py303
-rw-r--r--playbooks/aws/openshift-cluster/list.yml23
-rw-r--r--playbooks/aws/openshift-cluster/provision.yml17
-rw-r--r--playbooks/aws/openshift-cluster/provision_install.yml16
-rw-r--r--playbooks/aws/openshift-cluster/provision_nodes.yml18
-rw-r--r--playbooks/aws/openshift-cluster/provisioning_vars.example.yml28
-rw-r--r--playbooks/aws/openshift-cluster/scaleup.yml32
-rw-r--r--playbooks/aws/openshift-cluster/service.yml31
-rw-r--r--playbooks/aws/openshift-cluster/tasks/launch_instances.yml188
-rw-r--r--playbooks/aws/openshift-cluster/templates/user_data.j222
-rw-r--r--playbooks/aws/openshift-cluster/terminate.yml77
-rw-r--r--playbooks/aws/openshift-cluster/update.yml34
-rw-r--r--playbooks/aws/openshift-cluster/vars.yml33
-rw-r--r--playbooks/byo/openshift-checks/README.md48
-rw-r--r--playbooks/byo/openshift-checks/adhoc.yml27
-rw-r--r--playbooks/byo/openshift-checks/health.yml3
-rw-r--r--playbooks/byo/openshift-checks/pre-install.yml3
l---------playbooks/byo/openshift-checks/roles (renamed from playbooks/gce/openshift-cluster/roles)0
-rw-r--r--playbooks/byo/openshift-cluster/config.yml2
-rw-r--r--playbooks/byo/openshift-cluster/openshift-logging.yml3
-rw-r--r--playbooks/byo/openshift-cluster/openshift-prometheus.yml4
-rw-r--r--playbooks/byo/openshift-cluster/openshift-provisioners.yml6
-rw-r--r--playbooks/byo/openshift-cluster/service-catalog.yml3
-rw-r--r--playbooks/byo/openshift-etcd/config.yml8
-rw-r--r--playbooks/byo/openshift-etcd/migrate.yml6
-rw-r--r--playbooks/byo/openshift-etcd/restart.yml4
-rw-r--r--playbooks/byo/openshift-etcd/scaleup.yml6
-rw-r--r--playbooks/byo/openshift-loadbalancer/config.yml6
-rw-r--r--playbooks/byo/openshift-master/additional_config.yml6
-rw-r--r--playbooks/byo/openshift-master/config.yml6
-rw-r--r--playbooks/byo/openshift-master/restart.yml4
-rw-r--r--playbooks/byo/openshift-master/scaleup.yml9
-rw-r--r--playbooks/byo/openshift-nfs/config.yml6
-rw-r--r--playbooks/byo/openshift-node/config.yml6
-rw-r--r--playbooks/byo/openshift-node/restart.yml4
-rw-r--r--playbooks/byo/openshift-node/scaleup.yml9
-rw-r--r--playbooks/byo/rhel_subscribe.yml12
-rw-r--r--playbooks/byo/vagrant.yml4
-rw-r--r--playbooks/common/README.md7
-rw-r--r--playbooks/common/openshift-checks/adhoc.yml12
-rw-r--r--playbooks/common/openshift-checks/health.yml6
-rw-r--r--playbooks/common/openshift-checks/pre-install.yml8
-rw-r--r--playbooks/common/openshift-cluster/config.yml43
-rw-r--r--playbooks/common/openshift-cluster/enable_dnsmasq.yml6
-rw-r--r--playbooks/common/openshift-cluster/evaluate_groups.yml23
-rw-r--r--playbooks/common/openshift-cluster/initialize_facts.yml23
-rw-r--r--playbooks/common/openshift-cluster/initialize_firewall.yml7
-rw-r--r--playbooks/common/openshift-cluster/initialize_openshift_version.yml13
-rw-r--r--playbooks/common/openshift-cluster/openshift_hosted.yml4
-rw-r--r--playbooks/common/openshift-cluster/openshift_prometheus.yml9
-rw-r--r--playbooks/common/openshift-cluster/sanity_checks.yml51
-rw-r--r--playbooks/common/openshift-cluster/std_include.yml4
-rw-r--r--playbooks/common/openshift-cluster/tasks/set_etcd_launch_facts.yml2
-rw-r--r--playbooks/common/openshift-cluster/tasks/set_master_launch_facts.yml2
-rw-r--r--playbooks/common/openshift-cluster/tasks/set_node_launch_facts.yml2
-rw-r--r--playbooks/common/openshift-cluster/update_repos_and_packages.yml18
-rw-r--r--playbooks/common/openshift-cluster/upgrades/docker/docker_upgrade.yml3
-rw-r--r--playbooks/common/openshift-cluster/upgrades/docker/tasks/restart.yml (renamed from playbooks/common/openshift-cluster/upgrades/docker/restart.yml)0
-rw-r--r--playbooks/common/openshift-cluster/upgrades/docker/tasks/upgrade.yml (renamed from playbooks/common/openshift-cluster/upgrades/docker/upgrade.yml)0
-rw-r--r--playbooks/common/openshift-cluster/upgrades/docker/upgrade_check.yml4
-rw-r--r--playbooks/common/openshift-cluster/upgrades/etcd/backup.yml2
-rw-r--r--playbooks/common/openshift-cluster/upgrades/init.yml1
-rw-r--r--playbooks/common/openshift-cluster/upgrades/pre/tasks/verify_docker_upgrade_targets.yml (renamed from playbooks/common/openshift-cluster/upgrades/pre/verify_docker_upgrade_targets.yml)6
-rw-r--r--playbooks/common/openshift-cluster/upgrades/pre/verify_inventory_vars.yml4
-rw-r--r--playbooks/common/openshift-cluster/upgrades/pre/verify_nodes_running.yml13
-rw-r--r--playbooks/common/openshift-cluster/upgrades/upgrade_control_plane.yml25
-rw-r--r--playbooks/common/openshift-cluster/upgrades/v3_3/upgrade.yml2
-rw-r--r--playbooks/common/openshift-cluster/upgrades/v3_3/upgrade_control_plane.yml2
-rw-r--r--playbooks/common/openshift-cluster/upgrades/v3_3/upgrade_nodes.yml2
-rw-r--r--playbooks/common/openshift-cluster/upgrades/v3_4/upgrade.yml2
-rw-r--r--playbooks/common/openshift-cluster/upgrades/v3_4/upgrade_control_plane.yml2
-rw-r--r--playbooks/common/openshift-cluster/upgrades/v3_4/upgrade_nodes.yml2
-rw-r--r--playbooks/common/openshift-cluster/upgrades/v3_5/upgrade.yml2
-rw-r--r--playbooks/common/openshift-cluster/upgrades/v3_5/upgrade_control_plane.yml2
-rw-r--r--playbooks/common/openshift-cluster/upgrades/v3_5/upgrade_nodes.yml2
-rw-r--r--playbooks/common/openshift-cluster/upgrades/v3_6/upgrade.yml2
-rw-r--r--playbooks/common/openshift-cluster/upgrades/v3_6/upgrade_control_plane.yml2
-rw-r--r--playbooks/common/openshift-cluster/upgrades/v3_6/upgrade_nodes.yml2
-rw-r--r--playbooks/common/openshift-cluster/upgrades/v3_7/upgrade.yml2
-rw-r--r--playbooks/common/openshift-cluster/upgrades/v3_7/upgrade_control_plane.yml2
-rw-r--r--playbooks/common/openshift-cluster/upgrades/v3_7/upgrade_nodes.yml2
-rw-r--r--playbooks/common/openshift-cluster/upgrades/v3_7/validator.yml11
-rw-r--r--playbooks/common/openshift-etcd/config.yml1
-rw-r--r--playbooks/common/openshift-etcd/migrate.yml77
-rw-r--r--playbooks/common/openshift-etcd/scaleup.yml38
-rw-r--r--playbooks/common/openshift-etcd/service.yml23
-rw-r--r--playbooks/common/openshift-loadbalancer/config.yml1
-rw-r--r--playbooks/common/openshift-loadbalancer/service.yml23
-rw-r--r--playbooks/common/openshift-master/additional_config.yml (renamed from playbooks/common/openshift-cluster/additional_config.yml)13
-rw-r--r--playbooks/common/openshift-master/config.yml60
-rw-r--r--playbooks/common/openshift-master/restart.yml2
-rw-r--r--playbooks/common/openshift-master/scaleup.yml37
-rw-r--r--playbooks/common/openshift-master/service.yml23
-rw-r--r--playbooks/common/openshift-nfs/config.yml2
-rw-r--r--playbooks/common/openshift-nfs/service.yml21
-rw-r--r--playbooks/common/openshift-node/config.yml27
-rw-r--r--playbooks/common/openshift-node/scaleup.yml50
-rw-r--r--playbooks/common/openshift-node/service.yml26
-rw-r--r--playbooks/gce/README.md4
-rw-r--r--playbooks/gce/openshift-cluster/add_nodes.yml43
-rw-r--r--playbooks/gce/openshift-cluster/cluster_hosts.yml25
-rw-r--r--playbooks/gce/openshift-cluster/config.yml36
l---------playbooks/gce/openshift-cluster/filter_plugins1
-rw-r--r--playbooks/gce/openshift-cluster/launch.yml67
-rw-r--r--playbooks/gce/openshift-cluster/list.yml23
l---------playbooks/gce/openshift-cluster/lookup_plugins1
-rw-r--r--playbooks/gce/openshift-cluster/service.yml29
-rw-r--r--playbooks/gce/openshift-cluster/tasks/launch_instances.yml65
-rw-r--r--playbooks/gce/openshift-cluster/terminate.yml58
-rw-r--r--playbooks/gce/openshift-cluster/update.yml34
-rw-r--r--playbooks/gce/openshift-cluster/vars.yml18
-rw-r--r--playbooks/gcp/openshift-cluster/provision.yml19
-rw-r--r--playbooks/libvirt/README.md4
-rw-r--r--playbooks/libvirt/openshift-cluster/cluster_hosts.yml25
-rw-r--r--playbooks/libvirt/openshift-cluster/config.yml39
l---------playbooks/libvirt/openshift-cluster/filter_plugins1
-rw-r--r--playbooks/libvirt/openshift-cluster/launch.yml57
-rw-r--r--playbooks/libvirt/openshift-cluster/list.yml23
l---------playbooks/libvirt/openshift-cluster/lookup_plugins1
l---------playbooks/libvirt/openshift-cluster/roles1
-rw-r--r--playbooks/libvirt/openshift-cluster/service.yml34
-rw-r--r--playbooks/libvirt/openshift-cluster/tasks/configure_libvirt.yml6
-rw-r--r--playbooks/libvirt/openshift-cluster/tasks/configure_libvirt_network.yml11
-rw-r--r--playbooks/libvirt/openshift-cluster/tasks/configure_libvirt_storage_pool.yml30
-rw-r--r--playbooks/libvirt/openshift-cluster/tasks/launch_instances.yml142
-rw-r--r--playbooks/libvirt/openshift-cluster/templates/domain.xml65
-rw-r--r--playbooks/libvirt/openshift-cluster/templates/meta-data3
-rw-r--r--playbooks/libvirt/openshift-cluster/templates/network.xml23
-rw-r--r--playbooks/libvirt/openshift-cluster/templates/storage-pool.xml6
-rw-r--r--playbooks/libvirt/openshift-cluster/templates/user-data43
-rw-r--r--playbooks/libvirt/openshift-cluster/terminate.yml70
-rw-r--r--playbooks/libvirt/openshift-cluster/update.yml37
-rw-r--r--playbooks/libvirt/openshift-cluster/vars.yml40
-rw-r--r--playbooks/openstack/README.md4
-rw-r--r--playbooks/openstack/openshift-cluster/cluster_hosts.yml25
-rw-r--r--playbooks/openstack/openshift-cluster/config.yml33
-rw-r--r--playbooks/openstack/openshift-cluster/files/heat_stack.yaml508
-rw-r--r--playbooks/openstack/openshift-cluster/files/heat_stack_server.yaml152
l---------playbooks/openstack/openshift-cluster/filter_plugins1
-rw-r--r--playbooks/openstack/openshift-cluster/launch.yml191
-rw-r--r--playbooks/openstack/openshift-cluster/list.yml24
l---------playbooks/openstack/openshift-cluster/lookup_plugins1
l---------playbooks/openstack/openshift-cluster/roles1
-rw-r--r--playbooks/openstack/openshift-cluster/terminate.yml49
-rw-r--r--playbooks/openstack/openshift-cluster/update.yml34
-rw-r--r--playbooks/openstack/openshift-cluster/vars.yml38
-rw-r--r--roles/ansible_service_broker/vars/openshift-enterprise.yml2
-rw-r--r--roles/calico/defaults/main.yaml4
-rw-r--r--roles/calico/tasks/main.yml2
-rw-r--r--roles/calico_master/defaults/main.yaml2
-rw-r--r--roles/cockpit/defaults/main.yml4
-rw-r--r--roles/dns/README.md45
-rw-r--r--roles/dns/defaults/main.yml2
-rw-r--r--roles/dns/handlers/main.yml5
-rw-r--r--roles/dns/meta/main.yml9
-rw-r--r--roles/dns/tasks/main.yml46
-rw-r--r--roles/dns/templates/Dockerfile11
-rw-r--r--roles/dns/templates/named.conf23
-rw-r--r--roles/dns/templates/named.service.j215
-rw-r--r--roles/dns/templates/openshift-cluster.zone14
-rw-r--r--roles/docker/defaults/main.yml5
-rw-r--r--roles/docker/tasks/main.yml4
-rw-r--r--roles/docker/tasks/package_docker.yml14
-rw-r--r--roles/docker/tasks/systemcontainer_crio.yml21
-rw-r--r--roles/docker/tasks/systemcontainer_docker.yml20
-rw-r--r--roles/docker/templates/crio.conf.j27
-rw-r--r--roles/etcd/defaults/main.yaml4
-rw-r--r--roles/etcd/templates/etcd.conf.j226
-rw-r--r--roles/etcd_common/defaults/main.yml12
-rw-r--r--roles/etcd_common/tasks/backup.yml5
-rw-r--r--roles/etcd_common/tasks/main.yml2
-rw-r--r--roles/etcd_common/tasks/noop.yml4
-rw-r--r--roles/etcd_migrate/tasks/add_ttls.yml33
-rw-r--r--roles/etcd_migrate/tasks/check.yml3
-rw-r--r--roles/etcd_migrate/tasks/clean_data.yml5
-rw-r--r--roles/etcd_migrate/tasks/main.yml4
-rw-r--r--roles/etcd_migrate/tasks/migrate.yml56
-rw-r--r--roles/flannel_register/defaults/main.yaml5
-rw-r--r--roles/flannel_register/templates/flannel-config.json1
-rw-r--r--roles/lib_openshift/library/oc_adm_ca_server_cert.py9
-rw-r--r--roles/lib_openshift/library/oc_adm_csr.py1649
-rw-r--r--roles/lib_openshift/library/oc_adm_manage_node.py9
-rw-r--r--roles/lib_openshift/library/oc_adm_policy_group.py9
-rw-r--r--roles/lib_openshift/library/oc_adm_policy_user.py9
-rw-r--r--roles/lib_openshift/library/oc_adm_registry.py9
-rw-r--r--roles/lib_openshift/library/oc_adm_router.py9
-rw-r--r--roles/lib_openshift/library/oc_atomic_container.py4
-rw-r--r--roles/lib_openshift/library/oc_clusterrole.py9
-rw-r--r--roles/lib_openshift/library/oc_configmap.py9
-rw-r--r--roles/lib_openshift/library/oc_edit.py9
-rw-r--r--roles/lib_openshift/library/oc_env.py9
-rw-r--r--roles/lib_openshift/library/oc_group.py9
-rw-r--r--roles/lib_openshift/library/oc_image.py9
-rw-r--r--roles/lib_openshift/library/oc_label.py9
-rw-r--r--roles/lib_openshift/library/oc_obj.py9
-rw-r--r--roles/lib_openshift/library/oc_objectvalidator.py9
-rw-r--r--roles/lib_openshift/library/oc_process.py9
-rw-r--r--roles/lib_openshift/library/oc_project.py9
-rw-r--r--roles/lib_openshift/library/oc_pvc.py9
-rw-r--r--roles/lib_openshift/library/oc_route.py16
-rw-r--r--roles/lib_openshift/library/oc_scale.py9
-rw-r--r--roles/lib_openshift/library/oc_secret.py9
-rw-r--r--roles/lib_openshift/library/oc_service.py9
-rw-r--r--roles/lib_openshift/library/oc_serviceaccount.py9
-rw-r--r--roles/lib_openshift/library/oc_serviceaccount_secret.py9
-rw-r--r--roles/lib_openshift/library/oc_storageclass.py9
-rw-r--r--roles/lib_openshift/library/oc_user.py9
-rw-r--r--roles/lib_openshift/library/oc_version.py9
-rw-r--r--roles/lib_openshift/library/oc_volume.py9
-rw-r--r--roles/lib_openshift/src/ansible/oc_adm_csr.py36
-rw-r--r--roles/lib_openshift/src/ansible/oc_atomic_container.py4
-rw-r--r--roles/lib_openshift/src/class/oc_adm_csr.py197
-rw-r--r--roles/lib_openshift/src/class/oc_route.py7
-rw-r--r--roles/lib_openshift/src/doc/csr80
-rw-r--r--roles/lib_openshift/src/lib/base.py9
-rw-r--r--roles/lib_openshift/src/sources.yml10
-rwxr-xr-xroles/lib_openshift/src/test/integration/oc_adm_csr.yml28
-rwxr-xr-xroles/lib_openshift/src/test/integration/oc_configmap.yml4
-rwxr-xr-xroles/lib_openshift/src/test/unit/test_oc_configmap.py6
-rw-r--r--roles/lib_utils/library/iam_cert23.py314
-rw-r--r--roles/lib_utils/library/oo_iam_kms.py172
-rw-r--r--roles/lib_utils/library/repoquery.py18
-rw-r--r--roles/lib_utils/library/yedit.py1
-rw-r--r--roles/lib_utils/src/ansible/repoquery.py17
-rw-r--r--roles/lib_utils/src/lib/import.py1
-rw-r--r--roles/lib_utils/tasks/main.yml1
-rw-r--r--roles/nuage_common/defaults/main.yaml3
-rw-r--r--roles/nuage_common/tasks/main.yml27
-rw-r--r--roles/nuage_master/defaults/main.yml4
-rw-r--r--roles/nuage_master/handlers/main.yaml4
-rw-r--r--roles/nuage_master/tasks/main.yaml83
-rwxr-xr-xroles/nuage_master/templates/nuage-master-config-daemonset.j2111
-rwxr-xr-xroles/nuage_master/templates/nuage-node-config-daemonset.j2206
-rw-r--r--roles/nuage_master/templates/nuage-openshift-monitor.j241
-rw-r--r--roles/nuage_master/vars/main.yaml12
-rw-r--r--roles/nuage_node/defaults/main.yml4
-rw-r--r--roles/nuage_node/handlers/main.yaml6
-rw-r--r--roles/nuage_node/tasks/main.yaml51
-rw-r--r--roles/nuage_node/templates/vsp-openshift.j229
-rw-r--r--roles/nuage_node/vars/main.yaml2
-rw-r--r--roles/openshift_aws/README.md84
-rw-r--r--roles/openshift_aws/defaults/main.yml209
-rw-r--r--roles/openshift_aws/filter_plugins/filters.py28
-rw-r--r--roles/openshift_aws/meta/main.yml3
-rw-r--r--roles/openshift_aws/tasks/ami_copy.yml34
-rw-r--r--roles/openshift_aws/tasks/build_ami.yml48
-rw-r--r--roles/openshift_aws/tasks/build_node_group.yml34
-rw-r--r--roles/openshift_aws/tasks/elb.yml68
-rw-r--r--roles/openshift_aws/tasks/iam_cert.yml29
-rw-r--r--roles/openshift_aws/tasks/launch_config.yml45
-rw-r--r--roles/openshift_aws/tasks/provision.yml54
-rw-r--r--roles/openshift_aws/tasks/provision_nodes.yml66
-rw-r--r--roles/openshift_aws/tasks/s3.yml7
-rw-r--r--roles/openshift_aws/tasks/scale_group.yml32
-rw-r--r--roles/openshift_aws/tasks/seal_ami.yml49
-rw-r--r--roles/openshift_aws/tasks/security_group.yml45
-rw-r--r--roles/openshift_aws/tasks/ssh_keys.yml8
-rw-r--r--roles/openshift_aws/tasks/vpc.yml52
-rw-r--r--roles/openshift_cfme/defaults/main.yml2
-rw-r--r--roles/openshift_cfme/meta/main.yml1
-rw-r--r--roles/openshift_cfme/tasks/nfs.yml7
-rw-r--r--roles/openshift_cfme/templates/miq-pv-db.yaml.j22
-rw-r--r--roles/openshift_cfme/templates/miq-pv-region.yaml.j22
-rw-r--r--roles/openshift_cfme/templates/miq-pv-server.yaml.j22
-rw-r--r--roles/openshift_cli/meta/main.yml3
-rw-r--r--roles/openshift_cli/tasks/main.yml2
-rw-r--r--roles/openshift_cli_facts/meta/main.yml15
-rw-r--r--roles/openshift_cli_facts/tasks/main.yml6
-rw-r--r--roles/openshift_clock/defaults/main.yml2
-rw-r--r--roles/openshift_clock/meta/main.yml3
-rw-r--r--roles/openshift_clock/tasks/main.yaml17
-rw-r--r--roles/openshift_common/README.md45
-rw-r--r--roles/openshift_common/defaults/main.yml3
-rw-r--r--roles/openshift_common/meta/main.yml15
-rw-r--r--roles/openshift_common/tasks/main.yml78
-rw-r--r--roles/openshift_docker_facts/tasks/main.yml2
-rw-r--r--roles/openshift_examples/README.md14
-rwxr-xr-xroles/openshift_examples/examples-sync.sh1
-rw-r--r--roles/openshift_examples/files/examples/v1.5/cfme-templates/cfme-template.yaml19
-rw-r--r--roles/openshift_examples/files/examples/v3.6/cfme-templates/cfme-template.yaml19
-rw-r--r--roles/openshift_examples/files/examples/v3.6/db-templates/OWNERS12
-rw-r--r--roles/openshift_examples/files/examples/v3.6/db-templates/mariadb-ephemeral-template.json18
-rw-r--r--roles/openshift_examples/files/examples/v3.6/db-templates/mariadb-persistent-template.json18
-rw-r--r--roles/openshift_examples/files/examples/v3.6/db-templates/mongodb-ephemeral-template.json20
-rw-r--r--roles/openshift_examples/files/examples/v3.6/db-templates/mongodb-persistent-template.json20
-rw-r--r--roles/openshift_examples/files/examples/v3.6/db-templates/mysql-ephemeral-template.json21
-rw-r--r--roles/openshift_examples/files/examples/v3.6/db-templates/mysql-persistent-template.json18
-rw-r--r--roles/openshift_examples/files/examples/v3.6/db-templates/postgresql-ephemeral-template.json20
-rw-r--r--roles/openshift_examples/files/examples/v3.6/db-templates/postgresql-persistent-template.json20
-rw-r--r--roles/openshift_examples/files/examples/v3.6/db-templates/redis-ephemeral-template.json7
-rw-r--r--roles/openshift_examples/files/examples/v3.6/db-templates/redis-persistent-template.json7
-rw-r--r--roles/openshift_examples/files/examples/v3.6/image-streams/OWNERS14
-rw-r--r--roles/openshift_examples/files/examples/v3.6/image-streams/dotnet_imagestreams.json69
-rw-r--r--roles/openshift_examples/files/examples/v3.6/quickstart-templates/OWNERS12
-rw-r--r--roles/openshift_examples/files/examples/v3.6/quickstart-templates/cakephp-mysql-persistent.json6
-rw-r--r--roles/openshift_examples/files/examples/v3.6/quickstart-templates/cakephp-mysql.json6
-rw-r--r--roles/openshift_examples/files/examples/v3.6/quickstart-templates/dancer-mysql-persistent.json6
-rw-r--r--roles/openshift_examples/files/examples/v3.6/quickstart-templates/dancer-mysql.json6
-rw-r--r--roles/openshift_examples/files/examples/v3.6/quickstart-templates/django-postgresql-persistent.json6
-rw-r--r--roles/openshift_examples/files/examples/v3.6/quickstart-templates/django-postgresql.json6
-rw-r--r--roles/openshift_examples/files/examples/v3.6/quickstart-templates/dotnet-example.json6
-rw-r--r--roles/openshift_examples/files/examples/v3.6/quickstart-templates/dotnet-pgsql-persistent.json6
-rw-r--r--roles/openshift_examples/files/examples/v3.6/quickstart-templates/dotnet-runtime-example.json412
-rw-r--r--roles/openshift_examples/files/examples/v3.6/quickstart-templates/httpd.json6
-rw-r--r--roles/openshift_examples/files/examples/v3.6/quickstart-templates/jenkins-ephemeral-template.json10
-rw-r--r--roles/openshift_examples/files/examples/v3.6/quickstart-templates/jenkins-persistent-template.json10
-rw-r--r--roles/openshift_examples/files/examples/v3.6/quickstart-templates/nodejs-mongodb-persistent.json6
-rw-r--r--roles/openshift_examples/files/examples/v3.6/quickstart-templates/nodejs-mongodb.json6
-rw-r--r--roles/openshift_examples/files/examples/v3.6/quickstart-templates/rails-postgresql-persistent.json6
-rw-r--r--roles/openshift_examples/files/examples/v3.6/quickstart-templates/rails-postgresql.json6
-rw-r--r--roles/openshift_examples/files/examples/v3.7/db-templates/mariadb-ephemeral-template.json18
-rw-r--r--roles/openshift_examples/files/examples/v3.7/db-templates/mariadb-persistent-template.json18
-rw-r--r--roles/openshift_examples/files/examples/v3.7/db-templates/mongodb-ephemeral-template.json20
-rw-r--r--roles/openshift_examples/files/examples/v3.7/db-templates/mongodb-persistent-template.json20
-rw-r--r--roles/openshift_examples/files/examples/v3.7/db-templates/mysql-ephemeral-template.json21
-rw-r--r--roles/openshift_examples/files/examples/v3.7/db-templates/mysql-persistent-template.json18
-rw-r--r--roles/openshift_examples/files/examples/v3.7/db-templates/postgresql-ephemeral-template.json20
-rw-r--r--roles/openshift_examples/files/examples/v3.7/db-templates/postgresql-persistent-template.json20
-rw-r--r--roles/openshift_examples/files/examples/v3.7/db-templates/redis-ephemeral-template.json7
-rw-r--r--roles/openshift_examples/files/examples/v3.7/db-templates/redis-persistent-template.json7
-rw-r--r--roles/openshift_examples/files/examples/v3.7/image-streams/OWNERS1
-rw-r--r--roles/openshift_examples/files/examples/v3.7/image-streams/dotnet_imagestreams.json69
-rw-r--r--roles/openshift_examples/files/examples/v3.7/quickstart-templates/cakephp-mysql-persistent.json6
-rw-r--r--roles/openshift_examples/files/examples/v3.7/quickstart-templates/cakephp-mysql.json6
-rw-r--r--roles/openshift_examples/files/examples/v3.7/quickstart-templates/dancer-mysql-persistent.json6
-rw-r--r--roles/openshift_examples/files/examples/v3.7/quickstart-templates/dancer-mysql.json6
-rw-r--r--roles/openshift_examples/files/examples/v3.7/quickstart-templates/django-postgresql-persistent.json6
-rw-r--r--roles/openshift_examples/files/examples/v3.7/quickstart-templates/django-postgresql.json6
-rw-r--r--roles/openshift_examples/files/examples/v3.7/quickstart-templates/dotnet-example.json6
-rw-r--r--roles/openshift_examples/files/examples/v3.7/quickstart-templates/dotnet-pgsql-persistent.json6
-rw-r--r--roles/openshift_examples/files/examples/v3.7/quickstart-templates/dotnet-runtime-example.json412
-rw-r--r--roles/openshift_examples/files/examples/v3.7/quickstart-templates/httpd.json6
-rw-r--r--roles/openshift_examples/files/examples/v3.7/quickstart-templates/jenkins-ephemeral-template.json10
-rw-r--r--roles/openshift_examples/files/examples/v3.7/quickstart-templates/jenkins-persistent-template.json10
-rw-r--r--roles/openshift_examples/files/examples/v3.7/quickstart-templates/nodejs-mongodb-persistent.json6
-rw-r--r--roles/openshift_examples/files/examples/v3.7/quickstart-templates/nodejs-mongodb.json6
-rw-r--r--roles/openshift_examples/files/examples/v3.7/quickstart-templates/rails-postgresql-persistent.json6
-rw-r--r--roles/openshift_examples/files/examples/v3.7/quickstart-templates/rails-postgresql.json6
-rw-r--r--roles/openshift_examples/meta/main.yml3
-rwxr-xr-xroles/openshift_facts/library/openshift_facts.py177
-rw-r--r--roles/openshift_gcp/tasks/main.yaml43
-rw-r--r--roles/openshift_gcp/templates/dns.j2.sh13
-rw-r--r--roles/openshift_gcp/templates/provision.j2.sh318
-rw-r--r--roles/openshift_gcp/templates/remove.j2.sh156
-rw-r--r--roles/openshift_gcp_image_prep/files/partition.conf3
-rw-r--r--roles/openshift_gcp_image_prep/tasks/main.yaml18
-rw-r--r--roles/openshift_health_checker/action_plugins/openshift_health_check.py286
-rw-r--r--roles/openshift_health_checker/callback_plugins/zz_failure_summary.py314
-rw-r--r--roles/openshift_health_checker/library/aos_version.py77
-rw-r--r--roles/openshift_health_checker/openshift_checks/__init__.py132
-rw-r--r--roles/openshift_health_checker/openshift_checks/disk_availability.py12
-rw-r--r--roles/openshift_health_checker/openshift_checks/docker_image_availability.py86
-rw-r--r--roles/openshift_health_checker/openshift_checks/logging/elasticsearch.py8
-rw-r--r--roles/openshift_health_checker/openshift_checks/logging/logging.py4
-rw-r--r--roles/openshift_health_checker/openshift_checks/logging/logging_index_time.py2
-rw-r--r--roles/openshift_health_checker/openshift_checks/mixins.py3
-rw-r--r--roles/openshift_health_checker/openshift_checks/package_availability.py2
-rw-r--r--roles/openshift_health_checker/openshift_checks/package_update.py2
-rw-r--r--roles/openshift_health_checker/openshift_checks/package_version.py3
-rw-r--r--roles/openshift_health_checker/test/action_plugin_test.py149
-rw-r--r--roles/openshift_health_checker/test/conftest.py1
-rw-r--r--roles/openshift_health_checker/test/disk_availability_test.py13
-rw-r--r--roles/openshift_health_checker/test/docker_image_availability_test.py188
-rw-r--r--roles/openshift_health_checker/test/elasticsearch_test.py18
-rw-r--r--roles/openshift_health_checker/test/logging_index_time_test.py8
-rw-r--r--roles/openshift_health_checker/test/openshift_check_test.py43
-rw-r--r--roles/openshift_health_checker/test/ovs_version_test.py2
-rw-r--r--roles/openshift_health_checker/test/package_availability_test.py6
-rw-r--r--roles/openshift_health_checker/test/package_update_test.py6
-rw-r--r--roles/openshift_health_checker/test/package_version_test.py10
-rw-r--r--roles/openshift_health_checker/test/zz_failure_summary_test.py85
-rw-r--r--roles/openshift_hosted/README.md1
-rw-r--r--roles/openshift_hosted/defaults/main.yml17
-rw-r--r--roles/openshift_hosted/tasks/registry/registry.yml69
-rw-r--r--roles/openshift_hosted/tasks/registry/secure.yml100
-rw-r--r--roles/openshift_hosted/tasks/registry/secure/passthrough.yml45
-rw-r--r--roles/openshift_hosted/tasks/registry/secure/reencrypt.yml38
-rw-r--r--roles/openshift_hosted/tasks/registry/storage/object_storage.yml15
l---------roles/openshift_hosted/tasks/registry/storage/registry_config_secret.j21
-rw-r--r--roles/openshift_hosted/tasks/router/router.yml82
-rw-r--r--roles/openshift_hosted/templates/registry_config.j22
-rw-r--r--roles/openshift_hosted/templates/registry_config_secret.j29
-rw-r--r--roles/openshift_hosted_logging/meta/main.yaml1
-rw-r--r--roles/openshift_hosted_templates/files/v1.3/enterprise/registry-console.yaml2
-rw-r--r--roles/openshift_hosted_templates/files/v1.3/origin/registry-console.yaml2
-rw-r--r--roles/openshift_hosted_templates/files/v1.4/enterprise/registry-console.yaml2
-rw-r--r--roles/openshift_hosted_templates/files/v1.4/origin/registry-console.yaml2
-rw-r--r--roles/openshift_hosted_templates/files/v1.5/enterprise/registry-console.yaml2
-rw-r--r--roles/openshift_hosted_templates/files/v1.5/origin/registry-console.yaml2
-rw-r--r--roles/openshift_hosted_templates/files/v3.6/enterprise/registry-console.yaml2
-rw-r--r--roles/openshift_hosted_templates/files/v3.6/origin/registry-console.yaml2
-rw-r--r--roles/openshift_hosted_templates/files/v3.7/enterprise/registry-console.yaml2
-rw-r--r--roles/openshift_hosted_templates/files/v3.7/origin/registry-console.yaml2
-rw-r--r--roles/openshift_hosted_templates/meta/main.yml3
-rw-r--r--roles/openshift_loadbalancer/defaults/main.yml12
-rw-r--r--roles/openshift_logging/README.md17
-rw-r--r--roles/openshift_logging/defaults/main.yml5
-rw-r--r--roles/openshift_logging/tasks/annotate_ops_projects.yaml17
-rw-r--r--roles/openshift_logging/tasks/delete_logging.yaml10
-rw-r--r--roles/openshift_logging/tasks/install_logging.yaml19
-rw-r--r--roles/openshift_logging/vars/main.yaml2
-rw-r--r--roles/openshift_logging_curator/defaults/main.yml4
-rw-r--r--roles/openshift_logging_curator/tasks/main.yaml2
-rw-r--r--roles/openshift_logging_curator/templates/curator.j22
-rw-r--r--roles/openshift_logging_curator/vars/main.yml4
-rw-r--r--roles/openshift_logging_elasticsearch/defaults/main.yml4
-rw-r--r--roles/openshift_logging_elasticsearch/tasks/main.yaml6
-rw-r--r--roles/openshift_logging_elasticsearch/templates/elasticsearch.yml.j23
-rw-r--r--roles/openshift_logging_elasticsearch/templates/es.j215
-rw-r--r--roles/openshift_logging_elasticsearch/vars/main.yml4
-rw-r--r--roles/openshift_logging_fluentd/defaults/main.yml4
-rw-r--r--roles/openshift_logging_fluentd/templates/fluentd.j24
-rw-r--r--roles/openshift_logging_fluentd/vars/main.yml4
-rw-r--r--roles/openshift_logging_kibana/defaults/main.yml8
-rw-r--r--roles/openshift_logging_kibana/tasks/main.yaml4
-rw-r--r--roles/openshift_logging_kibana/templates/kibana.j24
-rw-r--r--roles/openshift_logging_kibana/vars/main.yml4
-rw-r--r--roles/openshift_logging_mux/defaults/main.yml4
-rw-r--r--roles/openshift_logging_mux/tasks/main.yaml2
-rw-r--r--roles/openshift_logging_mux/templates/mux.j22
-rw-r--r--roles/openshift_logging_mux/vars/main.yml4
-rw-r--r--roles/openshift_manageiq/vars/main.yml3
-rw-r--r--roles/openshift_master/README.md9
-rw-r--r--roles/openshift_master/defaults/main.yml28
-rw-r--r--roles/openshift_master/meta/main.yml16
-rw-r--r--roles/openshift_master/tasks/bootstrap.yml28
-rw-r--r--roles/openshift_master/tasks/main.yml51
-rw-r--r--roles/openshift_master/tasks/registry_auth.yml27
-rw-r--r--roles/openshift_master/tasks/systemd_units.yml17
-rw-r--r--roles/openshift_master/tasks/update_etcd_client_urls.yml8
-rw-r--r--roles/openshift_master/templates/docker-cluster/atomic-openshift-master-api.service.j214
-rw-r--r--roles/openshift_master/templates/docker-cluster/atomic-openshift-master-controllers.service.j214
-rw-r--r--roles/openshift_master/templates/master.yaml.v1.j26
-rw-r--r--roles/openshift_master/templates/native-cluster/atomic-openshift-master-api.service.j22
-rw-r--r--roles/openshift_master/templates/native-cluster/atomic-openshift-master-controllers.service.j22
-rw-r--r--roles/openshift_master/vars/main.yml19
-rw-r--r--roles/openshift_master_facts/filter_plugins/openshift_master.py30
-rw-r--r--roles/openshift_metrics/tasks/pre_install.yaml2
-rw-r--r--roles/openshift_node/README.md10
-rw-r--r--roles/openshift_node/defaults/main.yml97
-rw-r--r--roles/openshift_node/handlers/main.yml6
-rw-r--r--roles/openshift_node/meta/main.yml3
-rw-r--r--roles/openshift_node/tasks/bootstrap.yml66
-rw-r--r--roles/openshift_node/tasks/config.yml103
-rw-r--r--roles/openshift_node/tasks/install.yml31
-rw-r--r--roles/openshift_node/tasks/main.yml209
-rw-r--r--roles/openshift_node/tasks/openvswitch_system_container.yml2
-rw-r--r--roles/openshift_node/tasks/registry_auth.yml25
-rw-r--r--roles/openshift_node/tasks/systemd_units.yml48
-rw-r--r--roles/openshift_node/tasks/tuned.yml41
-rw-r--r--roles/openshift_node/templates/node.service.j22
-rw-r--r--roles/openshift_node/templates/node.yaml.v1.j214
-rw-r--r--roles/openshift_node/templates/openshift.docker.node.dep.service2
-rw-r--r--roles/openshift_node/templates/openshift.docker.node.service19
-rw-r--r--roles/openshift_node/templates/tuned/openshift-control-plane/tuned.conf25
-rw-r--r--roles/openshift_node/templates/tuned/openshift-node/tuned.conf10
-rw-r--r--roles/openshift_node/templates/tuned/openshift/tuned.conf24
-rw-r--r--roles/openshift_node/templates/tuned/recommend.conf8
-rw-r--r--roles/openshift_node_certificates/defaults/main.yml1
-rwxr-xr-xroles/openshift_node_dnsmasq/files/networkmanager/99-origin-dns.sh65
-rw-r--r--roles/openshift_node_dnsmasq/meta/main.yml1
-rw-r--r--roles/openshift_node_dnsmasq/tasks/main.yml11
-rw-r--r--roles/openshift_node_upgrade/README.md4
-rw-r--r--roles/openshift_node_upgrade/defaults/main.yml5
-rw-r--r--roles/openshift_node_upgrade/handlers/main.yml2
-rw-r--r--roles/openshift_node_upgrade/meta/main.yml1
-rw-r--r--roles/openshift_node_upgrade/tasks/main.yml4
-rw-r--r--roles/openshift_node_upgrade/tasks/systemd_units.yml6
-rw-r--r--roles/openshift_node_upgrade/templates/openshift.docker.node.service4
-rw-r--r--roles/openshift_persistent_volumes/README.md7
-rw-r--r--roles/openshift_persistent_volumes/meta/main.yml1
-rw-r--r--roles/openshift_prometheus/README.md95
-rw-r--r--roles/openshift_prometheus/defaults/main.yaml74
-rw-r--r--roles/openshift_prometheus/files/openshift_prometheus.exports3
-rw-r--r--roles/openshift_prometheus/meta/main.yaml19
-rw-r--r--roles/openshift_prometheus/tasks/create_pvs.yaml36
-rw-r--r--roles/openshift_prometheus/tasks/install_prometheus.yaml244
-rw-r--r--roles/openshift_prometheus/tasks/main.yaml26
-rw-r--r--roles/openshift_prometheus/tasks/nfs.yaml44
-rw-r--r--roles/openshift_prometheus/templates/alertmanager.yml.j220
-rw-r--r--roles/openshift_prometheus/templates/prom-pv-alertbuffer.yml.j215
-rw-r--r--roles/openshift_prometheus/templates/prom-pv-alertmanager.yml.j215
-rw-r--r--roles/openshift_prometheus/templates/prom-pv-server.yml.j215
-rw-r--r--roles/openshift_prometheus/templates/prometheus.rules.j24
-rw-r--r--roles/openshift_prometheus/templates/prometheus.yml.j2174
-rw-r--r--roles/openshift_prometheus/templates/prometheus_deployment.j2240
-rw-r--r--roles/openshift_prometheus/tests/inventory2
-rw-r--r--roles/openshift_prometheus/tests/test.yaml5
-rw-r--r--roles/openshift_repos/README.md10
-rw-r--r--roles/openshift_repos/tasks/main.yaml27
-rw-r--r--roles/openshift_repos/templates/yum_repo.j214
-rw-r--r--roles/openshift_sanitize_inventory/tasks/main.yml21
-rw-r--r--roles/openshift_sanitize_inventory/vars/main.yml7
-rw-r--r--roles/openshift_service_catalog/defaults/main.yml4
-rw-r--r--roles/openshift_service_catalog/files/openshift-ansible-catalog-console.js1
-rw-r--r--roles/openshift_service_catalog/tasks/install.yml46
-rw-r--r--roles/openshift_service_catalog/templates/api_server_service.j213
-rw-r--r--roles/openshift_service_catalog/templates/controller_manager_service.j213
-rw-r--r--roles/openshift_storage_glusterfs/README.md7
-rw-r--r--roles/openshift_storage_glusterfs/defaults/main.yml10
-rw-r--r--roles/openshift_storage_glusterfs/files/v3.7/deploy-heketi-template.yml143
-rw-r--r--roles/openshift_storage_glusterfs/files/v3.7/glusterfs-template.yml136
-rw-r--r--roles/openshift_storage_glusterfs/files/v3.7/heketi-template.yml134
-rw-r--r--roles/openshift_storage_glusterfs/tasks/glusterfs_common.yml1
-rw-r--r--roles/openshift_storage_glusterfs/tasks/glusterfs_config.yml1
-rw-r--r--roles/openshift_storage_glusterfs/tasks/glusterfs_registry.yml1
-rw-r--r--roles/openshift_storage_glusterfs/templates/v3.7/glusterfs-registry-endpoints.yml.j212
-rw-r--r--roles/openshift_storage_glusterfs/templates/v3.7/glusterfs-registry-service.yml.j210
-rw-r--r--roles/openshift_storage_glusterfs/templates/v3.7/glusterfs-storageclass.yml.j213
-rw-r--r--roles/openshift_storage_glusterfs/templates/v3.7/heketi-endpoints.yml.j212
-rw-r--r--roles/openshift_storage_glusterfs/templates/v3.7/heketi-service.yml.j210
-rw-r--r--roles/openshift_storage_glusterfs/templates/v3.7/heketi.json.j236
-rw-r--r--roles/openshift_storage_glusterfs/templates/v3.7/topology.json.j249
-rw-r--r--roles/openshift_storage_nfs/defaults/main.yml4
-rw-r--r--roles/openshift_version/defaults/main.yml1
-rw-r--r--roles/openshift_version/tasks/main.yml17
-rw-r--r--roles/openshift_version/tasks/set_version_containerized.yml2
-rw-r--r--roles/os_firewall/defaults/main.yml2
-rw-r--r--roles/os_firewall/tasks/iptables.yml2
-rw-r--r--roles/rhel_subscribe/tasks/enterprise.yml11
-rw-r--r--roles/rhel_subscribe/tasks/main.yml8
-rw-r--r--setup.py165
-rw-r--r--test/integration/openshift_health_checker/common.go2
-rw-r--r--test/openshift_version_tests.py30
-rw-r--r--tox.ini1
-rw-r--r--utils/docs/config.md1
574 files changed, 12280 insertions, 9493 deletions
diff --git a/.papr.inventory b/.papr.inventory
index 878d434e2..aa4324c21 100644
--- a/.papr.inventory
+++ b/.papr.inventory
@@ -11,6 +11,9 @@ openshift_image_tag="{{ lookup('env', 'OPENSHIFT_IMAGE_TAG') }}"
openshift_master_default_subdomain="{{ lookup('env', 'RHCI_ocp_node1_IP') }}.xip.io"
openshift_check_min_host_disk_gb=1.5
openshift_check_min_host_memory_gb=1.9
+osm_cluster_network_cidr=10.128.0.0/14
+openshift_portal_net=172.30.0.0/16
+osm_host_subnet_length=9
[masters]
ocp-master
diff --git a/.tito/packages/openshift-ansible b/.tito/packages/openshift-ansible
index 942c51f27..9a5acc500 100644
--- a/.tito/packages/openshift-ansible
+++ b/.tito/packages/openshift-ansible
@@ -1 +1 @@
-3.7.0-0.104.0 ./
+3.7.0-0.126.0 ./
diff --git a/DEPLOYMENT_TYPES.md b/DEPLOYMENT_TYPES.md
index 009a1d95c..e52e47202 100644
--- a/DEPLOYMENT_TYPES.md
+++ b/DEPLOYMENT_TYPES.md
@@ -12,6 +12,6 @@ The table below outlines the defaults per `openshift_deployment_type`:
|-----------------------------------------------------------------|------------------------------------------|----------------------------------------|
| **openshift.common.service_type** (also used for package names) | origin | atomic-openshift |
| **openshift.common.config_base** | /etc/origin | /etc/origin |
-| **openshift.common.data_dir** | /var/lib/origin | /var/lib/origin |
+| **openshift_data_dir** | /var/lib/origin | /var/lib/origin |
| **openshift.master.registry_url openshift.node.registry_url** | openshift/origin-${component}:${version} | openshift3/ose-${component}:${version} |
| **Image Streams** | centos | rhel |
diff --git a/README.md b/README.md
index 315c90063..03dac2282 100644
--- a/README.md
+++ b/README.md
@@ -38,7 +38,7 @@ Follow this release pattern and you can't go wrong:
| Origin/OCP | OpenShift-Ansible version | openshift-ansible branch |
| ------------- | ----------------- |----------------------------------|
| 1.3 / 3.3 | 3.3 | release-1.3 |
-| 1.4 / 3.4 | 3.4 | releaes-1.4 |
+| 1.4 / 3.4 | 3.4 | release-1.4 |
| 1.5 / 3.5 | 3.5 | release-1.5 |
| 3.*X* | 3.*X* | release-3.x |
@@ -55,7 +55,7 @@ you are not running a stable release.
***
Requirements:
- - Ansible >= 2.2.2.0
+ - Ansible >= 2.3.0.0
- Jinja >= 2.7
- pyOpenSSL
- python-lxml
@@ -67,14 +67,10 @@ you are not running a stable release.
dnf install -y ansible pyOpenSSL python-cryptography python-lxml
```
-2. Setup for a specific cloud:
+2. OpenShift Installation Documentation:
- - [AWS](http://github.com/openshift/openshift-ansible/blob/master/README_AWS.md)
- - [GCE](http://github.com/openshift/openshift-ansible/blob/master/README_GCE.md)
- - [local VMs](http://github.com/openshift/openshift-ansible/blob/master/README_libvirt.md)
- - Bring your own host deployments:
- - [OpenShift Enterprise](https://docs.openshift.com/enterprise/latest/install_config/install/advanced_install.html)
- - [OpenShift Origin](https://docs.openshift.org/latest/install_config/install/advanced_install.html)
+ - [OpenShift Enterprise](https://docs.openshift.com/enterprise/latest/install_config/install/advanced_install.html)
+ - [OpenShift Origin](https://docs.openshift.org/latest/install_config/install/advanced_install.html)
## Containerized OpenShift Ansible
diff --git a/README_AWS.md b/README_AWS.md
deleted file mode 100644
index 650a921a4..000000000
--- a/README_AWS.md
+++ /dev/null
@@ -1,200 +0,0 @@
-:warning: **WARNING** :warning: This feature is community supported and has not been tested by Red Hat. Visit [docs.openshift.com](https://docs.openshift.com) for [OpenShift Enterprise](https://docs.openshift.com/enterprise/latest/install_config/install/planning.html) or [OpenShift Origin](https://docs.openshift.org/latest/install_config/install/planning.html) supported installation docs.
-
-AWS Setup Instructions
-======================
-
-Get AWS API credentials
------------------------
-1. [AWS credentials documentation](http://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSGettingStartedGuide/AWSCredentials.html)
-
-
-Create a credentials file
--------------------------
-1. Create a credentials file (eg ~/.aws_creds) that looks something like this (variables must have have these exact names).
-```
- export AWS_ACCESS_KEY_ID='AKIASTUFF'
- export AWS_SECRET_ACCESS_KEY='STUFF'
-```
-2. source this file
-```
- source ~/.aws_creds
-```
-Note: You must source this file before running any Ansible commands.
-
-Alternatively, you could configure credentials in either ~/.boto or ~/.aws/credentials, see the [boto docs](http://docs.pythonboto.org/en/latest/boto_config_tut.html) for the format.
-
-Subscribe to CentOS
--------------------
-
-1. [CentOS on AWS](https://aws.amazon.com/marketplace/pp/B00O7WM7QW)
-
-
-Set up Security Group
----------------------
-By default, a cluster is launched into the `public` security group. Make sure you allow hosts to talk to each other on port `4789` for SDN.
-You may also want to allow access from the outside world on the following ports:
-
-```
-• 22/TCP - ssh
-• 80/TCP - Web Apps
-• 443/TCP - Web Apps (https)
-• 4789/UDP - SDN / VXLAN
-• 8443/TCP - OpenShift Console
-• 10250/TCP - kubelet
-```
-
-
-Determine your subnet and setup the VPC
----------------------------------------
-
-In the AWS VPC console, look up your subnet ID for the region you want to use and set it as such:
-
-- export ec2_vpc_subnet='my_vpc_subnet'
-
-Go to Your VPCs, select the VPC, and under Actions -> DNS Hostnames, set to Yes and Save.
-
-
-(Optional) Setup your $HOME/.ssh/config file
--------------------------------------------
-In case of a cluster creation, or any other case where you don't know the machine hostname in advance, you can use `.ssh/config`
-to setup a private key file to allow ansible to connect to the created hosts.
-
-To do so, add the the following entry to your $HOME/.ssh/config file and make it point to the private key file which allows you to login on AWS.
-```
-Host *.compute-1.amazonaws.com
- IdentityFile $HOME/.ssh/my_private_key.pem
-```
-
-Alternatively, you can configure your ssh-agent to hold the credentials to connect to your AWS instances.
-
-(Optional) Choose where the cluster will be launched
-----------------------------------------------------
-
-By default, a cluster is launched with the following configuration:
-
-- Instance type: m4.large
-- AMI: ami-7a9e9812 (for online deployments, ami-61bbf104 for origin deployments and ami-10663b78 for enterprise deployments)
-- Region: us-east-1
-- Keypair name: libra
-- Security group: public
-
-#### Master specific defaults:
-- Master root volume size: 10 (in GiBs)
-- Master root volume type: gp2
-- Master root volume iops: 500 (only applicable when volume type is io1)
-
-#### Node specific defaults:
-- Node root volume size: 10 (in GiBs)
-- Node root volume type: gp2
-- Node root volume iops: 500 (only applicable when volume type is io1)
-- Docker volume size: 25 (in GiBs)
-- Docker volume ephemeral: true (Whether the docker volume is ephemeral)
-- Docker volume type: gp2 (only applicable if ephemeral is false)
-- Docker volume iops: 500 (only applicable when volume type is io1)
-
-### Specifying ec2 instance type.
-
-#### All instances:
-
-- export ec2_instance_type='m4.large'
-
-#### Master instances:
-
-- export ec2_master_instance_type='m4.large'
-
-#### Infra node instances:
-
-- export ec2_infra_instance_type='m4.large'
-
-#### Non-infra node instances:
-
-- export ec2_node_instance_type='m4.large'
-
-#### etcd instances:
-
-- export ec2_etcd_instance_type='m4.large'
-
-If needed, these values can be changed by setting environment variables on your system.
-
-- export ec2_image='ami-307b3658'
-- export ec2_region='us-east-1'
-- export ec2_keypair='libra'
-- export ec2_security_groups="['public']"
-- export ec2_assign_public_ip='true'
-- export os_etcd_root_vol_size='20'
-- export os_etcd_root_vol_type='standard'
-- export os_etcd_vol_size='20'
-- export os_etcd_vol_type='standard'
-- export os_master_root_vol_size='20'
-- export os_master_root_vol_type='standard'
-- export os_node_root_vol_size='15'
-- export os_docker_vol_size='50'
-- export os_docker_vol_ephemeral='false'
-
-Install Dependencies
---------------------
-1. Ansible requires python-boto for aws operations:
-
-Fedora
-```
- dnf install -y ansible python-boto pyOpenSSL
-```
-
-RHEL/CentOS
-```
- yum install -y ansible python-boto pyOpenSSL
-```
-OSX:
-```
- pip install -U pyopenssl boto
-```
-
-
-Test The Setup
---------------
-1. cd openshift-ansible
-1. Try to list all instances (Passing an empty string as the cluster_id
-argument will result in all ec2 instances being listed)
-```
- bin/cluster list aws ''
-```
-
-Creating a cluster
-------------------
-1. To create a cluster with one master and two nodes
-```
- bin/cluster create aws <cluster-id>
-```
-
-Updating a cluster
----------------------
-1. To update the cluster
-```
- bin/cluster update aws <cluster-id>
-```
-
-Terminating a cluster
----------------------
-1. To terminate the cluster
-```
- bin/cluster terminate aws <cluster-id>
-```
-
-Specifying a deployment type
----------------------------
-The --deployment-type flag can be passed to bin/cluster to specify the deployment type
-1. To launch an OpenShift Enterprise cluster (requires a valid subscription):
-```
- bin/cluster create aws --deployment-type=openshift-enterprise <cluster-id>
-```
-Note: If no deployment type is specified, then the default is origin.
-
-
-## Post-ansible steps
-
-You should now be ready to follow the **What's Next?** section of the advanced installation guide to deploy your router, registry, and other components.
-
-Refer to the advanced installation guide for your deployment type:
-
-* [OpenShift Enterprise](https://docs.openshift.com/enterprise/latest/install_config/install/advanced_install.html#what-s-next)
-* [OpenShift Origin](https://docs.openshift.org/latest/install_config/install/advanced_install.html#what-s-next)
diff --git a/README_GCE.md b/README_GCE.md
deleted file mode 100644
index 99c8715de..000000000
--- a/README_GCE.md
+++ /dev/null
@@ -1,136 +0,0 @@
-:warning: **WARNING** :warning: This feature is community supported and has not been tested by Red Hat. Visit [docs.openshift.com](https://docs.openshift.com) for [OpenShift Enterprise](https://docs.openshift.com/enterprise/latest/install_config/install/index.html) or [OpenShift Origin](https://docs.openshift.org/latest/install_config/install/index.html) supported installation docs.
-
-GCE Setup Instructions
-======================
-
-Get a gce service key
----------------------
-1. Ask your GCE project administrator for a GCE service key
-
-Note: If your GCE project does not show a Service Account under <Project>/APIs & auth/Credentials, you will need to use "Create new Client ID" to create a Service Account before your administrator can create the service key for you.
-
-
-Convert a GCE service key into a pem (for ansible)
---------------------------------------------------
-1. mkdir -p ~/.gce
-1. The gce service key looks something like this: projectname-ef83bd90f261.p12
-.. The ef83bd90f261 part is the public hash (GCE_KEY_HASH), The projectname part, is the project name (PROJECT_NAME).
-1. Be in the same directory as the p12 key file.
-1. The commands below should be copy / paste-able
-1. Run these commands:
-```
- # Temporarily set hash variable and project name
- export GCE_KEY_HASH=ef83bd90f261
- export PROJECT_NAME=Project Name
- export PROJECT_ID=Project ID
-
- # Convert the service key (note: 'notasecret' is literally what we want here)
- openssl pkcs12 -in "${PROJECT_NAME}-${GCE_KEY_HASH}.p12" -passin pass:notasecret -nodes -nocerts | openssl rsa -out ${PROJECT_ID}-${GCE_KEY_HASH}.pem
-
- # Move the converted service key to the .gce dir
- mv ${PROJECT_ID}-${GCE_KEY_HASH}.pem ~/.gce
-```
-
-1. Once this is done, put the original service key file (projectname-ef83bd90f261.p12) somewhere safe, or delete it (your call, I don not know what else we will use it for, and we can always regen it if needed).
-
-
-Create a gce.ini file for GCE
---------------------------------
-* gce_service_account_email_address - Found in "APIs & auth" -> Credentials -> "Service Account" -> "Email Address"
-* gce_service_account_pem_file_path - Full path from previous steps
-* gce_project_id - Found in "Projects", it list all the gce projects you are associated with. The page lists their "Project Name" and "Project ID". You want the "Project ID"
-
-Mandatory customization variables (check the values according to your tenant):
-* zone = europe-west1-d
-* network = default
-
-Optional Variable Overrides:
-* gce_ssh_user - ssh user, defaults to the current logged in user
-* gce_machine_type = n1-standard-1 - default machine type
-* gce_machine_etcd_type = n1-standard-1 - machine type for etcd hosts
-* gce_machine_master_type = n1-standard-1 - machine type for master hosts
-* gce_machine_node_type = n1-standard-1 - machine type for node hosts
-* gce_machine_image = centos-7 - default image
-* gce_machine_etcd_image = centos-7 - image for etcd hosts
-* gce_machine_master_image = centos-7 - image for master hosts
-* gce_machine_node_image = centos-7 - image for node hosts
-
-
-1. vi ~/.gce/gce.ini
-1. make the contents look like this:
-```
-[gce]
-gce_service_account_email_address = long...@developer.gserviceaccount.com
-gce_service_account_pem_file_path = /full/path/to/project_id-gce_key_hash.pem
-gce_project_id = project_id
-zone = europe-west1-d
-network = default
-gce_machine_type = n1-standard-2
-gce_machine_master_type = n1-standard-1
-gce_machine_node_type = n1-standard-2
-gce_machine_image = centos-7
-gce_machine_master_image = centos-7
-gce_machine_node_image = centos-7
-
-```
-1. Define the environment variable GCE_INI_PATH so gce.py can pick it up and bin/cluster can also read it
-```
-export GCE_INI_PATH=~/.gce/gce.ini
-```
-
-
-Install Dependencies
---------------------
-1. Ansible requires libcloud for gce operations:
-```
- yum install -y ansible python-libcloud
-```
-
-> Installation using Mac OSX requires pycrypto library
->
-> <kbd>$ pip install pycrypto</kbd>
-
-Test The Setup
---------------
-1. cd openshift-ansible/
-1. Try to list all instances (Passing an empty string as the cluster_id
-argument will result in all gce instances being listed)
-```
- bin/cluster list gce ''
-```
-
-Creating a cluster
-------------------
-1. To create a cluster with one master, one infra node, and two compute nodes
-```
- bin/cluster create gce <cluster-id>
-```
-1. To create a cluster with 3 masters, 3 etcd hosts, 2 infra nodes and 10
-compute nodes
-```
- bin/cluster create gce -m 3 -e 3 -i 2 -n 10 <cluster-id>
-```
-
-Updating a cluster
----------------------
-1. To update the cluster
-```
- bin/cluster update gce <cluster-id>
-```
-
-Add additional nodes
----------------------
-1. To add additional infra nodes
-```
- bin/cluster add-nodes gce -i <num nodes> <cluster-id>
-```
-1. To add additional compute nodes
-```
- bin/cluster add-nodes gce -n <num nodes> <cluster-id>
-```
-Terminating a cluster
----------------------
-1. To terminate the cluster
-```
- bin/cluster terminate gce <cluster-id>
-```
diff --git a/README_libvirt.md b/README_libvirt.md
deleted file mode 100644
index 1661681a0..000000000
--- a/README_libvirt.md
+++ /dev/null
@@ -1,163 +0,0 @@
-:warning: **WARNING** :warning: This feature is community supported and has not been tested by Red Hat. Visit [docs.openshift.com](https://docs.openshift.com) for [OpenShift Enterprise](https://docs.openshift.com/enterprise/latest/install_config/install/index.html) or [OpenShift Origin](https://docs.openshift.org/latest/install_config/install/index.html) supported installation docs.
-
-LIBVIRT Setup instructions
-==========================
-
-`libvirt` is an `openshift-ansible` provider that uses `libvirt` to create local Fedora VMs that are provisioned exactly the same way that cloud VMs would be provisioned.
-
-This makes `libvirt` useful to develop, test and debug OpenShift and openshift-ansible locally on the developer’s workstation before going to the cloud.
-
-Install dependencies
---------------------
-
-1. Install [ansible](http://www.ansible.com/)
-2. Install [dnsmasq](http://www.thekelleys.org.uk/dnsmasq/doc.html)
-3. Install [ebtables](http://ebtables.netfilter.org/)
-4. Install [qemu and qemu-system-x86](http://wiki.qemu.org/Main_Page)
-5. Install [libvirt-python and libvirt](http://libvirt.org/)
-6. Install [genisoimage](http://cdrkit.org/) or [mkisofs](http://cdrtools.sourceforge.net/private/cdrecord.html)
-7. Enable and start the libvirt daemon, e.g:
- - `systemctl enable libvirtd`
- - `systemctl start libvirtd`
-8. [Grant libvirt access to your user¹](https://libvirt.org/aclpolkit.html)
-9. Check that your `$HOME` is accessible to the qemu user²
-10. Configure dns resolution on the host³
-11. Install libselinux-python
-12. Ensure you have an SSH private and public keypair at `~/.ssh/id_rsa` and `~/.ssh/id_rsa.pub`⁴
-
-#### ¹ Depending on your distribution, libvirt access may be denied by default or may require a password at each access.
-
-You can test it with the following command:
-
-```
-virsh -c qemu:///system pool-list
-```
-
-If you have access error messages, please read https://libvirt.org/acl.html and https://libvirt.org/aclpolkit.html .
-
-In short, if your libvirt has been compiled with Polkit support (ex: Arch, Fedora 21), you can create `/etc/polkit-1/rules.d/50-org.libvirt.unix.manage.rules` as follows to grant full access to libvirt to `$USER`
-
-```
-sudo /bin/sh -c "cat - > /etc/polkit-1/rules.d/50-org.libvirt.unix.manage.rules" << EOF
-polkit.addRule(function(action, subject) {
- if (action.id == "org.libvirt.unix.manage" &&
- subject.user == "$USER") {
- return polkit.Result.YES;
- polkit.log("action=" + action);
- polkit.log("subject=" + subject);
- }
-});
-EOF
-```
-
-If your libvirt has not been compiled with Polkit (ex: Ubuntu 14.04.1 LTS), check the permissions on the libvirt unix socket:
-
-```
-ls -l /var/run/libvirt/libvirt-sock
-srwxrwx--- 1 root libvirtd 0 févr. 12 16:03 /var/run/libvirt/libvirt-sock
-
-usermod -a -G libvirtd $USER
-# $USER needs to logout/login to have the new group be taken into account
-```
-
-(Replace `$USER` with your login name)
-
-#### ² Qemu will run with a specific user. It must have access to the VMs drives
-
-All the disk drive resources needed by the VMs (Fedora disk image, cloud-init files) are put inside `~/libvirt-storage-pool-openshift/`.
-
-As we’re using the `qemu:///system` instance of libvirt, qemu will run with a specific `user:group` distinct from your user. It is configured in `/etc/libvirt/qemu.conf`. That qemu user must have access to that libvirt storage pool.
-
-If your `$HOME` is world readable, everything is fine. If your `$HOME` is private, `ansible` will fail with an error message like:
-
-```
-error: Cannot access storage file '$HOME/libvirt-storage-pool-openshift/lenaic-master-216d8.qcow2' (as uid:99, gid:78): Permission denied
-```
-
-In order to fix that issue, you have several possibilities:
- * set `libvirt_storage_pool_path` inside `playbooks/libvirt/openshift-cluster/launch.yml` and `playbooks/libvirt/openshift-cluster/terminate.yml` to a directory:
- * backed by a filesystem with a lot of free disk space
- * writable by your user;
- * accessible by the qemu user.
- * Grant the qemu user access to the storage pool.
-
-On Arch or Fedora 22+:
-
-```
-setfacl -m g:kvm:--x ~
-```
-
-#### ³ Enabling DNS resolution to your guest VMs with NetworkManager
-
-- Verify NetworkManager is configured to use dnsmasq:
-
-```sh
-$ sudo vi /etc/NetworkManager/NetworkManager.conf
-[main]
-dns=dnsmasq
-```
-
-- Configure dnsmasq to use the Virtual Network router for example.com:
-
-```sh
-sudo vi /etc/NetworkManager/dnsmasq.d/libvirt_dnsmasq.conf
-server=/example.com/192.168.55.1
-```
-
-#### ⁴ Private and public keypair in ~/.ssh/id_rsa and ~/.ssh/id_rsa.pub
-
-This playbook uses SSH keys to communicate with the libvirt-driven virtual machines. At this time the names of those keys are fixed and cannot be changed.
-
-
-Test The Setup
---------------
-
-1. cd openshift-ansible/
-2. Try to list all instances (Passing an empty string as the cluster_id argument will result in all libvirt instances being listed)
-
-```
- bin/cluster list libvirt ''
-```
-
-Configuration
--------------
-
-The following options can be passed via the `-o` flag of the `create` command or as environment variables:
-
-* `image_url` (default to `http://cloud.centos.org/centos/7/images/CentOS-7-x86_64-GenericCloud.qcow2.xz`): URL of the QCOW2 image to download
-* `image_name` (default to `CentOS-7-x86_64-GenericCloud.qcow2`): Name of the QCOW2 image to boot the VMs on
-* `image_compression` (default to `xz`): Source QCOW2 compression (only xz supported at this time)
-* `image_sha256` (default to `dd0f5e610e7c5ffacaca35ed7a78a19142a588f4543da77b61c1fb0d74400471`): Expected SHA256 checksum of the downloaded image
-* `libvirt_storage_pool` (default to `openshift-ansible`): name of the libvirt storage pool for the VM images. It will be created if it does not exist
-* `libvirt_storage_pool_path` (default to `$HOME/libvirt-storage-pool-openshift-ansible`): path to `libvirt_storage_pool`, i.e. where the VM images are stored
-* `libvirt_network` (default to `openshift-ansible`): name of the libvirt network that the VMs will use. It will be created if it does not exist
-* `libvirt_instance_memory_mib` (default to `1024`): memory of the VMs in MiB
-* `libvirt_instance_vcpu` (default to `2`): number of vCPUs of the VMs
-* `skip_image_download` (default to `no`): Skip QCOW2 image download. This requires the `image_name` QCOW2 image to be already present in `$HOME/libvirt-storage-pool-openshift-ansible`
-
-Creating a cluster
-------------------
-
-1. To create a cluster with one master and two nodes
-
-```
- bin/cluster create libvirt lenaic
-```
-
-Updating a cluster
-------------------
-
-1. To update the cluster
-
-```
- bin/cluster update libvirt lenaic
-```
-
-Terminating a cluster
----------------------
-
-1. To terminate the cluster
-
-```
- bin/cluster terminate libvirt lenaic
-```
diff --git a/README_openstack.md b/README_openstack.md
deleted file mode 100644
index 2578488c7..000000000
--- a/README_openstack.md
+++ /dev/null
@@ -1,87 +0,0 @@
-:warning: **WARNING** :warning: This feature is community supported and has not been tested by Red Hat. Visit [docs.openshift.com](https://docs.openshift.com) for [OpenShift Enterprise](https://docs.openshift.com/enterprise/latest/install_config/install/index.html) or [OpenShift Origin](https://docs.openshift.org/latest/install_config/install/index.html) supported installation docs.
-
-OPENSTACK Setup instructions
-============================
-
-Requirements
-------------
-
-The OpenStack instance must have Neutron and Heat enabled.
-
-Install Dependencies
---------------------
-
-1. The OpenStack python clients for Nova, Neutron and Heat are required:
-
-* `python-novaclient`
-* `python-neutronclient`
-* `python-heatclient`
-
-On Fedora:
-```
- dnf install -y ansible python-novaclient python-neutronclient python-heatclient
-```
-
-On RHEL / CentOS:
-```
- yum install -y ansible python-novaclient python-neutronclient python-heatclient
- sudo pip install shade
-```
-
-Configuration
--------------
-
-The following options can be passed via the `-o` flag of the `create` command:
-
-* `infra_heat_stack` (default to `playbooks/openstack/openshift-cluster/files/heat_stack.yaml`): filename of the HEAT template to use to create the cluster infrastructure
-
-The following options are used only by `heat_stack.yaml`. They are so used only if the `infra_heat_stack` option is left with its default value.
-
-* `image_name`: Name of the image to use to spawn VMs
-* `public_key` (default to `~/.ssh/id_rsa.pub`): filename of the ssh public key
-* `etcd_flavor` (default to `m1.small`): The ID or name of the flavor for the etcd nodes
-* `master_flavor` (default to `m1.small`): The ID or name of the flavor for the master
-* `node_flavor` (default to `m1.medium`): The ID or name of the flavor for the compute nodes
-* `infra_flavor` (default to `m1.small`): The ID or name of the flavor for the infrastructure nodes
-* `network_prefix` (default to `openshift-ansible-<cluster_id>`): prefix prepended to all network objects (net, subnet, router, security groups)
-* `dns` (default to `8.8.8.8,8.8.4.4`): comma separated list of DNS to use
-* `net_cidr` (default to `192.168.<rand()>.0/24`): CIDR of the network created by `heat_stack.yaml`
-* `external_net` (default to `external`): Name of the external network to connect to
-* `floating_ip_pool` (default to `external`): comma separated list of floating IP pools
-* `ssh_from` (default to `0.0.0.0/0`): IPs authorized to connect to the VMs via ssh
-* `node_port_from` (default to `0.0.0.0/0`): IPs authorized to connect to the services exposed via nodePort
-* `heat_timeout` (default to `3`): Timeout (in minutes) passed to heat for create or update stack.
-
-
-Creating a cluster
-------------------
-
-1. To create a cluster with one master and two nodes
-
-```
- bin/cluster create openstack <cluster-id>
-```
-
-2. To create a cluster with one master and three nodes, a custom VM image and custom DNS:
-
-```
- bin/cluster create -n 3 -o image_name=rhel-7.1-openshift-2015.05.21 -o dns=172.16.50.210,172.16.50.250 openstack lenaic
-```
-
-Updating a cluster
-------------------
-
-1. To update the cluster
-
-```
- bin/cluster update openstack <cluster-id>
-```
-
-Terminating a cluster
----------------------
-
-1. To terminate the cluster
-
-```
- bin/cluster terminate openstack <cluster-id>
-```
diff --git a/README_vagrant.md b/README_vagrant.md
deleted file mode 100644
index cb62e31d8..000000000
--- a/README_vagrant.md
+++ /dev/null
@@ -1 +0,0 @@
-The Vagrant-based installation has been moved to: https://github.com/openshift/openshift-ansible-contrib/tree/master/vagrant
diff --git a/bin/README.md b/bin/README.md
deleted file mode 100644
index fec17cb9b..000000000
--- a/bin/README.md
+++ /dev/null
@@ -1,6 +0,0 @@
-# The `bin/cluster` tool
-
-This tool was meant to be the entry point for managing OpenShift clusters,
-running against different "providers" (`aws`, `gce`, `libvirt`, `openstack`),
-though its use is now deprecated in favor of the [`byo`](../playbooks/byo)
-playbooks.
diff --git a/bin/cluster b/bin/cluster
deleted file mode 100755
index f77eb36ad..000000000
--- a/bin/cluster
+++ /dev/null
@@ -1,424 +0,0 @@
-#!/usr/bin/env python2
-
-import argparse
-import ConfigParser
-import os
-import sys
-import subprocess
-import traceback
-
-
-class Cluster(object):
- """
- Provide Command, Control and Configuration (c3) Interface for OpenShift Clusters
- """
-
- def __init__(self):
- # setup ansible ssh environment
- if 'ANSIBLE_SSH_ARGS' not in os.environ:
- os.environ['ANSIBLE_SSH_ARGS'] = (
- '-o ForwardAgent=yes '
- '-o StrictHostKeyChecking=no '
- '-o UserKnownHostsFile=/dev/null '
- '-o ControlMaster=auto '
- '-o ControlPersist=600s '
- )
- # Because of `UserKnownHostsFile=/dev/null`
- # our `.ssh/known_hosts` file most probably misses the ssh host public keys
- # of our servers.
- # In that case, ansible serializes the execution of ansible modules
- # because we might be interactively prompted to accept the ssh host public keys.
- # Because of `StrictHostKeyChecking=no` we know that we won't be prompted
- # So, we don't want our modules execution to be serialized.
- os.environ['ANSIBLE_HOST_KEY_CHECKING'] = 'False'
- # TODO: A more secure way to proceed would consist in dynamically
- # retrieving the ssh host public keys from the IaaS interface
- if 'ANSIBLE_SSH_PIPELINING' not in os.environ:
- os.environ['ANSIBLE_SSH_PIPELINING'] = 'True'
-
- def get_deployment_type(self, args):
- """
- Get the deployment_type based on the environment variables and the
- command line arguments
- :param args: command line arguments provided by the user
- :return: string representing the deployment type
- """
- deployment_type = 'origin'
- if args.deployment_type:
- deployment_type = args.deployment_type
- elif 'OS_DEPLOYMENT_TYPE' in os.environ:
- deployment_type = os.environ['OS_DEPLOYMENT_TYPE']
- return deployment_type
-
-
- def create(self, args):
- """
- Create an OpenShift cluster for given provider
- :param args: command line arguments provided by user
- """
- cluster = {'cluster_id': args.cluster_id,
- 'deployment_type': self.get_deployment_type(args)}
- playbook = "playbooks/{0}/openshift-cluster/launch.yml".format(args.provider)
- inventory = self.setup_provider(args.provider)
-
- cluster['num_masters'] = args.masters
- cluster['num_nodes'] = args.nodes
- cluster['num_infra'] = args.infra
- cluster['num_etcd'] = args.etcd
- cluster['cluster_env'] = args.env
-
- if args.cloudprovider and args.provider == 'openstack':
- cluster['openshift_cloudprovider_kind'] = 'openstack'
- cluster['openshift_cloudprovider_openstack_auth_url'] = os.getenv('OS_AUTH_URL')
- cluster['openshift_cloudprovider_openstack_username'] = os.getenv('OS_USERNAME')
- cluster['openshift_cloudprovider_openstack_password'] = os.getenv('OS_PASSWORD')
- if 'OS_USER_DOMAIN_ID' in os.environ:
- cluster['openshift_cloudprovider_openstack_domain_id'] = os.getenv('OS_USER_DOMAIN_ID')
- if 'OS_USER_DOMAIN_NAME' in os.environ:
- cluster['openshift_cloudprovider_openstack_domain_name'] = os.getenv('OS_USER_DOMAIN_NAME')
- if 'OS_PROJECT_ID' in os.environ or 'OS_TENANT_ID' in os.environ:
- cluster['openshift_cloudprovider_openstack_tenant_id'] = os.getenv('OS_PROJECT_ID',os.getenv('OS_TENANT_ID'))
- if 'OS_PROJECT_NAME' is os.environ or 'OS_TENANT_NAME' in os.environ:
- cluster['openshift_cloudprovider_openstack_tenant_name'] = os.getenv('OS_PROJECT_NAME',os.getenv('OS_TENANT_NAME'))
- if 'OS_REGION_NAME' in os.environ:
- cluster['openshift_cloudprovider_openstack_region'] = os.getenv('OS_REGION_NAME')
-
- self.action(args, inventory, cluster, playbook)
-
- def add_nodes(self, args):
- """
- Add nodes to an existing cluster for given provider
- :param args: command line arguments provided by user
- """
- cluster = {'cluster_id': args.cluster_id,
- 'deployment_type': self.get_deployment_type(args),
- }
- playbook = "playbooks/{0}/openshift-cluster/add_nodes.yml".format(args.provider)
- inventory = self.setup_provider(args.provider)
-
- cluster['num_nodes'] = args.nodes
- cluster['num_infra'] = args.infra
- cluster['cluster_env'] = args.env
-
- self.action(args, inventory, cluster, playbook)
-
- def terminate(self, args):
- """
- Destroy OpenShift cluster
- :param args: command line arguments provided by user
- """
- cluster = {'cluster_id': args.cluster_id,
- 'deployment_type': self.get_deployment_type(args),
- 'cluster_env': args.env,
- }
- playbook = "playbooks/{0}/openshift-cluster/terminate.yml".format(args.provider)
- inventory = self.setup_provider(args.provider)
-
- self.action(args, inventory, cluster, playbook)
-
- def list(self, args):
- """
- List VMs in cluster
- :param args: command line arguments provided by user
- """
- cluster = {'cluster_id': args.cluster_id,
- 'deployment_type': self.get_deployment_type(args),
- 'cluster_env': args.env,
- }
- playbook = "playbooks/{0}/openshift-cluster/list.yml".format(args.provider)
- inventory = self.setup_provider(args.provider)
-
- self.action(args, inventory, cluster, playbook)
-
- def config(self, args):
- """
- Configure or reconfigure OpenShift across clustered VMs
- :param args: command line arguments provided by user
- """
- cluster = {'cluster_id': args.cluster_id,
- 'deployment_type': self.get_deployment_type(args),
- 'cluster_env': args.env,
- }
- playbook = "playbooks/{0}/openshift-cluster/config.yml".format(args.provider)
- inventory = self.setup_provider(args.provider)
-
- self.action(args, inventory, cluster, playbook)
-
- def update(self, args):
- """
- Update to latest OpenShift across clustered VMs
- :param args: command line arguments provided by user
- """
- cluster = {'cluster_id': args.cluster_id,
- 'deployment_type': self.get_deployment_type(args),
- 'cluster_env': args.env,
- }
-
- playbook = "playbooks/{0}/openshift-cluster/update.yml".format(args.provider)
- inventory = self.setup_provider(args.provider)
-
- self.action(args, inventory, cluster, playbook)
-
- def service(self, args):
- """
- Make the same service call across all nodes in the cluster
- :param args: command line arguments provided by user
- """
- cluster = {'cluster_id': args.cluster_id,
- 'deployment_type': self.get_deployment_type(args),
- 'new_cluster_state': args.state,
- 'cluster_env': args.env,
- }
-
- playbook = "playbooks/{0}/openshift-cluster/service.yml".format(args.provider)
- inventory = self.setup_provider(args.provider)
-
- self.action(args, inventory, cluster, playbook)
-
- def setup_provider(self, provider):
- """
- Setup ansible playbook environment
- :param provider: command line arguments provided by user
- :return: path to inventory for given provider
- """
- config = ConfigParser.ConfigParser()
- if 'gce' == provider:
- gce_ini_default_path = os.path.join('inventory/gce/hosts/gce.ini')
- gce_ini_path = os.environ.get('GCE_INI_PATH', gce_ini_default_path)
- if os.path.exists(gce_ini_path):
- config.readfp(open(gce_ini_path))
-
- for key in config.options('gce'):
- os.environ[key] = config.get('gce', key)
-
- inventory = '-i inventory/gce/hosts'
- elif 'aws' == provider:
- config.readfp(open('inventory/aws/hosts/ec2.ini'))
-
- for key in config.options('ec2'):
- os.environ[key] = config.get('ec2', key)
-
- inventory = '-i inventory/aws/hosts'
-
- key_vars = ['AWS_ACCESS_KEY_ID', 'AWS_SECRET_ACCESS_KEY']
- key_missing = [key for key in key_vars if key not in os.environ]
-
- boto_conf_files = ['~/.aws/credentials', '~/.boto']
- conf_exists = lambda conf: os.path.isfile(os.path.expanduser(conf))
- boto_configs = [conf for conf in boto_conf_files if conf_exists(conf)]
-
- if len(key_missing) > 0 and len(boto_configs) == 0:
- raise ValueError("PROVIDER aws requires {0} environment variable(s). See README_AWS.md".format(key_missing))
-
- elif 'libvirt' == provider:
- inventory = '-i inventory/libvirt/hosts'
- elif 'openstack' == provider:
- inventory = '-i inventory/openstack/hosts'
- else:
- # this code should never be reached
- raise ValueError("invalid PROVIDER {0}".format(provider))
-
- return inventory
-
- def action(self, args, inventory, cluster, playbook):
- """
- Build ansible-playbook command line and execute
- :param args: command line arguments provided by user
- :param inventory: derived provider library
- :param cluster: cluster variables for kubernetes
- :param playbook: ansible playbook to execute
- """
-
- verbose = ''
- if args.verbose > 0:
- verbose = '-{0}'.format('v' * args.verbose)
-
- if args.option:
- for opt in args.option:
- k, v = opt.split('=', 1)
- cluster['cli_' + k] = v
-
- ansible_extra_vars = '-e \'{0}\''.format(
- ' '.join(['%s=%s' % (key, value) for (key, value) in cluster.items()])
- )
-
- command = 'ansible-playbook {0} {1} {2} {3}'.format(
- verbose, inventory, ansible_extra_vars, playbook
- )
-
- if args.profile:
- command = 'ANSIBLE_CALLBACK_PLUGINS=ansible-profile/callback_plugins ' + command
-
- if args.verbose > 1:
- command = 'time {0}'.format(command)
-
- if args.verbose > 0:
- sys.stderr.write('RUN [{0}]\n'.format(command))
- sys.stderr.flush()
-
- try:
- subprocess.check_call(command, shell=True)
- except subprocess.CalledProcessError as exc:
- raise ActionFailed("ACTION [{0}] failed: {1}"
- .format(args.action, exc))
-
-
-class ActionFailed(Exception):
- """
- Raised when action failed.
- """
- pass
-
-
-if __name__ == '__main__':
- """
- User command to invoke ansible playbooks in a "known" configuration
-
- Reads ~/.openshift-ansible for default configuration items
- [DEFAULT]
- validate_cluster_ids = False
- cluster_ids = marketing,sales
- providers = gce,aws,libvirt,openstack
- """
-
- warning = ("================================================================================\n"
- "ATTENTION: You are running a community supported utility that has not been\n"
- "tested by Red Hat. Visit https://docs.openshift.com for supported installation\n"
- "instructions.\n"
- "================================================================================\n\n")
- sys.stderr.write(warning)
-
- cluster_config = ConfigParser.SafeConfigParser({
- 'cluster_ids': 'marketing,sales',
- 'validate_cluster_ids': 'False',
- 'providers': 'gce,aws,libvirt,openstack',
- })
-
- path = os.path.expanduser("~/.openshift-ansible")
- if os.path.isfile(path):
- cluster_config.read(path)
-
- cluster = Cluster()
-
- parser = argparse.ArgumentParser(
- formatter_class=argparse.RawDescriptionHelpFormatter,
- description='Python wrapper to ensure proper configuration for OpenShift ansible playbooks',
- epilog='''\
-This wrapper is overriding the following ansible variables:
-
- * ANSIBLE_SSH_ARGS:
- If not set in the environment, this wrapper will use the following value:
- `-o ForwardAgent=yes -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ControlMaster=auto -o ControlPersist=600s`
- If set in the environment, the environment variable value is left untouched and used.
-
- * ANSIBLE_SSH_PIPELINING:
- If not set in the environment, this wrapper will set it to `True`.
- If you experience issues with Ansible SSH pipelining, you can disable it by explicitly setting this environment variable to `False`.
-'''
- )
- parser.add_argument('-v', '--verbose', action='count',
- help='Multiple -v options increase the verbosity')
- parser.add_argument('--version', action='version', version='%(prog)s 0.3')
-
- meta_parser = argparse.ArgumentParser(add_help=False)
- providers = cluster_config.get('DEFAULT', 'providers').split(',')
- meta_parser.add_argument('provider', choices=providers, help='provider')
-
- if cluster_config.get('DEFAULT', 'validate_cluster_ids').lower() in ("yes", "true", "1"):
- meta_parser.add_argument('cluster_id', choices=cluster_config.get('DEFAULT', 'cluster_ids').split(','),
- help='prefix for cluster VM names')
- else:
- meta_parser.add_argument('cluster_id', help='prefix for cluster VM names')
-
- meta_parser.add_argument('-t', '--deployment-type',
- choices=['origin', 'atomic-enterprise', 'openshift-enterprise'],
- help='Deployment type. (default: origin)')
- meta_parser.add_argument('-o', '--option', action='append',
- help='options')
-
- meta_parser.add_argument('--env', default='dev', type=str,
- help='environment for the cluster. Defaults to \'dev\'.')
-
- meta_parser.add_argument('-p', '--profile', action='store_true',
- help='Enable playbook profiling')
-
- action_parser = parser.add_subparsers(dest='action', title='actions',
- description='Choose from valid actions')
-
- create_parser = action_parser.add_parser('create', help='Create a cluster',
- parents=[meta_parser])
- create_parser.add_argument('-c', '--cloudprovider', action='store_true',
- help='Enable the cloudprovider')
- create_parser.add_argument('-m', '--masters', default=1, type=int,
- help='number of masters to create in cluster')
- create_parser.add_argument('-n', '--nodes', default=2, type=int,
- help='number of nodes to create in cluster')
- create_parser.add_argument('-i', '--infra', default=1, type=int,
- help='number of infra nodes to create in cluster')
- create_parser.add_argument('-e', '--etcd', default=0, type=int,
- help='number of external etcd hosts to create in cluster')
- create_parser.set_defaults(func=cluster.create)
-
-
- create_parser = action_parser.add_parser('add-nodes', help='Add nodes to a cluster',
- parents=[meta_parser])
- create_parser.add_argument('-n', '--nodes', default=1, type=int,
- help='number of nodes to add to the cluster')
- create_parser.add_argument('-i', '--infra', default=1, type=int,
- help='number of infra nodes to add to the cluster')
- create_parser.set_defaults(func=cluster.add_nodes)
-
-
- config_parser = action_parser.add_parser('config',
- help='Configure or reconfigure a cluster',
- parents=[meta_parser])
- config_parser.set_defaults(func=cluster.config)
-
- terminate_parser = action_parser.add_parser('terminate',
- help='Destroy a cluster',
- parents=[meta_parser])
- terminate_parser.add_argument('-f', '--force', action='store_true',
- help='Destroy cluster without confirmation')
- terminate_parser.set_defaults(func=cluster.terminate)
-
- update_parser = action_parser.add_parser('update',
- help='Update OpenShift across cluster',
- parents=[meta_parser])
- update_parser.add_argument('-f', '--force', action='store_true',
- help='Update cluster without confirmation')
- update_parser.set_defaults(func=cluster.update)
-
- list_parser = action_parser.add_parser('list', help='List VMs in cluster',
- parents=[meta_parser])
- list_parser.set_defaults(func=cluster.list)
-
- service_parser = action_parser.add_parser('service', help='service for openshift across cluster',
- parents=[meta_parser])
- # choices are the only ones valid for the ansible service module: http://docs.ansible.com/service_module.html
- service_parser.add_argument('state', choices=['started', 'stopped', 'restarted', 'reloaded'],
- help='make service call across cluster')
- service_parser.set_defaults(func=cluster.service)
-
- args = parser.parse_args()
-
- if 'terminate' == args.action and not args.force:
- answer = raw_input("This will destroy the ENTIRE {0} cluster. Are you sure? [y/N] ".format(args.cluster_id))
- if answer not in ['y', 'Y']:
- sys.stderr.write('\nACTION [terminate] aborted by user!\n')
- exit(1)
-
- if 'update' == args.action and not args.force:
- answer = raw_input(
- "This is destructive and could corrupt {0} cluster. Continue? [y/N] ".format(args.cluster_id))
- if answer not in ['y', 'Y']:
- sys.stderr.write('\nACTION [update] aborted by user!\n')
- exit(1)
-
- try:
- args.func(args)
- except Exception as exc:
- if args.verbose:
- traceback.print_exc(file=sys.stderr)
- else:
- print >>sys.stderr, exc
- exit(1)
diff --git a/callback_plugins/aa_version_requirement.py b/callback_plugins/aa_version_requirement.py
index 20bdd9056..9562adb28 100644
--- a/callback_plugins/aa_version_requirement.py
+++ b/callback_plugins/aa_version_requirement.py
@@ -29,7 +29,7 @@ else:
# Set to minimum required Ansible version
-REQUIRED_VERSION = '2.2.2.0'
+REQUIRED_VERSION = '2.3.0.0'
DESCRIPTION = "Supported versions: %s or newer" % REQUIRED_VERSION
diff --git a/docs/proposals/README.md b/docs/proposals/README.md
new file mode 100644
index 000000000..89bbe5163
--- /dev/null
+++ b/docs/proposals/README.md
@@ -0,0 +1,27 @@
+# OpenShift-Ansible Proposal Process
+
+## Proposal Decision Tree
+TODO: Add details about when a proposal is or is not required.
+
+## Proposal Process
+The following process should be followed when a proposal is needed:
+
+1. Create a pull request with the initial proposal
+ * Use the [proposal template][template]
+ * Name the proposal using two or three topic words with underscores as a separator (i.e. proposal_template.md)
+ * Place the proposal in the docs/proposals directory
+2. Notify the development team of the proposal and request feedback
+3. Review the proposal on the OpenShift-Ansible Architecture Meeting
+4. Update the proposal as needed and ask for feedback
+5. Approved/Closed Phase
+ * If 75% or more of the active development team give the proposal a :+1: it is Approved
+ * If 50% or more of the active development team disagrees with the proposal it is Closed
+ * If the person proposing the proposal no longer wishes to continue they can request it to be Closed
+ * If there is no activity on a proposal, the active development team may Close the proposal at their discretion
+ * If none of the above is met the cycle can continue to Step 4.
+6. For approved proposals, the current development lead(s) will:
+ * Update the Pull Request with the result and merge the proposal
+ * Create a card on the Cluster Lifecycle [Trello board][trello] so it may be scheduled for implementation.
+
+[template]: proposal_template.md
+[trello]: https://trello.com/b/wJYDst6C
diff --git a/docs/proposals/playbook_consolidation.md b/docs/proposals/playbook_consolidation.md
new file mode 100644
index 000000000..98aedb021
--- /dev/null
+++ b/docs/proposals/playbook_consolidation.md
@@ -0,0 +1,178 @@
+# OpenShift-Ansible Playbook Consolidation
+
+## Description
+The designation of `byo` is no longer applicable due to being able to deploy on
+physical hardware or cloud resources using the playbooks in the `byo` directory.
+Consolidation of these directories will make maintaining the code base easier
+and provide a more straightforward project for users and developers.
+
+The main points of this proposal are:
+* Consolidate initialization playbooks into one set of playbooks in
+ `playbooks/init`.
+* Collapse the `playbooks/byo` and `playbooks/common` into one set of
+ directories at `playbooks/openshift-*`.
+
+This consolidation effort may be more appropriate when the project moves to
+using a container as the default installation method.
+
+## Design
+
+### Initialization Playbook Consolidation
+Currently there are two separate sets of initialization playbooks:
+* `playbooks/byo/openshift-cluster/initialize_groups.yml`
+* `playbooks/common/openshift-cluster/std_include.yml`
+
+Although these playbooks are located in the `openshift-cluster` directory they
+are shared by all of the `openshift-*` areas. These playbooks would be better
+organized in a `playbooks/init` directory collocated with all their related
+playbooks.
+
+In the example below, the following changes have been made:
+* `playbooks/byo/openshift-cluster/initialize_groups.yml` renamed to
+ `playbooks/init/initialize_host_groups.yml`
+* `playbooks/common/openshift-cluster/std_include.yml` renamed to
+ `playbooks/init/main.yml`
+* `- include: playbooks/init/initialize_host_groups.yml` has been added to the
+ top of `playbooks/init/main.yml`
+* All other related files for initialization have been moved to `playbooks/init`
+
+The `initialize_host_groups.yml` playbook is only one play with one task for
+importing variables for inventory group conversions. This task could be further
+consolidated with the play in `evaluate_groups.yml`.
+
+The new standard initialization playbook would be
+`playbooks/init/main.yml`.
+
+
+```
+
+> $ tree openshift-ansible/playbooks/init
+.
+├── evaluate_groups.yml
+├── initialize_facts.yml
+├── initialize_host_groups.yml
+├── initialize_openshift_repos.yml
+├── initialize_openshift_version.yml
+├── main.yml
+├── roles -> ../../roles
+├── validate_hostnames.yml
+└── vars
+ └── cluster_hosts.yml
+```
+
+```yaml
+# openshift-ansible/playbooks/init/main.yml
+---
+- include: initialize_host_groups.yml
+
+- include: evaluate_groups.yml
+
+- include: initialize_facts.yml
+
+- include: validate_hostnames.yml
+
+- include: initialize_openshift_repos.yml
+
+- include: initialize_openshift_version.yml
+```
+
+### `byo` and `common` Playbook Consolidation
+Historically, the `byo` directory coexisted with other platform directories
+which contained playbooks that then called into `common` playbooks to perform
+common installation steps for all platforms. Since the other platform
+directories have been removed this separation is no longer necessary.
+
+In the example below, the following changes have been made:
+* `playbooks/byo/openshift-master` renamed to
+ `playbooks/openshift-master`
+* `playbooks/common/openshift-master` renamed to
+ `playbooks/openshift-master/private`
+* Original `byo` entry point playbooks have been updated to include their
+ respective playbooks from `private/`.
+* Symbolic links have been updated as necessary
+
+All user consumable playbooks are in the root of `openshift-master` and no entry
+point playbooks exist in the `private` directory. Maintaining the separation
+between entry point playbooks and the private playbooks allows individual pieces
+of the deployments to be used as needed by other components.
+
+```
+openshift-ansible/playbooks/openshift-master
+> $ tree
+.
+├── config.yml
+├── private
+│   ├── additional_config.yml
+│   ├── config.yml
+│   ├── filter_plugins -> ../../../filter_plugins
+│   ├── library -> ../../../library
+│   ├── lookup_plugins -> ../../../lookup_plugins
+│   ├── restart_hosts.yml
+│   ├── restart_services.yml
+│   ├── restart.yml
+│   ├── roles -> ../../../roles
+│   ├── scaleup.yml
+│   └── validate_restart.yml
+├── restart.yml
+└── scaleup.yml
+```
+
+```yaml
+# openshift-ansible/playbooks/openshift-master/config.yml
+---
+- include: ../init/main.yml
+
+- include: private/config.yml
+```
+
+With the consolidation of the directory structure and component installs being
+removed from `openshift-cluster`, that directory is no longer necessary. To
+deploy an entire OpenShift cluster, a playbook would be created to tie together
+all of the different components. The following example shows how multiple
+components would be combined to perform a complete install.
+
+```yaml
+# openshift-ansible/playbooks/deploy_cluster.yml
+---
+- include: init/main.yml
+
+- include: openshift-etcd/private/config.yml
+
+- include: openshift-nfs/private/config.yml
+
+- include: openshift-loadbalancer/private/config.yml
+
+- include: openshift-master/private/config.yml
+
+- include: openshift-node/private/config.yml
+
+- include: openshift-glusterfs/private/config.yml
+
+- include: openshift-hosted/private/config.yml
+
+- include: openshift-service-catalog/private/config.yml
+```
+
+## User Story
+As a developer of OpenShift-Ansible,
+I want simplify the playbook directory structure
+so that users can easily find deployment playbooks and developers know where new
+features should be developed.
+
+## Implementation
+Given the size of this refactoring effort, it should be broken into smaller
+steps which can be completed independently while still maintaining a functional
+project.
+
+Steps:
+1. Update and merge consolidation of the initialization playbooks.
+2. Update each merge consolidation of each `openshift-*` component area
+3. Update and merge consolidation of `openshift-cluster`
+
+## Acceptance Criteria
+* Verify that all entry points playbooks install or configure as expected.
+* Verify that CI is updated for testing new playbook locations.
+* Verify that repo documentation is updated
+* Verify that user documentation is updated
+
+## References
diff --git a/docs/proposals/proposal_template.md b/docs/proposals/proposal_template.md
new file mode 100644
index 000000000..ece288037
--- /dev/null
+++ b/docs/proposals/proposal_template.md
@@ -0,0 +1,30 @@
+# Proposal Title
+
+## Description
+<Short introduction>
+
+## Rationale
+<Summary of main points of Design>
+
+## Design
+<Main content goes here>
+
+## Checklist
+* Item 1
+* Item 2
+* Item 3
+
+## User Story
+As a developer on OpenShift-Ansible,
+I want ...
+so that ...
+
+## Acceptance Criteria
+* Verify that ...
+* Verify that ...
+* Verify that ...
+
+## References
+* Link
+* Link
+* Link
diff --git a/docs/repo_structure.md b/docs/repo_structure.md
index f598f22c3..49300f80c 100644
--- a/docs/repo_structure.md
+++ b/docs/repo_structure.md
@@ -28,12 +28,6 @@ These are plugins used in playbooks and roles:
```
.
-├── bin [DEPRECATED] Contains the `bin/cluster` script, a
-│ wrapper around the Ansible playbooks that ensures proper
-│ configuration, and facilitates installing, updating,
-│ destroying and configuring OpenShift clusters.
-│ Note: this tool is kept in the repository for legacy
-│ reasons and will be removed at some point.
└── utils Contains the `atomic-openshift-installer` command, an
interactive CLI utility to install OpenShift across a
set of hosts.
diff --git a/filter_plugins/oo_filters.py b/filter_plugins/oo_filters.py
index 36a90a870..902436302 100644
--- a/filter_plugins/oo_filters.py
+++ b/filter_plugins/oo_filters.py
@@ -877,10 +877,8 @@ def oo_pods_match_component(pods, deployment_type, component):
raise errors.AnsibleFilterError("failed expects component to be a string")
image_prefix = 'openshift/origin-'
- if deployment_type in ['enterprise', 'online', 'openshift-enterprise']:
+ if deployment_type == 'openshift-enterprise':
image_prefix = 'openshift3/ose-'
- elif deployment_type == 'atomic-enterprise':
- image_prefix = 'aep3_beta/aep-'
matching_pods = []
image_regex = image_prefix + component + r'.*'
@@ -1024,6 +1022,18 @@ def oo_contains_rule(source, apiGroups, resources, verbs):
return False
+def oo_selector_to_string_list(user_dict):
+ """Convert a dict of selectors to a key=value list of strings
+
+Given input of {'region': 'infra', 'zone': 'primary'} returns a list
+of items as ['region=infra', 'zone=primary']
+ """
+ selectors = []
+ for key in user_dict:
+ selectors.append("{}={}".format(key, user_dict[key]))
+ return selectors
+
+
class FilterModule(object):
""" Custom ansible filter mapping """
@@ -1065,5 +1075,6 @@ class FilterModule(object):
"oo_openshift_loadbalancer_backends": oo_openshift_loadbalancer_backends,
"to_padded_yaml": to_padded_yaml,
"oo_random_word": oo_random_word,
- "oo_contains_rule": oo_contains_rule
+ "oo_contains_rule": oo_contains_rule,
+ "oo_selector_to_string_list": oo_selector_to_string_list
}
diff --git a/filter_plugins/openshift_node.py b/filter_plugins/openshift_node.py
index cad95ea6d..50c360e97 100644
--- a/filter_plugins/openshift_node.py
+++ b/filter_plugins/openshift_node.py
@@ -25,18 +25,7 @@ class FilterModule(object):
# We always use what they've specified if they've specified a value
if openshift_dns_ip is not None:
return openshift_dns_ip
-
- if bool(hostvars['openshift']['common']['use_dnsmasq']):
- return hostvars['ansible_default_ipv4']['address']
- elif bool(hostvars['openshift']['common']['version_gte_3_1_or_1_1']):
- if 'openshift_master_cluster_vip' in hostvars:
- return hostvars['openshift_master_cluster_vip']
- else:
- if 'openshift_master_cluster_vip' in hostvars:
- return hostvars['openshift_master_cluster_vip']
- elif 'openshift_node_first_master_ip' in hostvars:
- return hostvars['openshift_node_first_master_ip']
- return None
+ return hostvars['ansible_default_ipv4']['address']
def filters(self):
''' returns a mapping of filters to methods '''
diff --git a/filter_plugins/openshift_version.py b/filter_plugins/openshift_version.py
index 809e82488..c515f1a71 100644
--- a/filter_plugins/openshift_version.py
+++ b/filter_plugins/openshift_version.py
@@ -33,10 +33,10 @@ def legacy_gte_function_builder(name, versions):
returns True/False
"""
version_gte = False
- if 'enterprise' in deployment_type:
+ if deployment_type == 'openshift-enterprise':
if str(version) >= LooseVersion(enterprise_version):
version_gte = True
- elif 'origin' in deployment_type:
+ else:
if str(version) >= LooseVersion(origin_version):
version_gte = True
return version_gte
diff --git a/images/installer/README_INVENTORY_GENERATOR.md b/images/installer/README_INVENTORY_GENERATOR.md
new file mode 100644
index 000000000..9c10e4b71
--- /dev/null
+++ b/images/installer/README_INVENTORY_GENERATOR.md
@@ -0,0 +1,85 @@
+Dynamic Inventory Generation
+============================
+
+Script within the openshift-ansible image that can dynamically
+generate an Ansible inventory file from an existing cluster.
+
+## Configure
+
+User configuration helps to provide additional details when creating an inventory file.
+The default location of this file is in `/etc/inventory-generator-config.yaml`. The
+following configuration values are either expected or default to the given values when omitted:
+
+- `master_config_path`:
+ - specifies where to look for the bind-mounted `master-config.yaml` file in the container
+ - if omitted or a `null` value is given, its value is defaulted to `/opt/app-root/src/master-config.yaml`
+
+- `admin_kubeconfig_path`:
+ - specifies where to look for the bind-mounted `admin.kubeconfig` file in the container
+ - if omitted or a `null` value is given, its value is defaulted to `/opt/app-root/src/.kube/config`
+
+- `ansible_ssh_user`:
+ - specifies the ssh user to be used by Ansible when running the specified `PLAYBOOK_FILE` (see `README_CONTAINER_IMAGE.md` for additional information on this environment variable).
+ - if omitted, its value is defaulted to `root`
+
+- `ansible_become_user`:
+ - specifies a user to "become" on the remote host. Used for privilege escalation.
+ - If a non-null value is specified, `ansible_become` is implicitly set to `yes` in the resulting inventory file.
+
+See the supplied sample user configuration file in [`root/etc/inventory-generator-config.yaml`](./root/etc/inventory-generator-config.yaml) for additional optional inventory variables that may be specified.
+
+## Build
+
+See `README_CONTAINER_IMAGE.md` for information on building this image.
+
+## Run
+
+Given a master node's `master-config.yaml` file, a user configuration file (see "Configure" section), and an `admin.kubeconfig` file, the command below will:
+
+1. Use `oc` to query the host about additional node information (using the supplied `kubeconfig` file)
+2. Generate an inventory file based on information retrieved from `oc get nodes` and the given `master-config.yaml` file.
+3. run the specified [openshift-ansible](https://github.com/openshift/openshift-ansible) `health.yml` playbook using the generated inventory file from the previous step
+
+```
+docker run -u `id -u` \
+ -v $HOME/.ssh/id_rsa:/opt/app-root/src/.ssh/id_rsa:Z,ro \
+ -v /tmp/origin/master/admin.kubeconfig:/opt/app-root/src/.kube/config:Z \
+ -v /tmp/origin/master/master-config.yaml:/opt/app-root/src/master-config.yaml:Z \
+ -e OPTS="-v --become-user root" \
+ -e PLAYBOOK_FILE=playbooks/byo/openshift-checks/health.yml \
+ -e GENERATE_INVENTORY=true \
+ -e USER=`whoami` \
+ openshift/origin-ansible
+
+```
+
+**Note** In the command above, specifying the `GENERATE_INVENTORY` environment variable will automatically generate the inventory file in an expected location.
+An `INVENTORY_FILE` variable (or any other inventory location) does not need to be supplied when generating an inventory.
+
+## Debug
+
+To debug the `generate` script, run the above script interactively
+and manually execute `/usr/local/bin/generate`:
+
+```
+...
+docker run -u `id -u` \
+ -v ...
+ ...
+ -it openshift/origin-ansible /bin/bash
+
+---
+
+bash-4.2$ cd $HOME
+bash-4.2$ ls
+master-config.yaml
+bash-4.2$ /usr/local/bin/generate $HOME/generated_hosts
+bash-4.2$ ls
+generated_hosts master-config.yaml
+bash-4.2$ less generated_hosts
+...
+```
+
+## Notes
+
+See `README_CONTAINER_IMAGE.md` for additional information about this image.
diff --git a/images/installer/root/etc/inventory-generator-config.yaml b/images/installer/root/etc/inventory-generator-config.yaml
new file mode 100644
index 000000000..d56e3f4d2
--- /dev/null
+++ b/images/installer/root/etc/inventory-generator-config.yaml
@@ -0,0 +1,20 @@
+---
+# meta config
+master_config_path: "/opt/app-root/src/master-config.yaml"
+admin_kubeconfig_path: "/opt/app-root/src/.kube/config"
+
+# default user configuration
+ansible_ssh_user: ec2-user
+ansible_become: "yes"
+ansible_become_user: "root"
+
+# openshift-ansible inventory vars
+openshift_uninstall_images: false
+openshift_install_examples: true
+openshift_deployment_type: origin
+
+openshift_release: 3.6
+openshift_image_tag: v3.6.0
+openshift_hosted_logging_deploy: null # defaults to "true" if loggingPublicURL is set in master-config.yaml
+openshift_logging_image_version: v3.6.0
+openshift_disable_check: ""
diff --git a/images/installer/root/exports/config.json.template b/images/installer/root/exports/config.json.template
index 739c0080f..1a009fa7b 100644
--- a/images/installer/root/exports/config.json.template
+++ b/images/installer/root/exports/config.json.template
@@ -24,7 +24,7 @@
"PLAYBOOK_FILE=$PLAYBOOK_FILE",
"ANSIBLE_CONFIG=$ANSIBLE_CONFIG"
],
- "cwd": "/opt/app-root/src/",
+ "cwd": "/usr/share/ansible/openshift-ansible",
"rlimits": [
{
"type": "RLIMIT_NOFILE",
diff --git a/images/installer/root/usr/local/bin/generate b/images/installer/root/usr/local/bin/generate
new file mode 100755
index 000000000..3db7a3ee8
--- /dev/null
+++ b/images/installer/root/usr/local/bin/generate
@@ -0,0 +1,397 @@
+#!/bin/env python
+
+"""
+Attempts to read 'master-config.yaml' and extract remote
+host information to dynamically create an inventory file
+in order to run Ansible playbooks against that host.
+"""
+
+import os
+import re
+import shlex
+import shutil
+import subprocess
+import sys
+import yaml
+
+try:
+ HOME = os.environ['HOME']
+except KeyError:
+ print 'A required environment variable "$HOME" has not been set'
+ exit(1)
+
+DEFAULT_USER_CONFIG_PATH = '/etc/inventory-generator-config.yaml'
+DEFAULT_MASTER_CONFIG_PATH = HOME + '/master-config.yaml'
+DEFAULT_ADMIN_KUBECONFIG_PATH = HOME + '/.kube/config'
+
+INVENTORY_FULL_PATH = HOME + '/generated_hosts'
+USE_STDOUT = True
+
+if len(sys.argv) > 1:
+ INVENTORY_FULL_PATH = sys.argv[1]
+ USE_STDOUT = False
+
+
+class OpenShiftClientError(Exception):
+ """Base exception class for OpenShift CLI wrapper"""
+ pass
+
+
+class InvalidHost(Exception):
+ """Base exception class for host creation problems."""
+ pass
+
+
+class InvalidHostGroup(Exception):
+ """Base exception class for host-group creation problems."""
+ pass
+
+
+class OpenShiftClient:
+ oc = None
+ kubeconfig = None
+
+ def __init__(self, kubeconfig=DEFAULT_ADMIN_KUBECONFIG_PATH):
+ """Find and store path to oc binary"""
+ # https://github.com/openshift/openshift-ansible/issues/3410
+ # oc can be in /usr/local/bin in some cases, but that may not
+ # be in $PATH due to ansible/sudo
+ paths = os.environ.get("PATH", os.defpath).split(os.pathsep) + ['/usr/local/bin', os.path.expanduser('~/bin')]
+
+ oc_binary_name = 'oc'
+ oc_binary = None
+
+ # Use shutil.which if it is available, otherwise fallback to a naive path search
+ try:
+ which_result = shutil.which(oc_binary_name, path=os.pathsep.join(paths))
+ if which_result is not None:
+ oc_binary = which_result
+ except AttributeError:
+ for path in paths:
+ if os.path.exists(os.path.join(path, oc_binary_name)):
+ oc_binary = os.path.join(path, oc_binary_name)
+ break
+
+ if oc_binary is None:
+ raise OpenShiftClientError('Unable to locate `oc` binary. Not present in PATH.')
+
+ self.oc = oc_binary
+ self.kubeconfig = kubeconfig
+
+ def call(self, cmd_str):
+ """Execute a remote call using `oc`"""
+ cmd = [
+ self.oc,
+ '--config',
+ self.kubeconfig
+ ] + shlex.split(cmd_str)
+ try:
+ out = subprocess.check_output(list(cmd), stderr=subprocess.STDOUT)
+ except subprocess.CalledProcessError as err:
+ raise OpenShiftClientError('[rc {}] {}\n{}'.format(err.returncode, ' '.join(err.cmd), err.output))
+ return out
+
+ def whoami(self):
+ """Retrieve information about the current user in the given kubeconfig"""
+ return self.call('whoami')
+
+ def get_nodes(self):
+ """Retrieve remote node information as a yaml object"""
+ return self.call('get nodes -o yaml')
+
+
+class HostGroup:
+ groupname = ""
+ hosts = list()
+
+ def __init__(self, hosts):
+ if not hosts:
+ return
+ first = hosts[0].get_group_name()
+ for h in hosts:
+ if h.get_group_name() != first:
+ raise InvalidHostGroup("Attempt to create HostGroup with hosts of varying groups.")
+
+ self.hosts = hosts
+ self.groupname = first
+
+ def add_host(self, host):
+ """Add a new host to this group."""
+ self.hosts.append(host)
+
+ def get_group_name(self):
+ """Return the groupname associated with each aggregated host."""
+ return self.groupname
+
+ def get_hosts(self):
+ """Return aggregated hosts"""
+ return self.hosts
+
+ def string(self):
+ """Call the print method for each aggregated host; separated by newlines."""
+ infos = ""
+ for host in self.hosts:
+ infos += host.string() + "\n"
+ return infos
+
+
+class Host:
+ group = "masters"
+ alias = ""
+ hostname = ""
+ public_hostname = ""
+ ip_addr = ""
+ public_ip_addr = ""
+
+ def __init__(self, groupname):
+ if not groupname:
+ raise InvalidHost("Attempt to create Host with no group name provided.")
+ self.group = groupname
+
+ def get_group_name(self):
+ return self.group
+
+ def get_openshift_hostname(self):
+ return self.hostname
+
+ def host_alias(self, hostalias):
+ """Set an alias for this host."""
+ self.alias = hostalias
+
+ def address(self, ip):
+ """Set the ip address for this host."""
+ self.ip_addr = ip
+
+ def public_address(self, ip):
+ """Set the external ip address for this host."""
+ self.public_ip_addr = ip
+
+ def host_name(self, hname):
+ self.hostname = parse_hostname(hname)
+
+ def public_host_name(self, phname):
+ self.public_hostname = parse_hostname(phname)
+
+ def string(self):
+ """Print an inventory-file compatible string with host information"""
+ info = ""
+ if self.alias:
+ info += self.alias + " "
+ elif self.hostname:
+ info += self.hostname + " "
+ elif self.ip_addr:
+ info += self.ip_addr + " "
+ if self.ip_addr:
+ info += "openshift_ip=" + self.ip_addr + " "
+ if self.public_ip_addr:
+ info += "openshift_public_ip=" + self.public_ip_addr + " "
+ if self.hostname:
+ info += "openshift_hostname=" + self.hostname + " "
+ if self.public_hostname:
+ info += "openshift_public_hostname=" + self.public_hostname
+
+ return info
+
+
+def parse_hostname(host):
+ """Remove protocol and port from given hostname.
+ Return parsed string"""
+ no_proto = re.split('^http(s)?\:\/\/', host)
+ if no_proto:
+ host = no_proto[-1]
+
+ no_port = re.split('\:[0-9]+(/)?$', host)
+ if no_port:
+ host = no_port[0]
+
+ return host
+
+
+def main():
+ """Parse master-config file and populate inventory file."""
+ # set default values
+ USER_CONFIG = os.environ.get('CONFIG')
+ if not USER_CONFIG:
+ USER_CONFIG = DEFAULT_USER_CONFIG_PATH
+
+ # read user configuration
+ try:
+ config_file_obj = open(USER_CONFIG, 'r')
+ raw_config_file = config_file_obj.read()
+ user_config = yaml.load(raw_config_file)
+ if not user_config:
+ user_config = dict()
+ except IOError as err:
+ print "Unable to find or read user configuration file '{}': {}".format(USER_CONFIG, err)
+ exit(1)
+
+ master_config_path = user_config.get('master_config_path', DEFAULT_MASTER_CONFIG_PATH)
+ if not master_config_path:
+ master_config_path = DEFAULT_MASTER_CONFIG_PATH
+
+ admin_kubeconfig_path = user_config.get('admin_kubeconfig_path', DEFAULT_ADMIN_KUBECONFIG_PATH)
+ if not admin_kubeconfig_path:
+ admin_kubeconfig_path = DEFAULT_ADMIN_KUBECONFIG_PATH
+
+ try:
+ file_obj = open(master_config_path, 'r')
+ except IOError as err:
+ print "Unable to find or read host master configuration file '{}': {}".format(master_config_path, err)
+ exit(1)
+
+ raw_text = file_obj.read()
+
+ y = yaml.load(raw_text)
+ if y.get("kind", "") != "MasterConfig":
+ print "Bind-mounted host master configuration file is not of 'kind' MasterConfig. Aborting..."
+ exit(1)
+
+ # finish reading config file and begin gathering
+ # cluster information for inventory file
+ file_obj.close()
+
+ # set inventory values based on user configuration
+ ansible_ssh_user = user_config.get('ansible_ssh_user', 'root')
+ ansible_become_user = user_config.get('ansible_become_user')
+
+ openshift_uninstall_images = user_config.get('openshift_uninstall_images', False)
+ openshift_install_examples = user_config.get('openshift_install_examples', True)
+ openshift_deployment_type = user_config.get('openshift_deployment_type', 'origin')
+
+ openshift_release = user_config.get('openshift_release')
+ openshift_image_tag = user_config.get('openshift_image_tag')
+ openshift_logging_image_version = user_config.get('openshift_logging_image_version')
+ openshift_disable_check = user_config.get('openshift_disable_check')
+
+ # extract host config info from parsed yaml file
+ asset_config = y.get("assetConfig")
+ master_config = y.get("kubernetesMasterConfig")
+ etcd_config = y.get("etcdClientInfo")
+
+ # if master_config is missing, error out; we expect to be running on a master to be able to
+ # gather enough information to generate the rest of the inventory file.
+ if not master_config:
+ msg = "'kubernetesMasterConfig' missing from '{}'; unable to gather all necessary host information..."
+ print msg.format(master_config_path)
+ exit(1)
+
+ master_public_url = y.get("masterPublicURL")
+ if not master_public_url:
+ msg = "'kubernetesMasterConfig.masterPublicURL' missing from '{}'; Unable to connect to master host..."
+ print msg.format(master_config_path)
+ exit(1)
+
+ oc = OpenShiftClient(admin_kubeconfig_path)
+
+ # ensure kubeconfig is logged in with provided user, or fail with a friendly message otherwise
+ try:
+ oc.whoami()
+ except OpenShiftClientError as err:
+ msg = ("Unable to obtain user information using the provided kubeconfig file. "
+ "Current context does not appear to be able to authenticate to the server. "
+ "Error returned from server:\n\n{}")
+ print msg.format(str(err))
+ exit(1)
+
+ # connect to remote host using the provided config and extract all possible node information
+ nodes_config = yaml.load(oc.get_nodes())
+
+ # contains host types (e.g. masters, nodes, etcd)
+ host_groups = dict()
+ openshift_hosted_logging_deploy = False
+ is_etcd_deployed = master_config.get("storage-backend", "") in ["etcd3", "etcd2", "etcd"]
+
+ if asset_config and asset_config.get('loggingPublicURL'):
+ openshift_hosted_logging_deploy = True
+
+ openshift_hosted_logging_deploy = user_config.get("openshift_hosted_logging_deploy", openshift_hosted_logging_deploy)
+
+ m = Host("masters")
+ m.address(master_config["masterIP"])
+ m.public_host_name(master_public_url)
+ host_groups["masters"] = HostGroup([m])
+
+ if nodes_config:
+ node_hosts = list()
+ for node in nodes_config.get("items", []):
+ if node["kind"] != "Node":
+ continue
+
+ n = Host("nodes")
+
+ address = ""
+ internal_hostname = ""
+ for item in node["status"].get("addresses", []):
+ if not address and item['type'] in ['InternalIP', 'LegacyHostIP']:
+ address = item['address']
+
+ if item['type'] == 'Hostname':
+ internal_hostname = item['address']
+
+ n.address(address)
+ n.host_name(internal_hostname)
+ node_hosts.append(n)
+
+ host_groups["nodes"] = HostGroup(node_hosts)
+
+ if etcd_config:
+ etcd_hosts = list()
+ for url in etcd_config.get("urls", []):
+ e = Host("etcd")
+ e.host_name(url)
+ etcd_hosts.append(e)
+
+ host_groups["etcd"] = HostGroup(etcd_hosts)
+
+ # open new inventory file for writing
+ if USE_STDOUT:
+ inv_file_obj = sys.stdout
+ else:
+ try:
+ inv_file_obj = open(INVENTORY_FULL_PATH, 'w+')
+ except IOError as err:
+ print "Unable to create or open generated inventory file: {}".format(err)
+ exit(1)
+
+ inv_file_obj.write("[OSEv3:children]\n")
+ for group in host_groups:
+ inv_file_obj.write("{}\n".format(group))
+ inv_file_obj.write("\n")
+
+ inv_file_obj.write("[OSEv3:vars]\n")
+ if ansible_ssh_user:
+ inv_file_obj.write("ansible_ssh_user={}\n".format(ansible_ssh_user))
+ if ansible_become_user:
+ inv_file_obj.write("ansible_become_user={}\n".format(ansible_become_user))
+ inv_file_obj.write("ansible_become=yes\n")
+
+ if openshift_uninstall_images:
+ inv_file_obj.write("openshift_uninstall_images={}\n".format(str(openshift_uninstall_images)))
+ if openshift_deployment_type:
+ inv_file_obj.write("openshift_deployment_type={}\n".format(openshift_deployment_type))
+ if openshift_install_examples:
+ inv_file_obj.write("openshift_install_examples={}\n".format(str(openshift_install_examples)))
+
+ if openshift_release:
+ inv_file_obj.write("openshift_release={}\n".format(str(openshift_release)))
+ if openshift_image_tag:
+ inv_file_obj.write("openshift_image_tag={}\n".format(str(openshift_image_tag)))
+ if openshift_logging_image_version:
+ inv_file_obj.write("openshift_logging_image_version={}\n".format(str(openshift_logging_image_version)))
+ if openshift_disable_check:
+ inv_file_obj.write("openshift_disable_check={}\n".format(str(openshift_disable_check)))
+ inv_file_obj.write("\n")
+
+ inv_file_obj.write("openshift_hosted_logging_deploy={}\n".format(str(openshift_hosted_logging_deploy)))
+ inv_file_obj.write("\n")
+
+ for group in host_groups:
+ inv_file_obj.write("[{}]\n".format(host_groups[group].get_group_name()))
+ inv_file_obj.write(host_groups[group].string())
+ inv_file_obj.write("\n")
+
+ inv_file_obj.close()
+
+
+if __name__ == '__main__':
+ main()
diff --git a/images/installer/root/usr/local/bin/run b/images/installer/root/usr/local/bin/run
index 9401ea118..70aa0bac3 100755
--- a/images/installer/root/usr/local/bin/run
+++ b/images/installer/root/usr/local/bin/run
@@ -24,9 +24,12 @@ elif [[ -v INVENTORY_URL ]]; then
elif [[ -v DYNAMIC_SCRIPT_URL ]]; then
curl -o ${INVENTORY} ${DYNAMIC_SCRIPT_URL}
chmod 755 ${INVENTORY}
+elif [[ -v GENERATE_INVENTORY ]]; then
+ # dynamically generate inventory file using bind-mounted info
+ /usr/local/bin/generate ${INVENTORY}
else
echo
- echo "One of INVENTORY_FILE, INVENTORY_URL or DYNAMIC_SCRIPT_URL must be provided."
+ echo "One of INVENTORY_FILE, INVENTORY_URL, GENERATE_INVENTORY, or DYNAMIC_SCRIPT_URL must be provided."
exec /usr/local/bin/usage
fi
INVENTORY_ARG="-i ${INVENTORY}"
@@ -36,7 +39,7 @@ if [[ "$ALLOW_ANSIBLE_CONNECTION_LOCAL" = false ]]; then
fi
if [[ -v VAULT_PASS ]]; then
- VAULT_PASS_FILE=.vaultpass
+ VAULT_PASS_FILE="$(mktemp)"
echo ${VAULT_PASS} > ${VAULT_PASS_FILE}
VAULT_PASS_ARG="--vault-password-file ${VAULT_PASS_FILE}"
fi
diff --git a/inventory/README.md b/inventory/README.md
index b61bfff18..5e26e3c32 100644
--- a/inventory/README.md
+++ b/inventory/README.md
@@ -2,8 +2,4 @@
You can install OpenShift on:
-* [Amazon Web Services](aws/hosts/)
-* [BYO](byo/) (Bring your own), use this inventory config file to install OpenShift on your bare metal servers
-* [GCE](gce/) (Google Compute Engine)
-* [libvirt](libvirt/hosts/)
-* [OpenStack](openstack/hosts/)
+* [BYO](byo/) (Bring your own), use this inventory config file to install OpenShift on your pre-existing hosts
diff --git a/inventory/aws/hosts/ec2.ini b/inventory/aws/hosts/ec2.ini
deleted file mode 100644
index 64c097d47..000000000
--- a/inventory/aws/hosts/ec2.ini
+++ /dev/null
@@ -1,189 +0,0 @@
-# Ansible EC2 external inventory script settings
-#
-
-[ec2]
-
-# to talk to a private eucalyptus instance uncomment these lines
-# and edit edit eucalyptus_host to be the host name of your cloud controller
-#eucalyptus = True
-#eucalyptus_host = clc.cloud.domain.org
-
-# AWS regions to make calls to. Set this to 'all' to make request to all regions
-# in AWS and merge the results together. Alternatively, set this to a comma
-# separated list of regions. E.g. 'us-east-1,us-west-1,us-west-2'
-regions = all
-regions_exclude = us-gov-west-1,cn-north-1
-
-# When generating inventory, Ansible needs to know how to address a server.
-# Each EC2 instance has a lot of variables associated with it. Here is the list:
-# http://docs.pythonboto.org/en/latest/ref/ec2.html#module-boto.ec2.instance
-# Below are 2 variables that are used as the address of a server:
-# - destination_variable
-# - vpc_destination_variable
-
-# This is the normal destination variable to use. If you are running Ansible
-# from outside EC2, then 'public_dns_name' makes the most sense. If you are
-# running Ansible from within EC2, then perhaps you want to use the internal
-# address, and should set this to 'private_dns_name'. The key of an EC2 tag
-# may optionally be used; however the boto instance variables hold precedence
-# in the event of a collision.
-destination_variable = public_dns_name
-
-# This allows you to override the inventory_name with an ec2 variable, instead
-# of using the destination_variable above. Addressing (aka ansible_ssh_host)
-# will still use destination_variable. Tags should be written as 'tag_TAGNAME'.
-hostname_variable = tag_Name
-
-# For server inside a VPC, using DNS names may not make sense. When an instance
-# has 'subnet_id' set, this variable is used. If the subnet is public, setting
-# this to 'ip_address' will return the public IP address. For instances in a
-# private subnet, this should be set to 'private_ip_address', and Ansible must
-# be run from within EC2. The key of an EC2 tag may optionally be used; however
-# the boto instance variables hold precedence in the event of a collision.
-# WARNING: - instances that are in the private vpc, _without_ public ip address
-# will not be listed in the inventory until You set:
-# vpc_destination_variable = private_ip_address
-vpc_destination_variable = ip_address
-
-# The following two settings allow flexible ansible host naming based on a
-# python format string and a comma-separated list of ec2 tags. Note that:
-#
-# 1) If the tags referenced are not present for some instances, empty strings
-# will be substituted in the format string.
-# 2) This overrides both destination_variable and vpc_destination_variable.
-#
-#destination_format = {0}.{1}.example.com
-#destination_format_tags = Name,environment
-
-# To tag instances on EC2 with the resource records that point to them from
-# Route53, uncomment and set 'route53' to True.
-route53 = False
-
-# To exclude RDS instances from the inventory, uncomment and set to False.
-rds = False
-
-# To exclude ElastiCache instances from the inventory, uncomment and set to False.
-elasticache = False
-
-# Additionally, you can specify the list of zones to exclude looking up in
-# 'route53_excluded_zones' as a comma-separated list.
-# route53_excluded_zones = samplezone1.com, samplezone2.com
-
-# By default, only EC2 instances in the 'running' state are returned. Set
-# 'all_instances' to True to return all instances regardless of state.
-all_instances = False
-
-# By default, only EC2 instances in the 'running' state are returned. Specify
-# EC2 instance states to return as a comma-separated list. This
-# option is overridden when 'all_instances' is True.
-# instance_states = pending, running, shutting-down, terminated, stopping, stopped
-
-# By default, only RDS instances in the 'available' state are returned. Set
-# 'all_rds_instances' to True return all RDS instances regardless of state.
-all_rds_instances = False
-
-# Include RDS cluster information (Aurora etc.)
-include_rds_clusters = False
-
-# By default, only ElastiCache clusters and nodes in the 'available' state
-# are returned. Set 'all_elasticache_clusters' and/or 'all_elastic_nodes'
-# to True return all ElastiCache clusters and nodes, regardless of state.
-#
-# Note that all_elasticache_nodes only applies to listed clusters. That means
-# if you set all_elastic_clusters to false, no node will be return from
-# unavailable clusters, regardless of the state and to what you set for
-# all_elasticache_nodes.
-all_elasticache_replication_groups = False
-all_elasticache_clusters = False
-all_elasticache_nodes = False
-
-# API calls to EC2 are slow. For this reason, we cache the results of an API
-# call. Set this to the path you want cache files to be written to. Two files
-# will be written to this directory:
-# - ansible-ec2.cache
-# - ansible-ec2.index
-cache_path = ~/.ansible/tmp
-
-# The number of seconds a cache file is considered valid. After this many
-# seconds, a new API call will be made, and the cache file will be updated.
-# To disable the cache, set this value to 0
-cache_max_age = 300
-
-# Organize groups into a nested/hierarchy instead of a flat namespace.
-nested_groups = False
-
-# Replace - tags when creating groups to avoid issues with ansible
-replace_dash_in_groups = False
-
-# If set to true, any tag of the form "a,b,c" is expanded into a list
-# and the results are used to create additional tag_* inventory groups.
-expand_csv_tags = False
-
-# The EC2 inventory output can become very large. To manage its size,
-# configure which groups should be created.
-group_by_instance_id = True
-group_by_region = True
-group_by_availability_zone = True
-group_by_ami_id = True
-group_by_instance_type = True
-group_by_key_pair = True
-group_by_vpc_id = True
-group_by_security_group = True
-group_by_tag_keys = True
-group_by_tag_none = True
-group_by_route53_names = True
-group_by_rds_engine = True
-group_by_rds_parameter_group = True
-group_by_elasticache_engine = True
-group_by_elasticache_cluster = True
-group_by_elasticache_parameter_group = True
-group_by_elasticache_replication_group = True
-
-# If you only want to include hosts that match a certain regular expression
-# pattern_include = staging-*
-
-# If you want to exclude any hosts that match a certain regular expression
-# pattern_exclude = staging-*
-
-# Instance filters can be used to control which instances are retrieved for
-# inventory. For the full list of possible filters, please read the EC2 API
-# docs: http://docs.aws.amazon.com/AWSEC2/latest/APIReference/ApiReference-query-DescribeInstances.html#query-DescribeInstances-filters
-# Filters are key/value pairs separated by '=', to list multiple filters use
-# a list separated by commas. See examples below.
-
-# Retrieve only instances with (key=value) env=staging tag
-# instance_filters = tag:env=staging
-
-# Retrieve only instances with role=webservers OR role=dbservers tag
-# instance_filters = tag:role=webservers,tag:role=dbservers
-
-# Retrieve only t1.micro instances OR instances with tag env=staging
-# instance_filters = instance-type=t1.micro,tag:env=staging
-
-# You can use wildcards in filter values also. Below will list instances which
-# tag Name value matches webservers1*
-# (ex. webservers15, webservers1a, webservers123 etc)
-# instance_filters = tag:Name=webservers1*
-
-# A boto configuration profile may be used to separate out credentials
-# see http://boto.readthedocs.org/en/latest/boto_config_tut.html
-# boto_profile = some-boto-profile-name
-
-
-[credentials]
-
-# The AWS credentials can optionally be specified here. Credentials specified
-# here are ignored if the environment variable AWS_ACCESS_KEY_ID or
-# AWS_PROFILE is set, or if the boto_profile property above is set.
-#
-# Supplying AWS credentials here is not recommended, as it introduces
-# non-trivial security concerns. When going down this route, please make sure
-# to set access permissions for this file correctly, e.g. handle it the same
-# way as you would a private SSH key.
-#
-# Unlike the boto and AWS configure files, this section does not support
-# profiles.
-#
-# aws_access_key_id = AXXXXXXXXXXXXXX
-# aws_secret_access_key = XXXXXXXXXXXXXXXXXXX
-# aws_security_token = XXXXXXXXXXXXXXXXXXXXXXXXXXXX
diff --git a/inventory/aws/hosts/ec2.py b/inventory/aws/hosts/ec2.py
deleted file mode 100755
index b71458a29..000000000
--- a/inventory/aws/hosts/ec2.py
+++ /dev/null
@@ -1,1511 +0,0 @@
-#!/usr/bin/env python2
-# pylint: skip-file
-
-'''
-EC2 external inventory script
-=================================
-
-Generates inventory that Ansible can understand by making API request to
-AWS EC2 using the Boto library.
-
-NOTE: This script assumes Ansible is being executed where the environment
-variables needed for Boto have already been set:
- export AWS_ACCESS_KEY_ID='AK123'
- export AWS_SECRET_ACCESS_KEY='abc123'
-
-This script also assumes there is an ec2.ini file alongside it. To specify a
-different path to ec2.ini, define the EC2_INI_PATH environment variable:
-
- export EC2_INI_PATH=/path/to/my_ec2.ini
-
-If you're using eucalyptus you need to set the above variables and
-you need to define:
-
- export EC2_URL=http://hostname_of_your_cc:port/services/Eucalyptus
-
-If you're using boto profiles (requires boto>=2.24.0) you can choose a profile
-using the --boto-profile command line argument (e.g. ec2.py --boto-profile prod) or using
-the AWS_PROFILE variable:
-
- AWS_PROFILE=prod ansible-playbook -i ec2.py myplaybook.yml
-
-For more details, see: http://docs.pythonboto.org/en/latest/boto_config_tut.html
-
-When run against a specific host, this script returns the following variables:
- - ec2_ami_launch_index
- - ec2_architecture
- - ec2_association
- - ec2_attachTime
- - ec2_attachment
- - ec2_attachmentId
- - ec2_block_devices
- - ec2_client_token
- - ec2_deleteOnTermination
- - ec2_description
- - ec2_deviceIndex
- - ec2_dns_name
- - ec2_eventsSet
- - ec2_group_name
- - ec2_hypervisor
- - ec2_id
- - ec2_image_id
- - ec2_instanceState
- - ec2_instance_type
- - ec2_ipOwnerId
- - ec2_ip_address
- - ec2_item
- - ec2_kernel
- - ec2_key_name
- - ec2_launch_time
- - ec2_monitored
- - ec2_monitoring
- - ec2_networkInterfaceId
- - ec2_ownerId
- - ec2_persistent
- - ec2_placement
- - ec2_platform
- - ec2_previous_state
- - ec2_private_dns_name
- - ec2_private_ip_address
- - ec2_publicIp
- - ec2_public_dns_name
- - ec2_ramdisk
- - ec2_reason
- - ec2_region
- - ec2_requester_id
- - ec2_root_device_name
- - ec2_root_device_type
- - ec2_security_group_ids
- - ec2_security_group_names
- - ec2_shutdown_state
- - ec2_sourceDestCheck
- - ec2_spot_instance_request_id
- - ec2_state
- - ec2_state_code
- - ec2_state_reason
- - ec2_status
- - ec2_subnet_id
- - ec2_tenancy
- - ec2_virtualization_type
- - ec2_vpc_id
-
-These variables are pulled out of a boto.ec2.instance object. There is a lack of
-consistency with variable spellings (camelCase and underscores) since this
-just loops through all variables the object exposes. It is preferred to use the
-ones with underscores when multiple exist.
-
-In addition, if an instance has AWS Tags associated with it, each tag is a new
-variable named:
- - ec2_tag_[Key] = [Value]
-
-Security groups are comma-separated in 'ec2_security_group_ids' and
-'ec2_security_group_names'.
-'''
-
-# (c) 2012, Peter Sankauskas
-#
-# This file is part of Ansible,
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
-
-######################################################################
-
-import sys
-import os
-import argparse
-import re
-from time import time
-import boto
-from boto import ec2
-from boto import rds
-from boto import elasticache
-from boto import route53
-import six
-
-from ansible.module_utils import ec2 as ec2_utils
-
-HAS_BOTO3 = False
-try:
- import boto3
- HAS_BOTO3 = True
-except ImportError:
- pass
-
-from six.moves import configparser
-from collections import defaultdict
-
-try:
- import json
-except ImportError:
- import simplejson as json
-
-
-class Ec2Inventory(object):
-
- def _empty_inventory(self):
- return {"_meta" : {"hostvars" : {}}}
-
- def __init__(self):
- ''' Main execution path '''
-
- # Inventory grouped by instance IDs, tags, security groups, regions,
- # and availability zones
- self.inventory = self._empty_inventory()
-
- # Index of hostname (address) to instance ID
- self.index = {}
-
- # Boto profile to use (if any)
- self.boto_profile = None
-
- # AWS credentials.
- self.credentials = {}
-
- # Read settings and parse CLI arguments
- self.parse_cli_args()
- self.read_settings()
-
- # Make sure that profile_name is not passed at all if not set
- # as pre 2.24 boto will fall over otherwise
- if self.boto_profile:
- if not hasattr(boto.ec2.EC2Connection, 'profile_name'):
- self.fail_with_error("boto version must be >= 2.24 to use profile")
-
- # Cache
- if self.args.refresh_cache:
- self.do_api_calls_update_cache()
- elif not self.is_cache_valid():
- self.do_api_calls_update_cache()
-
- # Data to print
- if self.args.host:
- data_to_print = self.get_host_info()
-
- elif self.args.list:
- # Display list of instances for inventory
- if self.inventory == self._empty_inventory():
- data_to_print = self.get_inventory_from_cache()
- else:
- data_to_print = self.json_format_dict(self.inventory, True)
-
- print(data_to_print)
-
-
- def is_cache_valid(self):
- ''' Determines if the cache files have expired, or if it is still valid '''
-
- if os.path.isfile(self.cache_path_cache):
- mod_time = os.path.getmtime(self.cache_path_cache)
- current_time = time()
- if (mod_time + self.cache_max_age) > current_time:
- if os.path.isfile(self.cache_path_index):
- return True
-
- return False
-
-
- def read_settings(self):
- ''' Reads the settings from the ec2.ini file '''
- if six.PY3:
- config = configparser.ConfigParser()
- else:
- config = configparser.SafeConfigParser()
- ec2_default_ini_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'ec2.ini')
- ec2_ini_path = os.path.expanduser(os.path.expandvars(os.environ.get('EC2_INI_PATH', ec2_default_ini_path)))
- config.read(ec2_ini_path)
-
- # is eucalyptus?
- self.eucalyptus_host = None
- self.eucalyptus = False
- if config.has_option('ec2', 'eucalyptus'):
- self.eucalyptus = config.getboolean('ec2', 'eucalyptus')
- if self.eucalyptus and config.has_option('ec2', 'eucalyptus_host'):
- self.eucalyptus_host = config.get('ec2', 'eucalyptus_host')
-
- # Regions
- self.regions = []
- configRegions = config.get('ec2', 'regions')
- configRegions_exclude = config.get('ec2', 'regions_exclude')
- if (configRegions == 'all'):
- if self.eucalyptus_host:
- self.regions.append(boto.connect_euca(host=self.eucalyptus_host).region.name, **self.credentials)
- else:
- for regionInfo in ec2.regions():
- if regionInfo.name not in configRegions_exclude:
- self.regions.append(regionInfo.name)
- else:
- self.regions = configRegions.split(",")
-
- # Destination addresses
- self.destination_variable = config.get('ec2', 'destination_variable')
- self.vpc_destination_variable = config.get('ec2', 'vpc_destination_variable')
-
- if config.has_option('ec2', 'hostname_variable'):
- self.hostname_variable = config.get('ec2', 'hostname_variable')
- else:
- self.hostname_variable = None
-
- if config.has_option('ec2', 'destination_format') and \
- config.has_option('ec2', 'destination_format_tags'):
- self.destination_format = config.get('ec2', 'destination_format')
- self.destination_format_tags = config.get('ec2', 'destination_format_tags').split(',')
- else:
- self.destination_format = None
- self.destination_format_tags = None
-
- # Route53
- self.route53_enabled = config.getboolean('ec2', 'route53')
- self.route53_excluded_zones = []
- if config.has_option('ec2', 'route53_excluded_zones'):
- self.route53_excluded_zones.extend(
- config.get('ec2', 'route53_excluded_zones', '').split(','))
-
- # Include RDS instances?
- self.rds_enabled = True
- if config.has_option('ec2', 'rds'):
- self.rds_enabled = config.getboolean('ec2', 'rds')
-
- # Include RDS cluster instances?
- if config.has_option('ec2', 'include_rds_clusters'):
- self.include_rds_clusters = config.getboolean('ec2', 'include_rds_clusters')
- else:
- self.include_rds_clusters = False
-
- # Include ElastiCache instances?
- self.elasticache_enabled = True
- if config.has_option('ec2', 'elasticache'):
- self.elasticache_enabled = config.getboolean('ec2', 'elasticache')
-
- # Return all EC2 instances?
- if config.has_option('ec2', 'all_instances'):
- self.all_instances = config.getboolean('ec2', 'all_instances')
- else:
- self.all_instances = False
-
- # Instance states to be gathered in inventory. Default is 'running'.
- # Setting 'all_instances' to 'yes' overrides this option.
- ec2_valid_instance_states = [
- 'pending',
- 'running',
- 'shutting-down',
- 'terminated',
- 'stopping',
- 'stopped'
- ]
- self.ec2_instance_states = []
- if self.all_instances:
- self.ec2_instance_states = ec2_valid_instance_states
- elif config.has_option('ec2', 'instance_states'):
- for instance_state in config.get('ec2', 'instance_states').split(','):
- instance_state = instance_state.strip()
- if instance_state not in ec2_valid_instance_states:
- continue
- self.ec2_instance_states.append(instance_state)
- else:
- self.ec2_instance_states = ['running']
-
- # Return all RDS instances? (if RDS is enabled)
- if config.has_option('ec2', 'all_rds_instances') and self.rds_enabled:
- self.all_rds_instances = config.getboolean('ec2', 'all_rds_instances')
- else:
- self.all_rds_instances = False
-
- # Return all ElastiCache replication groups? (if ElastiCache is enabled)
- if config.has_option('ec2', 'all_elasticache_replication_groups') and self.elasticache_enabled:
- self.all_elasticache_replication_groups = config.getboolean('ec2', 'all_elasticache_replication_groups')
- else:
- self.all_elasticache_replication_groups = False
-
- # Return all ElastiCache clusters? (if ElastiCache is enabled)
- if config.has_option('ec2', 'all_elasticache_clusters') and self.elasticache_enabled:
- self.all_elasticache_clusters = config.getboolean('ec2', 'all_elasticache_clusters')
- else:
- self.all_elasticache_clusters = False
-
- # Return all ElastiCache nodes? (if ElastiCache is enabled)
- if config.has_option('ec2', 'all_elasticache_nodes') and self.elasticache_enabled:
- self.all_elasticache_nodes = config.getboolean('ec2', 'all_elasticache_nodes')
- else:
- self.all_elasticache_nodes = False
-
- # boto configuration profile (prefer CLI argument)
- self.boto_profile = self.args.boto_profile
- if config.has_option('ec2', 'boto_profile') and not self.boto_profile:
- self.boto_profile = config.get('ec2', 'boto_profile')
-
- # AWS credentials (prefer environment variables)
- if not (self.boto_profile or os.environ.get('AWS_ACCESS_KEY_ID') or
- os.environ.get('AWS_PROFILE')):
- if config.has_option('credentials', 'aws_access_key_id'):
- aws_access_key_id = config.get('credentials', 'aws_access_key_id')
- else:
- aws_access_key_id = None
- if config.has_option('credentials', 'aws_secret_access_key'):
- aws_secret_access_key = config.get('credentials', 'aws_secret_access_key')
- else:
- aws_secret_access_key = None
- if config.has_option('credentials', 'aws_security_token'):
- aws_security_token = config.get('credentials', 'aws_security_token')
- else:
- aws_security_token = None
- if aws_access_key_id:
- self.credentials = {
- 'aws_access_key_id': aws_access_key_id,
- 'aws_secret_access_key': aws_secret_access_key
- }
- if aws_security_token:
- self.credentials['security_token'] = aws_security_token
-
- # Cache related
- cache_dir = os.path.expanduser(config.get('ec2', 'cache_path'))
- if self.boto_profile:
- cache_dir = os.path.join(cache_dir, 'profile_' + self.boto_profile)
- if not os.path.exists(cache_dir):
- os.makedirs(cache_dir)
-
- cache_name = 'ansible-ec2'
- aws_profile = lambda: (self.boto_profile or
- os.environ.get('AWS_PROFILE') or
- os.environ.get('AWS_ACCESS_KEY_ID') or
- self.credentials.get('aws_access_key_id', None))
- if aws_profile():
- cache_name = '%s-%s' % (cache_name, aws_profile())
- self.cache_path_cache = cache_dir + "/%s.cache" % cache_name
- self.cache_path_index = cache_dir + "/%s.index" % cache_name
- self.cache_max_age = config.getint('ec2', 'cache_max_age')
-
- if config.has_option('ec2', 'expand_csv_tags'):
- self.expand_csv_tags = config.getboolean('ec2', 'expand_csv_tags')
- else:
- self.expand_csv_tags = False
-
- # Configure nested groups instead of flat namespace.
- if config.has_option('ec2', 'nested_groups'):
- self.nested_groups = config.getboolean('ec2', 'nested_groups')
- else:
- self.nested_groups = False
-
- # Replace dash or not in group names
- if config.has_option('ec2', 'replace_dash_in_groups'):
- self.replace_dash_in_groups = config.getboolean('ec2', 'replace_dash_in_groups')
- else:
- self.replace_dash_in_groups = True
-
- # Configure which groups should be created.
- group_by_options = [
- 'group_by_instance_id',
- 'group_by_region',
- 'group_by_availability_zone',
- 'group_by_ami_id',
- 'group_by_instance_type',
- 'group_by_key_pair',
- 'group_by_vpc_id',
- 'group_by_security_group',
- 'group_by_tag_keys',
- 'group_by_tag_none',
- 'group_by_route53_names',
- 'group_by_rds_engine',
- 'group_by_rds_parameter_group',
- 'group_by_elasticache_engine',
- 'group_by_elasticache_cluster',
- 'group_by_elasticache_parameter_group',
- 'group_by_elasticache_replication_group',
- ]
- for option in group_by_options:
- if config.has_option('ec2', option):
- setattr(self, option, config.getboolean('ec2', option))
- else:
- setattr(self, option, True)
-
- # Do we need to just include hosts that match a pattern?
- try:
- pattern_include = config.get('ec2', 'pattern_include')
- if pattern_include and len(pattern_include) > 0:
- self.pattern_include = re.compile(pattern_include)
- else:
- self.pattern_include = None
- except configparser.NoOptionError:
- self.pattern_include = None
-
- # Do we need to exclude hosts that match a pattern?
- try:
- pattern_exclude = config.get('ec2', 'pattern_exclude');
- if pattern_exclude and len(pattern_exclude) > 0:
- self.pattern_exclude = re.compile(pattern_exclude)
- else:
- self.pattern_exclude = None
- except configparser.NoOptionError:
- self.pattern_exclude = None
-
- # Instance filters (see boto and EC2 API docs). Ignore invalid filters.
- self.ec2_instance_filters = defaultdict(list)
- if config.has_option('ec2', 'instance_filters'):
-
- filters = [f for f in config.get('ec2', 'instance_filters').split(',') if f]
-
- for instance_filter in filters:
- instance_filter = instance_filter.strip()
- if not instance_filter or '=' not in instance_filter:
- continue
- filter_key, filter_value = [x.strip() for x in instance_filter.split('=', 1)]
- if not filter_key:
- continue
- self.ec2_instance_filters[filter_key].append(filter_value)
-
- def parse_cli_args(self):
- ''' Command line argument processing '''
-
- parser = argparse.ArgumentParser(description='Produce an Ansible Inventory file based on EC2')
- parser.add_argument('--list', action='store_true', default=True,
- help='List instances (default: True)')
- parser.add_argument('--host', action='store',
- help='Get all the variables about a specific instance')
- parser.add_argument('--refresh-cache', action='store_true', default=False,
- help='Force refresh of cache by making API requests to EC2 (default: False - use cache files)')
- parser.add_argument('--profile', '--boto-profile', action='store', dest='boto_profile',
- help='Use boto profile for connections to EC2')
- self.args = parser.parse_args()
-
-
- def do_api_calls_update_cache(self):
- ''' Do API calls to each region, and save data in cache files '''
-
- if self.route53_enabled:
- self.get_route53_records()
-
- for region in self.regions:
- self.get_instances_by_region(region)
- if self.rds_enabled:
- self.get_rds_instances_by_region(region)
- if self.elasticache_enabled:
- self.get_elasticache_clusters_by_region(region)
- self.get_elasticache_replication_groups_by_region(region)
- if self.include_rds_clusters:
- self.include_rds_clusters_by_region(region)
-
- self.write_to_cache(self.inventory, self.cache_path_cache)
- self.write_to_cache(self.index, self.cache_path_index)
-
- def connect(self, region):
- ''' create connection to api server'''
- if self.eucalyptus:
- conn = boto.connect_euca(host=self.eucalyptus_host, **self.credentials)
- conn.APIVersion = '2010-08-31'
- else:
- conn = self.connect_to_aws(ec2, region)
- return conn
-
- def boto_fix_security_token_in_profile(self, connect_args):
- ''' monkey patch for boto issue boto/boto#2100 '''
- profile = 'profile ' + self.boto_profile
- if boto.config.has_option(profile, 'aws_security_token'):
- connect_args['security_token'] = boto.config.get(profile, 'aws_security_token')
- return connect_args
-
- def connect_to_aws(self, module, region):
- connect_args = self.credentials
-
- # only pass the profile name if it's set (as it is not supported by older boto versions)
- if self.boto_profile:
- connect_args['profile_name'] = self.boto_profile
- self.boto_fix_security_token_in_profile(connect_args)
-
- conn = module.connect_to_region(region, **connect_args)
- # connect_to_region will fail "silently" by returning None if the region name is wrong or not supported
- if conn is None:
- self.fail_with_error("region name: %s likely not supported, or AWS is down. connection to region failed." % region)
- return conn
-
- def get_instances_by_region(self, region):
- ''' Makes an AWS EC2 API call to the list of instances in a particular
- region '''
-
- try:
- conn = self.connect(region)
- reservations = []
- if self.ec2_instance_filters:
- for filter_key, filter_values in self.ec2_instance_filters.items():
- reservations.extend(conn.get_all_instances(filters = { filter_key : filter_values }))
- else:
- reservations = conn.get_all_instances()
-
- # Pull the tags back in a second step
- # AWS are on record as saying that the tags fetched in the first `get_all_instances` request are not
- # reliable and may be missing, and the only way to guarantee they are there is by calling `get_all_tags`
- instance_ids = []
- for reservation in reservations:
- instance_ids.extend([instance.id for instance in reservation.instances])
-
- max_filter_value = 199
- tags = []
- for i in range(0, len(instance_ids), max_filter_value):
- tags.extend(conn.get_all_tags(filters={'resource-type': 'instance', 'resource-id': instance_ids[i:i+max_filter_value]}))
-
- tags_by_instance_id = defaultdict(dict)
- for tag in tags:
- tags_by_instance_id[tag.res_id][tag.name] = tag.value
-
- for reservation in reservations:
- for instance in reservation.instances:
- instance.tags = tags_by_instance_id[instance.id]
- self.add_instance(instance, region)
-
- except boto.exception.BotoServerError as e:
- if e.error_code == 'AuthFailure':
- error = self.get_auth_error_message()
- else:
- backend = 'Eucalyptus' if self.eucalyptus else 'AWS'
- error = "Error connecting to %s backend.\n%s" % (backend, e.message)
- self.fail_with_error(error, 'getting EC2 instances')
-
- def get_rds_instances_by_region(self, region):
- ''' Makes an AWS API call to the list of RDS instances in a particular
- region '''
-
- try:
- conn = self.connect_to_aws(rds, region)
- if conn:
- marker = None
- while True:
- instances = conn.get_all_dbinstances(marker=marker)
- marker = instances.marker
- for instance in instances:
- self.add_rds_instance(instance, region)
- if not marker:
- break
- except boto.exception.BotoServerError as e:
- error = e.reason
-
- if e.error_code == 'AuthFailure':
- error = self.get_auth_error_message()
- if not e.reason == "Forbidden":
- error = "Looks like AWS RDS is down:\n%s" % e.message
- self.fail_with_error(error, 'getting RDS instances')
-
- def include_rds_clusters_by_region(self, region):
- if not HAS_BOTO3:
- self.fail_with_error("Working with RDS clusters requires boto3 - please install boto3 and try again",
- "getting RDS clusters")
-
- client = ec2_utils.boto3_inventory_conn('client', 'rds', region, **self.credentials)
-
- marker, clusters = '', []
- while marker is not None:
- resp = client.describe_db_clusters(Marker=marker)
- clusters.extend(resp["DBClusters"])
- marker = resp.get('Marker', None)
-
- account_id = boto.connect_iam().get_user().arn.split(':')[4]
- c_dict = {}
- for c in clusters:
- # remove these datetime objects as there is no serialisation to json
- # currently in place and we don't need the data yet
- if 'EarliestRestorableTime' in c:
- del c['EarliestRestorableTime']
- if 'LatestRestorableTime' in c:
- del c['LatestRestorableTime']
-
- if self.ec2_instance_filters == {}:
- matches_filter = True
- else:
- matches_filter = False
-
- try:
- # arn:aws:rds:<region>:<account number>:<resourcetype>:<name>
- tags = client.list_tags_for_resource(
- ResourceName='arn:aws:rds:' + region + ':' + account_id + ':cluster:' + c['DBClusterIdentifier'])
- c['Tags'] = tags['TagList']
-
- if self.ec2_instance_filters:
- for filter_key, filter_values in self.ec2_instance_filters.items():
- # get AWS tag key e.g. tag:env will be 'env'
- tag_name = filter_key.split(":", 1)[1]
- # Filter values is a list (if you put multiple values for the same tag name)
- matches_filter = any(d['Key'] == tag_name and d['Value'] in filter_values for d in c['Tags'])
-
- if matches_filter:
- # it matches a filter, so stop looking for further matches
- break
-
- except Exception as e:
- if e.message.find('DBInstanceNotFound') >= 0:
- # AWS RDS bug (2016-01-06) means deletion does not fully complete and leave an 'empty' cluster.
- # Ignore errors when trying to find tags for these
- pass
-
- # ignore empty clusters caused by AWS bug
- if len(c['DBClusterMembers']) == 0:
- continue
- elif matches_filter:
- c_dict[c['DBClusterIdentifier']] = c
-
- self.inventory['db_clusters'] = c_dict
-
- def get_elasticache_clusters_by_region(self, region):
- ''' Makes an AWS API call to the list of ElastiCache clusters (with
- nodes' info) in a particular region.'''
-
- # ElastiCache boto module doesn't provide a get_all_intances method,
- # that's why we need to call describe directly (it would be called by
- # the shorthand method anyway...)
- try:
- conn = self.connect_to_aws(elasticache, region)
- if conn:
- # show_cache_node_info = True
- # because we also want nodes' information
- response = conn.describe_cache_clusters(None, None, None, True)
-
- except boto.exception.BotoServerError as e:
- error = e.reason
-
- if e.error_code == 'AuthFailure':
- error = self.get_auth_error_message()
- if not e.reason == "Forbidden":
- error = "Looks like AWS ElastiCache is down:\n%s" % e.message
- self.fail_with_error(error, 'getting ElastiCache clusters')
-
- try:
- # Boto also doesn't provide wrapper classes to CacheClusters or
- # CacheNodes. Because of that we can't make use of the get_list
- # method in the AWSQueryConnection. Let's do the work manually
- clusters = response['DescribeCacheClustersResponse']['DescribeCacheClustersResult']['CacheClusters']
-
- except KeyError as e:
- error = "ElastiCache query to AWS failed (unexpected format)."
- self.fail_with_error(error, 'getting ElastiCache clusters')
-
- for cluster in clusters:
- self.add_elasticache_cluster(cluster, region)
-
- def get_elasticache_replication_groups_by_region(self, region):
- ''' Makes an AWS API call to the list of ElastiCache replication groups
- in a particular region.'''
-
- # ElastiCache boto module doesn't provide a get_all_intances method,
- # that's why we need to call describe directly (it would be called by
- # the shorthand method anyway...)
- try:
- conn = self.connect_to_aws(elasticache, region)
- if conn:
- response = conn.describe_replication_groups()
-
- except boto.exception.BotoServerError as e:
- error = e.reason
-
- if e.error_code == 'AuthFailure':
- error = self.get_auth_error_message()
- if not e.reason == "Forbidden":
- error = "Looks like AWS ElastiCache [Replication Groups] is down:\n%s" % e.message
- self.fail_with_error(error, 'getting ElastiCache clusters')
-
- try:
- # Boto also doesn't provide wrapper classes to ReplicationGroups
- # Because of that we can't make use of the get_list method in the
- # AWSQueryConnection. Let's do the work manually
- replication_groups = response['DescribeReplicationGroupsResponse']['DescribeReplicationGroupsResult']['ReplicationGroups']
-
- except KeyError as e:
- error = "ElastiCache [Replication Groups] query to AWS failed (unexpected format)."
- self.fail_with_error(error, 'getting ElastiCache clusters')
-
- for replication_group in replication_groups:
- self.add_elasticache_replication_group(replication_group, region)
-
- def get_auth_error_message(self):
- ''' create an informative error message if there is an issue authenticating'''
- errors = ["Authentication error retrieving ec2 inventory."]
- if None in [os.environ.get('AWS_ACCESS_KEY_ID'), os.environ.get('AWS_SECRET_ACCESS_KEY')]:
- errors.append(' - No AWS_ACCESS_KEY_ID or AWS_SECRET_ACCESS_KEY environment vars found')
- else:
- errors.append(' - AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment vars found but may not be correct')
-
- boto_paths = ['/etc/boto.cfg', '~/.boto', '~/.aws/credentials']
- boto_config_found = list(p for p in boto_paths if os.path.isfile(os.path.expanduser(p)))
- if len(boto_config_found) > 0:
- errors.append(" - Boto configs found at '%s', but the credentials contained may not be correct" % ', '.join(boto_config_found))
- else:
- errors.append(" - No Boto config found at any expected location '%s'" % ', '.join(boto_paths))
-
- return '\n'.join(errors)
-
- def fail_with_error(self, err_msg, err_operation=None):
- '''log an error to std err for ansible-playbook to consume and exit'''
- if err_operation:
- err_msg = 'ERROR: "{err_msg}", while: {err_operation}'.format(
- err_msg=err_msg, err_operation=err_operation)
- sys.stderr.write(err_msg)
- sys.exit(1)
-
- def get_instance(self, region, instance_id):
- conn = self.connect(region)
-
- reservations = conn.get_all_instances([instance_id])
- for reservation in reservations:
- for instance in reservation.instances:
- return instance
-
- def add_instance(self, instance, region):
- ''' Adds an instance to the inventory and index, as long as it is
- addressable '''
-
- # Only return instances with desired instance states
- if instance.state not in self.ec2_instance_states:
- return
-
- # Select the best destination address
- if self.destination_format and self.destination_format_tags:
- dest = self.destination_format.format(*[ getattr(instance, 'tags').get(tag, '') for tag in self.destination_format_tags ])
- elif instance.subnet_id:
- dest = getattr(instance, self.vpc_destination_variable, None)
- if dest is None:
- dest = getattr(instance, 'tags').get(self.vpc_destination_variable, None)
- else:
- dest = getattr(instance, self.destination_variable, None)
- if dest is None:
- dest = getattr(instance, 'tags').get(self.destination_variable, None)
-
- if not dest:
- # Skip instances we cannot address (e.g. private VPC subnet)
- return
-
- # Set the inventory name
- hostname = None
- if self.hostname_variable:
- if self.hostname_variable.startswith('tag_'):
- hostname = instance.tags.get(self.hostname_variable[4:], None)
- else:
- hostname = getattr(instance, self.hostname_variable)
-
- # If we can't get a nice hostname, use the destination address
- if not hostname:
- hostname = dest
- else:
- hostname = self.to_safe(hostname).lower()
-
- # if we only want to include hosts that match a pattern, skip those that don't
- if self.pattern_include and not self.pattern_include.match(hostname):
- return
-
- # if we need to exclude hosts that match a pattern, skip those
- if self.pattern_exclude and self.pattern_exclude.match(hostname):
- return
-
- # Add to index
- self.index[hostname] = [region, instance.id]
-
- # Inventory: Group by instance ID (always a group of 1)
- if self.group_by_instance_id:
- self.inventory[instance.id] = [hostname]
- if self.nested_groups:
- self.push_group(self.inventory, 'instances', instance.id)
-
- # Inventory: Group by region
- if self.group_by_region:
- self.push(self.inventory, region, hostname)
- if self.nested_groups:
- self.push_group(self.inventory, 'regions', region)
-
- # Inventory: Group by availability zone
- if self.group_by_availability_zone:
- self.push(self.inventory, instance.placement, hostname)
- if self.nested_groups:
- if self.group_by_region:
- self.push_group(self.inventory, region, instance.placement)
- self.push_group(self.inventory, 'zones', instance.placement)
-
- # Inventory: Group by Amazon Machine Image (AMI) ID
- if self.group_by_ami_id:
- ami_id = self.to_safe(instance.image_id)
- self.push(self.inventory, ami_id, hostname)
- if self.nested_groups:
- self.push_group(self.inventory, 'images', ami_id)
-
- # Inventory: Group by instance type
- if self.group_by_instance_type:
- type_name = self.to_safe('type_' + instance.instance_type)
- self.push(self.inventory, type_name, hostname)
- if self.nested_groups:
- self.push_group(self.inventory, 'types', type_name)
-
- # Inventory: Group by key pair
- if self.group_by_key_pair and instance.key_name:
- key_name = self.to_safe('key_' + instance.key_name)
- self.push(self.inventory, key_name, hostname)
- if self.nested_groups:
- self.push_group(self.inventory, 'keys', key_name)
-
- # Inventory: Group by VPC
- if self.group_by_vpc_id and instance.vpc_id:
- vpc_id_name = self.to_safe('vpc_id_' + instance.vpc_id)
- self.push(self.inventory, vpc_id_name, hostname)
- if self.nested_groups:
- self.push_group(self.inventory, 'vpcs', vpc_id_name)
-
- # Inventory: Group by security group
- if self.group_by_security_group:
- try:
- for group in instance.groups:
- key = self.to_safe("security_group_" + group.name)
- self.push(self.inventory, key, hostname)
- if self.nested_groups:
- self.push_group(self.inventory, 'security_groups', key)
- except AttributeError:
- self.fail_with_error('\n'.join(['Package boto seems a bit older.',
- 'Please upgrade boto >= 2.3.0.']))
-
- # Inventory: Group by tag keys
- if self.group_by_tag_keys:
- for k, v in instance.tags.items():
- if self.expand_csv_tags and v and ',' in v:
- values = map(lambda x: x.strip(), v.split(','))
- else:
- values = [v]
-
- for v in values:
- if v:
- key = self.to_safe("tag_" + k + "=" + v)
- else:
- key = self.to_safe("tag_" + k)
- self.push(self.inventory, key, hostname)
- if self.nested_groups:
- self.push_group(self.inventory, 'tags', self.to_safe("tag_" + k))
- if v:
- self.push_group(self.inventory, self.to_safe("tag_" + k), key)
-
- # Inventory: Group by Route53 domain names if enabled
- if self.route53_enabled and self.group_by_route53_names:
- route53_names = self.get_instance_route53_names(instance)
- for name in route53_names:
- self.push(self.inventory, name, hostname)
- if self.nested_groups:
- self.push_group(self.inventory, 'route53', name)
-
- # Global Tag: instances without tags
- if self.group_by_tag_none and len(instance.tags) == 0:
- self.push(self.inventory, 'tag_none', hostname)
- if self.nested_groups:
- self.push_group(self.inventory, 'tags', 'tag_none')
-
- # Global Tag: tag all EC2 instances
- self.push(self.inventory, 'ec2', hostname)
-
- self.inventory["_meta"]["hostvars"][hostname] = self.get_host_info_dict_from_instance(instance)
- self.inventory["_meta"]["hostvars"][hostname]['ansible_ssh_host'] = dest
-
-
- def add_rds_instance(self, instance, region):
- ''' Adds an RDS instance to the inventory and index, as long as it is
- addressable '''
-
- # Only want available instances unless all_rds_instances is True
- if not self.all_rds_instances and instance.status != 'available':
- return
-
- # Select the best destination address
- dest = instance.endpoint[0]
-
- if not dest:
- # Skip instances we cannot address (e.g. private VPC subnet)
- return
-
- # Set the inventory name
- hostname = None
- if self.hostname_variable:
- if self.hostname_variable.startswith('tag_'):
- hostname = instance.tags.get(self.hostname_variable[4:], None)
- else:
- hostname = getattr(instance, self.hostname_variable)
-
- # If we can't get a nice hostname, use the destination address
- if not hostname:
- hostname = dest
-
- hostname = self.to_safe(hostname).lower()
-
- # Add to index
- self.index[hostname] = [region, instance.id]
-
- # Inventory: Group by instance ID (always a group of 1)
- if self.group_by_instance_id:
- self.inventory[instance.id] = [hostname]
- if self.nested_groups:
- self.push_group(self.inventory, 'instances', instance.id)
-
- # Inventory: Group by region
- if self.group_by_region:
- self.push(self.inventory, region, hostname)
- if self.nested_groups:
- self.push_group(self.inventory, 'regions', region)
-
- # Inventory: Group by availability zone
- if self.group_by_availability_zone:
- self.push(self.inventory, instance.availability_zone, hostname)
- if self.nested_groups:
- if self.group_by_region:
- self.push_group(self.inventory, region, instance.availability_zone)
- self.push_group(self.inventory, 'zones', instance.availability_zone)
-
- # Inventory: Group by instance type
- if self.group_by_instance_type:
- type_name = self.to_safe('type_' + instance.instance_class)
- self.push(self.inventory, type_name, hostname)
- if self.nested_groups:
- self.push_group(self.inventory, 'types', type_name)
-
- # Inventory: Group by VPC
- if self.group_by_vpc_id and instance.subnet_group and instance.subnet_group.vpc_id:
- vpc_id_name = self.to_safe('vpc_id_' + instance.subnet_group.vpc_id)
- self.push(self.inventory, vpc_id_name, hostname)
- if self.nested_groups:
- self.push_group(self.inventory, 'vpcs', vpc_id_name)
-
- # Inventory: Group by security group
- if self.group_by_security_group:
- try:
- if instance.security_group:
- key = self.to_safe("security_group_" + instance.security_group.name)
- self.push(self.inventory, key, hostname)
- if self.nested_groups:
- self.push_group(self.inventory, 'security_groups', key)
-
- except AttributeError:
- self.fail_with_error('\n'.join(['Package boto seems a bit older.',
- 'Please upgrade boto >= 2.3.0.']))
-
-
- # Inventory: Group by engine
- if self.group_by_rds_engine:
- self.push(self.inventory, self.to_safe("rds_" + instance.engine), hostname)
- if self.nested_groups:
- self.push_group(self.inventory, 'rds_engines', self.to_safe("rds_" + instance.engine))
-
- # Inventory: Group by parameter group
- if self.group_by_rds_parameter_group:
- self.push(self.inventory, self.to_safe("rds_parameter_group_" + instance.parameter_group.name), hostname)
- if self.nested_groups:
- self.push_group(self.inventory, 'rds_parameter_groups', self.to_safe("rds_parameter_group_" + instance.parameter_group.name))
-
- # Global Tag: all RDS instances
- self.push(self.inventory, 'rds', hostname)
-
- self.inventory["_meta"]["hostvars"][hostname] = self.get_host_info_dict_from_instance(instance)
- self.inventory["_meta"]["hostvars"][hostname]['ansible_ssh_host'] = dest
-
- def add_elasticache_cluster(self, cluster, region):
- ''' Adds an ElastiCache cluster to the inventory and index, as long as
- it's nodes are addressable '''
-
- # Only want available clusters unless all_elasticache_clusters is True
- if not self.all_elasticache_clusters and cluster['CacheClusterStatus'] != 'available':
- return
-
- # Select the best destination address
- if 'ConfigurationEndpoint' in cluster and cluster['ConfigurationEndpoint']:
- # Memcached cluster
- dest = cluster['ConfigurationEndpoint']['Address']
- is_redis = False
- else:
- # Redis sigle node cluster
- # Because all Redis clusters are single nodes, we'll merge the
- # info from the cluster with info about the node
- dest = cluster['CacheNodes'][0]['Endpoint']['Address']
- is_redis = True
-
- if not dest:
- # Skip clusters we cannot address (e.g. private VPC subnet)
- return
-
- # Add to index
- self.index[dest] = [region, cluster['CacheClusterId']]
-
- # Inventory: Group by instance ID (always a group of 1)
- if self.group_by_instance_id:
- self.inventory[cluster['CacheClusterId']] = [dest]
- if self.nested_groups:
- self.push_group(self.inventory, 'instances', cluster['CacheClusterId'])
-
- # Inventory: Group by region
- if self.group_by_region and not is_redis:
- self.push(self.inventory, region, dest)
- if self.nested_groups:
- self.push_group(self.inventory, 'regions', region)
-
- # Inventory: Group by availability zone
- if self.group_by_availability_zone and not is_redis:
- self.push(self.inventory, cluster['PreferredAvailabilityZone'], dest)
- if self.nested_groups:
- if self.group_by_region:
- self.push_group(self.inventory, region, cluster['PreferredAvailabilityZone'])
- self.push_group(self.inventory, 'zones', cluster['PreferredAvailabilityZone'])
-
- # Inventory: Group by node type
- if self.group_by_instance_type and not is_redis:
- type_name = self.to_safe('type_' + cluster['CacheNodeType'])
- self.push(self.inventory, type_name, dest)
- if self.nested_groups:
- self.push_group(self.inventory, 'types', type_name)
-
- # Inventory: Group by VPC (information not available in the current
- # AWS API version for ElastiCache)
-
- # Inventory: Group by security group
- if self.group_by_security_group and not is_redis:
-
- # Check for the existence of the 'SecurityGroups' key and also if
- # this key has some value. When the cluster is not placed in a SG
- # the query can return None here and cause an error.
- if 'SecurityGroups' in cluster and cluster['SecurityGroups'] is not None:
- for security_group in cluster['SecurityGroups']:
- key = self.to_safe("security_group_" + security_group['SecurityGroupId'])
- self.push(self.inventory, key, dest)
- if self.nested_groups:
- self.push_group(self.inventory, 'security_groups', key)
-
- # Inventory: Group by engine
- if self.group_by_elasticache_engine and not is_redis:
- self.push(self.inventory, self.to_safe("elasticache_" + cluster['Engine']), dest)
- if self.nested_groups:
- self.push_group(self.inventory, 'elasticache_engines', self.to_safe(cluster['Engine']))
-
- # Inventory: Group by parameter group
- if self.group_by_elasticache_parameter_group:
- self.push(self.inventory, self.to_safe("elasticache_parameter_group_" + cluster['CacheParameterGroup']['CacheParameterGroupName']), dest)
- if self.nested_groups:
- self.push_group(self.inventory, 'elasticache_parameter_groups', self.to_safe(cluster['CacheParameterGroup']['CacheParameterGroupName']))
-
- # Inventory: Group by replication group
- if self.group_by_elasticache_replication_group and 'ReplicationGroupId' in cluster and cluster['ReplicationGroupId']:
- self.push(self.inventory, self.to_safe("elasticache_replication_group_" + cluster['ReplicationGroupId']), dest)
- if self.nested_groups:
- self.push_group(self.inventory, 'elasticache_replication_groups', self.to_safe(cluster['ReplicationGroupId']))
-
- # Global Tag: all ElastiCache clusters
- self.push(self.inventory, 'elasticache_clusters', cluster['CacheClusterId'])
-
- host_info = self.get_host_info_dict_from_describe_dict(cluster)
-
- self.inventory["_meta"]["hostvars"][dest] = host_info
-
- # Add the nodes
- for node in cluster['CacheNodes']:
- self.add_elasticache_node(node, cluster, region)
-
- def add_elasticache_node(self, node, cluster, region):
- ''' Adds an ElastiCache node to the inventory and index, as long as
- it is addressable '''
-
- # Only want available nodes unless all_elasticache_nodes is True
- if not self.all_elasticache_nodes and node['CacheNodeStatus'] != 'available':
- return
-
- # Select the best destination address
- dest = node['Endpoint']['Address']
-
- if not dest:
- # Skip nodes we cannot address (e.g. private VPC subnet)
- return
-
- node_id = self.to_safe(cluster['CacheClusterId'] + '_' + node['CacheNodeId'])
-
- # Add to index
- self.index[dest] = [region, node_id]
-
- # Inventory: Group by node ID (always a group of 1)
- if self.group_by_instance_id:
- self.inventory[node_id] = [dest]
- if self.nested_groups:
- self.push_group(self.inventory, 'instances', node_id)
-
- # Inventory: Group by region
- if self.group_by_region:
- self.push(self.inventory, region, dest)
- if self.nested_groups:
- self.push_group(self.inventory, 'regions', region)
-
- # Inventory: Group by availability zone
- if self.group_by_availability_zone:
- self.push(self.inventory, cluster['PreferredAvailabilityZone'], dest)
- if self.nested_groups:
- if self.group_by_region:
- self.push_group(self.inventory, region, cluster['PreferredAvailabilityZone'])
- self.push_group(self.inventory, 'zones', cluster['PreferredAvailabilityZone'])
-
- # Inventory: Group by node type
- if self.group_by_instance_type:
- type_name = self.to_safe('type_' + cluster['CacheNodeType'])
- self.push(self.inventory, type_name, dest)
- if self.nested_groups:
- self.push_group(self.inventory, 'types', type_name)
-
- # Inventory: Group by VPC (information not available in the current
- # AWS API version for ElastiCache)
-
- # Inventory: Group by security group
- if self.group_by_security_group:
-
- # Check for the existence of the 'SecurityGroups' key and also if
- # this key has some value. When the cluster is not placed in a SG
- # the query can return None here and cause an error.
- if 'SecurityGroups' in cluster and cluster['SecurityGroups'] is not None:
- for security_group in cluster['SecurityGroups']:
- key = self.to_safe("security_group_" + security_group['SecurityGroupId'])
- self.push(self.inventory, key, dest)
- if self.nested_groups:
- self.push_group(self.inventory, 'security_groups', key)
-
- # Inventory: Group by engine
- if self.group_by_elasticache_engine:
- self.push(self.inventory, self.to_safe("elasticache_" + cluster['Engine']), dest)
- if self.nested_groups:
- self.push_group(self.inventory, 'elasticache_engines', self.to_safe("elasticache_" + cluster['Engine']))
-
- # Inventory: Group by parameter group (done at cluster level)
-
- # Inventory: Group by replication group (done at cluster level)
-
- # Inventory: Group by ElastiCache Cluster
- if self.group_by_elasticache_cluster:
- self.push(self.inventory, self.to_safe("elasticache_cluster_" + cluster['CacheClusterId']), dest)
-
- # Global Tag: all ElastiCache nodes
- self.push(self.inventory, 'elasticache_nodes', dest)
-
- host_info = self.get_host_info_dict_from_describe_dict(node)
-
- if dest in self.inventory["_meta"]["hostvars"]:
- self.inventory["_meta"]["hostvars"][dest].update(host_info)
- else:
- self.inventory["_meta"]["hostvars"][dest] = host_info
-
- def add_elasticache_replication_group(self, replication_group, region):
- ''' Adds an ElastiCache replication group to the inventory and index '''
-
- # Only want available clusters unless all_elasticache_replication_groups is True
- if not self.all_elasticache_replication_groups and replication_group['Status'] != 'available':
- return
-
- # Select the best destination address (PrimaryEndpoint)
- dest = replication_group['NodeGroups'][0]['PrimaryEndpoint']['Address']
-
- if not dest:
- # Skip clusters we cannot address (e.g. private VPC subnet)
- return
-
- # Add to index
- self.index[dest] = [region, replication_group['ReplicationGroupId']]
-
- # Inventory: Group by ID (always a group of 1)
- if self.group_by_instance_id:
- self.inventory[replication_group['ReplicationGroupId']] = [dest]
- if self.nested_groups:
- self.push_group(self.inventory, 'instances', replication_group['ReplicationGroupId'])
-
- # Inventory: Group by region
- if self.group_by_region:
- self.push(self.inventory, region, dest)
- if self.nested_groups:
- self.push_group(self.inventory, 'regions', region)
-
- # Inventory: Group by availability zone (doesn't apply to replication groups)
-
- # Inventory: Group by node type (doesn't apply to replication groups)
-
- # Inventory: Group by VPC (information not available in the current
- # AWS API version for replication groups
-
- # Inventory: Group by security group (doesn't apply to replication groups)
- # Check this value in cluster level
-
- # Inventory: Group by engine (replication groups are always Redis)
- if self.group_by_elasticache_engine:
- self.push(self.inventory, 'elasticache_redis', dest)
- if self.nested_groups:
- self.push_group(self.inventory, 'elasticache_engines', 'redis')
-
- # Global Tag: all ElastiCache clusters
- self.push(self.inventory, 'elasticache_replication_groups', replication_group['ReplicationGroupId'])
-
- host_info = self.get_host_info_dict_from_describe_dict(replication_group)
-
- self.inventory["_meta"]["hostvars"][dest] = host_info
-
- def get_route53_records(self):
- ''' Get and store the map of resource records to domain names that
- point to them. '''
-
- r53_conn = route53.Route53Connection()
- all_zones = r53_conn.get_zones()
-
- route53_zones = [ zone for zone in all_zones if zone.name[:-1]
- not in self.route53_excluded_zones ]
-
- self.route53_records = {}
-
- for zone in route53_zones:
- rrsets = r53_conn.get_all_rrsets(zone.id)
-
- for record_set in rrsets:
- record_name = record_set.name
-
- if record_name.endswith('.'):
- record_name = record_name[:-1]
-
- for resource in record_set.resource_records:
- self.route53_records.setdefault(resource, set())
- self.route53_records[resource].add(record_name)
-
-
- def get_instance_route53_names(self, instance):
- ''' Check if an instance is referenced in the records we have from
- Route53. If it is, return the list of domain names pointing to said
- instance. If nothing points to it, return an empty list. '''
-
- instance_attributes = [ 'public_dns_name', 'private_dns_name',
- 'ip_address', 'private_ip_address' ]
-
- name_list = set()
-
- for attrib in instance_attributes:
- try:
- value = getattr(instance, attrib)
- except AttributeError:
- continue
-
- if value in self.route53_records:
- name_list.update(self.route53_records[value])
-
- return list(name_list)
-
- def get_host_info_dict_from_instance(self, instance):
- instance_vars = {}
- for key in vars(instance):
- value = getattr(instance, key)
- key = self.to_safe('ec2_' + key)
-
- # Handle complex types
- # state/previous_state changed to properties in boto in https://github.com/boto/boto/commit/a23c379837f698212252720d2af8dec0325c9518
- if key == 'ec2__state':
- instance_vars['ec2_state'] = instance.state or ''
- instance_vars['ec2_state_code'] = instance.state_code
- elif key == 'ec2__previous_state':
- instance_vars['ec2_previous_state'] = instance.previous_state or ''
- instance_vars['ec2_previous_state_code'] = instance.previous_state_code
- elif type(value) in [int, bool]:
- instance_vars[key] = value
- elif isinstance(value, six.string_types):
- instance_vars[key] = value.strip()
- elif type(value) == type(None):
- instance_vars[key] = ''
- elif key == 'ec2_region':
- instance_vars[key] = value.name
- elif key == 'ec2__placement':
- instance_vars['ec2_placement'] = value.zone
- elif key == 'ec2_tags':
- for k, v in value.items():
- if self.expand_csv_tags and ',' in v:
- v = list(map(lambda x: x.strip(), v.split(',')))
- key = self.to_safe('ec2_tag_' + k)
- instance_vars[key] = v
- elif key == 'ec2_groups':
- group_ids = []
- group_names = []
- for group in value:
- group_ids.append(group.id)
- group_names.append(group.name)
- instance_vars["ec2_security_group_ids"] = ','.join([str(i) for i in group_ids])
- instance_vars["ec2_security_group_names"] = ','.join([str(i) for i in group_names])
- elif key == 'ec2_block_device_mapping':
- instance_vars["ec2_block_devices"] = {}
- for k, v in value.items():
- instance_vars["ec2_block_devices"][ os.path.basename(k) ] = v.volume_id
- else:
- pass
- # TODO Product codes if someone finds them useful
- #print key
- #print type(value)
- #print value
-
- return instance_vars
-
- def get_host_info_dict_from_describe_dict(self, describe_dict):
- ''' Parses the dictionary returned by the API call into a flat list
- of parameters. This method should be used only when 'describe' is
- used directly because Boto doesn't provide specific classes. '''
-
- # I really don't agree with prefixing everything with 'ec2'
- # because EC2, RDS and ElastiCache are different services.
- # I'm just following the pattern used until now to not break any
- # compatibility.
-
- host_info = {}
- for key in describe_dict:
- value = describe_dict[key]
- key = self.to_safe('ec2_' + self.uncammelize(key))
-
- # Handle complex types
-
- # Target: Memcached Cache Clusters
- if key == 'ec2_configuration_endpoint' and value:
- host_info['ec2_configuration_endpoint_address'] = value['Address']
- host_info['ec2_configuration_endpoint_port'] = value['Port']
-
- # Target: Cache Nodes and Redis Cache Clusters (single node)
- if key == 'ec2_endpoint' and value:
- host_info['ec2_endpoint_address'] = value['Address']
- host_info['ec2_endpoint_port'] = value['Port']
-
- # Target: Redis Replication Groups
- if key == 'ec2_node_groups' and value:
- host_info['ec2_endpoint_address'] = value[0]['PrimaryEndpoint']['Address']
- host_info['ec2_endpoint_port'] = value[0]['PrimaryEndpoint']['Port']
- replica_count = 0
- for node in value[0]['NodeGroupMembers']:
- if node['CurrentRole'] == 'primary':
- host_info['ec2_primary_cluster_address'] = node['ReadEndpoint']['Address']
- host_info['ec2_primary_cluster_port'] = node['ReadEndpoint']['Port']
- host_info['ec2_primary_cluster_id'] = node['CacheClusterId']
- elif node['CurrentRole'] == 'replica':
- host_info['ec2_replica_cluster_address_'+ str(replica_count)] = node['ReadEndpoint']['Address']
- host_info['ec2_replica_cluster_port_'+ str(replica_count)] = node['ReadEndpoint']['Port']
- host_info['ec2_replica_cluster_id_'+ str(replica_count)] = node['CacheClusterId']
- replica_count += 1
-
- # Target: Redis Replication Groups
- if key == 'ec2_member_clusters' and value:
- host_info['ec2_member_clusters'] = ','.join([str(i) for i in value])
-
- # Target: All Cache Clusters
- elif key == 'ec2_cache_parameter_group':
- host_info["ec2_cache_node_ids_to_reboot"] = ','.join([str(i) for i in value['CacheNodeIdsToReboot']])
- host_info['ec2_cache_parameter_group_name'] = value['CacheParameterGroupName']
- host_info['ec2_cache_parameter_apply_status'] = value['ParameterApplyStatus']
-
- # Target: Almost everything
- elif key == 'ec2_security_groups':
-
- # Skip if SecurityGroups is None
- # (it is possible to have the key defined but no value in it).
- if value is not None:
- sg_ids = []
- for sg in value:
- sg_ids.append(sg['SecurityGroupId'])
- host_info["ec2_security_group_ids"] = ','.join([str(i) for i in sg_ids])
-
- # Target: Everything
- # Preserve booleans and integers
- elif type(value) in [int, bool]:
- host_info[key] = value
-
- # Target: Everything
- # Sanitize string values
- elif isinstance(value, six.string_types):
- host_info[key] = value.strip()
-
- # Target: Everything
- # Replace None by an empty string
- elif type(value) == type(None):
- host_info[key] = ''
-
- else:
- # Remove non-processed complex types
- pass
-
- return host_info
-
- def get_host_info(self):
- ''' Get variables about a specific host '''
-
- if len(self.index) == 0:
- # Need to load index from cache
- self.load_index_from_cache()
-
- if not self.args.host in self.index:
- # try updating the cache
- self.do_api_calls_update_cache()
- if not self.args.host in self.index:
- # host might not exist anymore
- return self.json_format_dict({}, True)
-
- (region, instance_id) = self.index[self.args.host]
-
- instance = self.get_instance(region, instance_id)
- return self.json_format_dict(self.get_host_info_dict_from_instance(instance), True)
-
- def push(self, my_dict, key, element):
- ''' Push an element onto an array that may not have been defined in
- the dict '''
- group_info = my_dict.setdefault(key, [])
- if isinstance(group_info, dict):
- host_list = group_info.setdefault('hosts', [])
- host_list.append(element)
- else:
- group_info.append(element)
-
- def push_group(self, my_dict, key, element):
- ''' Push a group as a child of another group. '''
- parent_group = my_dict.setdefault(key, {})
- if not isinstance(parent_group, dict):
- parent_group = my_dict[key] = {'hosts': parent_group}
- child_groups = parent_group.setdefault('children', [])
- if element not in child_groups:
- child_groups.append(element)
-
- def get_inventory_from_cache(self):
- ''' Reads the inventory from the cache file and returns it as a JSON
- object '''
-
- cache = open(self.cache_path_cache, 'r')
- json_inventory = cache.read()
- return json_inventory
-
-
- def load_index_from_cache(self):
- ''' Reads the index from the cache file sets self.index '''
-
- cache = open(self.cache_path_index, 'r')
- json_index = cache.read()
- self.index = json.loads(json_index)
-
-
- def write_to_cache(self, data, filename):
- ''' Writes data in JSON format to a file '''
-
- json_data = self.json_format_dict(data, True)
- cache = open(filename, 'w')
- cache.write(json_data)
- cache.close()
-
- def uncammelize(self, key):
- temp = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', key)
- return re.sub('([a-z0-9])([A-Z])', r'\1_\2', temp).lower()
-
- def to_safe(self, word):
- ''' Converts 'bad' characters in a string to underscores so they can be used as Ansible groups '''
- regex = "[^A-Za-z0-9\_"
- if not self.replace_dash_in_groups:
- regex += "\-"
- return re.sub(regex + "]", "_", word)
-
- def json_format_dict(self, data, pretty=False):
- ''' Converts a dict to a JSON object and dumps it as a formatted
- string '''
-
- if pretty:
- return json.dumps(data, sort_keys=True, indent=2)
- else:
- return json.dumps(data)
-
-
-# Run the script
-Ec2Inventory()
diff --git a/inventory/aws/hosts/hosts b/inventory/aws/hosts/hosts
deleted file mode 100644
index 3996e577e..000000000
--- a/inventory/aws/hosts/hosts
+++ /dev/null
@@ -1 +0,0 @@
-localhost ansible_connection=local ansible_become=no ansible_python_interpreter='/usr/bin/env python2'
diff --git a/inventory/byo/hosts.origin.example b/inventory/byo/hosts.origin.example
index 385278f3b..486fe56a0 100644
--- a/inventory/byo/hosts.origin.example
+++ b/inventory/byo/hosts.origin.example
@@ -34,17 +34,17 @@ openshift_deployment_type=origin
# use this to lookup the latest exact version of the container images, which is the tag actually used to configure
# the cluster. For RPM installations we just verify the version detected in your configured repos matches this
# release.
-openshift_release=v3.6
+openshift_release=v3.7
# Specify an exact container image tag to install or configure.
# WARNING: This value will be used for all hosts in containerized environments, even those that have another version installed.
# This could potentially trigger an upgrade and downtime, so be careful with modifying this value after the cluster is set up.
-#openshift_image_tag=v3.6.0
+#openshift_image_tag=v3.7.0
# Specify an exact rpm version to install or configure.
# WARNING: This value will be used for all hosts in RPM based environments, even those that have another version installed.
# This could potentially trigger an upgrade and downtime, so be careful with modifying this value after the cluster is set up.
-#openshift_pkg_version=-3.6.0
+#openshift_pkg_version=-3.7.0
# This enables all the system containers except for docker:
#openshift_use_system_containers=False
@@ -56,6 +56,9 @@ openshift_release=v3.6
#openshift_use_node_system_container=False
#openshift_use_master_system_container=False
#openshift_use_etcd_system_container=False
+#
+# In either case, system_images_registry must be specified to be able to find the system images
+#system_images_registry="docker.io"
# Install the openshift examples
#openshift_install_examples=true
@@ -111,11 +114,11 @@ openshift_release=v3.6
# Instead of using docker, replacec it with cri-o
# NOTE: This uses openshift_docker_systemcontainer_image_registry_override as it's override
# just as container-engine does.
-#openshift_docker_use_crio=False
+#openshift_use_crio=False
# Force the registry to use for the docker/crio system container. By default the registry
# will be built off of the deployment type and ansible_distribution. Only
# use this option if you are sure you know what you are doing!
-#openshift_docker_systemcontainer_image_registry_override="registry.example.com"
+#openshift_docker_systemcontainer_image_override="registry.example.com/container-engine:latest"
#openshift_crio_systemcontainer_image_registry_override="registry.example.com"
# Items added, as is, to end of /etc/sysconfig/docker OPTIONS
# Default value: "--log-driver=journald"
@@ -377,45 +380,9 @@ openshift_master_identity_providers=[{'name': 'htpasswd_auth', 'login': 'true',
# and is in the form of a list. If no data is passed then a default router will be
# created. There are multiple combinations of router sharding. The one described
# below supports routers on separate nodes.
-#openshift_hosted_routers:
-#- name: router1
-# stats_port: 1936
-# ports:
-# - 80:80
-# - 443:443
-# replicas: 1
-# namespace: default
-# serviceaccount: router
-# selector: type=router1
-# images: "openshift3/ose-${component}:${version}"
-# edits: []
-# certificate:
-# certfile: /path/to/certificate/abc.crt
-# keyfile: /path/to/certificate/abc.key
-# cafile: /path/to/certificate/ca.crt
-#- name: router2
-# stats_port: 1936
-# ports:
-# - 80:80
-# - 443:443
-# replicas: 1
-# namespace: default
-# serviceaccount: router
-# selector: type=router2
-# images: "openshift3/ose-${component}:${version}"
-# certificate:
-# certfile: /path/to/certificate/xyz.crt
-# keyfile: /path/to/certificate/xyz.key
-# cafile: /path/to/certificate/ca.crt
-# edits:
-# # ROUTE_LABELS sets the router to listen for routes
-# # tagged with the provided values
-# - key: spec.template.spec.containers[0].env
-# value:
-# name: ROUTE_LABELS
-# value: "route=external"
-# action: append
#
+#openshift_hosted_routers=[{'name': 'router1', 'certificate': {'certfile': '/path/to/certificate/abc.crt', 'keyfile': '/path/to/certificate/abc.key', 'cafile': '/path/to/certificate/ca.crt'}, 'replicas': 1, 'serviceaccount': 'router', 'namespace': 'default', 'stats_port': 1936, 'edits': [], 'images': 'openshift3/ose-${component}:${version}', 'selector': 'type=router1', 'ports': ['80:80', '443:443']}, {'name': 'router2', 'certificate': {'certfile': '/path/to/certificate/xyz.crt', 'keyfile': '/path/to/certificate/xyz.key', 'cafile': '/path/to/certificate/ca.crt'}, 'replicas': 1, 'serviceaccount': 'router', 'namespace': 'default', 'stats_port': 1936, 'edits': [{'action': 'append', 'key': 'spec.template.spec.containers[0].env', 'value': {'name': 'ROUTE_LABELS', 'value': 'route=external'}}], 'images': 'openshift3/ose-${component}:${version}', 'selector': 'type=router2', 'ports': ['80:80', '443:443']}]
+
# OpenShift Registry Console Options
# Override the console image prefix for enterprise deployments, not used in origin
# default is "registry.access.redhat.com/openshift3/" and the image appended is "registry-console"
@@ -571,7 +538,7 @@ openshift_master_identity_providers=[{'name': 'htpasswd_auth', 'login': 'true',
#openshift_hosted_metrics_public_url=https://hawkular-metrics.example.com/hawkular/metrics
# Configure the prefix and version for the component images
#openshift_hosted_metrics_deployer_prefix=docker.io/openshift/origin-
-#openshift_hosted_metrics_deployer_version=3.6.0
+#openshift_hosted_metrics_deployer_version=v3.7.0
#
# StorageClass
# openshift_storageclass_name=gp2
@@ -626,7 +593,7 @@ openshift_master_identity_providers=[{'name': 'htpasswd_auth', 'login': 'true',
#openshift_hosted_logging_elasticsearch_cluster_size=1
# Configure the prefix and version for the component images
#openshift_hosted_logging_deployer_prefix=docker.io/openshift/origin-
-#openshift_hosted_logging_deployer_version=3.6.0
+#openshift_hosted_logging_deployer_version=v3.7.0
# Configure the multi-tenant SDN plugin (default is 'redhat/openshift-ovs-subnet')
# os_sdn_network_plugin_name='redhat/openshift-ovs-multitenant'
@@ -646,6 +613,12 @@ openshift_master_identity_providers=[{'name': 'htpasswd_auth', 'login': 'true',
# WORKAROUND : If you must use an overlapping subnet, you can configure a non conflicting
# docker0 CIDR range by adding '--bip=192.168.2.1/24' to DOCKER_NETWORK_OPTIONS
# environment variable located in /etc/sysconfig/docker-network.
+# When upgrading or scaling up the following must match whats in your master config!
+# Inventory: master yaml field
+# osm_cluster_network_cidr: clusterNetworkCIDR
+# openshift_portal_net: serviceNetworkCIDR
+# When installing osm_cluster_network_cidr and openshift_portal_net must be set.
+# Sane examples are provided below.
#osm_cluster_network_cidr=10.128.0.0/14
#openshift_portal_net=172.30.0.0/16
@@ -667,6 +640,10 @@ openshift_master_identity_providers=[{'name': 'htpasswd_auth', 'login': 'true',
# Configure number of bits to allocate to each host’s subnet e.g. 9
# would mean a /23 network on the host.
+# When upgrading or scaling up the following must match whats in your master config!
+# Inventory: master yaml field
+# osm_host_subnet_length: hostSubnetLength
+# When installing osm_host_subnet_length must be set. A sane example is provided below.
#osm_host_subnet_length=9
# Configure master API and console ports.
@@ -752,11 +729,10 @@ openshift_master_identity_providers=[{'name': 'htpasswd_auth', 'login': 'true',
# Setting this variable to true will override that check.
#openshift_override_hostname_check=true
-# Configure dnsmasq for cluster dns, switch the host's local resolver to use dnsmasq
-# and configure node's dnsIP to point at the node's local dnsmasq instance. Defaults
-# to True for Origin 1.2 and OSE 3.2. False for 1.1 / 3.1 installs, this cannot
-# be used with 1.0 and 3.0.
+# openshift_use_dnsmasq is deprecated. This must be true, or installs will fail
+# in versions >= 3.6
#openshift_use_dnsmasq=False
+
# Define an additional dnsmasq.conf file to deploy to /etc/dnsmasq.d/openshift-ansible.conf
# This is useful for POC environments where DNS may not actually be available yet or to set
# options like 'strict-order' to alter dnsmasq configuration.
diff --git a/inventory/byo/hosts.ose.example b/inventory/byo/hosts.ose.example
index 87fdee904..92a0927e5 100644
--- a/inventory/byo/hosts.ose.example
+++ b/inventory/byo/hosts.ose.example
@@ -34,17 +34,17 @@ openshift_deployment_type=openshift-enterprise
# use this to lookup the latest exact version of the container images, which is the tag actually used to configure
# the cluster. For RPM installations we just verify the version detected in your configured repos matches this
# release.
-openshift_release=v3.6
+openshift_release=v3.7
# Specify an exact container image tag to install or configure.
# WARNING: This value will be used for all hosts in containerized environments, even those that have another version installed.
# This could potentially trigger an upgrade and downtime, so be careful with modifying this value after the cluster is set up.
-#openshift_image_tag=v3.6.0
+#openshift_image_tag=v3.7.0
# Specify an exact rpm version to install or configure.
# WARNING: This value will be used for all hosts in RPM based environments, even those that have another version installed.
# This could potentially trigger an upgrade and downtime, so be careful with modifying this value after the cluster is set up.
-#openshift_pkg_version=-3.6.0
+#openshift_pkg_version=-3.7.0
# This enables all the system containers except for docker:
#openshift_use_system_containers=False
@@ -56,6 +56,9 @@ openshift_release=v3.6
#openshift_use_node_system_container=False
#openshift_use_master_system_container=False
#openshift_use_etcd_system_container=False
+#
+# In either case, system_images_registry must be specified to be able to find the system images
+#system_images_registry="registry.access.redhat.com"
# Install the openshift examples
#openshift_install_examples=true
@@ -111,11 +114,11 @@ openshift_release=v3.6
# Install and run cri-o along side docker
# NOTE: This uses openshift_docker_systemcontainer_image_registry_override as it's override
# just as container-engine does.
-#openshift_docker_use_crio=False
+#openshift_use_crio=False
# Force the registry to use for the container-engine/crio system container. By default the registry
# will be built off of the deployment type and ansible_distribution. Only
# use this option if you are sure you know what you are doing!
-#openshift_docker_systemcontainer_image_registry_override="registry.example.com"
+#openshift_docker_systemcontainer_image_override="registry.example.com/container-engine:latest"
#openshift_crio_systemcontainer_image_registry_override="registry.example.com"
# Items added, as is, to end of /etc/sysconfig/docker OPTIONS
# Default value: "--log-driver=journald"
@@ -167,6 +170,14 @@ openshift_release=v3.6
# modify image streams to point at that registry by setting the following to true
#openshift_examples_modify_imagestreams=true
+# If oreg_url points to a registry requiring authentication, provide the following:
+#oreg_auth_user=some_user
+#oreg_auth_password='my-pass'
+# NOTE: oreg_url must be defined by the user for oreg_auth_* to have any affect.
+# oreg_auth_pass should be generated from running docker login.
+# To update registry auth credentials, uncomment the following:
+#oreg_auth_credentials_replace: True
+
# OpenShift repository configuration
#openshift_additional_repos=[{'id': 'ose-devel', 'name': 'ose-devel', 'baseurl': 'http://example.com/puddle/build/AtomicOpenShift/3.1/latest/RH7-RHOSE-3.0/$basearch/os', 'enabled': 1, 'gpgcheck': 0}]
#openshift_repos_enable_testing=false
@@ -376,44 +387,8 @@ openshift_master_identity_providers=[{'name': 'htpasswd_auth', 'login': 'true',
# and is in the form of a list. If no data is passed then a default router will be
# created. There are multiple combinations of router sharding. The one described
# below supports routers on separate nodes.
-#openshift_hosted_routers:
-#- name: router1
-# stats_port: 1936
-# ports:
-# - 80:80
-# - 443:443
-# replicas: 1
-# namespace: default
-# serviceaccount: router
-# selector: type=router1
-# images: "openshift3/ose-${component}:${version}"
-# edits: []
-# certificate:
-# certfile: /path/to/certificate/abc.crt
-# keyfile: /path/to/certificate/abc.key
-# cafile: /path/to/certificate/ca.crt
-#- name: router2
-# stats_port: 1936
-# ports:
-# - 80:80
-# - 443:443
-# replicas: 1
-# namespace: default
-# serviceaccount: router
-# selector: type=router2
-# images: "openshift3/ose-${component}:${version}"
-# certificate:
-# certfile: /path/to/certificate/xyz.crt
-# keyfile: /path/to/certificate/xyz.key
-# cafile: /path/to/certificate/ca.crt
-# edits:
-# # ROUTE_LABELS sets the router to listen for routes
-# # tagged with the provided values
-# - key: spec.template.spec.containers[0].env
-# value:
-# name: ROUTE_LABELS
-# value: "route=external"
-# action: append
+#
+#openshift_hosted_routers=[{'name': 'router1', 'certificate': {'certfile': '/path/to/certificate/abc.crt', 'keyfile': '/path/to/certificate/abc.key', 'cafile': '/path/to/certificate/ca.crt'}, 'replicas': 1, 'serviceaccount': 'router', 'namespace': 'default', 'stats_port': 1936, 'edits': [], 'images': 'openshift3/ose-${component}:${version}', 'selector': 'type=router1', 'ports': ['80:80', '443:443']}, {'name': 'router2', 'certificate': {'certfile': '/path/to/certificate/xyz.crt', 'keyfile': '/path/to/certificate/xyz.key', 'cafile': '/path/to/certificate/ca.crt'}, 'replicas': 1, 'serviceaccount': 'router', 'namespace': 'default', 'stats_port': 1936, 'edits': [{'action': 'append', 'key': 'spec.template.spec.containers[0].env', 'value': {'name': 'ROUTE_LABELS', 'value': 'route=external'}}], 'images': 'openshift3/ose-${component}:${version}', 'selector': 'type=router2', 'ports': ['80:80', '443:443']}]
# OpenShift Registry Console Options
# Override the console image prefix for enterprise deployments, not used in origin
@@ -571,7 +546,7 @@ openshift_master_identity_providers=[{'name': 'htpasswd_auth', 'login': 'true',
#openshift_hosted_metrics_public_url=https://hawkular-metrics.example.com/hawkular/metrics
# Configure the prefix and version for the component images
#openshift_hosted_metrics_deployer_prefix=registry.example.com:8888/openshift3/
-#openshift_hosted_metrics_deployer_version=3.6.0
+#openshift_hosted_metrics_deployer_version=3.7.0
#
# StorageClass
# openshift_storageclass_name=gp2
@@ -626,7 +601,7 @@ openshift_master_identity_providers=[{'name': 'htpasswd_auth', 'login': 'true',
#openshift_hosted_logging_elasticsearch_cluster_size=1
# Configure the prefix and version for the component images
#openshift_hosted_logging_deployer_prefix=registry.example.com:8888/openshift3/
-#openshift_hosted_logging_deployer_version=3.6.0
+#openshift_hosted_logging_deployer_version=3.7.0
# Configure the multi-tenant SDN plugin (default is 'redhat/openshift-ovs-subnet')
# os_sdn_network_plugin_name='redhat/openshift-ovs-multitenant'
@@ -646,6 +621,12 @@ openshift_master_identity_providers=[{'name': 'htpasswd_auth', 'login': 'true',
# WORKAROUND : If you must use an overlapping subnet, you can configure a non conflicting
# docker0 CIDR range by adding '--bip=192.168.2.1/24' to DOCKER_NETWORK_OPTIONS
# environment variable located in /etc/sysconfig/docker-network.
+# When upgrading or scaling up the following must match whats in your master config!
+# Inventory: master yaml field
+# osm_cluster_network_cidr: clusterNetworkCIDR
+# openshift_portal_net: serviceNetworkCIDR
+# When installing osm_cluster_network_cidr and openshift_portal_net must be set.
+# Sane examples are provided below.
#osm_cluster_network_cidr=10.128.0.0/14
#openshift_portal_net=172.30.0.0/16
@@ -667,6 +648,10 @@ openshift_master_identity_providers=[{'name': 'htpasswd_auth', 'login': 'true',
# Configure number of bits to allocate to each host’s subnet e.g. 9
# would mean a /23 network on the host.
+# When upgrading or scaling up the following must match whats in your master config!
+# Inventory: master yaml field
+# osm_host_subnet_length: hostSubnetLength
+# When installing osm_host_subnet_length must be set. A sane example is provided below.
#osm_host_subnet_length=9
# Configure master API and console ports.
@@ -752,10 +737,8 @@ openshift_master_identity_providers=[{'name': 'htpasswd_auth', 'login': 'true',
# Setting this variable to true will override that check.
#openshift_override_hostname_check=true
-# Configure dnsmasq for cluster dns, switch the host's local resolver to use dnsmasq
-# and configure node's dnsIP to point at the node's local dnsmasq instance. Defaults
-# to True for Origin 1.2 and OSE 3.2. False for 1.1 / 3.1 installs, this cannot
-# be used with 1.0 and 3.0.
+# openshift_use_dnsmasq is deprecated. This must be true, or installs will fail
+# in versions >= 3.6
#openshift_use_dnsmasq=False
# Define an additional dnsmasq.conf file to deploy to /etc/dnsmasq.d/openshift-ansible.conf
# This is useful for POC environments where DNS may not actually be available yet or to set
diff --git a/inventory/gce/hosts/gce.py b/inventory/gce/hosts/gce.py
deleted file mode 100755
index 2be46a58c..000000000
--- a/inventory/gce/hosts/gce.py
+++ /dev/null
@@ -1,477 +0,0 @@
-#!/usr/bin/env python2
-# pylint: skip-file
-# Copyright 2013 Google Inc.
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
-
-'''
-GCE external inventory script
-=================================
-
-Generates inventory that Ansible can understand by making API requests
-Google Compute Engine via the libcloud library. Full install/configuration
-instructions for the gce* modules can be found in the comments of
-ansible/test/gce_tests.py.
-
-When run against a specific host, this script returns the following variables
-based on the data obtained from the libcloud Node object:
- - gce_uuid
- - gce_id
- - gce_image
- - gce_machine_type
- - gce_private_ip
- - gce_public_ip
- - gce_name
- - gce_description
- - gce_status
- - gce_zone
- - gce_tags
- - gce_metadata
- - gce_network
-
-When run in --list mode, instances are grouped by the following categories:
- - zone:
- zone group name examples are us-central1-b, europe-west1-a, etc.
- - instance tags:
- An entry is created for each tag. For example, if you have two instances
- with a common tag called 'foo', they will both be grouped together under
- the 'tag_foo' name.
- - network name:
- the name of the network is appended to 'network_' (e.g. the 'default'
- network will result in a group named 'network_default')
- - machine type
- types follow a pattern like n1-standard-4, g1-small, etc.
- - running status:
- group name prefixed with 'status_' (e.g. status_running, status_stopped,..)
- - image:
- when using an ephemeral/scratch disk, this will be set to the image name
- used when creating the instance (e.g. debian-7-wheezy-v20130816). when
- your instance was created with a root persistent disk it will be set to
- 'persistent_disk' since there is no current way to determine the image.
-
-Examples:
- Execute uname on all instances in the us-central1-a zone
- $ ansible -i gce.py us-central1-a -m shell -a "/bin/uname -a"
-
- Use the GCE inventory script to print out instance specific information
- $ contrib/inventory/gce.py --host my_instance
-
-Author: Eric Johnson <erjohnso@google.com>
-Contributors: Matt Hite <mhite@hotmail.com>, Tom Melendez <supertom@google.com>
-Version: 0.0.3
-'''
-
-__requires__ = ['pycrypto>=2.6']
-try:
- import pkg_resources
-except ImportError:
- # Use pkg_resources to find the correct versions of libraries and set
- # sys.path appropriately when there are multiversion installs. We don't
- # fail here as there is code that better expresses the errors where the
- # library is used.
- pass
-
-USER_AGENT_PRODUCT="Ansible-gce_inventory_plugin"
-USER_AGENT_VERSION="v2"
-
-import sys
-import os
-import argparse
-
-from time import time
-
-import ConfigParser
-
-import logging
-logging.getLogger('libcloud.common.google').addHandler(logging.NullHandler())
-
-try:
- import json
-except ImportError:
- import simplejson as json
-
-try:
- from libcloud.compute.types import Provider
- from libcloud.compute.providers import get_driver
- _ = Provider.GCE
-except:
- sys.exit("GCE inventory script requires libcloud >= 0.13")
-
-
-class CloudInventoryCache(object):
- def __init__(self, cache_name='ansible-cloud-cache', cache_path='/tmp',
- cache_max_age=300):
- cache_dir = os.path.expanduser(cache_path)
- if not os.path.exists(cache_dir):
- os.makedirs(cache_dir)
- self.cache_path_cache = os.path.join(cache_dir, cache_name)
-
- self.cache_max_age = cache_max_age
-
- def is_valid(self, max_age=None):
- ''' Determines if the cache files have expired, or if it is still valid '''
-
- if max_age is None:
- max_age = self.cache_max_age
-
- if os.path.isfile(self.cache_path_cache):
- mod_time = os.path.getmtime(self.cache_path_cache)
- current_time = time()
- if (mod_time + max_age) > current_time:
- return True
-
- return False
-
- def get_all_data_from_cache(self, filename=''):
- ''' Reads the JSON inventory from the cache file. Returns Python dictionary. '''
-
- data = ''
- if not filename:
- filename = self.cache_path_cache
- with open(filename, 'r') as cache:
- data = cache.read()
- return json.loads(data)
-
- def write_to_cache(self, data, filename=''):
- ''' Writes data to file as JSON. Returns True. '''
- if not filename:
- filename = self.cache_path_cache
- json_data = json.dumps(data)
- with open(filename, 'w') as cache:
- cache.write(json_data)
- return True
-
-
-class GceInventory(object):
- def __init__(self):
- # Cache object
- self.cache = None
- # dictionary containing inventory read from disk
- self.inventory = {}
-
- # Read settings and parse CLI arguments
- self.parse_cli_args()
- self.config = self.get_config()
- self.driver = self.get_gce_driver()
- self.ip_type = self.get_inventory_options()
- if self.ip_type:
- self.ip_type = self.ip_type.lower()
-
- # Cache management
- start_inventory_time = time()
- cache_used = False
- if self.args.refresh_cache or not self.cache.is_valid():
- self.do_api_calls_update_cache()
- else:
- self.load_inventory_from_cache()
- cache_used = True
- self.inventory['_meta']['stats'] = {'use_cache': True}
- self.inventory['_meta']['stats'] = {
- 'inventory_load_time': time() - start_inventory_time,
- 'cache_used': cache_used
- }
-
- # Just display data for specific host
- if self.args.host:
- print(self.json_format_dict(
- self.inventory['_meta']['hostvars'][self.args.host],
- pretty=self.args.pretty))
- else:
- # Otherwise, assume user wants all instances grouped
- zones = self.parse_env_zones()
- print(self.json_format_dict(self.inventory,
- pretty=self.args.pretty))
- sys.exit(0)
-
- def get_config(self):
- """
- Reads the settings from the gce.ini file.
-
- Populates a SafeConfigParser object with defaults and
- attempts to read an .ini-style configuration from the filename
- specified in GCE_INI_PATH. If the environment variable is
- not present, the filename defaults to gce.ini in the current
- working directory.
- """
- gce_ini_default_path = os.path.join(
- os.path.dirname(os.path.realpath(__file__)), "gce.ini")
- gce_ini_path = os.environ.get('GCE_INI_PATH', gce_ini_default_path)
-
- # Create a ConfigParser.
- # This provides empty defaults to each key, so that environment
- # variable configuration (as opposed to INI configuration) is able
- # to work.
- config = ConfigParser.SafeConfigParser(defaults={
- 'gce_service_account_email_address': '',
- 'gce_service_account_pem_file_path': '',
- 'gce_project_id': '',
- 'libcloud_secrets': '',
- 'inventory_ip_type': '',
- 'cache_path': '~/.ansible/tmp',
- 'cache_max_age': '300'
- })
- if 'gce' not in config.sections():
- config.add_section('gce')
- if 'inventory' not in config.sections():
- config.add_section('inventory')
- if 'cache' not in config.sections():
- config.add_section('cache')
-
- config.read(gce_ini_path)
-
- #########
- # Section added for processing ini settings
- #########
-
- # Set the instance_states filter based on config file options
- self.instance_states = []
- if config.has_option('gce', 'instance_states'):
- states = config.get('gce', 'instance_states')
- # Ignore if instance_states is an empty string.
- if states:
- self.instance_states = states.split(',')
-
- # Caching
- cache_path = config.get('cache', 'cache_path')
- cache_max_age = config.getint('cache', 'cache_max_age')
- # TOOD(supertom): support project-specific caches
- cache_name = 'ansible-gce.cache'
- self.cache = CloudInventoryCache(cache_path=cache_path,
- cache_max_age=cache_max_age,
- cache_name=cache_name)
- return config
-
- def get_inventory_options(self):
- """Determine inventory options. Environment variables always
- take precedence over configuration files."""
- ip_type = self.config.get('inventory', 'inventory_ip_type')
- # If the appropriate environment variables are set, they override
- # other configuration
- ip_type = os.environ.get('INVENTORY_IP_TYPE', ip_type)
- return ip_type
-
- def get_gce_driver(self):
- """Determine the GCE authorization settings and return a
- libcloud driver.
- """
- # Attempt to get GCE params from a configuration file, if one
- # exists.
- secrets_path = self.config.get('gce', 'libcloud_secrets')
- secrets_found = False
- try:
- import secrets
- args = list(getattr(secrets, 'GCE_PARAMS', []))
- kwargs = getattr(secrets, 'GCE_KEYWORD_PARAMS', {})
- secrets_found = True
- except:
- pass
-
- if not secrets_found and secrets_path:
- if not secrets_path.endswith('secrets.py'):
- err = "Must specify libcloud secrets file as "
- err += "/absolute/path/to/secrets.py"
- sys.exit(err)
- sys.path.append(os.path.dirname(secrets_path))
- try:
- import secrets
- args = list(getattr(secrets, 'GCE_PARAMS', []))
- kwargs = getattr(secrets, 'GCE_KEYWORD_PARAMS', {})
- secrets_found = True
- except:
- pass
- if not secrets_found:
- args = [
- self.config.get('gce','gce_service_account_email_address'),
- self.config.get('gce','gce_service_account_pem_file_path')
- ]
- kwargs = {'project': self.config.get('gce', 'gce_project_id')}
-
- # If the appropriate environment variables are set, they override
- # other configuration; process those into our args and kwargs.
- args[0] = os.environ.get('GCE_EMAIL', args[0])
- args[1] = os.environ.get('GCE_PEM_FILE_PATH', args[1])
- kwargs['project'] = os.environ.get('GCE_PROJECT', kwargs['project'])
-
- # Retrieve and return the GCE driver.
- gce = get_driver(Provider.GCE)(*args, **kwargs)
- gce.connection.user_agent_append(
- '%s/%s' % (USER_AGENT_PRODUCT, USER_AGENT_VERSION),
- )
- return gce
-
- def parse_env_zones(self):
- '''returns a list of comma separated zones parsed from the GCE_ZONE environment variable.
- If provided, this will be used to filter the results of the grouped_instances call'''
- import csv
- reader = csv.reader([os.environ.get('GCE_ZONE',"")], skipinitialspace=True)
- zones = [r for r in reader]
- return [z for z in zones[0]]
-
- def parse_cli_args(self):
- ''' Command line argument processing '''
-
- parser = argparse.ArgumentParser(
- description='Produce an Ansible Inventory file based on GCE')
- parser.add_argument('--list', action='store_true', default=True,
- help='List instances (default: True)')
- parser.add_argument('--host', action='store',
- help='Get all information about an instance')
- parser.add_argument('--pretty', action='store_true', default=False,
- help='Pretty format (default: False)')
- parser.add_argument(
- '--refresh-cache', action='store_true', default=False,
- help='Force refresh of cache by making API requests (default: False - use cache files)')
- self.args = parser.parse_args()
-
-
- def node_to_dict(self, inst):
- md = {}
-
- if inst is None:
- return {}
-
- if 'items' in inst.extra['metadata']:
- for entry in inst.extra['metadata']['items']:
- md[entry['key']] = entry['value']
-
- net = inst.extra['networkInterfaces'][0]['network'].split('/')[-1]
- # default to exernal IP unless user has specified they prefer internal
- if self.ip_type == 'internal':
- ssh_host = inst.private_ips[0]
- else:
- ssh_host = inst.public_ips[0] if len(inst.public_ips) >= 1 else inst.private_ips[0]
-
- return {
- 'gce_uuid': inst.uuid,
- 'gce_id': inst.id,
- 'gce_image': inst.image,
- 'gce_machine_type': inst.size,
- 'gce_private_ip': inst.private_ips[0],
- 'gce_public_ip': inst.public_ips[0] if len(inst.public_ips) >= 1 else None,
- 'gce_name': inst.name,
- 'gce_description': inst.extra['description'],
- 'gce_status': inst.extra['status'],
- 'gce_zone': inst.extra['zone'].name,
- 'gce_tags': inst.extra['tags'],
- 'gce_metadata': md,
- 'gce_network': net,
- # Hosts don't have a public name, so we add an IP
- 'ansible_ssh_host': ssh_host
- }
-
- def load_inventory_from_cache(self):
- ''' Loads inventory from JSON on disk. '''
-
- try:
- self.inventory = self.cache.get_all_data_from_cache()
- hosts = self.inventory['_meta']['hostvars']
- except Exception as e:
- print(
- "Invalid inventory file %s. Please rebuild with -refresh-cache option."
- % (self.cache.cache_path_cache))
- raise
-
- def do_api_calls_update_cache(self):
- ''' Do API calls and save data in cache. '''
- zones = self.parse_env_zones()
- data = self.group_instances(zones)
- self.cache.write_to_cache(data)
- self.inventory = data
-
- def list_nodes(self):
- all_nodes = []
- params, more_results = {'maxResults': 500}, True
- while more_results:
- self.driver.connection.gce_params=params
- all_nodes.extend(self.driver.list_nodes())
- more_results = 'pageToken' in params
- return all_nodes
-
- def group_instances(self, zones=None):
- '''Group all instances'''
- groups = {}
- meta = {}
- meta["hostvars"] = {}
-
- for node in self.list_nodes():
-
- # This check filters on the desired instance states defined in the
- # config file with the instance_states config option.
- #
- # If the instance_states list is _empty_ then _ALL_ states are returned.
- #
- # If the instance_states list is _populated_ then check the current
- # state against the instance_states list
- if self.instance_states and not node.extra['status'] in self.instance_states:
- continue
-
- name = node.name
-
- meta["hostvars"][name] = self.node_to_dict(node)
-
- zone = node.extra['zone'].name
-
- # To avoid making multiple requests per zone
- # we list all nodes and then filter the results
- if zones and zone not in zones:
- continue
-
- if zone in groups: groups[zone].append(name)
- else: groups[zone] = [name]
-
- tags = node.extra['tags']
- for t in tags:
- if t.startswith('group-'):
- tag = t[6:]
- else:
- tag = 'tag_%s' % t
- if tag in groups: groups[tag].append(name)
- else: groups[tag] = [name]
-
- net = node.extra['networkInterfaces'][0]['network'].split('/')[-1]
- net = 'network_%s' % net
- if net in groups: groups[net].append(name)
- else: groups[net] = [name]
-
- machine_type = node.size
- if machine_type in groups: groups[machine_type].append(name)
- else: groups[machine_type] = [name]
-
- image = node.image and node.image or 'persistent_disk'
- if image in groups: groups[image].append(name)
- else: groups[image] = [name]
-
- status = node.extra['status']
- stat = 'status_%s' % status.lower()
- if stat in groups: groups[stat].append(name)
- else: groups[stat] = [name]
-
- groups["_meta"] = meta
-
- return groups
-
- def json_format_dict(self, data, pretty=False):
- ''' Converts a dict to a JSON object and dumps it as a formatted
- string '''
-
- if pretty:
- return json.dumps(data, sort_keys=True, indent=2)
- else:
- return json.dumps(data)
-
-# Run the script
-if __name__ == '__main__':
- GceInventory()
diff --git a/inventory/gce/hosts/hosts b/inventory/gce/hosts/hosts
deleted file mode 100644
index 3996e577e..000000000
--- a/inventory/gce/hosts/hosts
+++ /dev/null
@@ -1 +0,0 @@
-localhost ansible_connection=local ansible_become=no ansible_python_interpreter='/usr/bin/env python2'
diff --git a/inventory/libvirt/hosts/hosts b/inventory/libvirt/hosts/hosts
deleted file mode 100644
index 3996e577e..000000000
--- a/inventory/libvirt/hosts/hosts
+++ /dev/null
@@ -1 +0,0 @@
-localhost ansible_connection=local ansible_become=no ansible_python_interpreter='/usr/bin/env python2'
diff --git a/inventory/libvirt/hosts/libvirt.ini b/inventory/libvirt/hosts/libvirt.ini
deleted file mode 100644
index 62ff204dd..000000000
--- a/inventory/libvirt/hosts/libvirt.ini
+++ /dev/null
@@ -1,20 +0,0 @@
-# Ansible libvirt external inventory script settings
-#
-
-[libvirt]
-
-uri = qemu:///system
-
-# API calls to libvirt can be slow. For this reason, we cache the results of an API
-# call. Set this to the path you want cache files to be written to. Two files
-# will be written to this directory:
-# - ansible-libvirt.cache
-# - ansible-libvirt.index
-cache_path = /tmp
-
-# The number of seconds a cache file is considered valid. After this many
-# seconds, a new API call will be made, and the cache file will be updated.
-cache_max_age = 900
-
-
-
diff --git a/inventory/libvirt/hosts/libvirt_generic.py b/inventory/libvirt/hosts/libvirt_generic.py
deleted file mode 100755
index d63e07b64..000000000
--- a/inventory/libvirt/hosts/libvirt_generic.py
+++ /dev/null
@@ -1,191 +0,0 @@
-#!/usr/bin/env python2
-# pylint: skip-file
-
-'''
-libvirt external inventory script
-=================================
-
-Ansible has a feature where instead of reading from /etc/ansible/hosts
-as a text file, it can query external programs to obtain the list
-of hosts, groups the hosts are in, and even variables to assign to each host.
-
-To use this, copy this file over /etc/ansible/hosts and chmod +x the file.
-This, more or less, allows you to keep one central database containing
-info about all of your managed instances.
-
-'''
-
-# (c) 2015, Jason DeTiberus <jdetiber@redhat.com>
-#
-# This file is part of Ansible,
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
-
-######################################################################
-
-import argparse
-import ConfigParser
-import os
-import sys
-import libvirt
-import xml.etree.ElementTree as ET
-
-try:
- import json
-except ImportError:
- import simplejson as json
-
-
-class LibvirtInventory(object):
- ''' libvirt dynamic inventory '''
-
- def __init__(self):
- ''' Main execution path '''
-
- self.inventory = dict() # A list of groups and the hosts in that group
- self.cache = dict() # Details about hosts in the inventory
-
- # Read settings and parse CLI arguments
- self.read_settings()
- self.parse_cli_args()
-
- if self.args.host:
- print(_json_format_dict(self.get_host_info(), self.args.pretty))
- elif self.args.list:
- print(_json_format_dict(self.get_inventory(), self.args.pretty))
- else: # default action with no options
- print(_json_format_dict(self.get_inventory(), self.args.pretty))
-
- def read_settings(self):
- ''' Reads the settings from the libvirt.ini file '''
-
- config = ConfigParser.SafeConfigParser()
- config.read(
- os.path.dirname(os.path.realpath(__file__)) + '/libvirt.ini'
- )
- self.libvirt_uri = config.get('libvirt', 'uri')
-
- def parse_cli_args(self):
- ''' Command line argument processing '''
-
- parser = argparse.ArgumentParser(
- description='Produce an Ansible Inventory file based on libvirt'
- )
- parser.add_argument(
- '--list',
- action='store_true',
- default=True,
- help='List instances (default: True)'
- )
- parser.add_argument(
- '--host',
- action='store',
- help='Get all the variables about a specific instance'
- )
- parser.add_argument(
- '--pretty',
- action='store_true',
- default=False,
- help='Pretty format (default: False)'
- )
- self.args = parser.parse_args()
-
- def get_host_info(self):
- ''' Get variables about a specific host '''
-
- inventory = self.get_inventory()
- if self.args.host in inventory['_meta']['hostvars']:
- return inventory['_meta']['hostvars'][self.args.host]
-
- def get_inventory(self):
- ''' Construct the inventory '''
-
- inventory = dict(_meta=dict(hostvars=dict()))
-
- conn = libvirt.openReadOnly(self.libvirt_uri)
- if conn is None:
- print("Failed to open connection to %s" % self.libvirt_uri)
- sys.exit(1)
-
- domains = conn.listAllDomains()
- if domains is None:
- print("Failed to list domains for connection %s" % self.libvirt_uri)
- sys.exit(1)
-
- for domain in domains:
- hostvars = dict(libvirt_name=domain.name(),
- libvirt_id=domain.ID(),
- libvirt_uuid=domain.UUIDString())
- domain_name = domain.name()
-
- # TODO: add support for guests that are not in a running state
- state, _ = domain.state()
- # 2 is the state for a running guest
- if state != 1:
- continue
-
- hostvars['libvirt_status'] = 'running'
-
- root = ET.fromstring(domain.XMLDesc())
- ansible_ns = {'ansible': 'https://github.com/ansible/ansible'}
- for tag_elem in root.findall('./metadata/ansible:tags/ansible:tag', ansible_ns):
- tag = tag_elem.text
- _push(inventory, "tag_%s" % tag, domain_name)
- _push(hostvars, 'libvirt_tags', tag)
-
- # TODO: support more than one network interface, also support
- # interface types other than 'network'
- interface = root.find("./devices/interface[@type='network']")
- if interface is not None:
- source_elem = interface.find('source')
- mac_elem = interface.find('mac')
- if source_elem is not None and \
- mac_elem is not None:
- # Adding this to disable pylint check specifically
- # ignoring libvirt-python versions that
- # do not include DHCPLeases
- # This is needed until we upgrade the build bot to
- # RHEL7 (>= 1.2.6 libvirt)
- # pylint: disable=no-member
- dhcp_leases = conn.networkLookupByName(source_elem.get('network')) \
- .DHCPLeases(mac_elem.get('address'))
- if len(dhcp_leases) > 0:
- ip_address = dhcp_leases[0]['ipaddr']
- hostvars['ansible_ssh_host'] = ip_address
- hostvars['libvirt_ip_address'] = ip_address
-
- inventory['_meta']['hostvars'][domain_name] = hostvars
-
- return inventory
-
-def _push(my_dict, key, element):
- '''
- Push element to the my_dict[key] list.
- After having initialized my_dict[key] if it dosn't exist.
- '''
-
- if key in my_dict:
- my_dict[key].append(element)
- else:
- my_dict[key] = [element]
-
-def _json_format_dict(data, pretty=False):
- ''' Serialize data to a JSON formated str '''
-
- if pretty:
- return json.dumps(data, sort_keys=True, indent=2)
- else:
- return json.dumps(data)
-
-LibvirtInventory()
diff --git a/inventory/openstack/hosts/hosts b/inventory/openstack/hosts/hosts
deleted file mode 100644
index 9b63e98f4..000000000
--- a/inventory/openstack/hosts/hosts
+++ /dev/null
@@ -1 +0,0 @@
-localhost ansible_become=no ansible_python_interpreter='/usr/bin/env python2' connection=local
diff --git a/inventory/openstack/hosts/openstack.py b/inventory/openstack/hosts/openstack.py
deleted file mode 100755
index deefd3b5d..000000000
--- a/inventory/openstack/hosts/openstack.py
+++ /dev/null
@@ -1,247 +0,0 @@
-#!/usr/bin/env python
-# pylint: skip-file
-
-# Copyright (c) 2012, Marco Vito Moscaritolo <marco@agavee.com>
-# Copyright (c) 2013, Jesse Keating <jesse.keating@rackspace.com>
-# Copyright (c) 2015, Hewlett-Packard Development Company, L.P.
-# Copyright (c) 2016, Rackspace Australia
-#
-# This module is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This software is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this software. If not, see <http://www.gnu.org/licenses/>.
-
-# The OpenStack Inventory module uses os-client-config for configuration.
-# https://github.com/stackforge/os-client-config
-# This means it will either:
-# - Respect normal OS_* environment variables like other OpenStack tools
-# - Read values from a clouds.yaml file.
-# If you want to configure via clouds.yaml, you can put the file in:
-# - Current directory
-# - ~/.config/openstack/clouds.yaml
-# - /etc/openstack/clouds.yaml
-# - /etc/ansible/openstack.yml
-# The clouds.yaml file can contain entries for multiple clouds and multiple
-# regions of those clouds. If it does, this inventory module will connect to
-# all of them and present them as one contiguous inventory.
-#
-# See the adjacent openstack.yml file for an example config file
-# There are two ansible inventory specific options that can be set in
-# the inventory section.
-# expand_hostvars controls whether or not the inventory will make extra API
-# calls to fill out additional information about each server
-# use_hostnames changes the behavior from registering every host with its UUID
-# and making a group of its hostname to only doing this if the
-# hostname in question has more than one server
-# fail_on_errors causes the inventory to fail and return no hosts if one cloud
-# has failed (for example, bad credentials or being offline).
-# When set to False, the inventory will return hosts from
-# whichever other clouds it can contact. (Default: True)
-
-import argparse
-import collections
-import os
-import sys
-import time
-from distutils.version import StrictVersion
-
-try:
- import json
-except:
- import simplejson as json
-
-import os_client_config
-import shade
-import shade.inventory
-
-CONFIG_FILES = ['/etc/ansible/openstack.yaml', '/etc/ansible/openstack.yml']
-
-
-def get_groups_from_server(server_vars, namegroup=True):
- groups = []
-
- region = server_vars['region']
- cloud = server_vars['cloud']
- metadata = server_vars.get('metadata', {})
-
- # Create a group for the cloud
- groups.append(cloud)
-
- # Create a group on region
- groups.append(region)
-
- # And one by cloud_region
- groups.append("%s_%s" % (cloud, region))
-
- # Check if group metadata key in servers' metadata
- if 'group' in metadata:
- groups.append(metadata['group'])
-
- for extra_group in metadata.get('groups', '').split(','):
- if extra_group:
- groups.append(extra_group.strip())
-
- groups.append('instance-%s' % server_vars['id'])
- if namegroup:
- groups.append(server_vars['name'])
-
- for key in ('flavor', 'image'):
- if 'name' in server_vars[key]:
- groups.append('%s-%s' % (key, server_vars[key]['name']))
-
- for key, value in iter(metadata.items()):
- groups.append('meta-%s_%s' % (key, value))
-
- az = server_vars.get('az', None)
- if az:
- # Make groups for az, region_az and cloud_region_az
- groups.append(az)
- groups.append('%s_%s' % (region, az))
- groups.append('%s_%s_%s' % (cloud, region, az))
- return groups
-
-
-def get_host_groups(inventory, refresh=False):
- (cache_file, cache_expiration_time) = get_cache_settings()
- if is_cache_stale(cache_file, cache_expiration_time, refresh=refresh):
- groups = to_json(get_host_groups_from_cloud(inventory))
- open(cache_file, 'w').write(groups)
- else:
- groups = open(cache_file, 'r').read()
- return groups
-
-
-def append_hostvars(hostvars, groups, key, server, namegroup=False):
- hostvars[key] = dict(
- ansible_ssh_host=server['interface_ip'],
- openstack=server)
- for group in get_groups_from_server(server, namegroup=namegroup):
- groups[group].append(key)
-
-
-def get_host_groups_from_cloud(inventory):
- groups = collections.defaultdict(list)
- firstpass = collections.defaultdict(list)
- hostvars = {}
- list_args = {}
- if hasattr(inventory, 'extra_config'):
- use_hostnames = inventory.extra_config['use_hostnames']
- list_args['expand'] = inventory.extra_config['expand_hostvars']
- if StrictVersion(shade.__version__) >= StrictVersion("1.6.0"):
- list_args['fail_on_cloud_config'] = \
- inventory.extra_config['fail_on_errors']
- else:
- use_hostnames = False
-
- for server in inventory.list_hosts(**list_args):
-
- if 'interface_ip' not in server:
- continue
- firstpass[server['name']].append(server)
- for name, servers in firstpass.items():
- if len(servers) == 1 and use_hostnames:
- append_hostvars(hostvars, groups, name, servers[0])
- else:
- server_ids = set()
- # Trap for duplicate results
- for server in servers:
- server_ids.add(server['id'])
- if len(server_ids) == 1 and use_hostnames:
- append_hostvars(hostvars, groups, name, servers[0])
- else:
- for server in servers:
- append_hostvars(
- hostvars, groups, server['id'], server,
- namegroup=True)
- groups['_meta'] = {'hostvars': hostvars}
- return groups
-
-
-def is_cache_stale(cache_file, cache_expiration_time, refresh=False):
- ''' Determines if cache file has expired, or if it is still valid '''
- if refresh:
- return True
- if os.path.isfile(cache_file) and os.path.getsize(cache_file) > 0:
- mod_time = os.path.getmtime(cache_file)
- current_time = time.time()
- if (mod_time + cache_expiration_time) > current_time:
- return False
- return True
-
-
-def get_cache_settings():
- config = os_client_config.config.OpenStackConfig(
- config_files=os_client_config.config.CONFIG_FILES + CONFIG_FILES)
- # For inventory-wide caching
- cache_expiration_time = config.get_cache_expiration_time()
- cache_path = config.get_cache_path()
- if not os.path.exists(cache_path):
- os.makedirs(cache_path)
- cache_file = os.path.join(cache_path, 'ansible-inventory.cache')
- return (cache_file, cache_expiration_time)
-
-
-def to_json(in_dict):
- return json.dumps(in_dict, sort_keys=True, indent=2)
-
-
-def parse_args():
- parser = argparse.ArgumentParser(description='OpenStack Inventory Module')
- parser.add_argument('--private',
- action='store_true',
- help='Use private address for ansible host')
- parser.add_argument('--refresh', action='store_true',
- help='Refresh cached information')
- parser.add_argument('--debug', action='store_true', default=False,
- help='Enable debug output')
- group = parser.add_mutually_exclusive_group(required=True)
- group.add_argument('--list', action='store_true',
- help='List active servers')
- group.add_argument('--host', help='List details about the specific host')
-
- return parser.parse_args()
-
-
-def main():
- args = parse_args()
- try:
- config_files = os_client_config.config.CONFIG_FILES + CONFIG_FILES
- shade.simple_logging(debug=args.debug)
- inventory_args = dict(
- refresh=args.refresh,
- config_files=config_files,
- private=args.private,
- )
- if hasattr(shade.inventory.OpenStackInventory, 'extra_config'):
- inventory_args.update(dict(
- config_key='ansible',
- config_defaults={
- 'use_hostnames': False,
- 'expand_hostvars': True,
- 'fail_on_errors': True,
- }
- ))
-
- inventory = shade.inventory.OpenStackInventory(**inventory_args)
-
- if args.list:
- output = get_host_groups(inventory, refresh=args.refresh)
- elif args.host:
- output = to_json(inventory.get_host(args.host))
- print(output)
- except shade.OpenStackCloudException as e:
- sys.stderr.write('%s\n' % e.message)
- sys.exit(1)
- sys.exit(0)
-
-
-if __name__ == '__main__':
- main()
diff --git a/openshift-ansible.spec b/openshift-ansible.spec
index 1c3b1757c..3be13145e 100644
--- a/openshift-ansible.spec
+++ b/openshift-ansible.spec
@@ -10,14 +10,14 @@
Name: openshift-ansible
Version: 3.7.0
-Release: 0.104.0%{?dist}
+Release: 0.126.0%{?dist}
Summary: Openshift and Atomic Enterprise Ansible
License: ASL 2.0
URL: https://github.com/openshift/openshift-ansible
Source0: https://github.com/openshift/openshift-ansible/archive/%{commit}/%{name}-%{version}.tar.gz
BuildArch: noarch
-Requires: ansible >= 2.2.2.0
+Requires: ansible >= 2.3
Requires: python2
Requires: python-six
Requires: tar
@@ -280,6 +280,196 @@ Atomic OpenShift Utilities includes
%changelog
+* Mon Sep 11 2017 Jenkins CD Merge Bot <smunilla@redhat.com> 3.7.0-0.126.0
+- Fix rpm version logic for hosts (mgugino@redhat.com)
+- Revert back to hostnamectl and previous default of not setting hostname
+ (sdodson@redhat.com)
+- Correct include path to not follow symlink (rteague@redhat.com)
+- Fix include path for docker upgrade tasks (rteague@redhat.com)
+- Fix issue with etcd_common when using pre_upgrade tag (rteague@redhat.com)
+- inventory: Denote new required upgrade variables (smilner@redhat.com)
+- upgrade: Verify required network items are set (smilner@redhat.com)
+- ami build process calls openshift-node/config.yml (kwoodson@redhat.com)
+
+* Fri Sep 08 2017 Scott Dodson <sdodson@redhat.com> 3.7.0-0.125.1
+- Consolidating AWS roles and variables underneath openshift_aws role.
+ (kwoodson@redhat.com)
+- Fix README.md typo (mgugino@redhat.com)
+- Fixing variables and allowing custom ami. (kwoodson@redhat.com)
+- Remove openshift-common (mgugino@redhat.com)
+- Fix openshift_master_config_dir (sdodson@redhat.com)
+- remove experimental-cri flag from node config (sjenning@redhat.com)
+- cri-o: Split RHEL and CentOS images (smilner@redhat.com)
+- openshift_checks aos_version: also check installed under yum
+ (lmeyer@redhat.com)
+- Create ansible role for deploying prometheus on openshift (zgalor@redhat.com)
+- Fix: set openshift_master_config_dir to the correct value.
+ (mgugino@redhat.com)
+- Bump ansible requirement to 2.3 (sdodson@redhat.com)
+- Move master additional config out of base (rteague@redhat.com)
+- Import dnf only if importing yum fails (jhadvig@redhat.com)
+- output skopeo image check command (nakayamakenjiro@gmail.com)
+- skip openshift_cfme_nfs_server if not using nfs (sdw35@cornell.edu)
+- bug 1487573. Bump the allowed ES versions (jcantril@redhat.com)
+- update env in etcd.conf.j2 to reflect the latest naming (jchaloup@redhat.com)
+- logging set memory request to limit (jcantril@redhat.com)
+- Use the proper pod subnet instead the services one (edu@redhat.com)
+- elasticsearch: reintroduce readiness probe (jwozniak@redhat.com)
+- cri-o: add support for additional registries (gscrivan@redhat.com)
+- reverse order between router cert generation (mewt.fr@gmail.com)
+- ensured to always use a certificate for the router (mewt.fr@gmail.com)
+- Adding proxy env vars for dc/docker-registry (kwoodson@redhat.com)
+- oc_atomic_container: support Skopeo output (gscrivan@redhat.com)
+
+* Tue Sep 05 2017 Jenkins CD Merge Bot <smunilla@redhat.com> 3.7.0-0.125.0
+-
+
+* Tue Sep 05 2017 Jenkins CD Merge Bot <smunilla@redhat.com> 3.7.0-0.124.0
+- Fix ansible_syntax check (rteague@redhat.com)
+- Standardize etcd entry point playbooks (rteague@redhat.com)
+- Adding deprecation checks to ansible_syntax (rteague@redhat.com)
+- Break out master config into stand-alone playbook (rteague@redhat.com)
+- Move all-in-one fail check to evaluate_groups.yml (rteague@redhat.com)
+- Break out node config into stand-alone playbook (rteague@redhat.com)
+- Adding another default to protect against missing name/desc
+ (kwoodson@redhat.com)
+- Removed dns role (mgugino@redhat.com)
+- Fix typo in variable names for glusterfs firewall configuration
+ (bacek@bacek.com)
+- disk_availability: fix bug where msg is overwritten (lmeyer@redhat.com)
+- Added firwall defaults to etcd role. (kwoodson@redhat.com)
+- Remove meta depends from clock (mgugino@redhat.com)
+- Only run migrate auth for < 3.7 (rteague@redhat.com)
+- Fix openshift_master upgrade (mgugino@redhat.com)
+- Merging openshift_node with openshift bootstrap. (kwoodson@redhat.com)
+- Test: Fail on entry point playbooks in common (rteague@redhat.com)
+- Bug 1467265 - logging: add 'purge' option with uninstall
+ (jwozniak@redhat.com)
+- openshift_checks: ignore hidden files in checks dir
+ (miciah.masters@gmail.com)
+
+* Wed Aug 30 2017 Jenkins CD Merge Bot <smunilla@redhat.com> 3.7.0-0.123.0
+-
+
+* Wed Aug 30 2017 Jenkins CD Merge Bot <smunilla@redhat.com> 3.7.0-0.122.0
+- Update openshift_hosted_routers example to be in ini format.
+ (abutcher@redhat.com)
+- Update calico to v2.5 (djosborne10@gmail.com)
+
+* Wed Aug 30 2017 Jenkins CD Merge Bot <smunilla@redhat.com> 3.7.0-0.121.0
+- Revert "logging set memory request to limit" (sdodson@redhat.com)
+- Move firewall install and fix scaleup playbooks (rteague@redhat.com)
+- Fix group conditional requirements (rteague@redhat.com)
+- Updating openshift_service_catalog to use oc_service over oc_obj to resolve
+ idempotency issues being seen from rerunning role (ewolinet@redhat.com)
+- annotate the infra projects for logging to fix bz1480988
+ (jcantril@redhat.com)
+- docker_image_availability: timeout skopeo inspect (lmeyer@redhat.com)
+- Fix scaleup on containerized installations (sdodson@redhat.com)
+- bug 1480878. Default pvc for logging (jcantril@redhat.com)
+- logging set memory request to limit (jcantril@redhat.com)
+- openshift_cfme: add nfs directory support (fsimonce@redhat.com)
+
+* Tue Aug 29 2017 Jenkins CD Merge Bot <smunilla@redhat.com> 3.7.0-0.120.0
+- Nuage changes to add custom mounts for atomic-openshift-node service
+ (rohan.s.parulekar@nuagenetworks.net)
+- Add independent registry auth support (mgugino@redhat.com)
+- roles: use openshift_use_crio (gscrivan@redhat.com)
+- cri-o: change to system runc (gscrivan@redhat.com)
+- cri-o: rename openshift_docker_use_crio to openshift_use_crio
+ (gscrivan@redhat.com)
+- Remove unsupported playbooks and utilities (rteague@redhat.com)
+- Updating default tag for enterprise installation for ASB
+ (ewolinet@redhat.com)
+- Only validate certificates that are passed to oc_route (zgalor@redhat.com)
+
+* Mon Aug 28 2017 Jenkins CD Merge Bot <smunilla@redhat.com> 3.7.0-0.118.0
+- Fix origin metrics and logging container version
+ (gevorg15@users.noreply.github.com)
+- Removing deprecation warnings for when conditions. (kwoodson@redhat.com)
+- Default to global setting for firewall. (kwoodson@redhat.com)
+- system-containers: Fallback for system_images_registry (smilner@redhat.com)
+- inventory: Add system_images_registry example (smilner@redhat.com)
+- Remove near-meta role openshift_cli_facts (mgugino@redhat.com)
+- Update error message: s/non-unique/duplicate (rhcarvalho@gmail.com)
+- Make pylint disables more specific (rhcarvalho@gmail.com)
+- Handle exceptions in failure summary cb plugin (rhcarvalho@gmail.com)
+- Rewrite failure summary callback plugin (rhcarvalho@gmail.com)
+- Handle more exceptions when running checks (rhcarvalho@gmail.com)
+- List known checks/tags when check name is invalid (rhcarvalho@gmail.com)
+- List existing health checks when none is requested (rhcarvalho@gmail.com)
+- Add playbook for running arbitrary health checks (rhcarvalho@gmail.com)
+- Update health check README (rhcarvalho@gmail.com)
+- Standardize openshift_provisioners entry point (rteague@redhat.com)
+- Remove unused upgrade playbook (rteague@redhat.com)
+- Bug 1471322: logging roles based image versions (jwozniak@redhat.com)
+
+* Fri Aug 25 2017 Jenkins CD Merge Bot <smunilla@redhat.com> 3.7.0-0.117.0
+- Standardize openshift-checks code paths (rteague@redhat.com)
+
+* Fri Aug 25 2017 Jenkins CD Merge Bot <smunilla@redhat.com> 3.7.0-0.116.0
+- Add missing hostnames to registry cert (sdodson@redhat.com)
+
+* Fri Aug 25 2017 Jenkins CD Merge Bot <smunilla@redhat.com> 3.7.0-0.115.0
+-
+
+* Fri Aug 25 2017 Jenkins CD Merge Bot <smunilla@redhat.com> 3.7.0-0.114.0
+-
+
+* Fri Aug 25 2017 Jenkins CD Merge Bot <smunilla@redhat.com> 3.7.0-0.113.0
+- openshift_version: enterprise accepts new style pre-release
+ (smilner@redhat.com)
+- Nuage changes for Atomic hosts OSE Integration
+ (rohan.s.parulekar@nuagenetworks.net)
+
+* Fri Aug 25 2017 Jenkins CD Merge Bot <smunilla@redhat.com> 3.7.0-0.112.0
+- fix #5206. Default ES cpu limit (jcantril@redhat.com)
+
+* Fri Aug 25 2017 Jenkins CD Merge Bot <smunilla@redhat.com> 3.7.0-0.111.0
+- Upgrade check for OpenShift authorization objects (rteague@redhat.com)
+
+* Fri Aug 25 2017 Jenkins CD Merge Bot <smunilla@redhat.com> 3.7.0-0.110.0
+- Setup tuned profiles in /etc/tuned (jmencak@redhat.com)
+
+* Thu Aug 24 2017 Jenkins CD Merge Bot <smunilla@redhat.com> 3.7.0-0.109.0
+-
+
+* Thu Aug 24 2017 Jenkins CD Merge Bot <smunilla@redhat.com> 3.7.0-0.108.0
+-
+
+* Thu Aug 24 2017 Jenkins CD Merge Bot <smunilla@redhat.com> 3.7.0-0.107.0
+-
+
+* Thu Aug 24 2017 Jenkins CD Merge Bot <smunilla@redhat.com> 3.7.0-0.106.0
+- Add dotnet 2.0 to v3.6 (sdodson@redhat.com)
+- Add dotnet 2.0 to v3.7 (sdodson@redhat.com)
+- Update v3.6 content (sdodson@redhat.com)
+- Update all image streams and templates (sdodson@redhat.com)
+- Passing memory and cpu limit for ops ES install (ewolinet@redhat.com)
+- If IP4_NAMESERVERS are unset then pull the value from /etc/resolv.conf
+ (sdodson@redhat.com)
+- New tuned profile hierarchy. (jmencak@redhat.com)
+- GlusterFS: add minor README note for #5071 (jarrpa@redhat.com)
+- Update cfme templates to auto-generate postgresql password
+ https://bugzilla.redhat.com/show_bug.cgi?id=1461973 (simaishi@redhat.com)
+
+* Wed Aug 23 2017 Jenkins CD Merge Bot <smunilla@redhat.com> 3.7.0-0.105.0
+- Fix generated content (sdodson@redhat.com)
+- Switch to migrating one host and forming a new cluster (sdodson@redhat.com)
+- First attempt at provisioning. (kwoodson@redhat.com)
+- First attempt at creating the cert signer. (kwoodson@redhat.com)
+- remove out of scope variable from exception message
+ (maxamillion@fedoraproject.org)
+- raise AosVersionException if no expected packages found by dnf query
+ (maxamillion@fedoraproject.org)
+- Fix missing space in calico ansible roles (djosborne10@gmail.com)
+- Allow GCS object storage to be configured (ccoleman@redhat.com)
+- add dnf support to roles/openshift_health_checker/library/aos_version.py
+ (maxamillion@fedoraproject.org)
+- Add hostname/nodename length check (mgugino@redhat.com)
+- Refactor openshift_hosted's docker-registry route setup (dms@redhat.com)
+- bug 1468987: kibana_proxy OOM (jwozniak@redhat.com)
+
* Sun Aug 20 2017 Jenkins CD Merge Bot <smunilla@redhat.com> 3.7.0-0.104.0
- Ensure that openshift_node_facts has been called for dns_ip
(sdodson@redhat.com)
diff --git a/playbooks/README.md b/playbooks/README.md
index 5857a9f59..290d4c082 100644
--- a/playbooks/README.md
+++ b/playbooks/README.md
@@ -12,8 +12,6 @@ And:
- [`adhoc`](adhoc) is a generic home for playbooks and tasks that are community
supported and not officially maintained.
-- [`aws`](aws), [`gce`](gce), [`libvirt`](libvirt) and [`openstack`](openstack)
- are related to the [`bin/cluster`](../bin) tool and its usage is deprecated.
Refer to the `README.md` file in each playbook directory for more information
about them.
diff --git a/playbooks/adhoc/uninstall.yml b/playbooks/adhoc/uninstall.yml
index 58b3a7835..5072d10fa 100644
--- a/playbooks/adhoc/uninstall.yml
+++ b/playbooks/adhoc/uninstall.yml
@@ -35,11 +35,9 @@
- /etc/dnsmasq.d/origin-upstream-dns.conf
- /etc/dnsmasq.d/openshift-ansible.conf
- /etc/NetworkManager/dispatcher.d/99-origin-dns.sh
- when: openshift_use_dnsmasq | default(true) | bool
- service:
name: NetworkManager
state: restarted
- when: openshift_use_dnsmasq | default(true) | bool
- name: Stop services
service: name={{ item }} state=stopped
with_items:
diff --git a/playbooks/aws/README.md b/playbooks/aws/README.md
index 99698b4d0..2b3d4329e 100644
--- a/playbooks/aws/README.md
+++ b/playbooks/aws/README.md
@@ -1,4 +1,256 @@
# AWS playbooks
-This playbook directory is meant to be driven by [`bin/cluster`](../../bin),
-which is community supported and most use is considered deprecated.
+## Provisioning
+
+With recent desire for provisioning from customers and developers alike, the AWS
+ playbook directory now supports a limited set of ansible playbooks to achieve a
+ complete cluster setup. These playbooks bring into alignment our desire to
+ deploy highly scalable Openshift clusters utilizing AWS auto scale groups and
+ custom AMIs.
+
+### Where do I start?
+
+Before any provisioning may occur, AWS account credentials must be present in the environment. This can be done in two ways:
+
+- Create the following file `~/.aws/credentials` with the contents (substitute your access key and secret key):
+ ```
+ [myaccount]
+ aws_access_key_id = <Your access_key here>
+ aws_secret_access_key = <Your secret acces key here>
+ ```
+ From the shell:
+ ```
+ $ export AWS_PROFILE=myaccount
+ ```
+ ---
+- Alternatively to using a profile you can export your AWS credentials as environment variables.
+ ```
+ $ export AWS_ACCESS_KEY_ID=AKIXXXXXX
+ $ export AWS_SECRET_ACCESS_KEY=XXXXXX
+ ```
+
+### Let's Provision!
+
+The newly added playbooks are the following:
+- build_ami.yml - Builds a custom AMI. This currently requires the user to supply a valid AMI with access to repositories that contain openshift repositories.
+- provision.yml - Create a vpc, elbs, security groups, launch config, asg's, etc.
+- install.yml - Calls the openshift-ansible installer on the newly created instances
+- provision_nodes.yml - Creates the infra and compute node scale groups
+- accept.yml - This is a playbook to accept infra and compute nodes into the cluster
+- provision_install.yml - This is a combination of all 3 of the above playbooks. (provision, install, and provision_nodes as well as accept.yml)
+
+The current expected work flow should be to provide an AMI with access to Openshift repositories. There should be a repository specified in the `openshift_additional_repos` parameter of the inventory file. The next expectation is a minimal set of values in the `provisioning_vars.yml` file to configure the desired settings for cluster instances. These settings are AWS specific and should be tailored to the consumer's AWS custom account settings.
+
+```yaml
+---
+# when creating an AMI set this to True
+# when installing a cluster set this to False
+openshift_node_bootstrap: True
+
+# specify a clusterid
+# openshift_aws_clusterid: default
+
+# specify a region
+# openshift_aws_region: us-east-1
+
+# must specify a base_ami when building an AMI
+# openshift_aws_base_ami: # base image for AMI to build from
+# specify when using a custom AMI
+# openshift_aws_ami:
+
+# when creating an encrypted AMI please specify use_encryption
+# openshift_aws_ami_encrypt: False
+
+# custom certificates are required for the ELB
+# openshift_aws_iam_cert_path: '/path/to/cert/wildcard.<clusterid>.<domain>.com.crt'
+# openshift_aws_iam_cert_key_path: '/path/to/key/wildcard.<clusterid>.<domain>.com.key'
+# openshift_aws_iam_cert_chain_path: '/path/to/ca_cert_file/ca.crt'
+
+# This is required for any ec2 instances
+# openshift_aws_ssh_key_name: myuser_key
+
+# This will ensure these users are created
+#openshift_aws_users:
+#- key_name: myuser_key
+# username: myuser
+# pub_key: |
+# ssh-rsa AAAA
+```
+
+If customization is required for the instances, scale groups, or any other configurable option please see the ['openshift_aws/defaults/main.yml'](../../roles/openshift_aws/defaults/main.yml) for variables and overrides. These overrides can be placed in the `provisioning_vars.yml`, `inventory`, or `group_vars`.
+
+In order to create the bootstrap-able AMI we need to create an openshift-ansible inventory file. This file enables us to create the AMI using the openshift-ansible node roles. The exception here is that there will be no hosts specified by the inventory file. Here is an example:
+
+```ini
+[OSEv3:children]
+masters
+nodes
+etcd
+
+[OSEv3:children]
+masters
+nodes
+etcd
+
+[OSEv3:vars]
+################################################################################
+# Ensure these variables are set for bootstrap
+################################################################################
+# openshift_deployment_type is required for installation
+openshift_deployment_type=origin
+
+# required when building an AMI. This will
+# be dependent on the version provided by the yum repository
+openshift_pkg_version=-3.6.0
+
+openshift_master_bootstrap_enabled=True
+
+openshift_hosted_router_wait=False
+openshift_hosted_registry_wait=False
+
+# Repository for installation
+openshift_additional_repos=[{'name': 'openshift-repo', 'id': 'openshift-repo', 'baseurl': 'https://mirror.openshift.com/enterprise/enterprise-3.6/latest/x86_64/os/', 'enabled': 'yes', 'gpgcheck': 0, 'sslverify': 'no', 'sslclientcert': '/var/lib/yum/client-cert.pem', 'sslclientkey': '/var/lib/yum/client-key.pem', 'gpgkey': 'https://mirror.ops.rhcloud.com/libra/keys/RPM-GPG-KEY-redhat-release https://mirror.ops.rhcloud.com/libra/keys/RPM-GPG-KEY-redhat-beta https://mirror.ops.rhcloud.com/libra/keys/RPM-GPG-KEY-redhat-openshifthosted'}]
+
+################################################################################
+# cluster specific settings maybe be placed here
+
+[masters]
+
+[etcd]
+
+[nodes]
+```
+
+There are more examples of cluster inventory settings [`here`](../../inventory/byo/).
+
+#### Step 1
+
+Once the `inventory` and the `provisioning_vars.yml` file has been updated with the correct settings for the desired AWS account then we are ready to build an AMI.
+
+```
+$ ansible-playbook -i inventory.yml build_ami.yml -e @provisioning_vars.yml
+```
+
+1. This script will build a VPC. Default name will be clusterid if not specified.
+2. Create an ssh key required for the instance.
+3. Create a security group.
+4. Create an instance using the key from step 2 or a specified key.
+5. Run openshift-ansible setup roles to ensure packages and services are correctly configured.
+6. Create the AMI.
+7. If encryption is desired
+ - A KMS key is created with the name of $clusterid
+ - An encrypted AMI will be produced with $clusterid KMS key
+8. Terminate the instance used to configure the AMI.
+
+More AMI specific options can be found in ['openshift_aws/defaults/main.yml'](../../roles/openshift_aws/defaults/main.yml). When creating an encrypted AMI please specify use_encryption:
+```
+# openshift_aws_ami_encrypt: True # defaults to false
+```
+
+**Note**: This will ensure to take the recently created AMI and encrypt it to be used later. If encryption is not desired then set the value to false (defaults to false). The AMI id will be fetched and used according to its most recent creation date.
+
+#### Step 2
+
+Now that we have created an AMI for our Openshift installation, there are two ways to use the AMI.
+
+1. In the default behavior, the AMI id will be found and used in the last created fashion.
+2. The `openshift_aws_ami` option can be specified. This will allow the user to override the behavior of the role and use a custom AMI specified in the `openshift_aws_ami` variable.
+
+We are now ready to provision and install the cluster. This can be accomplished by calling all of the following steps at once or one-by-one. The all in one can be called like this:
+```
+$ ansible-playbook -i inventory.yml provision_install.yml -e @provisioning_vars.yml
+```
+
+If this is the first time running through this process, please attempt the following steps one-by-one and ensure the setup works correctly.
+
+#### Step 3
+
+We are ready to create the master instances.
+
+```
+$ ansible-playbook provision.yml -e @provisioning_vars.yml
+```
+
+This playbook runs through the following steps:
+1. Ensures a VPC is created.
+2. Ensures a SSH key exists.
+3. Creates an s3 bucket for the registry named $clusterid-docker-registry
+4. Create master security groups.
+5. Create a master launch config.
+6. Create the master auto scaling groups.
+7. If certificates are desired for ELB, they will be uploaded.
+8. Create internal and external master ELBs.
+9. Add newly created masters to the correct groups.
+10. Set a couple of important facts for the masters.
+
+At this point we have successfully created the infrastructure including the master nodes.
+
+#### Step 4
+
+Now it is time to install Openshift using the openshift-ansible installer. This can be achieved by running the following playbook:
+
+```
+$ ansible-playbook -i inventory.yml install.yml @provisioning_vars.yml
+```
+This playbook accomplishes the following:
+1. Builds a dynamic inventory file by querying AWS.
+2. Runs the [`byo`](../../common/openshift-cluster/config.yml)
+
+Once this playbook completes, the cluster masters should be installed and configured.
+
+#### Step 5
+
+Now that we have a cluster deployed it will be more interesting to create some node types. This can be done easily with the following playbook:
+
+```
+$ ansible-playbook provision_nodes.yml -e @provisioning_vars.yml
+```
+
+Once this playbook completes, it should create the compute and infra node scale groups. These nodes will attempt to register themselves to the cluster. These requests must be approved by an administrator.
+
+#### Step 6
+
+To facilitate the node registration process, nodes may be registered by running the following script `accept.yml`. This script can register in a few different ways.
+- approve_all - **Note**: this option is for development and test environments. Security is bypassed
+- nodes - A list of node names that will be accepted into the cluster
+
+```yaml
+ oc_adm_csr:
+ #approve_all: True
+ nodes: < list of nodes here >
+ timeout: 0
+```
+
+Once the desired accept method is chosen, run the following playbook `accept.yml`:
+1. Run the following playbook.
+```
+$ ansible-playbook accept.yml -e @provisioning_vars.yml
+```
+
+Login to a master and run the following command:
+```
+ssh root@<master ip address>
+$ oc --config=/etc/origin/master/admin.kubeconfig get csr
+node-bootstrapper-client-ip-172-31-49-148-ec2-internal 1h system:serviceaccount:openshift-infra:node-bootstrapper Approved,Issued
+node-bootstrapper-server-ip-172-31-49-148-ec2-internal 1h system:node:ip-172-31-49-148.ec2.internal Approved,Issued
+```
+
+Verify the `CONDITION` is `Approved,Issued` on the `csr` objects. There are two for each node required.
+1. `node-bootstrapper-client` is a request to access the api/controllers.
+2. `node-bootstrapper-server` is a request to join the cluster.
+
+Once this is complete, verify the nodes have joined the cluster and are `ready`.
+
+```
+$ oc --config=/etc/origin/master/admin.kubeconfig get nodes
+NAME STATUS AGE VERSION
+ip-172-31-49-148.ec2.internal Ready 1h v1.6.1+5115d708d7
+```
+
+### Ready To Work!
+
+At this point your cluster should be ready for workloads. Proceed to deploy applications on your cluster.
+
+### Still to come
+
+There are more enhancements that are arriving for provisioning. These will include more playbooks that enhance the provisioning capabilities.
diff --git a/playbooks/aws/openshift-cluster/accept.yml b/playbooks/aws/openshift-cluster/accept.yml
new file mode 100755
index 000000000..ffc367f9f
--- /dev/null
+++ b/playbooks/aws/openshift-cluster/accept.yml
@@ -0,0 +1,53 @@
+#!/usr/bin/ansible-playbook
+---
+- name: Setup the vpc and the master node group
+ hosts: localhost
+ remote_user: root
+ gather_facts: no
+ tasks:
+ - name: Alert user to variables needed - clusterid
+ debug:
+ msg: "openshift_aws_clusterid={{ openshift_aws_clusterid | default('default') }}"
+
+ - name: Alert user to variables needed - region
+ debug:
+ msg: "openshift_aws_region={{ openshift_aws_region | default('us-east-1') }}"
+
+ - name: bring lib_openshift into scope
+ include_role:
+ name: lib_openshift
+
+ - name: fetch masters
+ ec2_remote_facts:
+ region: "{{ openshift_aws_region | default('us-east-1') }}"
+ filters:
+ "tag:clusterid": "{{ openshift_aws_clusterid | default('default') }}"
+ "tag:host-type": master
+ instance-state-name: running
+ register: mastersout
+ retries: 20
+ delay: 3
+ until: "'instances' in mastersout and mastersout.instances|length > 0"
+
+ - name: fetch new node instances
+ ec2_remote_facts:
+ region: "{{ openshift_aws_region | default('us-east-1') }}"
+ filters:
+ "tag:clusterid": "{{ openshift_aws_clusterid | default('default') }}"
+ "tag:host-type": node
+ instance-state-name: running
+ register: instancesout
+ retries: 20
+ delay: 3
+ until: "'instances' in instancesout and instancesout.instances|length > 0"
+
+ - debug:
+ msg: "{{ instancesout.instances|map(attribute='private_dns_name') | list | regex_replace('.ec2.internal') }}"
+
+ - name: approve nodes
+ oc_adm_csr:
+ #approve_all: True
+ nodes: "{{ instancesout.instances|map(attribute='private_dns_name') | list | regex_replace('.ec2.internal') }}"
+ timeout: 0
+ register: nodeout
+ delegate_to: "{{ mastersout.instances[0].public_ip_address }}"
diff --git a/playbooks/aws/openshift-cluster/add_nodes.yml b/playbooks/aws/openshift-cluster/add_nodes.yml
deleted file mode 100644
index 0e8eb90c1..000000000
--- a/playbooks/aws/openshift-cluster/add_nodes.yml
+++ /dev/null
@@ -1,35 +0,0 @@
----
-- name: Launch instance(s)
- hosts: localhost
- connection: local
- become: no
- gather_facts: no
- vars_files:
- - vars.yml
- vars:
- oo_extend_env: True
- tasks:
- - include: ../../common/openshift-cluster/tasks/set_node_launch_facts.yml
- vars:
- type: "compute"
- count: "{{ num_nodes }}"
- - include: tasks/launch_instances.yml
- vars:
- instances: "{{ node_names }}"
- cluster: "{{ cluster_id }}"
- type: "{{ k8s_type }}"
- g_sub_host_type: "{{ sub_host_type }}"
-
- - include: ../../common/openshift-cluster/tasks/set_node_launch_facts.yml
- vars:
- type: "infra"
- count: "{{ num_infra }}"
- - include: tasks/launch_instances.yml
- vars:
- instances: "{{ node_names }}"
- cluster: "{{ cluster_id }}"
- type: "{{ k8s_type }}"
- g_sub_host_type: "{{ sub_host_type }}"
-
-- include: scaleup.yml
-- include: list.yml
diff --git a/playbooks/aws/openshift-cluster/build_ami.yml b/playbooks/aws/openshift-cluster/build_ami.yml
new file mode 100644
index 000000000..fc11205d8
--- /dev/null
+++ b/playbooks/aws/openshift-cluster/build_ami.yml
@@ -0,0 +1,78 @@
+---
+- hosts: localhost
+ connection: local
+ gather_facts: no
+ tasks:
+ - name: Require openshift_aws_base_ami
+ fail:
+ msg: "A base AMI is required for AMI building. Please ensure `openshift_aws_base_ami` is defined."
+ when: openshift_aws_base_ami is undefined
+
+ - name: "Alert user to variables needed and their values - {{ item.name }}"
+ debug:
+ msg: "{{ item.msg }}"
+ with_items:
+ - name: openshift_aws_clusterid
+ msg: "openshift_aws_clusterid={{ openshift_aws_clusterid | default('default') }}"
+ - name: openshift_aws_region
+ msg: "openshift_aws_region={{ openshift_aws_region | default('us-east-1') }}"
+
+ - name: create an instance and prepare for ami
+ include_role:
+ name: openshift_aws
+ tasks_from: build_ami.yml
+ vars:
+ openshift_aws_node_group_type: compute
+
+ - name: fetch newly created instances
+ ec2_remote_facts:
+ region: "{{ openshift_aws_region | default('us-east-1') }}"
+ filters:
+ "tag:Name": "{{ openshift_aws_base_ami_name | default('ami_base') }}"
+ instance-state-name: running
+ register: instancesout
+ retries: 20
+ delay: 3
+ until: instancesout.instances|length > 0
+
+ - name: wait for ssh to become available
+ wait_for:
+ port: 22
+ host: "{{ instancesout.instances[0].public_ip_address }}"
+ timeout: 300
+ search_regex: OpenSSH
+
+ - name: add host to nodes
+ add_host:
+ groups: nodes
+ name: "{{ instancesout.instances[0].public_dns_name }}"
+
+ - name: set the user to perform installation
+ set_fact:
+ ansible_ssh_user: root
+
+- name: normalize groups
+ include: ../../byo/openshift-cluster/initialize_groups.yml
+
+- name: run the std_include
+ include: ../../common/openshift-cluster/evaluate_groups.yml
+
+- name: run the std_include
+ include: ../../common/openshift-cluster/initialize_facts.yml
+
+- name: run the std_include
+ include: ../../common/openshift-cluster/initialize_openshift_repos.yml
+
+- name: install node config
+ include: ../../common/openshift-node/config.yml
+
+- hosts: localhost
+ connection: local
+ become: no
+ tasks:
+ - name: seal the ami
+ include_role:
+ name: openshift_aws
+ tasks_from: seal_ami.yml
+ vars:
+ openshift_aws_ami_name: "openshift-gi-{{ lookup('pipe', 'date +%Y%m%d%H%M')}}"
diff --git a/playbooks/aws/openshift-cluster/cluster_hosts.yml b/playbooks/aws/openshift-cluster/cluster_hosts.yml
deleted file mode 100644
index c2f4dfedc..000000000
--- a/playbooks/aws/openshift-cluster/cluster_hosts.yml
+++ /dev/null
@@ -1,25 +0,0 @@
----
-g_all_hosts: "{{ groups['tag_clusterid_' ~ cluster_id] | default([])
- | intersect(groups['tag_environment_' ~ cluster_env] | default([])) }}"
-
-g_etcd_hosts: "{{ g_all_hosts | intersect(groups['tag_host-type_etcd'] | default([])) }}"
-
-g_new_etcd_hosts: "{{ g_all_hosts | intersect(groups['tag_host-type_new_etcd'] | default([])) }}"
-
-g_lb_hosts: "{{ g_all_hosts | intersect(groups['tag_host-type_lb'] | default([])) }}"
-
-g_nfs_hosts: "{{ g_all_hosts | intersect(groups['tag_host-type_nfs'] | default([])) }}"
-
-g_glusterfs_hosts: "{{ g_all_hosts | intersect(groups['tag_host-type-glusterfs'] | default([])) }}"
-
-g_master_hosts: "{{ g_all_hosts | intersect(groups['tag_host-type_master'] | default([])) }}"
-
-g_new_master_hosts: "{{ g_all_hosts | intersect(groups['tag_host-type_new_master'] | default([])) }}"
-
-g_node_hosts: "{{ g_all_hosts | intersect(groups['tag_host-type_node'] | default([])) }}"
-
-g_new_node_hosts: "{{ g_all_hosts | intersect(groups['tag_host-type_new_node'] | default([])) }}"
-
-g_infra_hosts: "{{ g_node_hosts | intersect(groups['tag_sub-host-type_infra'] | default([])) }}"
-
-g_compute_hosts: "{{ g_node_hosts | intersect(groups['tag_sub-host-type_compute'] | default([])) }}"
diff --git a/playbooks/aws/openshift-cluster/config.yml b/playbooks/aws/openshift-cluster/config.yml
deleted file mode 100644
index 821a0f30e..000000000
--- a/playbooks/aws/openshift-cluster/config.yml
+++ /dev/null
@@ -1,37 +0,0 @@
----
-- hosts: localhost
- gather_facts: no
- tasks:
- - include_vars: vars.yml
- - include_vars: cluster_hosts.yml
- - add_host:
- name: "{{ item }}"
- groups: l_oo_all_hosts
- with_items: "{{ g_all_hosts | default([]) }}"
-
-- hosts: l_oo_all_hosts
- gather_facts: no
- tasks:
- - include_vars: vars.yml
- - include_vars: cluster_hosts.yml
-
-- include: ../../common/openshift-cluster/config.yml
- vars:
- g_ssh_user: "{{ deployment_vars[deployment_type].ssh_user }}"
- g_sudo: "{{ deployment_vars[deployment_type].become }}"
- g_nodeonmaster: true
- openshift_cluster_id: "{{ cluster_id }}"
- openshift_debug_level: "{{ debug_level }}"
- openshift_deployment_type: "{{ deployment_type }}"
- openshift_public_hostname: "{{ ec2_ip_address }}"
- openshift_hosted_registry_selector: 'type=infra'
- openshift_hosted_router_selector: 'type=infra'
- openshift_node_labels:
- region: "{{ deployment_vars[deployment_type].region }}"
- type: "{{ hostvars[inventory_hostname]['ec2_tag_sub-host-type'] }}"
- openshift_master_cluster_method: 'native'
- openshift_use_openshift_sdn: "{{ lookup('oo_option', 'use_openshift_sdn') }}"
- os_sdn_network_plugin_name: "{{ lookup('oo_option', 'sdn_network_plugin_name') }}"
- openshift_use_flannel: "{{ lookup('oo_option', 'use_flannel') }}"
- openshift_use_calico: "{{ lookup('oo_option', 'use_calico') }}"
- openshift_use_fluentd: "{{ lookup('oo_option', 'use_fluentd') }}"
diff --git a/playbooks/aws/openshift-cluster/install.yml b/playbooks/aws/openshift-cluster/install.yml
new file mode 100644
index 000000000..86d58a68e
--- /dev/null
+++ b/playbooks/aws/openshift-cluster/install.yml
@@ -0,0 +1,74 @@
+---
+- name: Setup the vpc and the master node group
+ hosts: localhost
+ tasks:
+ - name: Alert user to variables needed - clusterid
+ debug:
+ msg: "openshift_aws_clusterid={{ openshift_aws_clusterid | default('default') }}"
+
+ - name: Alert user to variables needed - region
+ debug:
+ msg: "openshift_aws_region={{ openshift_aws_region | default('us-east-1') }}"
+
+ - name: fetch newly created instances
+ ec2_remote_facts:
+ region: "{{ openshift_aws_region | default('us-east-1') }}"
+ filters:
+ "tag:clusterid": "{{ openshift_aws_clusterid | default('default') }}"
+ "tag:host-type": master
+ instance-state-name: running
+ register: instancesout
+ retries: 20
+ delay: 3
+ until: instancesout.instances|length > 0
+
+ - name: add new master to masters group
+ add_host:
+ groups: "masters,etcd,nodes"
+ name: "{{ item.public_ip_address }}"
+ hostname: "{{ openshift_aws_clusterid | default('default') }}-master-{{ item.id[:-5] }}"
+ with_items: "{{ instancesout.instances }}"
+
+ - name: wait for ssh to become available
+ wait_for:
+ port: 22
+ host: "{{ item.public_ip_address }}"
+ timeout: 300
+ search_regex: OpenSSH
+ with_items: "{{ instancesout.instances }}"
+
+- name: set the master facts for hostname to elb
+ hosts: masters
+ gather_facts: no
+ remote_user: root
+ tasks:
+ - name: fetch elbs
+ ec2_elb_facts:
+ region: "{{ openshift_aws_region | default('us-east-1') }}"
+ names:
+ - "{{ item }}"
+ with_items:
+ - "{{ openshift_aws_clusterid | default('default') }}-master-external"
+ - "{{ openshift_aws_clusterid | default('default') }}-master-internal"
+ delegate_to: localhost
+ register: elbs
+
+ - debug: var=elbs
+
+ - name: set fact
+ set_fact:
+ openshift_master_cluster_hostname: "{{ elbs.results[1].elbs[0].dns_name }}"
+ osm_custom_cors_origins:
+ - "{{ elbs.results[1].elbs[0].dns_name }}"
+ - "console.{{ openshift_aws_clusterid | default('default') }}.openshift.com"
+ - "api.{{ openshift_aws_clusterid | default('default') }}.openshift.com"
+ with_items: "{{ groups['masters'] }}"
+
+- name: normalize groups
+ include: ../../byo/openshift-cluster/initialize_groups.yml
+
+- name: run the std_include
+ include: ../../common/openshift-cluster/std_include.yml
+
+- name: run the config
+ include: ../../common/openshift-cluster/config.yml
diff --git a/playbooks/aws/openshift-cluster/launch.yml b/playbooks/aws/openshift-cluster/launch.yml
deleted file mode 100644
index 3edace493..000000000
--- a/playbooks/aws/openshift-cluster/launch.yml
+++ /dev/null
@@ -1,54 +0,0 @@
----
-- name: Launch instance(s)
- hosts: localhost
- connection: local
- become: no
- gather_facts: no
- vars_files:
- - vars.yml
- tasks:
- - include: ../../common/openshift-cluster/tasks/set_etcd_launch_facts.yml
- - include: tasks/launch_instances.yml
- vars:
- instances: "{{ etcd_names }}"
- cluster: "{{ cluster_id }}"
- type: "{{ k8s_type }}"
- g_sub_host_type: "default"
-
- - include: ../../common/openshift-cluster/tasks/set_master_launch_facts.yml
- - include: tasks/launch_instances.yml
- vars:
- instances: "{{ master_names }}"
- cluster: "{{ cluster_id }}"
- type: "{{ k8s_type }}"
- g_sub_host_type: "default"
-
- - include: ../../common/openshift-cluster/tasks/set_node_launch_facts.yml
- vars:
- type: "compute"
- count: "{{ num_nodes }}"
- - include: tasks/launch_instances.yml
- vars:
- instances: "{{ node_names }}"
- cluster: "{{ cluster_id }}"
- type: "{{ k8s_type }}"
- g_sub_host_type: "{{ sub_host_type }}"
-
- - include: ../../common/openshift-cluster/tasks/set_node_launch_facts.yml
- vars:
- type: "infra"
- count: "{{ num_infra }}"
- - include: tasks/launch_instances.yml
- vars:
- instances: "{{ node_names }}"
- cluster: "{{ cluster_id }}"
- type: "{{ k8s_type }}"
- g_sub_host_type: "{{ sub_host_type }}"
-
- - add_host:
- name: "{{ master_names.0 }}"
- groups: service_master
- when: master_names is defined and master_names.0 is defined
-
-- include: update.yml
-- include: list.yml
diff --git a/playbooks/aws/openshift-cluster/library/ec2_ami_find.py b/playbooks/aws/openshift-cluster/library/ec2_ami_find.py
deleted file mode 100644
index 99d0f44f0..000000000
--- a/playbooks/aws/openshift-cluster/library/ec2_ami_find.py
+++ /dev/null
@@ -1,303 +0,0 @@
-#!/usr/bin/python
-#pylint: skip-file
-# flake8: noqa
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
-
-DOCUMENTATION = '''
----
-module: ec2_ami_find
-version_added: 2.0
-short_description: Searches for AMIs to obtain the AMI ID and other information
-description:
- - Returns list of matching AMIs with AMI ID, along with other useful information
- - Can search AMIs with different owners
- - Can search by matching tag(s), by AMI name and/or other criteria
- - Results can be sorted and sliced
-author: Tom Bamford
-notes:
- - This module is not backwards compatible with the previous version of the ec2_search_ami module which worked only for Ubuntu AMIs listed on cloud-images.ubuntu.com.
- - See the example below for a suggestion of how to search by distro/release.
-options:
- region:
- description:
- - The AWS region to use.
- required: true
- aliases: [ 'aws_region', 'ec2_region' ]
- owner:
- description:
- - Search AMIs owned by the specified owner
- - Can specify an AWS account ID, or one of the special IDs 'self', 'amazon' or 'aws-marketplace'
- - If not specified, all EC2 AMIs in the specified region will be searched.
- - You can include wildcards in many of the search options. An asterisk (*) matches zero or more characters, and a question mark (?) matches exactly one character. You can escape special characters using a backslash (\) before the character. For example, a value of \*amazon\?\\ searches for the literal string *amazon?\.
- required: false
- default: null
- ami_id:
- description:
- - An AMI ID to match.
- default: null
- required: false
- ami_tags:
- description:
- - A hash/dictionary of tags to match for the AMI.
- default: null
- required: false
- architecture:
- description:
- - An architecture type to match (e.g. x86_64).
- default: null
- required: false
- hypervisor:
- description:
- - A hypervisor type type to match (e.g. xen).
- default: null
- required: false
- is_public:
- description:
- - Whether or not the image(s) are public.
- choices: ['yes', 'no']
- default: null
- required: false
- name:
- description:
- - An AMI name to match.
- default: null
- required: false
- platform:
- description:
- - Platform type to match.
- default: null
- required: false
- sort:
- description:
- - Optional attribute which with to sort the results.
- - If specifying 'tag', the 'tag_name' parameter is required.
- choices: ['name', 'description', 'tag']
- default: null
- required: false
- sort_tag:
- description:
- - Tag name with which to sort results.
- - Required when specifying 'sort=tag'.
- default: null
- required: false
- sort_order:
- description:
- - Order in which to sort results.
- - Only used when the 'sort' parameter is specified.
- choices: ['ascending', 'descending']
- default: 'ascending'
- required: false
- sort_start:
- description:
- - Which result to start with (when sorting).
- - Corresponds to Python slice notation.
- default: null
- required: false
- sort_end:
- description:
- - Which result to end with (when sorting).
- - Corresponds to Python slice notation.
- default: null
- required: false
- state:
- description:
- - AMI state to match.
- default: 'available'
- required: false
- virtualization_type:
- description:
- - Virtualization type to match (e.g. hvm).
- default: null
- required: false
- no_result_action:
- description:
- - What to do when no results are found.
- - "'success' reports success and returns an empty array"
- - "'fail' causes the module to report failure"
- choices: ['success', 'fail']
- default: 'success'
- required: false
-requirements:
- - boto
-
-'''
-
-EXAMPLES = '''
-# Note: These examples do not set authentication details, see the AWS Guide for details.
-
-# Search for the AMI tagged "project:website"
-- ec2_ami_find:
- owner: self
- tags:
- project: website
- no_result_action: fail
- register: ami_find
-
-# Search for the latest Ubuntu 14.04 AMI
-- ec2_ami_find:
- name: "ubuntu/images/ebs/ubuntu-trusty-14.04-amd64-server-*"
- owner: 099720109477
- sort: name
- sort_order: descending
- sort_end: 1
- register: ami_find
-
-# Launch an EC2 instance
-- ec2:
- image: "{{ ami_search.results[0].ami_id }}"
- instance_type: m4.medium
- key_name: mykey
- wait: yes
-'''
-
-try:
- import boto.ec2
- HAS_BOTO=True
-except ImportError:
- HAS_BOTO=False
-
-import json
-
-def main():
- argument_spec = ec2_argument_spec()
- argument_spec.update(dict(
- region = dict(required=True,
- aliases = ['aws_region', 'ec2_region']),
- owner = dict(required=False, default=None),
- ami_id = dict(required=False),
- ami_tags = dict(required=False, type='dict',
- aliases = ['search_tags', 'image_tags']),
- architecture = dict(required=False),
- hypervisor = dict(required=False),
- is_public = dict(required=False),
- name = dict(required=False),
- platform = dict(required=False),
- sort = dict(required=False, default=None,
- choices=['name', 'description', 'tag']),
- sort_tag = dict(required=False),
- sort_order = dict(required=False, default='ascending',
- choices=['ascending', 'descending']),
- sort_start = dict(required=False),
- sort_end = dict(required=False),
- state = dict(required=False, default='available'),
- virtualization_type = dict(required=False),
- no_result_action = dict(required=False, default='success',
- choices = ['success', 'fail']),
- )
- )
-
- module = AnsibleModule(
- argument_spec=argument_spec,
- )
-
- if not HAS_BOTO:
- module.fail_json(msg='boto required for this module, install via pip or your package manager')
-
- ami_id = module.params.get('ami_id')
- ami_tags = module.params.get('ami_tags')
- architecture = module.params.get('architecture')
- hypervisor = module.params.get('hypervisor')
- is_public = module.params.get('is_public')
- name = module.params.get('name')
- owner = module.params.get('owner')
- platform = module.params.get('platform')
- sort = module.params.get('sort')
- sort_tag = module.params.get('sort_tag')
- sort_order = module.params.get('sort_order')
- sort_start = module.params.get('sort_start')
- sort_end = module.params.get('sort_end')
- state = module.params.get('state')
- virtualization_type = module.params.get('virtualization_type')
- no_result_action = module.params.get('no_result_action')
-
- filter = {'state': state}
-
- if ami_id:
- filter['image_id'] = ami_id
- if ami_tags:
- for tag in ami_tags:
- filter['tag:'+tag] = ami_tags[tag]
- if architecture:
- filter['architecture'] = architecture
- if hypervisor:
- filter['hypervisor'] = hypervisor
- if is_public:
- filter['is_public'] = is_public
- if name:
- filter['name'] = name
- if platform:
- filter['platform'] = platform
- if virtualization_type:
- filter['virtualization_type'] = virtualization_type
-
- ec2 = ec2_connect(module)
-
- images_result = ec2.get_all_images(owners=owner, filters=filter)
-
- if no_result_action == 'fail' and len(images_result) == 0:
- module.fail_json(msg="No AMIs matched the attributes: %s" % json.dumps(filter))
-
- results = []
- for image in images_result:
- data = {
- 'ami_id': image.id,
- 'architecture': image.architecture,
- 'description': image.description,
- 'is_public': image.is_public,
- 'name': image.name,
- 'owner_id': image.owner_id,
- 'platform': image.platform,
- 'root_device_name': image.root_device_name,
- 'root_device_type': image.root_device_type,
- 'state': image.state,
- 'tags': image.tags,
- 'virtualization_type': image.virtualization_type,
- }
-
- if image.kernel_id:
- data['kernel_id'] = image.kernel_id
- if image.ramdisk_id:
- data['ramdisk_id'] = image.ramdisk_id
-
- results.append(data)
-
- if sort == 'tag':
- if not sort_tag:
- module.fail_json(msg="'sort_tag' option must be given with 'sort=tag'")
- results.sort(key=lambda e: e['tags'][sort_tag], reverse=(sort_order=='descending'))
- elif sort:
- results.sort(key=lambda e: e[sort], reverse=(sort_order=='descending'))
-
- try:
- if sort and sort_start and sort_end:
- results = results[int(sort_start):int(sort_end)]
- elif sort and sort_start:
- results = results[int(sort_start):]
- elif sort and sort_end:
- results = results[:int(sort_end)]
- except TypeError:
- module.fail_json(msg="Please supply numeric values for sort_start and/or sort_end")
-
- module.exit_json(results=results)
-
-# import module snippets
-from ansible.module_utils.basic import *
-from ansible.module_utils.ec2 import *
-
-if __name__ == '__main__':
- main()
-
diff --git a/playbooks/aws/openshift-cluster/list.yml b/playbooks/aws/openshift-cluster/list.yml
deleted file mode 100644
index ed8aac398..000000000
--- a/playbooks/aws/openshift-cluster/list.yml
+++ /dev/null
@@ -1,23 +0,0 @@
----
-- name: Generate oo_list_hosts group
- hosts: localhost
- gather_facts: no
- connection: local
- become: no
- vars_files:
- - vars.yml
- tasks:
- - set_fact: scratch_group=tag_clusterid_{{ cluster_id }}
- when: cluster_id != ''
- - set_fact: scratch_group=all
- when: cluster_id == ''
- - add_host:
- name: "{{ item }}"
- groups: oo_list_hosts
- ansible_ssh_user: "{{ deployment_vars[deployment_type].ssh_user }}"
- ansible_become: "{{ deployment_vars[deployment_type].become }}"
- oo_public_ipv4: "{{ hostvars[item].ec2_ip_address }}"
- oo_private_ipv4: "{{ hostvars[item].ec2_private_ip_address }}"
- with_items: "{{ groups[scratch_group] | default([]) | difference(['localhost']) }}"
- - debug:
- msg: "{{ hostvars | oo_select_keys(groups[scratch_group] | default([])) | oo_pretty_print_cluster }}"
diff --git a/playbooks/aws/openshift-cluster/provision.yml b/playbooks/aws/openshift-cluster/provision.yml
new file mode 100644
index 000000000..db7afac6f
--- /dev/null
+++ b/playbooks/aws/openshift-cluster/provision.yml
@@ -0,0 +1,17 @@
+---
+- name: Setup the vpc and the master node group
+ hosts: localhost
+ tasks:
+
+ - name: Alert user to variables needed - clusterid
+ debug:
+ msg: "openshift_aws_clusterid={{ openshift_aws_clusterid | default('default') }}"
+
+ - name: Alert user to variables needed - region
+ debug:
+ msg: "openshift_aws_region={{ openshift_aws_region | default('us-east-1') }}"
+
+ - name: create default vpc
+ include_role:
+ name: openshift_aws
+ tasks_from: provision.yml
diff --git a/playbooks/aws/openshift-cluster/provision_install.yml b/playbooks/aws/openshift-cluster/provision_install.yml
new file mode 100644
index 000000000..e787deced
--- /dev/null
+++ b/playbooks/aws/openshift-cluster/provision_install.yml
@@ -0,0 +1,16 @@
+---
+# Once an AMI is built then this script is used for
+# the one stop shop to provision and install a cluster
+# this playbook is run with the following parameters:
+# ansible-playbook -i openshift-ansible-inventory provision_install.yml
+- name: Include the provision.yml playbook to create cluster
+ include: provision.yml
+
+- name: Include the install.yml playbook to install cluster
+ include: install.yml
+
+- name: Include the install.yml playbook to install cluster
+ include: provision_nodes.yml
+
+- name: Include the accept.yml playbook to accept nodes into the cluster
+ include: accept.yml
diff --git a/playbooks/aws/openshift-cluster/provision_nodes.yml b/playbooks/aws/openshift-cluster/provision_nodes.yml
new file mode 100644
index 000000000..44c686e08
--- /dev/null
+++ b/playbooks/aws/openshift-cluster/provision_nodes.yml
@@ -0,0 +1,18 @@
+---
+- name: create the node scale groups
+ hosts: localhost
+ connection: local
+ gather_facts: yes
+ tasks:
+ - name: Alert user to variables needed - clusterid
+ debug:
+ msg: "openshift_aws_clusterid={{ openshift_aws_clusterid | default('default') }}"
+
+ - name: Alert user to variables needed - region
+ debug:
+ msg: "openshift_aws_region={{ openshift_aws_region | default('us-east-1') }}"
+
+ - name: create the node groups
+ include_role:
+ name: openshift_aws
+ tasks_from: provision_nodes.yml
diff --git a/playbooks/aws/openshift-cluster/provisioning_vars.example.yml b/playbooks/aws/openshift-cluster/provisioning_vars.example.yml
new file mode 100644
index 000000000..28eb9c993
--- /dev/null
+++ b/playbooks/aws/openshift-cluster/provisioning_vars.example.yml
@@ -0,0 +1,28 @@
+---
+# when creating an AMI set this option to True
+# when installing the cluster, set this to False
+openshift_node_bootstrap: True
+
+# specify a clusterid
+#openshift_aws_clusterid: default
+
+# must specify a base_ami when building an AMI
+#openshift_aws_base_ami:
+
+# when creating an encrypted AMI please specify use_encryption
+#openshift_aws_ami_encrypt: False
+
+# custom certificates are required for the ELB
+#openshift_aws_iam_cert_path: '/path/to/wildcard.<clusterid>.example.com.crt'
+#openshift_aws_iam_key_path: '/path/to/wildcard.<clusterid>.example.com.key'
+#openshift_aws_iam_cert_chain_path: '/path/to/cert.ca.crt'
+
+# This is required for any ec2 instances
+#openshift_aws_ssh_key_name: myuser_key
+
+# This will ensure these users are created
+#openshift_aws_users:
+#- key_name: myuser_key
+# username: myuser
+# pub_key: |
+# ssh-rsa AAAA
diff --git a/playbooks/aws/openshift-cluster/scaleup.yml b/playbooks/aws/openshift-cluster/scaleup.yml
deleted file mode 100644
index 6fa9142a0..000000000
--- a/playbooks/aws/openshift-cluster/scaleup.yml
+++ /dev/null
@@ -1,32 +0,0 @@
----
-
-- hosts: localhost
- gather_facts: no
- connection: local
- become: no
- vars_files:
- - vars.yml
- tasks:
- - name: Evaluate oo_hosts_to_update
- add_host:
- name: "{{ item }}"
- groups: oo_hosts_to_update
- ansible_ssh_user: "{{ deployment_vars[deployment_type].ssh_user }}"
- ansible_become: "{{ deployment_vars[deployment_type].become }}"
- with_items: "{{ groups.nodes_to_add }}"
-
-- include: ../../common/openshift-cluster/update_repos_and_packages.yml
-
-- include: ../../common/openshift-cluster/scaleup.yml
- vars_files:
- - ../../aws/openshift-cluster/vars.yml
- - ../../aws/openshift-cluster/cluster_hosts.yml
- vars:
- g_new_node_hosts: "{{ groups.nodes_to_add }}"
- g_ssh_user: "{{ deployment_vars[deployment_type].ssh_user }}"
- g_sudo: "{{ deployment_vars[deployment_type].become }}"
- g_nodeonmaster: true
- openshift_cluster_id: "{{ cluster_id }}"
- openshift_debug_level: "{{ debug_level }}"
- openshift_deployment_type: "{{ deployment_type }}"
- openshift_public_hostname: "{{ ec2_ip_address }}"
diff --git a/playbooks/aws/openshift-cluster/service.yml b/playbooks/aws/openshift-cluster/service.yml
deleted file mode 100644
index f7f4812bb..000000000
--- a/playbooks/aws/openshift-cluster/service.yml
+++ /dev/null
@@ -1,31 +0,0 @@
----
-- name: Call same systemctl command for openshift on all instance(s)
- hosts: localhost
- connection: local
- become: no
- gather_facts: no
- vars_files:
- - vars.yml
- - cluster_hosts.yml
- tasks:
- - fail: msg="cluster_id is required to be injected in this playbook"
- when: cluster_id is not defined
-
- - name: Evaluate g_service_masters
- add_host:
- name: "{{ item }}"
- groups: g_service_masters
- ansible_ssh_user: "{{ deployment_vars[deployment_type].ssh_user }}"
- ansible_become: "{{ deployment_vars[deployment_type].become }}"
- with_items: "{{ master_hosts | default([]) }}"
-
- - name: Evaluate g_service_nodes
- add_host:
- name: "{{ item }}"
- groups: g_service_nodes
- ansible_ssh_user: "{{ deployment_vars[deployment_type].ssh_user }}"
- ansible_become: "{{ deployment_vars[deployment_type].become }}"
- with_items: "{{ node_hosts | default([]) }}"
-
-- include: ../../common/openshift-node/service.yml
-- include: ../../common/openshift-master/service.yml
diff --git a/playbooks/aws/openshift-cluster/tasks/launch_instances.yml b/playbooks/aws/openshift-cluster/tasks/launch_instances.yml
deleted file mode 100644
index 608512b79..000000000
--- a/playbooks/aws/openshift-cluster/tasks/launch_instances.yml
+++ /dev/null
@@ -1,188 +0,0 @@
----
-- set_fact:
- created_by: "{{ lookup('env', 'LOGNAME')|default(cluster, true) }}"
- docker_vol_ephemeral: "{{ lookup('env', 'os_docker_vol_ephemeral') | default(false, true) }}"
- cluster: "{{ cluster_id }}"
- env: "{{ cluster_env }}"
- host_type: "{{ type }}"
- sub_host_type: "{{ g_sub_host_type }}"
-
-- set_fact:
- ec2_instance_type: "{{ lookup('env', 'ec2_master_instance_type') | default(deployment_vars[deployment_type].type, true) }}"
- ec2_security_groups: "{{ lookup('env', 'ec2_master_security_groups') | default(deployment_vars[deployment_type].security_groups, true) }}"
- when: host_type == "master" and sub_host_type == "default"
-
-- set_fact:
- ec2_instance_type: "{{ lookup('env', 'ec2_etcd_instance_type') | default(deployment_vars[deployment_type].type, true) }}"
- ec2_security_groups: "{{ lookup('env', 'ec2_etcd_security_groups') | default(deployment_vars[deployment_type].security_groups, true) }}"
- when: host_type == "etcd" and sub_host_type == "default"
-
-- set_fact:
- ec2_instance_type: "{{ lookup('env', 'ec2_infra_instance_type') | default(deployment_vars[deployment_type].type, true) }}"
- ec2_security_groups: "{{ lookup('env', 'ec2_infra_security_groups') | default(deployment_vars[deployment_type].security_groups, true) }}"
- when: host_type == "node" and sub_host_type == "infra"
-
-- set_fact:
- ec2_instance_type: "{{ lookup('env', 'ec2_node_instance_type') | default(deployment_vars[deployment_type].type, true) }}"
- ec2_security_groups: "{{ lookup('env', 'ec2_node_security_groups') | default(deployment_vars[deployment_type].security_groups, true) }}"
- when: host_type == "node" and sub_host_type == "compute"
-
-- set_fact:
- ec2_instance_type: "{{ deployment_vars[deployment_type].type }}"
- when: ec2_instance_type is not defined
-- set_fact:
- ec2_security_groups: "{{ deployment_vars[deployment_type].security_groups }}"
- when: ec2_security_groups is not defined
-
-- name: Find amis for deployment_type
- ec2_ami_find:
- region: "{{ deployment_vars[deployment_type].region }}"
- ami_id: "{{ deployment_vars[deployment_type].image }}"
- name: "{{ deployment_vars[deployment_type].image_name }}"
- register: ami_result
-
-- fail: msg="Could not find requested ami"
- when: not ami_result.results
-
-- set_fact:
- latest_ami: "{{ ami_result.results | oo_ami_selector(deployment_vars[deployment_type].image_name) }}"
- volume_defs:
- etcd:
- root:
- volume_size: "{{ lookup('env', 'os_etcd_root_vol_size') | default(25, true) }}"
- device_type: "{{ lookup('env', 'os_etcd_root_vol_type') | default('gp2', true) }}"
- iops: "{{ lookup('env', 'os_etcd_root_vol_iops') | default(500, true) }}"
- master:
- root:
- volume_size: "{{ lookup('env', 'os_master_root_vol_size') | default(25, true) }}"
- device_type: "{{ lookup('env', 'os_master_root_vol_type') | default('gp2', true) }}"
- iops: "{{ lookup('env', 'os_master_root_vol_iops') | default(500, true) }}"
- docker:
- volume_size: "{{ lookup('env', 'os_docker_vol_size') | default(10, true) }}"
- device_type: "{{ lookup('env', 'os_docker_vol_type') | default('gp2', true) }}"
- iops: "{{ lookup('env', 'os_docker_vol_iops') | default(500, true) }}"
- node:
- root:
- volume_size: "{{ lookup('env', 'os_node_root_vol_size') | default(85, true) }}"
- device_type: "{{ lookup('env', 'os_node_root_vol_type') | default('gp2', true) }}"
- iops: "{{ lookup('env', 'os_node_root_vol_iops') | default(500, true) }}"
- docker:
- volume_size: "{{ lookup('env', 'os_docker_vol_size') | default(32, true) }}"
- device_type: "{{ lookup('env', 'os_docker_vol_type') | default('gp2', true) }}"
- iops: "{{ lookup('env', 'os_docker_vol_iops') | default(500, true) }}"
-
-- set_fact:
- volumes: "{{ volume_defs | oo_ec2_volume_definition(host_type, docker_vol_ephemeral | bool) }}"
-
-- name: Launch instance(s)
- ec2:
- state: present
- region: "{{ deployment_vars[deployment_type].region }}"
- keypair: "{{ deployment_vars[deployment_type].keypair }}"
- group: "{{ deployment_vars[deployment_type].security_groups }}"
- instance_type: "{{ ec2_instance_type }}"
- image: "{{ deployment_vars[deployment_type].image }}"
- count: "{{ instances | length }}"
- vpc_subnet_id: "{{ deployment_vars[deployment_type].vpc_subnet }}"
- assign_public_ip: "{{ deployment_vars[deployment_type].assign_public_ip }}"
- user_data: "{{ lookup('template', '../templates/user_data.j2') }}"
- wait: yes
- instance_tags:
- created-by: "{{ created_by }}"
- clusterid: "{{ cluster }}"
- environment: "{{ cluster_env }}"
- host-type: "{{ host_type }}"
- sub-host-type: "{{ sub_host_type }}"
- volumes: "{{ volumes }}"
- register: ec2
-
-- name: Add Name tag to instances
- ec2_tag: resource={{ item.1.id }} region={{ deployment_vars[deployment_type].region }} state=present
- with_together:
- - "{{ instances }}"
- - "{{ ec2.instances }}"
- args:
- tags:
- Name: "{{ item.0 }}"
-
-- set_fact:
- instance_groups: >
- tag_created-by_{{ created_by }}, tag_clusterid_{{ cluster }},
- tag_environment_{{ cluster_env }}, tag_host-type_{{ host_type }},
- tag_sub-host-type_{{ sub_host_type }}
-
-- set_fact:
- node_label:
- region: "{{ deployment_vars[deployment_type].region }}"
- type: "{{sub_host_type}}"
- when: host_type == "node"
-
-- set_fact:
- node_label:
- region: "{{ deployment_vars[deployment_type].region }}"
- type: "{{host_type}}"
- when: host_type != "node"
-
-- set_fact:
- logrotate:
- - name: syslog
- path: |
- /var/log/cron
- /var/log/maillog
- /var/log/messages
- /var/log/secure
- /var/log/spooler"
- options:
- - daily
- - rotate 7
- - compress
- - sharedscripts
- - missingok
- scripts:
- postrotate: "/bin/kill -HUP `cat /var/run/syslogd.pid 2> /dev/null` 2> /dev/null || true"
-
-- name: Add new instances groups and variables
- add_host:
- hostname: "{{ item.0 }}"
- ansible_ssh_host: "{{ item.1.dns_name }}"
- ansible_ssh_user: "{{ deployment_vars[deployment_type].ssh_user }}"
- ansible_become: "{{ deployment_vars[deployment_type].become }}"
- groups: "{{ instance_groups }}"
- ec2_private_ip_address: "{{ item.1.private_ip }}"
- ec2_ip_address: "{{ item.1.public_ip }}"
- ec2_tag_sub-host-type: "{{ sub_host_type }}"
- openshift_node_labels: "{{ node_label }}"
- logrotate_scripts: "{{ logrotate }}"
- with_together:
- - "{{ instances }}"
- - "{{ ec2.instances }}"
-
-- name: Add new instances to nodes_to_add group if needed
- add_host:
- hostname: "{{ item.0 }}"
- ansible_ssh_host: "{{ item.1.dns_name }}"
- ansible_ssh_user: "{{ deployment_vars[deployment_type].ssh_user }}"
- ansible_become: "{{ deployment_vars[deployment_type].become }}"
- groups: nodes_to_add
- ec2_private_ip_address: "{{ item.1.private_ip }}"
- ec2_ip_address: "{{ item.1.public_ip }}"
- openshift_node_labels: "{{ node_label }}"
- logrotate_scripts: "{{ logrotate }}"
- with_together:
- - "{{ instances }}"
- - "{{ ec2.instances }}"
- when: oo_extend_env is defined and oo_extend_env | bool
-
-- name: Wait for ssh
- wait_for: "port=22 host={{ item.dns_name }}"
- with_items: "{{ ec2.instances }}"
-
-- name: Wait for user setup
- command: "ssh -o StrictHostKeyChecking=no -o PasswordAuthentication=no -o ConnectTimeout=10 -o UserKnownHostsFile=/dev/null {{ hostvars[item.0].ansible_ssh_user }}@{{ item.1.dns_name }} echo {{ hostvars[item.0].ansible_ssh_user }} user is setup"
- register: result
- until: result.rc == 0
- retries: 20
- delay: 10
- with_together:
- - "{{ instances }}"
- - "{{ ec2.instances }}"
diff --git a/playbooks/aws/openshift-cluster/templates/user_data.j2 b/playbooks/aws/openshift-cluster/templates/user_data.j2
deleted file mode 100644
index b1087f9c4..000000000
--- a/playbooks/aws/openshift-cluster/templates/user_data.j2
+++ /dev/null
@@ -1,22 +0,0 @@
-#cloud-config
-{% if type in ['node', 'master'] and 'docker' in volume_defs[type] %}
-mounts:
-- [ xvdb ]
-- [ ephemeral0 ]
-{% endif %}
-
-write_files:
-{% if type in ['node', 'master'] and 'docker' in volume_defs[type] %}
-- content: |
- DEVS=/dev/xvdb
- VG=docker_vg
- path: /etc/sysconfig/docker-storage-setup
- owner: root:root
- permissions: '0644'
-{% endif %}
-{% if deployment_vars[deployment_type].become | bool %}
-- path: /etc/sudoers.d/99-{{ deployment_vars[deployment_type].ssh_user }}-cloud-init-requiretty
- permissions: 440
- content: |
- Defaults:{{ deployment_vars[deployment_type].ssh_user }} !requiretty
-{% endif %}
diff --git a/playbooks/aws/openshift-cluster/terminate.yml b/playbooks/aws/openshift-cluster/terminate.yml
deleted file mode 100644
index 1f15aa4bf..000000000
--- a/playbooks/aws/openshift-cluster/terminate.yml
+++ /dev/null
@@ -1,77 +0,0 @@
----
-- name: Terminate instance(s)
- hosts: localhost
- connection: local
- become: no
- gather_facts: no
- vars_files:
- - vars.yml
- tasks:
- - add_host:
- name: "{{ item }}"
- groups: oo_hosts_to_terminate
- ansible_ssh_user: "{{ deployment_vars[deployment_type].ssh_user }}"
- ansible_become: "{{ deployment_vars[deployment_type].become }}"
- with_items: "{{ (groups['tag_clusterid_' ~ cluster_id] | default([])) | difference(['localhost']) }}"
-
-- name: Unsubscribe VMs
- hosts: oo_hosts_to_terminate
- roles:
- - role: rhel_unsubscribe
- when: deployment_type in ['atomic-enterprise', 'enterprise', 'openshift-enterprise'] and
- ansible_distribution == "RedHat" and
- lookup('oo_option', 'rhel_skip_subscription') | default(rhsub_skip, True) |
- default('no', True) | lower in ['no', 'false']
-
-- name: Terminate instances
- hosts: localhost
- connection: local
- become: no
- gather_facts: no
- tasks:
- - name: Remove tags from instances
- ec2_tag:
- resource: "{{ hostvars[item]['ec2_id'] }}"
- region: "{{ hostvars[item]['ec2_region'] }}"
- state: absent
- tags:
- environment: "{{ hostvars[item]['ec2_tag_environment'] }}"
- clusterid: "{{ hostvars[item]['ec2_tag_clusterid'] }}"
- host-type: "{{ hostvars[item]['ec2_tag_host-type'] }}"
- sub_host_type: "{{ hostvars[item]['ec2_tag_sub-host-type'] }}"
- with_items: "{{ groups.oo_hosts_to_terminate }}"
- when: "'oo_hosts_to_terminate' in groups"
-
- - name: Terminate instances
- ec2:
- state: absent
- instance_ids: ["{{ hostvars[item].ec2_id }}"]
- region: "{{ hostvars[item].ec2_region }}"
- ignore_errors: yes
- register: ec2_term
- with_items: "{{ groups.oo_hosts_to_terminate }}"
- when: "'oo_hosts_to_terminate' in groups"
-
- # Fail if any of the instances failed to terminate with an error other
- # than 403 Forbidden
- - fail:
- msg: "Terminating instance {{ item.ec2_id }} failed with message {{ item.msg }}"
- when: "'oo_hosts_to_terminate' in groups and item.has_key('failed') and item.failed"
- with_items: "{{ ec2_term.results }}"
-
- - name: Stop instance if termination failed
- ec2:
- state: stopped
- instance_ids: ["{{ item.item.ec2_id }}"]
- region: "{{ item.item.ec2_region }}"
- register: ec2_stop
- when: "'oo_hosts_to_terminate' in groups and item.has_key('failed') and item.failed"
- with_items: "{{ ec2_term.results }}"
-
- - name: Rename stopped instances
- ec2_tag: resource={{ item.item.item.ec2_id }} region={{ item.item.item.ec2_region }} state=present
- args:
- tags:
- Name: "{{ item.item.item.ec2_tag_Name }}-terminate"
- with_items: "{{ ec2_stop.results }}"
- when: ec2_stop | changed
diff --git a/playbooks/aws/openshift-cluster/update.yml b/playbooks/aws/openshift-cluster/update.yml
deleted file mode 100644
index ed05d61ed..000000000
--- a/playbooks/aws/openshift-cluster/update.yml
+++ /dev/null
@@ -1,34 +0,0 @@
----
-- hosts: localhost
- gather_facts: no
- tasks:
- - include_vars: vars.yml
- - include_vars: cluster_hosts.yml
- - add_host:
- name: "{{ item }}"
- groups: l_oo_all_hosts
- with_items: "{{ g_all_hosts }}"
-
-- hosts: l_oo_all_hosts
- gather_facts: no
- tasks:
- - include_vars: vars.yml
- - include_vars: cluster_hosts.yml
-
-- name: Update - Populate oo_hosts_to_update group
- hosts: localhost
- connection: local
- become: no
- gather_facts: no
- tasks:
- - name: Update - Evaluate oo_hosts_to_update
- add_host:
- name: "{{ item }}"
- groups: oo_hosts_to_update
- ansible_ssh_user: "{{ deployment_vars[deployment_type].ssh_user }}"
- ansible_become: "{{ deployment_vars[deployment_type].become }}"
- with_items: "{{ g_all_hosts | default([]) }}"
-
-- include: ../../common/openshift-cluster/update_repos_and_packages.yml
-
-- include: config.yml
diff --git a/playbooks/aws/openshift-cluster/vars.yml b/playbooks/aws/openshift-cluster/vars.yml
deleted file mode 100644
index d774187f0..000000000
--- a/playbooks/aws/openshift-cluster/vars.yml
+++ /dev/null
@@ -1,33 +0,0 @@
----
-debug_level: 2
-
-deployment_rhel7_ent_base:
- # rhel-7.1, requires cloud access subscription
- image: "{{ lookup('oo_option', 'ec2_image') | default('ami-10251c7a', True) }}"
- image_name: "{{ lookup('oo_option', 'ec2_image_name') | default(None, True) }}"
- region: "{{ lookup('oo_option', 'ec2_region') | default('us-east-1', True) }}"
- ssh_user: ec2-user
- become: yes
- keypair: "{{ lookup('oo_option', 'ec2_keypair') | default('libra', True) }}"
- type: "{{ lookup('oo_option', 'ec2_instance_type') | default('m4.large', True) }}"
- security_groups: "{{ lookup('oo_option', 'ec2_security_groups') | default([ 'public' ], True) }}"
- vpc_subnet: "{{ lookup('oo_option', 'ec2_vpc_subnet') | default(omit, True) }}"
- assign_public_ip: "{{ lookup('oo_option', 'ec2_assign_public_ip') | default(omit, True) }}"
-
-deployment_vars:
- origin:
- # centos-7, requires marketplace
- image: "{{ lookup('oo_option', 'ec2_image') | default('ami-6d1c2007', True) }}"
- image_name: "{{ lookup('oo_option', 'ec2_image_name') | default(None, True) }}"
- region: "{{ lookup('oo_option', 'ec2_region') | default('us-east-1', True) }}"
- ssh_user: centos
- become: yes
- keypair: "{{ lookup('oo_option', 'ec2_keypair') | default('libra', True) }}"
- type: "{{ lookup('oo_option', 'ec2_instance_type') | default('m4.large', True) }}"
- security_groups: "{{ lookup('oo_option', 'ec2_security_groups') | default([ 'public' ], True) }}"
- vpc_subnet: "{{ lookup('oo_option', 'ec2_vpc_subnet') | default(omit, True) }}"
- assign_public_ip: "{{ lookup('oo_option', 'ec2_assign_public_ip') | default(omit, True) }}"
-
- enterprise: "{{ deployment_rhel7_ent_base }}"
- openshift-enterprise: "{{ deployment_rhel7_ent_base }}"
- atomic-enterprise: "{{ deployment_rhel7_ent_base }}"
diff --git a/playbooks/byo/openshift-checks/README.md b/playbooks/byo/openshift-checks/README.md
index f0f14b268..b26e7d7ed 100644
--- a/playbooks/byo/openshift-checks/README.md
+++ b/playbooks/byo/openshift-checks/README.md
@@ -7,15 +7,14 @@ Ansible's default operation mode is to fail fast, on the first error. However,
when performing checks, it is useful to gather as much information about
problems as possible in a single run.
-Thus, the playbooks run a battery of checks against the inventory hosts and have
-Ansible gather intermediate errors, giving a more complete diagnostic of the
-state of each host. If any check failed, the playbook run will be marked as
-failed.
+Thus, the playbooks run a battery of checks against the inventory hosts and
+gather intermediate errors, giving a more complete diagnostic of the state of
+each host. If any check failed, the playbook run will be marked as failed.
To facilitate understanding the problems that were encountered, a custom
callback plugin summarizes execution errors at the end of a playbook run.
-# Available playbooks
+## Available playbooks
1. Pre-install playbook ([pre-install.yml](pre-install.yml)) - verifies system
requirements and look for common problems that can prevent a successful
@@ -27,6 +26,10 @@ callback plugin summarizes execution errors at the end of a playbook run.
3. Certificate expiry playbooks ([certificate_expiry](certificate_expiry)) -
check that certificates in use are valid and not expiring soon.
+4. Adhoc playbook ([adhoc.yml](adhoc.yml)) - use it to run adhoc checks or to
+ list existing checks.
+ See the [next section](#the-adhoc-playbook) for a usage example.
+
## Running
With a [recent installation of Ansible](../../../README.md#setup), run the playbook
@@ -59,6 +62,41 @@ against your inventory file. Here is the step-by-step:
$ ansible-playbook -i <inventory file> playbooks/byo/openshift-checks/certificate_expiry/default.yaml -v
```
+### The adhoc playbook
+
+The adhoc playbook gives flexibility to run any check or a custom group of
+checks. What will be run is determined by the `openshift_checks` variable,
+which, among other ways supported by Ansible, can be set on the command line
+using the `-e` flag.
+
+For example, to run the `docker_storage` check:
+
+```console
+$ ansible-playbook -i <inventory file> playbooks/byo/openshift-checks/adhoc.yml -e openshift_checks=docker_storage
+```
+
+To run more checks, use a comma-separated list of check names:
+
+```console
+$ ansible-playbook -i <inventory file> playbooks/byo/openshift-checks/adhoc.yml -e openshift_checks=docker_storage,disk_availability
+```
+
+To run an entire class of checks, use the name of a check group tag, prefixed by `@`. This will run all checks tagged `preflight`:
+
+```console
+$ ansible-playbook -i <inventory file> playbooks/byo/openshift-checks/adhoc.yml -e openshift_checks=@preflight
+```
+
+It is valid to specify multiple check tags and individual check names together
+in a comma-separated list.
+
+To list all of the available checks and tags, run the adhoc playbook without
+setting the `openshift_checks` variable:
+
+```console
+$ ansible-playbook -i <inventory file> playbooks/byo/openshift-checks/adhoc.yml
+```
+
## Running in a container
This repository is built into a Docker image including Ansible so that it can
diff --git a/playbooks/byo/openshift-checks/adhoc.yml b/playbooks/byo/openshift-checks/adhoc.yml
new file mode 100644
index 000000000..226bed732
--- /dev/null
+++ b/playbooks/byo/openshift-checks/adhoc.yml
@@ -0,0 +1,27 @@
+---
+# NOTE: ideally this would be just part of a single play in
+# common/openshift-checks/adhoc.yml that lists the existing checks when
+# openshift_checks is not set or run the requested checks. However, to actually
+# run the checks we need to have the included dependencies to run first and that
+# takes time. To speed up listing checks, we use this separate play that runs
+# before the include of dependencies to save time and improve the UX.
+- name: OpenShift health checks
+ # NOTE: though the openshift_checks variable could be potentially defined on
+ # individual hosts while not defined for localhost, we do not support that
+ # usage. Running this play only in localhost speeds up execution.
+ hosts: localhost
+ connection: local
+ roles:
+ - openshift_health_checker
+ vars:
+ - r_openshift_health_checker_playbook_context: adhoc
+ pre_tasks:
+ - name: List known health checks
+ action: openshift_health_check
+ when: openshift_checks is undefined or not openshift_checks
+
+- include: ../openshift-cluster/initialize_groups.yml
+
+- include: ../../common/openshift-cluster/std_include.yml
+
+- include: ../../common/openshift-checks/adhoc.yml
diff --git a/playbooks/byo/openshift-checks/health.yml b/playbooks/byo/openshift-checks/health.yml
index dfc1a7db0..96a71e4dc 100644
--- a/playbooks/byo/openshift-checks/health.yml
+++ b/playbooks/byo/openshift-checks/health.yml
@@ -1,3 +1,6 @@
---
- include: ../openshift-cluster/initialize_groups.yml
+
+- include: ../../common/openshift-cluster/std_include.yml
+
- include: ../../common/openshift-checks/health.yml
diff --git a/playbooks/byo/openshift-checks/pre-install.yml b/playbooks/byo/openshift-checks/pre-install.yml
index 5e8c3ab9b..dd93df0bb 100644
--- a/playbooks/byo/openshift-checks/pre-install.yml
+++ b/playbooks/byo/openshift-checks/pre-install.yml
@@ -1,3 +1,6 @@
---
- include: ../openshift-cluster/initialize_groups.yml
+
+- include: ../../common/openshift-cluster/std_include.yml
+
- include: ../../common/openshift-checks/pre-install.yml
diff --git a/playbooks/gce/openshift-cluster/roles b/playbooks/byo/openshift-checks/roles
index 20c4c58cf..20c4c58cf 120000
--- a/playbooks/gce/openshift-cluster/roles
+++ b/playbooks/byo/openshift-checks/roles
diff --git a/playbooks/byo/openshift-cluster/config.yml b/playbooks/byo/openshift-cluster/config.yml
index acf5469bf..60fa44c5b 100644
--- a/playbooks/byo/openshift-cluster/config.yml
+++ b/playbooks/byo/openshift-cluster/config.yml
@@ -9,6 +9,4 @@
- include: ../../common/openshift-cluster/config.yml
vars:
- openshift_cluster_id: "{{ cluster_id | default('default') }}"
- openshift_debug_level: "{{ debug_level | default(2) }}"
openshift_deployment_subtype: "{{ deployment_subtype | default(none) }}"
diff --git a/playbooks/byo/openshift-cluster/openshift-logging.yml b/playbooks/byo/openshift-cluster/openshift-logging.yml
index bbec3a4c2..a523bb47f 100644
--- a/playbooks/byo/openshift-cluster/openshift-logging.yml
+++ b/playbooks/byo/openshift-cluster/openshift-logging.yml
@@ -13,6 +13,3 @@
- always
- include: ../../common/openshift-cluster/openshift_logging.yml
- vars:
- openshift_cluster_id: "{{ cluster_id | default('default') }}"
- openshift_debug_level: "{{ debug_level | default(2) }}"
diff --git a/playbooks/byo/openshift-cluster/openshift-prometheus.yml b/playbooks/byo/openshift-cluster/openshift-prometheus.yml
new file mode 100644
index 000000000..15917078d
--- /dev/null
+++ b/playbooks/byo/openshift-cluster/openshift-prometheus.yml
@@ -0,0 +1,4 @@
+---
+- include: initialize_groups.yml
+
+- include: ../../common/openshift-cluster/openshift_prometheus.yml
diff --git a/playbooks/byo/openshift-cluster/openshift-provisioners.yml b/playbooks/byo/openshift-cluster/openshift-provisioners.yml
new file mode 100644
index 000000000..8e80f158b
--- /dev/null
+++ b/playbooks/byo/openshift-cluster/openshift-provisioners.yml
@@ -0,0 +1,6 @@
+---
+- include: initialize_groups.yml
+
+- include: ../../common/openshift-cluster/std_include.yml
+
+- include: ../../common/openshift-cluster/openshift_provisioners.yml
diff --git a/playbooks/byo/openshift-cluster/service-catalog.yml b/playbooks/byo/openshift-cluster/service-catalog.yml
index 6f95b4e2d..40a7606e7 100644
--- a/playbooks/byo/openshift-cluster/service-catalog.yml
+++ b/playbooks/byo/openshift-cluster/service-catalog.yml
@@ -13,6 +13,3 @@
- always
- include: ../../common/openshift-cluster/service_catalog.yml
- vars:
- openshift_cluster_id: "{{ cluster_id | default('default') }}"
- openshift_debug_level: "{{ debug_level | default(2) }}"
diff --git a/playbooks/byo/openshift-etcd/config.yml b/playbooks/byo/openshift-etcd/config.yml
index dd3f47a4d..1342bd60c 100644
--- a/playbooks/byo/openshift-etcd/config.yml
+++ b/playbooks/byo/openshift-etcd/config.yml
@@ -1,14 +1,6 @@
---
- include: ../openshift-cluster/initialize_groups.yml
- tags:
- - always
- include: ../../common/openshift-cluster/std_include.yml
- tags:
- - always
- include: ../../common/openshift-etcd/config.yml
- vars:
- openshift_cluster_id: "{{ cluster_id | default('default') }}"
- openshift_debug_level: "{{ debug_level | default(2) }}"
- openshift_deployment_subtype: "{{ deployment_subtype | default(none) }}"
diff --git a/playbooks/byo/openshift-etcd/migrate.yml b/playbooks/byo/openshift-etcd/migrate.yml
index 143016159..2dec2bef6 100644
--- a/playbooks/byo/openshift-etcd/migrate.yml
+++ b/playbooks/byo/openshift-etcd/migrate.yml
@@ -1,8 +1,6 @@
---
- include: ../openshift-cluster/initialize_groups.yml
- tags:
- - always
+
+- include: ../../common/openshift-cluster/std_include.yml
- include: ../../common/openshift-etcd/migrate.yml
- tags:
- - always
diff --git a/playbooks/byo/openshift-etcd/restart.yml b/playbooks/byo/openshift-etcd/restart.yml
index d43533641..034bba4b4 100644
--- a/playbooks/byo/openshift-etcd/restart.yml
+++ b/playbooks/byo/openshift-etcd/restart.yml
@@ -1,10 +1,6 @@
---
- include: ../openshift-cluster/initialize_groups.yml
- tags:
- - always
- include: ../../common/openshift-cluster/std_include.yml
- tags:
- - always
- include: ../../common/openshift-etcd/restart.yml
diff --git a/playbooks/byo/openshift-etcd/scaleup.yml b/playbooks/byo/openshift-etcd/scaleup.yml
index c35fd9f37..a2a5856a9 100644
--- a/playbooks/byo/openshift-etcd/scaleup.yml
+++ b/playbooks/byo/openshift-etcd/scaleup.yml
@@ -1,8 +1,6 @@
---
- include: ../openshift-cluster/initialize_groups.yml
-- include: ../../common/openshift-cluster/evaluate_groups.yml
+- include: ../../common/openshift-cluster/std_include.yml
+
- include: ../../common/openshift-etcd/scaleup.yml
- vars:
- openshift_cluster_id: "{{ cluster_id | default('default') }}"
- openshift_deployment_type: "{{ deployment_type }}"
diff --git a/playbooks/byo/openshift-loadbalancer/config.yml b/playbooks/byo/openshift-loadbalancer/config.yml
new file mode 100644
index 000000000..32c828f97
--- /dev/null
+++ b/playbooks/byo/openshift-loadbalancer/config.yml
@@ -0,0 +1,6 @@
+---
+- include: ../openshift-cluster/initialize_groups.yml
+
+- include: ../../common/openshift-cluster/std_include.yml
+
+- include: ../../common/openshift-loadbalancer/config.yml
diff --git a/playbooks/byo/openshift-master/additional_config.yml b/playbooks/byo/openshift-master/additional_config.yml
new file mode 100644
index 000000000..b3d7b5731
--- /dev/null
+++ b/playbooks/byo/openshift-master/additional_config.yml
@@ -0,0 +1,6 @@
+---
+- include: ../openshift-cluster/initialize_groups.yml
+
+- include: ../../common/openshift-cluster/std_include.yml
+
+- include: ../../common/openshift-master/additional_config.yml
diff --git a/playbooks/byo/openshift-master/config.yml b/playbooks/byo/openshift-master/config.yml
new file mode 100644
index 000000000..98be0c448
--- /dev/null
+++ b/playbooks/byo/openshift-master/config.yml
@@ -0,0 +1,6 @@
+---
+- include: ../openshift-cluster/initialize_groups.yml
+
+- include: ../../common/openshift-cluster/std_include.yml
+
+- include: ../../common/openshift-master/config.yml
diff --git a/playbooks/byo/openshift-master/restart.yml b/playbooks/byo/openshift-master/restart.yml
index 7988863f3..8950efd00 100644
--- a/playbooks/byo/openshift-master/restart.yml
+++ b/playbooks/byo/openshift-master/restart.yml
@@ -1,10 +1,6 @@
---
- include: ../openshift-cluster/initialize_groups.yml
- tags:
- - always
- include: ../../common/openshift-cluster/std_include.yml
- tags:
- - always
- include: ../../common/openshift-master/restart.yml
diff --git a/playbooks/byo/openshift-master/scaleup.yml b/playbooks/byo/openshift-master/scaleup.yml
index 64811e80d..a09edd55a 100644
--- a/playbooks/byo/openshift-master/scaleup.yml
+++ b/playbooks/byo/openshift-master/scaleup.yml
@@ -1,7 +1,7 @@
---
- include: ../openshift-cluster/initialize_groups.yml
-- name: Ensure there are new_masters
+- name: Ensure there are new_masters or new_nodes
hosts: localhost
connection: local
become: no
@@ -13,9 +13,8 @@
add hosts to the new_masters and new_nodes host groups to add
masters.
when:
- - (g_new_master_hosts | default([]) | length == 0) or (g_new_node_hosts | default([]) | length == 0)
+ - (g_new_master_hosts | default([]) | length == 0) and (g_new_node_hosts | default([]) | length == 0)
+
+- include: ../../common/openshift-cluster/std_include.yml
- include: ../../common/openshift-master/scaleup.yml
- vars:
- openshift_cluster_id: "{{ cluster_id | default('default') }}"
- openshift_debug_level: "{{ debug_level | default(2) }}"
diff --git a/playbooks/byo/openshift-nfs/config.yml b/playbooks/byo/openshift-nfs/config.yml
new file mode 100644
index 000000000..93b24411e
--- /dev/null
+++ b/playbooks/byo/openshift-nfs/config.yml
@@ -0,0 +1,6 @@
+---
+- include: ../openshift-cluster/initialize_groups.yml
+
+- include: ../../common/openshift-cluster/std_include.yml
+
+- include: ../../common/openshift-nfs/config.yml
diff --git a/playbooks/byo/openshift-node/config.yml b/playbooks/byo/openshift-node/config.yml
new file mode 100644
index 000000000..839dc36ff
--- /dev/null
+++ b/playbooks/byo/openshift-node/config.yml
@@ -0,0 +1,6 @@
+---
+- include: ../openshift-cluster/initialize_groups.yml
+
+- include: ../../common/openshift-cluster/std_include.yml
+
+- include: ../../common/openshift-node/config.yml
diff --git a/playbooks/byo/openshift-node/restart.yml b/playbooks/byo/openshift-node/restart.yml
index 92665d71d..ccf9e82da 100644
--- a/playbooks/byo/openshift-node/restart.yml
+++ b/playbooks/byo/openshift-node/restart.yml
@@ -1,10 +1,6 @@
---
- include: ../openshift-cluster/initialize_groups.yml
- tags:
- - always
- include: ../../common/openshift-cluster/std_include.yml
- tags:
- - always
- include: ../../common/openshift-node/restart.yml
diff --git a/playbooks/byo/openshift-node/scaleup.yml b/playbooks/byo/openshift-node/scaleup.yml
index fda89b1ea..e0c36fb69 100644
--- a/playbooks/byo/openshift-node/scaleup.yml
+++ b/playbooks/byo/openshift-node/scaleup.yml
@@ -14,9 +14,6 @@
when:
- g_new_node_hosts | default([]) | length == 0
-- include: ../../common/openshift-node/scaleup.yml
- vars:
- openshift_cluster_id: "{{ cluster_id | default('default') }}"
- openshift_debug_level: "{{ debug_level | default(2) }}"
- openshift_master_etcd_hosts: "{{ groups.etcd | default([]) }}"
- openshift_master_etcd_port: 2379
+- include: ../../common/openshift-cluster/std_include.yml
+
+- include: ../../common/openshift-node/config.yml
diff --git a/playbooks/byo/rhel_subscribe.yml b/playbooks/byo/rhel_subscribe.yml
index 1b14ff32e..06f914981 100644
--- a/playbooks/byo/rhel_subscribe.yml
+++ b/playbooks/byo/rhel_subscribe.yml
@@ -8,9 +8,9 @@
hosts: OSEv3
roles:
- role: rhel_subscribe
- when: deployment_type in ['atomic-enterprise', 'enterprise', 'openshift-enterprise'] and
- ansible_distribution == "RedHat" and
- lookup('oo_option', 'rhel_skip_subscription') | default(rhsub_skip, True) |
- default('no', True) | lower in ['no', 'false']
- - openshift_repos
- - os_update_latest
+ when:
+ - deployment_type == 'openshift-enterprise'
+ - ansible_distribution == "RedHat"
+ - lookup('oo_option', 'rhel_skip_subscription') | default(rhsub_skip, True) | default('no', True) | lower in ['no', 'false']
+ - role: openshift_repos
+ - role: os_update_latest
diff --git a/playbooks/byo/vagrant.yml b/playbooks/byo/vagrant.yml
deleted file mode 100644
index 76246e7b0..000000000
--- a/playbooks/byo/vagrant.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-- include: rhel_subscribe.yml
-
-- include: config.yml
diff --git a/playbooks/common/README.md b/playbooks/common/README.md
index 0b5e26989..968bd99cb 100644
--- a/playbooks/common/README.md
+++ b/playbooks/common/README.md
@@ -1,9 +1,8 @@
# Common playbooks
This directory has a generic set of playbooks that are included by playbooks in
-[`byo`](../byo), as well as other playbooks related to the
-[`bin/cluster`](../../bin) tool.
+[`byo`](../byo).
Note: playbooks in this directory use generic group names that do not line up
-with the groups used by the `byo` playbooks or `bin/cluster` derived playbooks,
-requiring an explicit remapping of groups.
+with the groups used by the `byo` playbooks, requiring an explicit remapping of
+groups.
diff --git a/playbooks/common/openshift-checks/adhoc.yml b/playbooks/common/openshift-checks/adhoc.yml
new file mode 100644
index 000000000..dfcef8435
--- /dev/null
+++ b/playbooks/common/openshift-checks/adhoc.yml
@@ -0,0 +1,12 @@
+---
+- name: OpenShift health checks
+ hosts: oo_all_hosts
+ roles:
+ - openshift_health_checker
+ vars:
+ - r_openshift_health_checker_playbook_context: adhoc
+ post_tasks:
+ - name: Run health checks
+ action: openshift_health_check
+ args:
+ checks: '{{ openshift_checks | default([]) }}'
diff --git a/playbooks/common/openshift-checks/health.yml b/playbooks/common/openshift-checks/health.yml
index ff5b5af67..21ea785ef 100644
--- a/playbooks/common/openshift-checks/health.yml
+++ b/playbooks/common/openshift-checks/health.yml
@@ -1,10 +1,6 @@
---
-- include: ../openshift-cluster/std_include.yml
- tags:
- - always
-
- name: Run OpenShift health checks
- hosts: OSEv3
+ hosts: oo_all_hosts
roles:
- openshift_health_checker
vars:
diff --git a/playbooks/common/openshift-checks/pre-install.yml b/playbooks/common/openshift-checks/pre-install.yml
index 861229f21..88e6f9120 100644
--- a/playbooks/common/openshift-checks/pre-install.yml
+++ b/playbooks/common/openshift-checks/pre-install.yml
@@ -1,10 +1,6 @@
---
-- include: ../openshift-cluster/std_include.yml
- tags:
- - always
-
-- hosts: OSEv3
- name: run OpenShift pre-install checks
+- name: run OpenShift pre-install checks
+ hosts: oo_all_hosts
roles:
- openshift_health_checker
vars:
diff --git a/playbooks/common/openshift-cluster/config.yml b/playbooks/common/openshift-cluster/config.yml
index e1df71112..bbd5a0185 100644
--- a/playbooks/common/openshift-cluster/config.yml
+++ b/playbooks/common/openshift-cluster/config.yml
@@ -18,33 +18,20 @@
- docker_image_availability
- docker_storage
-- include: initialize_firewall.yml
- tags:
- - always
-
-- hosts: localhost
- tasks:
- - fail:
- msg: No etcd hosts defined. Running an all-in-one master is deprecated and will no longer be supported in a future upgrade.
- when: groups.oo_etcd_to_config | default([]) | length == 0 and not openshift_master_unsupported_all_in_one | default(False)
-
- include: initialize_oo_option_facts.yml
tags:
- always
-- name: Disable excluders
+- name: Set hostname
hosts: oo_masters_to_config:oo_nodes_to_config
- tags:
- - always
- gather_facts: no
- roles:
- - role: openshift_excluder
- r_openshift_excluder_action: disable
- r_openshift_excluder_service_type: "{{ openshift.common.service_type }}"
+ tasks:
+ # TODO: switch back to hostname module once we depend on ansible-2.4
+ # https://github.com/ansible/ansible/pull/25906
+ - name: Set hostname
+ command: "hostnamectl set-hostname {{ openshift.common.hostname }}"
+ when: openshift_set_hostname | default(false,true) | bool
- include: ../openshift-etcd/config.yml
- tags:
- - etcd
- include: ../openshift-nfs/config.yml
tags:
@@ -55,12 +42,8 @@
- loadbalancer
- include: ../openshift-master/config.yml
- tags:
- - master
-- include: additional_config.yml
- tags:
- - master
+- include: ../openshift-master/additional_config.yml
- include: ../openshift-node/config.yml
tags:
@@ -79,13 +62,3 @@
- openshift_enable_service_catalog | default(false) | bool
tags:
- servicecatalog
-
-- name: Re-enable excluder if it was previously enabled
- hosts: oo_masters_to_config:oo_nodes_to_config
- tags:
- - always
- gather_facts: no
- roles:
- - role: openshift_excluder
- r_openshift_excluder_action: enable
- r_openshift_excluder_service_type: "{{ openshift.common.service_type }}"
diff --git a/playbooks/common/openshift-cluster/enable_dnsmasq.yml b/playbooks/common/openshift-cluster/enable_dnsmasq.yml
index 50351588f..be14b06f0 100644
--- a/playbooks/common/openshift-cluster/enable_dnsmasq.yml
+++ b/playbooks/common/openshift-cluster/enable_dnsmasq.yml
@@ -27,9 +27,6 @@
role: "{{ item.role }}"
local_facts: "{{ item.local_facts }}"
with_items:
- - role: common
- local_facts:
- use_dnsmasq: True
- role: master
local_facts:
dns_port: '8053'
@@ -50,9 +47,6 @@
role: "{{ item.role }}"
local_facts: "{{ item.local_facts }}"
with_items:
- - role: common
- local_facts:
- use_dnsmasq: True
- role: node
local_facts:
dns_ip: "{{ hostvars[inventory_hostname]['ansible_default_ipv4']['address'] }}"
diff --git a/playbooks/common/openshift-cluster/evaluate_groups.yml b/playbooks/common/openshift-cluster/evaluate_groups.yml
index c56b07037..e55b2f964 100644
--- a/playbooks/common/openshift-cluster/evaluate_groups.yml
+++ b/playbooks/common/openshift-cluster/evaluate_groups.yml
@@ -13,12 +13,12 @@
- name: Evaluate groups - g_master_hosts or g_new_master_hosts required
fail:
msg: This playbook requires g_master_hosts or g_new_master_hosts to be set
- when: g_master_hosts is not defined or g_new_master_hosts is not defined
+ when: g_master_hosts is not defined and g_new_master_hosts is not defined
- name: Evaluate groups - g_node_hosts or g_new_node_hosts required
fail:
msg: This playbook requires g_node_hosts or g_new_node_hosts to be set
- when: g_node_hosts is not defined or g_new_node_hosts is not defined
+ when: g_node_hosts is not defined and g_new_node_hosts is not defined
- name: Evaluate groups - g_lb_hosts required
fail:
@@ -33,13 +33,26 @@
- name: Evaluate groups - g_nfs_hosts is single host
fail:
msg: The nfs group must be limited to one host
- when: (groups[g_nfs_hosts] | default([])) | length > 1
+ when: g_nfs_hosts | default([]) | length > 1
- name: Evaluate groups - g_glusterfs_hosts required
fail:
msg: This playbook requires g_glusterfs_hosts to be set
when: g_glusterfs_hosts is not defined
+ - name: Evaluate groups - Fail if no etcd hosts group is defined
+ fail:
+ msg: >
+ Running etcd as an embedded service is no longer supported. If this is a
+ new install please define an 'etcd' group with either one or three
+ hosts. These hosts may be the same hosts as your masters. If this is an
+ upgrade you may set openshift_master_unsupported_embedded_etcd=true
+ until a migration playbook becomes available.
+ when:
+ - g_etcd_hosts | default([]) | length not in [3,1]
+ - not openshift_master_unsupported_embedded_etcd | default(False)
+ - not openshift_node_bootstrap | default(False)
+
- name: Evaluate oo_all_hosts
add_host:
name: "{{ item }}"
@@ -117,7 +130,7 @@
add_host:
name: "{{ item }}"
groups: oo_etcd_hosts_to_backup
- with_items: "{{ groups.oo_etcd_to_config if groups.oo_etcd_to_config is defined and groups.oo_etcd_to_config | length > 0 else groups.oo_first_master }}"
+ with_items: "{{ groups.oo_etcd_to_config if groups.oo_etcd_to_config is defined and groups.oo_etcd_to_config | length > 0 else (groups.oo_first_master | default([])) }}"
changed_when: False
- name: Evaluate oo_nodes_to_config
@@ -173,5 +186,5 @@
groups: oo_etcd_to_migrate
ansible_ssh_user: "{{ g_ssh_user | default(omit) }}"
ansible_become: "{{ g_sudo | default(omit) }}"
- with_items: "{{ groups.oo_etcd_to_config if groups.oo_etcd_to_config | default([]) | length != 0 else groups.oo_first_master }}"
+ with_items: "{{ groups.oo_etcd_to_config if groups.oo_etcd_to_config | default([]) | length != 0 else (groups.oo_first_master |default([]))}}"
changed_when: no
diff --git a/playbooks/common/openshift-cluster/initialize_facts.yml b/playbooks/common/openshift-cluster/initialize_facts.yml
index 4bf5d33b1..0723575c2 100644
--- a/playbooks/common/openshift-cluster/initialize_facts.yml
+++ b/playbooks/common/openshift-cluster/initialize_facts.yml
@@ -108,14 +108,27 @@
when:
- l_any_system_container | bool
+ - name: Default system_images_registry to a enterprise registry
+ set_fact:
+ system_images_registry: "registry.access.redhat.com"
+ when:
+ - system_images_registry is not defined
+ - openshift_deployment_type == "openshift-enterprise"
+
+ - name: Default system_images_registry to community registry
+ set_fact:
+ system_images_registry: "docker.io"
+ when:
+ - system_images_registry is not defined
+ - openshift_deployment_type == "origin"
+
- name: Gather Cluster facts and set is_containerized if needed
openshift_facts:
role: common
local_facts:
- debug_level: "{{ openshift_debug_level | default(2) }}"
deployment_type: "{{ openshift_deployment_type }}"
deployment_subtype: "{{ openshift_deployment_subtype | default(None) }}"
- cluster_id: "{{ openshift_cluster_id | default('default') }}"
+ cli_image: "{{ osm_image | default(None) }}"
hostname: "{{ openshift_hostname | default(None) }}"
ip: "{{ openshift_ip | default(None) }}"
is_containerized: "{{ l_is_containerized | default(None) }}"
@@ -124,7 +137,7 @@
is_master_system_container: "{{ l_is_master_system_container | default(false) }}"
is_etcd_system_container: "{{ l_is_etcd_system_container | default(false) }}"
etcd_runtime: "{{ l_etcd_runtime }}"
- system_images_registry: "{{ system_images_registry | default('') }}"
+ system_images_registry: "{{ system_images_registry }}"
public_hostname: "{{ openshift_public_hostname | default(None) }}"
public_ip: "{{ openshift_public_ip | default(None) }}"
portal_net: "{{ openshift_portal_net | default(openshift_master_portal_net) | default(None) }}"
@@ -133,8 +146,6 @@
no_proxy: "{{ openshift_no_proxy | default(None) }}"
generate_no_proxy_hosts: "{{ openshift_generate_no_proxy_hosts | default(True) }}"
no_proxy_internal_hostnames: "{{ openshift_no_proxy_internal_hostnames | default(None) }}"
- sdn_network_plugin_name: "{{ os_sdn_network_plugin_name | default(None) }}"
- use_openshift_sdn: "{{ openshift_use_openshift_sdn | default(None) }}"
- name: initialize_facts set_fact repoquery command
set_fact:
@@ -142,4 +153,4 @@
- name: initialize_facts set_fact on openshift_docker_hosted_registry_network
set_fact:
- openshift_docker_hosted_registry_network: "{{ hostvars[groups.oo_first_master.0].openshift.common.portal_net }}"
+ openshift_docker_hosted_registry_network: "{{ '' if 'oo_first_master' not in groups else hostvars[groups.oo_first_master.0].openshift.common.portal_net }}"
diff --git a/playbooks/common/openshift-cluster/initialize_firewall.yml b/playbooks/common/openshift-cluster/initialize_firewall.yml
deleted file mode 100644
index f0374fbc7..000000000
--- a/playbooks/common/openshift-cluster/initialize_firewall.yml
+++ /dev/null
@@ -1,7 +0,0 @@
----
-- name: Initialize host firewall
- hosts: oo_all_hosts
- tasks:
- - name: Install and configure the proper firewall settings
- include_role:
- name: os_firewall
diff --git a/playbooks/common/openshift-cluster/initialize_openshift_version.yml b/playbooks/common/openshift-cluster/initialize_openshift_version.yml
index 7112a6084..1b186f181 100644
--- a/playbooks/common/openshift-cluster/initialize_openshift_version.yml
+++ b/playbooks/common/openshift-cluster/initialize_openshift_version.yml
@@ -1,4 +1,12 @@
---
+- name: Set version_install_base_package true on masters and nodes
+ hosts: oo_masters_to_config:oo_nodes_to_config
+ tasks:
+ - name: Set version_install_base_package true
+ set_fact:
+ version_install_base_package: True
+ when: version_install_base_package is not defined
+
# NOTE: requires openshift_facts be run
- name: Determine openshift_version to configure on first master
hosts: oo_first_master
@@ -12,5 +20,10 @@
hosts: oo_all_hosts:!oo_first_master
vars:
openshift_version: "{{ hostvars[groups.oo_first_master.0].openshift_version }}"
+ pre_tasks:
+ - set_fact:
+ openshift_pkg_version: -{{ openshift_version }}
+ when: openshift_pkg_version is not defined
+ - debug: msg="openshift_pkg_version set to {{ openshift_pkg_version }}"
roles:
- openshift_version
diff --git a/playbooks/common/openshift-cluster/openshift_hosted.yml b/playbooks/common/openshift-cluster/openshift_hosted.yml
index 99a634970..75339f6df 100644
--- a/playbooks/common/openshift-cluster/openshift_hosted.yml
+++ b/playbooks/common/openshift-cluster/openshift_hosted.yml
@@ -29,7 +29,6 @@
- role: openshift_default_storage_class
when: openshift_cloudprovider_kind is defined and (openshift_cloudprovider_kind == 'aws' or openshift_cloudprovider_kind == 'gce')
- role: openshift_hosted
- r_openshift_hosted_use_calico: "{{ openshift.common.use_calico | default(false) | bool }}"
- role: openshift_metrics
when: openshift_hosted_metrics_deploy | default(false) | bool
- role: openshift_logging
@@ -49,6 +48,9 @@
- role: cockpit-ui
when: ( openshift.common.version_gte_3_3_or_1_3 | bool ) and ( openshift_hosted_manage_registry | default(true) | bool ) and not (openshift.docker.hosted_registry_insecure | default(false) | bool)
+ - role: openshift_prometheus
+ when: openshift_hosted_prometheus_deploy | default(false) | bool
+
- name: Update master-config for publicLoggingURL
hosts: oo_masters_to_config:!oo_first_master
tags:
diff --git a/playbooks/common/openshift-cluster/openshift_prometheus.yml b/playbooks/common/openshift-cluster/openshift_prometheus.yml
new file mode 100644
index 000000000..a979c0c00
--- /dev/null
+++ b/playbooks/common/openshift-cluster/openshift_prometheus.yml
@@ -0,0 +1,9 @@
+---
+- include: std_include.yml
+
+- name: OpenShift Prometheus
+ hosts: oo_first_master
+ roles:
+ - openshift_prometheus
+ vars:
+ openshift_prometheus_state: present
diff --git a/playbooks/common/openshift-cluster/sanity_checks.yml b/playbooks/common/openshift-cluster/sanity_checks.yml
new file mode 100644
index 000000000..26716a92d
--- /dev/null
+++ b/playbooks/common/openshift-cluster/sanity_checks.yml
@@ -0,0 +1,51 @@
+---
+- name: Verify Requirements
+ hosts: oo_all_hosts
+ tasks:
+ - fail:
+ msg: Flannel can not be used with openshift sdn, set openshift_use_openshift_sdn=false if you want to use flannel
+ when: openshift_use_openshift_sdn | default(true) | bool and openshift_use_flannel | default(false) | bool
+
+ - fail:
+ msg: Nuage sdn can not be used with openshift sdn, set openshift_use_openshift_sdn=false if you want to use nuage
+ when: openshift_use_openshift_sdn | default(true) | bool and openshift_use_nuage | default(false) | bool
+
+ - fail:
+ msg: Nuage sdn can not be used with flannel
+ when: openshift_use_flannel | default(false) | bool and openshift_use_nuage | default(false) | bool
+
+ - fail:
+ msg: Contiv can not be used with openshift sdn, set openshift_use_openshift_sdn=false if you want to use contiv
+ when: openshift_use_openshift_sdn | default(true) | bool and openshift_use_contiv | default(false) | bool
+
+ - fail:
+ msg: Contiv can not be used with flannel
+ when: openshift_use_flannel | default(false) | bool and openshift_use_contiv | default(false) | bool
+
+ - fail:
+ msg: Contiv can not be used with nuage
+ when: openshift_use_nuage | default(false) | bool and openshift_use_contiv | default(false) | bool
+
+ - fail:
+ msg: Calico can not be used with openshift sdn, set openshift_use_openshift_sdn=false if you want to use Calico
+ when: openshift_use_openshift_sdn | default(true) | bool and openshift_use_calico | default(false) | bool
+
+ - fail:
+ msg: The Calico playbook does not yet integrate with the Flannel playbook in Openshift. Set either openshift_use_calico or openshift_use_flannel, but not both.
+ when: openshift_use_calico | default(false) | bool and openshift_use_flannel | default(false) | bool
+
+ - fail:
+ msg: Calico can not be used with Nuage in Openshift. Set either openshift_use_calico or openshift_use_nuage, but not both
+ when: openshift_use_calico | default(false) | bool and openshift_use_nuage | default(false) | bool
+
+ - fail:
+ msg: Calico can not be used with Contiv in Openshift. Set either openshift_use_calico or openshift_use_contiv, but not both
+ when: openshift_use_calico | default(false) | bool and openshift_use_contiv | default(false) | bool
+
+ - fail:
+ msg: openshift_hostname must be 63 characters or less
+ when: openshift_hostname is defined and openshift_hostname | length > 63
+
+ - fail:
+ msg: openshift_public_hostname must be 63 characters or less
+ when: openshift_public_hostname is defined and openshift_public_hostname | length > 63
diff --git a/playbooks/common/openshift-cluster/std_include.yml b/playbooks/common/openshift-cluster/std_include.yml
index 6cc56889a..cef0072f3 100644
--- a/playbooks/common/openshift-cluster/std_include.yml
+++ b/playbooks/common/openshift-cluster/std_include.yml
@@ -7,6 +7,10 @@
tags:
- always
+- include: sanity_checks.yml
+ tags:
+ - always
+
- include: validate_hostnames.yml
tags:
- node
diff --git a/playbooks/common/openshift-cluster/tasks/set_etcd_launch_facts.yml b/playbooks/common/openshift-cluster/tasks/set_etcd_launch_facts.yml
index 1a6580795..eb118365a 100644
--- a/playbooks/common/openshift-cluster/tasks/set_etcd_launch_facts.yml
+++ b/playbooks/common/openshift-cluster/tasks/set_etcd_launch_facts.yml
@@ -3,7 +3,7 @@
- name: Generate etcd instance names(s)
set_fact:
- scratch_name: "{{ cluster_id }}-{{ k8s_type }}-{{ '%05x' | format(1048576 | random) }}"
+ scratch_name: "{{ openshift_cluster_id | default('default') }}-{{ k8s_type }}-{{ '%05x' | format(1048576 | random) }}"
register: etcd_names_output
with_sequence: count={{ num_etcd }}
diff --git a/playbooks/common/openshift-cluster/tasks/set_master_launch_facts.yml b/playbooks/common/openshift-cluster/tasks/set_master_launch_facts.yml
index 36d7b7870..783f70f50 100644
--- a/playbooks/common/openshift-cluster/tasks/set_master_launch_facts.yml
+++ b/playbooks/common/openshift-cluster/tasks/set_master_launch_facts.yml
@@ -3,7 +3,7 @@
- name: Generate master instance names(s)
set_fact:
- scratch_name: "{{ cluster_id }}-{{ k8s_type }}-{{ '%05x' | format(1048576 | random) }}"
+ scratch_name: "{{ openshift_cluster_id | default('default') }}-{{ k8s_type }}-{{ '%05x' | format(1048576 | random) }}"
register: master_names_output
with_sequence: count={{ num_masters }}
diff --git a/playbooks/common/openshift-cluster/tasks/set_node_launch_facts.yml b/playbooks/common/openshift-cluster/tasks/set_node_launch_facts.yml
index 278942f8b..c103e40a9 100644
--- a/playbooks/common/openshift-cluster/tasks/set_node_launch_facts.yml
+++ b/playbooks/common/openshift-cluster/tasks/set_node_launch_facts.yml
@@ -5,7 +5,7 @@
- name: Generate node instance names(s)
set_fact:
- scratch_name: "{{ cluster_id }}-{{ k8s_type }}-{{ sub_host_type }}-{{ '%05x' | format(1048576 | random) }}"
+ scratch_name: "{{ openshift_cluster_id | default('default') }}-{{ k8s_type }}-{{ sub_host_type }}-{{ '%05x' | format(1048576 | random) }}"
register: node_names_output
with_sequence: count={{ number_nodes }}
diff --git a/playbooks/common/openshift-cluster/update_repos_and_packages.yml b/playbooks/common/openshift-cluster/update_repos_and_packages.yml
deleted file mode 100644
index be956fca5..000000000
--- a/playbooks/common/openshift-cluster/update_repos_and_packages.yml
+++ /dev/null
@@ -1,18 +0,0 @@
----
-- include: evaluate_groups.yml
-
-- name: Subscribe hosts, update repos and update OS packages
- hosts: oo_hosts_to_update
- roles:
- # Explicitly calling openshift_facts because it appears that when
- # rhel_subscribe is skipped that the openshift_facts dependency for
- # openshift_repos is also skipped (this is the case at least for Ansible
- # 2.0.2)
- - openshift_facts
- - role: rhel_subscribe
- when: deployment_type in ["enterprise", "atomic-enterprise", "openshift-enterprise"] and
- ansible_distribution == "RedHat" and
- lookup('oo_option', 'rhel_skip_subscription') | default(rhsub_skip, True) |
- default('no', True) | lower in ['no', 'false']
- - openshift_repos
- - os_update_latest
diff --git a/playbooks/common/openshift-cluster/upgrades/docker/docker_upgrade.yml b/playbooks/common/openshift-cluster/upgrades/docker/docker_upgrade.yml
index 02b8a9d3c..98953f72e 100644
--- a/playbooks/common/openshift-cluster/upgrades/docker/docker_upgrade.yml
+++ b/playbooks/common/openshift-cluster/upgrades/docker/docker_upgrade.yml
@@ -4,7 +4,6 @@
# Do not allow adding hosts during upgrade.
g_new_master_hosts: []
g_new_node_hosts: []
- openshift_cluster_id: "{{ cluster_id | default('default') }}"
- include: ../initialize_nodes_to_upgrade.yml
@@ -60,7 +59,7 @@
retries: 60
delay: 60
- - include: upgrade.yml
+ - include: tasks/upgrade.yml
when: l_docker_upgrade is defined and l_docker_upgrade | bool
- name: Set node schedulability
diff --git a/playbooks/common/openshift-cluster/upgrades/docker/restart.yml b/playbooks/common/openshift-cluster/upgrades/docker/tasks/restart.yml
index 83f16ac0d..83f16ac0d 100644
--- a/playbooks/common/openshift-cluster/upgrades/docker/restart.yml
+++ b/playbooks/common/openshift-cluster/upgrades/docker/tasks/restart.yml
diff --git a/playbooks/common/openshift-cluster/upgrades/docker/upgrade.yml b/playbooks/common/openshift-cluster/upgrades/docker/tasks/upgrade.yml
index 808cc562c..808cc562c 100644
--- a/playbooks/common/openshift-cluster/upgrades/docker/upgrade.yml
+++ b/playbooks/common/openshift-cluster/upgrades/docker/tasks/upgrade.yml
diff --git a/playbooks/common/openshift-cluster/upgrades/docker/upgrade_check.yml b/playbooks/common/openshift-cluster/upgrades/docker/upgrade_check.yml
index b2a2eac9a..52345a9ba 100644
--- a/playbooks/common/openshift-cluster/upgrades/docker/upgrade_check.yml
+++ b/playbooks/common/openshift-cluster/upgrades/docker/upgrade_check.yml
@@ -18,12 +18,16 @@
- name: Get current version of Docker
command: "{{ repoquery_cmd }} --installed --qf '%{version}' docker"
register: curr_docker_version
+ retries: 4
+ until: curr_docker_version | succeeded
changed_when: false
- name: Get latest available version of Docker
command: >
{{ repoquery_cmd }} --qf '%{version}' "docker"
register: avail_docker_version
+ retries: 4
+ until: avail_docker_version | succeeded
# Don't expect docker rpm to be available on hosts that don't already have it installed:
when: pkg_check.rc == 0
failed_when: false
diff --git a/playbooks/common/openshift-cluster/upgrades/etcd/backup.yml b/playbooks/common/openshift-cluster/upgrades/etcd/backup.yml
index 616ba04f8..2cc6c9019 100644
--- a/playbooks/common/openshift-cluster/upgrades/etcd/backup.yml
+++ b/playbooks/common/openshift-cluster/upgrades/etcd/backup.yml
@@ -2,7 +2,7 @@
- name: Backup etcd
hosts: oo_etcd_hosts_to_backup
roles:
- - role: openshift_facts
+ - role: openshift_etcd_facts
- role: etcd_common
r_etcd_common_action: backup
r_etcd_common_backup_tag: etcd_backup_tag
diff --git a/playbooks/common/openshift-cluster/upgrades/init.yml b/playbooks/common/openshift-cluster/upgrades/init.yml
index 0f421928b..c98065cf4 100644
--- a/playbooks/common/openshift-cluster/upgrades/init.yml
+++ b/playbooks/common/openshift-cluster/upgrades/init.yml
@@ -4,7 +4,6 @@
# Do not allow adding hosts during upgrade.
g_new_master_hosts: []
g_new_node_hosts: []
- openshift_cluster_id: "{{ cluster_id | default('default') }}"
- include: ../initialize_oo_option_facts.yml
diff --git a/playbooks/common/openshift-cluster/upgrades/pre/verify_docker_upgrade_targets.yml b/playbooks/common/openshift-cluster/upgrades/pre/tasks/verify_docker_upgrade_targets.yml
index 9d8b73cff..6d8503879 100644
--- a/playbooks/common/openshift-cluster/upgrades/pre/verify_docker_upgrade_targets.yml
+++ b/playbooks/common/openshift-cluster/upgrades/pre/tasks/verify_docker_upgrade_targets.yml
@@ -1,8 +1,10 @@
---
# Only check if docker upgrade is required if docker_upgrade is not
# already set to False.
-- include: ../docker/upgrade_check.yml
- when: docker_upgrade is not defined or docker_upgrade | bool and not openshift.common.is_atomic | bool
+- include: ../../docker/upgrade_check.yml
+ when:
+ - docker_upgrade is not defined or (docker_upgrade | bool)
+ - not (openshift.common.is_atomic | bool)
# Additional checks for Atomic hosts:
diff --git a/playbooks/common/openshift-cluster/upgrades/pre/verify_inventory_vars.yml b/playbooks/common/openshift-cluster/upgrades/pre/verify_inventory_vars.yml
index 9a959a959..3c0017891 100644
--- a/playbooks/common/openshift-cluster/upgrades/pre/verify_inventory_vars.yml
+++ b/playbooks/common/openshift-cluster/upgrades/pre/verify_inventory_vars.yml
@@ -5,9 +5,9 @@
tasks:
- fail:
msg: >
- This upgrade is only supported for origin, openshift-enterprise, and online
+ This upgrade is only supported for origin and openshift-enterprise
deployment types
- when: deployment_type not in ['origin','openshift-enterprise', 'online']
+ when: deployment_type not in ['origin','openshift-enterprise']
# Error out in situations where the user has older versions specified in their
# inventory in any of the openshift_release, openshift_image_tag, and
diff --git a/playbooks/common/openshift-cluster/upgrades/pre/verify_nodes_running.yml b/playbooks/common/openshift-cluster/upgrades/pre/verify_nodes_running.yml
deleted file mode 100644
index 354af3cde..000000000
--- a/playbooks/common/openshift-cluster/upgrades/pre/verify_nodes_running.yml
+++ /dev/null
@@ -1,13 +0,0 @@
----
-- name: Verify node processes
- hosts: oo_nodes_to_config
- roles:
- - openshift_facts
- - openshift_docker_facts
- tasks:
- - name: Ensure Node is running
- service:
- name: "{{ openshift.common.service_type }}-node"
- state: started
- enabled: yes
- when: openshift.common.is_containerized | bool
diff --git a/playbooks/common/openshift-cluster/upgrades/upgrade_control_plane.yml b/playbooks/common/openshift-cluster/upgrades/upgrade_control_plane.yml
index abcd21c90..b75aae589 100644
--- a/playbooks/common/openshift-cluster/upgrades/upgrade_control_plane.yml
+++ b/playbooks/common/openshift-cluster/upgrades/upgrade_control_plane.yml
@@ -13,11 +13,11 @@
{{ openshift.common.client_binary }} adm --config={{ openshift.common.config_base }}/master/admin.kubeconfig
migrate storage --include=* --confirm
register: l_pb_upgrade_control_plane_pre_upgrade_storage
- when: openshift_upgrade_pre_storage_migration_enabled | default(true,true) | bool
+ when: openshift_upgrade_pre_storage_migration_enabled | default(true) | bool
failed_when:
- - openshift_upgrade_pre_storage_migration_enabled | default(true,true) | bool
+ - openshift_upgrade_pre_storage_migration_enabled | default(true) | bool
- l_pb_upgrade_control_plane_pre_upgrade_storage.rc != 0
- - openshift_upgrade_pre_storage_migration_fatal | default(true,true) | bool
+ - openshift_upgrade_pre_storage_migration_fatal | default(true) | bool
# If facts cache were for some reason deleted, this fact may not be set, and if not set
# it will always default to true. This causes problems for the etcd data dir fact detection
@@ -91,10 +91,7 @@
- include_vars: ../../../../roles/openshift_master/vars/main.yml
- - name: Remove any legacy systemd units
- include: ../../../../roles/openshift_master/tasks/clean_systemd_units.yml
-
- - name: Update systemd units
+ - name: Remove any legacy systemd units and update systemd units
include: ../../../../roles/openshift_master/tasks/systemd_units.yml
- name: Check for ca-bundle.crt
@@ -154,11 +151,11 @@
{{ openshift.common.client_binary }} adm --config={{ openshift.common.config_base }}/master/admin.kubeconfig
migrate storage --include=clusterpolicies --confirm
register: l_pb_upgrade_control_plane_post_upgrade_storage
- when: openshift_upgrade_post_storage_migration_enabled | default(true,true) | bool
+ when: openshift_upgrade_post_storage_migration_enabled | default(true) | bool
failed_when:
- - openshift_upgrade_post_storage_migration_enabled | default(true,true) | bool
+ - openshift_upgrade_post_storage_migration_enabled | default(true) | bool
- l_pb_upgrade_control_plane_post_upgrade_storage.rc != 0
- - openshift_upgrade_post_storage_migration_fatal | default(false,true) | bool
+ - openshift_upgrade_post_storage_migration_fatal | default(false) | bool
run_once: true
delegate_to: "{{ groups.oo_first_master.0 }}"
@@ -250,11 +247,11 @@
migrate storage --include=* --confirm
run_once: true
register: l_pb_upgrade_control_plane_post_upgrade_storage
- when: openshift_upgrade_post_storage_migration_enabled | default(true,true) | bool
+ when: openshift_upgrade_post_storage_migration_enabled | default(true) | bool
failed_when:
- - openshift_upgrade_post_storage_migration_enabled | default(true,true) | bool
+ - openshift_upgrade_post_storage_migration_enabled | default(true) | bool
- l_pb_upgrade_control_plane_post_upgrade_storage.rc != 0
- - openshift_upgrade_post_storage_migration_fatal | default(false,true) | bool
+ - openshift_upgrade_post_storage_migration_fatal | default(false) | bool
- set_fact:
reconcile_complete: True
@@ -284,7 +281,7 @@
roles:
- openshift_facts
tasks:
- - include: docker/upgrade.yml
+ - include: docker/tasks/upgrade.yml
when: l_docker_upgrade is defined and l_docker_upgrade | bool and not openshift.common.is_atomic | bool
- name: Drain and upgrade master nodes
diff --git a/playbooks/common/openshift-cluster/upgrades/v3_3/upgrade.yml b/playbooks/common/openshift-cluster/upgrades/v3_3/upgrade.yml
index 0f6fb46a4..a241ef039 100644
--- a/playbooks/common/openshift-cluster/upgrades/v3_3/upgrade.yml
+++ b/playbooks/common/openshift-cluster/upgrades/v3_3/upgrade.yml
@@ -89,7 +89,7 @@
- name: Verify docker upgrade targets
hosts: oo_masters_to_config:oo_nodes_to_upgrade:oo_etcd_to_config
tasks:
- - include: ../pre/verify_docker_upgrade_targets.yml
+ - include: ../pre/tasks/verify_docker_upgrade_targets.yml
tags:
- pre_upgrade
diff --git a/playbooks/common/openshift-cluster/upgrades/v3_3/upgrade_control_plane.yml b/playbooks/common/openshift-cluster/upgrades/v3_3/upgrade_control_plane.yml
index cfba788a8..54c85f0fb 100644
--- a/playbooks/common/openshift-cluster/upgrades/v3_3/upgrade_control_plane.yml
+++ b/playbooks/common/openshift-cluster/upgrades/v3_3/upgrade_control_plane.yml
@@ -93,7 +93,7 @@
- name: Verify docker upgrade targets
hosts: oo_masters_to_config:oo_etcd_to_config
tasks:
- - include: ../pre/verify_docker_upgrade_targets.yml
+ - include: ../pre/tasks/verify_docker_upgrade_targets.yml
tags:
- pre_upgrade
diff --git a/playbooks/common/openshift-cluster/upgrades/v3_3/upgrade_nodes.yml b/playbooks/common/openshift-cluster/upgrades/v3_3/upgrade_nodes.yml
index 1054f430e..cee4e9087 100644
--- a/playbooks/common/openshift-cluster/upgrades/v3_3/upgrade_nodes.yml
+++ b/playbooks/common/openshift-cluster/upgrades/v3_3/upgrade_nodes.yml
@@ -90,7 +90,7 @@
- name: Verify docker upgrade targets
hosts: oo_nodes_to_upgrade
tasks:
- - include: ../pre/verify_docker_upgrade_targets.yml
+ - include: ../pre/tasks/verify_docker_upgrade_targets.yml
tags:
- pre_upgrade
diff --git a/playbooks/common/openshift-cluster/upgrades/v3_4/upgrade.yml b/playbooks/common/openshift-cluster/upgrades/v3_4/upgrade.yml
index 783289c87..ae217ba2e 100644
--- a/playbooks/common/openshift-cluster/upgrades/v3_4/upgrade.yml
+++ b/playbooks/common/openshift-cluster/upgrades/v3_4/upgrade.yml
@@ -89,7 +89,7 @@
- name: Verify docker upgrade targets
hosts: oo_masters_to_config:oo_nodes_to_upgrade:oo_etcd_to_config
tasks:
- - include: ../pre/verify_docker_upgrade_targets.yml
+ - include: ../pre/tasks/verify_docker_upgrade_targets.yml
tags:
- pre_upgrade
diff --git a/playbooks/common/openshift-cluster/upgrades/v3_4/upgrade_control_plane.yml b/playbooks/common/openshift-cluster/upgrades/v3_4/upgrade_control_plane.yml
index 8aa443c3c..d7cb38d03 100644
--- a/playbooks/common/openshift-cluster/upgrades/v3_4/upgrade_control_plane.yml
+++ b/playbooks/common/openshift-cluster/upgrades/v3_4/upgrade_control_plane.yml
@@ -93,7 +93,7 @@
- name: Verify docker upgrade targets
hosts: oo_masters_to_config:oo_etcd_to_config
tasks:
- - include: ../pre/verify_docker_upgrade_targets.yml
+ - include: ../pre/tasks/verify_docker_upgrade_targets.yml
tags:
- pre_upgrade
diff --git a/playbooks/common/openshift-cluster/upgrades/v3_4/upgrade_nodes.yml b/playbooks/common/openshift-cluster/upgrades/v3_4/upgrade_nodes.yml
index 436795694..8531e6045 100644
--- a/playbooks/common/openshift-cluster/upgrades/v3_4/upgrade_nodes.yml
+++ b/playbooks/common/openshift-cluster/upgrades/v3_4/upgrade_nodes.yml
@@ -90,7 +90,7 @@
- name: Verify docker upgrade targets
hosts: oo_nodes_to_upgrade
tasks:
- - include: ../pre/verify_docker_upgrade_targets.yml
+ - include: ../pre/tasks/verify_docker_upgrade_targets.yml
tags:
- pre_upgrade
diff --git a/playbooks/common/openshift-cluster/upgrades/v3_5/upgrade.yml b/playbooks/common/openshift-cluster/upgrades/v3_5/upgrade.yml
index 9a000265e..a3d0d6305 100644
--- a/playbooks/common/openshift-cluster/upgrades/v3_5/upgrade.yml
+++ b/playbooks/common/openshift-cluster/upgrades/v3_5/upgrade.yml
@@ -89,7 +89,7 @@
- name: Verify docker upgrade targets
hosts: oo_masters_to_config:oo_nodes_to_upgrade:oo_etcd_to_config
tasks:
- - include: ../pre/verify_docker_upgrade_targets.yml
+ - include: ../pre/tasks/verify_docker_upgrade_targets.yml
tags:
- pre_upgrade
diff --git a/playbooks/common/openshift-cluster/upgrades/v3_5/upgrade_control_plane.yml b/playbooks/common/openshift-cluster/upgrades/v3_5/upgrade_control_plane.yml
index 2dd9676c7..5fee56615 100644
--- a/playbooks/common/openshift-cluster/upgrades/v3_5/upgrade_control_plane.yml
+++ b/playbooks/common/openshift-cluster/upgrades/v3_5/upgrade_control_plane.yml
@@ -93,7 +93,7 @@
- name: Verify docker upgrade targets
hosts: oo_masters_to_config:oo_etcd_to_config
tasks:
- - include: ../pre/verify_docker_upgrade_targets.yml
+ - include: ../pre/tasks/verify_docker_upgrade_targets.yml
tags:
- pre_upgrade
diff --git a/playbooks/common/openshift-cluster/upgrades/v3_5/upgrade_nodes.yml b/playbooks/common/openshift-cluster/upgrades/v3_5/upgrade_nodes.yml
index d5fe8285e..e29d0f8e6 100644
--- a/playbooks/common/openshift-cluster/upgrades/v3_5/upgrade_nodes.yml
+++ b/playbooks/common/openshift-cluster/upgrades/v3_5/upgrade_nodes.yml
@@ -90,7 +90,7 @@
- name: Verify docker upgrade targets
hosts: oo_nodes_to_upgrade
tasks:
- - include: ../pre/verify_docker_upgrade_targets.yml
+ - include: ../pre/tasks/verify_docker_upgrade_targets.yml
tags:
- pre_upgrade
diff --git a/playbooks/common/openshift-cluster/upgrades/v3_6/upgrade.yml b/playbooks/common/openshift-cluster/upgrades/v3_6/upgrade.yml
index 8ceab09f4..51acd17da 100644
--- a/playbooks/common/openshift-cluster/upgrades/v3_6/upgrade.yml
+++ b/playbooks/common/openshift-cluster/upgrades/v3_6/upgrade.yml
@@ -93,7 +93,7 @@
- name: Verify docker upgrade targets
hosts: oo_masters_to_config:oo_nodes_to_upgrade:oo_etcd_to_config
tasks:
- - include: ../pre/verify_docker_upgrade_targets.yml
+ - include: ../pre/tasks/verify_docker_upgrade_targets.yml
tags:
- pre_upgrade
diff --git a/playbooks/common/openshift-cluster/upgrades/v3_6/upgrade_control_plane.yml b/playbooks/common/openshift-cluster/upgrades/v3_6/upgrade_control_plane.yml
index f765e9064..9fe059ac9 100644
--- a/playbooks/common/openshift-cluster/upgrades/v3_6/upgrade_control_plane.yml
+++ b/playbooks/common/openshift-cluster/upgrades/v3_6/upgrade_control_plane.yml
@@ -93,7 +93,7 @@
- name: Verify docker upgrade targets
hosts: oo_masters_to_config:oo_etcd_to_config
tasks:
- - include: ../pre/verify_docker_upgrade_targets.yml
+ - include: ../pre/tasks/verify_docker_upgrade_targets.yml
tags:
- pre_upgrade
diff --git a/playbooks/common/openshift-cluster/upgrades/v3_6/upgrade_nodes.yml b/playbooks/common/openshift-cluster/upgrades/v3_6/upgrade_nodes.yml
index 8bed6a8c2..1b10d4e37 100644
--- a/playbooks/common/openshift-cluster/upgrades/v3_6/upgrade_nodes.yml
+++ b/playbooks/common/openshift-cluster/upgrades/v3_6/upgrade_nodes.yml
@@ -90,7 +90,7 @@
- name: Verify docker upgrade targets
hosts: oo_nodes_to_upgrade
tasks:
- - include: ../pre/verify_docker_upgrade_targets.yml
+ - include: ../pre/tasks/verify_docker_upgrade_targets.yml
tags:
- pre_upgrade
diff --git a/playbooks/common/openshift-cluster/upgrades/v3_7/upgrade.yml b/playbooks/common/openshift-cluster/upgrades/v3_7/upgrade.yml
index 4f05d0c64..9ec40723a 100644
--- a/playbooks/common/openshift-cluster/upgrades/v3_7/upgrade.yml
+++ b/playbooks/common/openshift-cluster/upgrades/v3_7/upgrade.yml
@@ -93,7 +93,7 @@
- name: Verify docker upgrade targets
hosts: oo_masters_to_config:oo_nodes_to_upgrade:oo_etcd_to_config
tasks:
- - include: ../pre/verify_docker_upgrade_targets.yml
+ - include: ../pre/tasks/verify_docker_upgrade_targets.yml
tags:
- pre_upgrade
diff --git a/playbooks/common/openshift-cluster/upgrades/v3_7/upgrade_control_plane.yml b/playbooks/common/openshift-cluster/upgrades/v3_7/upgrade_control_plane.yml
index 2ef95e778..f97f34c3b 100644
--- a/playbooks/common/openshift-cluster/upgrades/v3_7/upgrade_control_plane.yml
+++ b/playbooks/common/openshift-cluster/upgrades/v3_7/upgrade_control_plane.yml
@@ -93,7 +93,7 @@
- name: Verify docker upgrade targets
hosts: oo_masters_to_config:oo_etcd_to_config
tasks:
- - include: ../pre/verify_docker_upgrade_targets.yml
+ - include: ../pre/tasks/verify_docker_upgrade_targets.yml
tags:
- pre_upgrade
diff --git a/playbooks/common/openshift-cluster/upgrades/v3_7/upgrade_nodes.yml b/playbooks/common/openshift-cluster/upgrades/v3_7/upgrade_nodes.yml
index abc4c245b..e95b90cd5 100644
--- a/playbooks/common/openshift-cluster/upgrades/v3_7/upgrade_nodes.yml
+++ b/playbooks/common/openshift-cluster/upgrades/v3_7/upgrade_nodes.yml
@@ -90,7 +90,7 @@
- name: Verify docker upgrade targets
hosts: oo_nodes_to_upgrade
tasks:
- - include: ../pre/verify_docker_upgrade_targets.yml
+ - include: ../pre/tasks/verify_docker_upgrade_targets.yml
tags:
- pre_upgrade
diff --git a/playbooks/common/openshift-cluster/upgrades/v3_7/validator.yml b/playbooks/common/openshift-cluster/upgrades/v3_7/validator.yml
index 90e95422b..f76fc68d1 100644
--- a/playbooks/common/openshift-cluster/upgrades/v3_7/validator.yml
+++ b/playbooks/common/openshift-cluster/upgrades/v3_7/validator.yml
@@ -7,6 +7,17 @@
hosts: oo_first_master
roles:
- { role: lib_openshift }
+
tasks:
- name: Check for invalid namespaces and SDN errors
oc_objectvalidator:
+
+ - name: Confirm OpenShift authorization objects are in sync
+ command: >
+ {{ openshift.common.client_binary }} adm migrate authorization
+ when: not openshift.common.version_gte_3_7 | bool
+ changed_when: false
+ register: l_oc_result
+ until: l_oc_result.rc == 0
+ retries: 4
+ delay: 15
diff --git a/playbooks/common/openshift-etcd/config.yml b/playbooks/common/openshift-etcd/config.yml
index 2cb6197d1..f2b85eea1 100644
--- a/playbooks/common/openshift-etcd/config.yml
+++ b/playbooks/common/openshift-etcd/config.yml
@@ -3,6 +3,7 @@
hosts: oo_etcd_to_config
any_errors_fatal: true
roles:
+ - role: os_firewall
- role: openshift_etcd
etcd_peers: "{{ groups.oo_etcd_to_config | default([], true) }}"
etcd_ca_host: "{{ groups.oo_etcd_to_config.0 }}"
diff --git a/playbooks/common/openshift-etcd/migrate.yml b/playbooks/common/openshift-etcd/migrate.yml
index 3e7a48669..e4ab0aa41 100644
--- a/playbooks/common/openshift-etcd/migrate.yml
+++ b/playbooks/common/openshift-etcd/migrate.yml
@@ -1,34 +1,20 @@
---
-- include: ../openshift-cluster/evaluate_groups.yml
- tags:
- - always
-
- name: Run pre-checks
hosts: oo_etcd_to_migrate
- tags:
- - always
roles:
- role: etcd_migrate
r_etcd_migrate_action: check
r_etcd_common_embedded_etcd: "{{ groups.oo_etcd_to_config | default([]) | length == 0 }}"
etcd_peer: "{{ ansible_default_ipv4.address }}"
-- include: ../openshift-cluster/initialize_facts.yml
- tags:
- - always
-
+# TODO: This will be different for release-3.6 branch
- name: Prepare masters for etcd data migration
hosts: oo_masters_to_config
tasks:
- set_fact:
master_services:
- - "{{ openshift.common.service_type + '-master' }}"
- - set_fact:
- master_services:
- "{{ openshift.common.service_type + '-master-controllers' }}"
- "{{ openshift.common.service_type + '-master-api' }}"
- when:
- - (openshift_master_cluster_method is defined and openshift_master_cluster_method == "native") or openshift.common.is_master_system_container | bool
- debug:
msg: "master service name: {{ master_services }}"
- name: Stop masters
@@ -40,8 +26,6 @@
- name: Backup v2 data
hosts: oo_etcd_to_migrate
gather_facts: no
- tags:
- - always
roles:
- role: openshift_facts
- role: etcd_common
@@ -67,16 +51,53 @@
when:
- etcd_backup_failed | length > 0
-- name: Migrate etcd data from v2 to v3
+- name: Stop etcd
hosts: oo_etcd_to_migrate
gather_facts: no
- tags:
- - always
+ pre_tasks:
+ - set_fact:
+ l_etcd_service: "{{ 'etcd_container' if openshift.common.is_containerized else 'etcd' }}"
+ - name: Disable etcd members
+ service:
+ name: "{{ l_etcd_service }}"
+ state: stopped
+
+- name: Migrate data on first etcd
+ hosts: oo_etcd_to_migrate[0]
+ gather_facts: no
roles:
- role: etcd_migrate
r_etcd_migrate_action: migrate
r_etcd_common_embedded_etcd: "{{ groups.oo_etcd_to_config | default([]) | length == 0 }}"
- etcd_peer: "{{ ansible_default_ipv4.address }}"
+ etcd_peer: "{{ openshift.common.ip }}"
+ etcd_url_scheme: "https"
+ etcd_peer_url_scheme: "https"
+
+- name: Clean data stores on remaining etcd hosts
+ hosts: oo_etcd_to_migrate[1:]
+ gather_facts: no
+ roles:
+ - role: etcd_migrate
+ r_etcd_migrate_action: clean_data
+ r_etcd_common_embedded_etcd: "{{ groups.oo_etcd_to_config | default([]) | length == 0 }}"
+ etcd_peer: "{{ openshift.common.ip }}"
+ etcd_url_scheme: "https"
+ etcd_peer_url_scheme: "https"
+ post_tasks:
+ - name: Add etcd hosts
+ delegate_to: localhost
+ add_host:
+ name: "{{ item }}"
+ groups: oo_new_etcd_to_config
+ ansible_ssh_user: "{{ g_ssh_user | default(omit) }}"
+ ansible_become: "{{ g_sudo | default(omit) }}"
+ with_items: "{{ groups.oo_etcd_to_migrate[1:] | default([]) }}"
+ changed_when: no
+ - name: Set success
+ set_fact:
+ r_etcd_migrate_success: true
+
+- include: ./scaleup.yml
- name: Gate on etcd migration
hosts: oo_masters_to_config
@@ -89,6 +110,16 @@
- set_fact:
etcd_migration_failed: "{{ groups.oo_etcd_to_migrate | difference(etcd_migration_completed) }}"
+- name: Add TTLs on the first master
+ hosts: oo_first_master[0]
+ roles:
+ - role: etcd_migrate
+ r_etcd_migrate_action: add_ttls
+ etcd_peer: "{{ hostvars[groups.oo_etcd_to_migrate.0].openshift.common.ip }}"
+ etcd_url_scheme: "https"
+ etcd_peer_url_scheme: "https"
+ when: etcd_migration_failed | length == 0
+
- name: Configure masters if etcd data migration is succesfull
hosts: oo_masters_to_config
roles:
@@ -100,10 +131,6 @@
msg: "Skipping master re-configuration since migration failed."
when:
- etcd_migration_failed | length > 0
-
-- name: Start masters after etcd data migration
- hosts: oo_masters_to_config
- tasks:
- name: Start master services
service:
name: "{{ item }}"
diff --git a/playbooks/common/openshift-etcd/scaleup.yml b/playbooks/common/openshift-etcd/scaleup.yml
index 192305bc8..d3fa48bad 100644
--- a/playbooks/common/openshift-etcd/scaleup.yml
+++ b/playbooks/common/openshift-etcd/scaleup.yml
@@ -23,16 +23,52 @@
-C {{ etcd_peer_url_scheme }}://{{ hostvars[etcd_ca_host].etcd_hostname }}:{{ etcd_client_port }}
member add {{ etcd_hostname }} {{ etcd_peer_url_scheme }}://{{ etcd_ip }}:{{ etcd_peer_port }}
delegate_to: "{{ etcd_ca_host }}"
+ failed_when:
+ - etcd_add_check.rc == 1
+ - ("peerURL exists" not in etcd_add_check.stderr)
register: etcd_add_check
+ retries: 3
+ delay: 10
+ until: etcd_add_check.rc == 0
roles:
+ - role: os_firewall
+ when: etcd_add_check.rc == 0
- role: openshift_etcd
when: etcd_add_check.rc == 0
etcd_peers: "{{ groups.oo_etcd_to_config | union(groups.oo_new_etcd_to_config)| default([], true) }}"
etcd_ca_host: "{{ groups.oo_etcd_to_config.0 }}"
etcd_certificates_etcd_hosts: "{{ groups.oo_etcd_to_config | default([], true) }}"
etcd_initial_cluster_state: "existing"
- initial_etcd_cluster: "{{ etcd_add_check.stdout_lines[3] | regex_replace('ETCD_INITIAL_CLUSTER=','') }}"
+ initial_etcd_cluster: "{{ etcd_add_check.stdout_lines[3] | regex_replace('ETCD_INITIAL_CLUSTER=','') | regex_replace('\"','') }}"
etcd_ca_setup: False
r_etcd_common_etcd_runtime: "{{ openshift.common.etcd_runtime }}"
- role: nickhammond.logrotate
when: etcd_add_check.rc == 0
+ post_tasks:
+ - name: Verify cluster is stable
+ command: >
+ /usr/bin/etcdctl --cert-file {{ etcd_peer_cert_file }}
+ --key-file {{ etcd_peer_key_file }}
+ --ca-file {{ etcd_peer_ca_file }}
+ -C {{ etcd_peer_url_scheme }}://{{ hostvars[etcd_ca_host].etcd_hostname }}:{{ etcd_client_port }}
+ cluster-health
+ register: scaleup_health
+ retries: 3
+ delay: 30
+ until: scaleup_health.rc == 0
+
+- name: Update master etcd client urls
+ hosts: oo_masters_to_config
+ serial: 1
+ tasks:
+ - include_role:
+ name: openshift_master
+ tasks_from: update_etcd_client_urls
+ vars:
+ etcd_ca_host: "{{ groups.oo_etcd_to_config.0 }}"
+ openshift_ca_host: "{{ groups.oo_first_master.0 }}"
+ openshift_master_etcd_hosts: "{{ hostvars
+ | oo_select_keys(groups['oo_etcd_to_config'] | union(groups['oo_new_etcd_to_config']))
+ | oo_collect('openshift.common.hostname')
+ | default(none, true) }}"
+ openshift_master_etcd_port: "{{ (etcd_client_port | default('2379')) if (groups.oo_etcd_to_config is defined and groups.oo_etcd_to_config) else none }}"
diff --git a/playbooks/common/openshift-etcd/service.yml b/playbooks/common/openshift-etcd/service.yml
deleted file mode 100644
index ced4bddc5..000000000
--- a/playbooks/common/openshift-etcd/service.yml
+++ /dev/null
@@ -1,23 +0,0 @@
----
-- name: Populate g_service_masters host group if needed
- hosts: localhost
- connection: local
- become: no
- gather_facts: no
- tasks:
- - fail: msg="new_cluster_state is required to be injected in this playbook"
- when: new_cluster_state is not defined
-
- - name: Evaluate g_service_etcd
- add_host:
- name: "{{ item }}"
- groups: g_service_etcd
- with_items: "{{ oo_host_group_exp | default([]) }}"
- changed_when: False
-
-- name: Change etcd state on etcd instance(s)
- hosts: g_service_etcd
- connection: ssh
- gather_facts: no
- tasks:
- - service: name=etcd state="{{ new_cluster_state }}"
diff --git a/playbooks/common/openshift-loadbalancer/config.yml b/playbooks/common/openshift-loadbalancer/config.yml
index 2dacc1218..09ed81a83 100644
--- a/playbooks/common/openshift-loadbalancer/config.yml
+++ b/playbooks/common/openshift-loadbalancer/config.yml
@@ -14,4 +14,5 @@
+ openshift_loadbalancer_additional_backends | default([]) }}"
openshift_image_tag: "{{ hostvars[groups.oo_first_master.0].openshift_image_tag }}"
roles:
+ - role: os_firewall
- role: openshift_loadbalancer
diff --git a/playbooks/common/openshift-loadbalancer/service.yml b/playbooks/common/openshift-loadbalancer/service.yml
deleted file mode 100644
index d3762c961..000000000
--- a/playbooks/common/openshift-loadbalancer/service.yml
+++ /dev/null
@@ -1,23 +0,0 @@
----
-- name: Populate g_service_nodes host group if needed
- hosts: localhost
- connection: local
- become: no
- gather_facts: no
- tasks:
- - fail: msg="new_cluster_state is required to be injected in this playbook"
- when: new_cluster_state is not defined
-
- - name: Evaluate g_service_lb
- add_host:
- name: "{{ item }}"
- groups: g_service_lb
- with_items: "{{ oo_host_group_exp | default([]) }}"
- changed_when: False
-
-- name: Change state on lb instance(s)
- hosts: g_service_lb
- connection: ssh
- gather_facts: no
- tasks:
- - service: name=haproxy state="{{ new_cluster_state }}"
diff --git a/playbooks/common/openshift-cluster/additional_config.yml b/playbooks/common/openshift-master/additional_config.yml
index c0ea93d2c..de467a722 100644
--- a/playbooks/common/openshift-cluster/additional_config.yml
+++ b/playbooks/common/openshift-master/additional_config.yml
@@ -11,13 +11,16 @@
when: openshift_master_ha | bool and openshift.master.cluster_method == "pacemaker"
- role: openshift_examples
registry_url: "{{ openshift.master.registry_url }}"
- when: openshift.common.install_examples | bool
+ when: openshift_install_examples | default(True)
- role: openshift_hosted_templates
registry_url: "{{ openshift.master.registry_url }}"
- role: openshift_manageiq
- when: openshift.common.use_manageiq | bool
+ when: openshift_use_manageiq | default(false) | bool
- role: cockpit
- when: not openshift.common.is_atomic and ( deployment_type in ['atomic-enterprise','openshift-enterprise'] ) and
- (osm_use_cockpit | bool or osm_use_cockpit is undefined ) and ( openshift.common.deployment_subtype != 'registry' )
+ when:
+ - openshift.common.is_atomic
+ - deployment_type == 'openshift-enterprise'
+ - osm_use_cockpit is undefined or osm_use_cockpit | bool
+ - openshift.common.deployment_subtype != 'registry'
- role: flannel_register
- when: openshift.common.use_flannel | bool
+ when: openshift_use_flannel | default(false) | bool
diff --git a/playbooks/common/openshift-master/config.yml b/playbooks/common/openshift-master/config.yml
index b30450def..3decbd973 100644
--- a/playbooks/common/openshift-master/config.yml
+++ b/playbooks/common/openshift-master/config.yml
@@ -1,4 +1,12 @@
---
+- name: Disable excluders
+ hosts: oo_masters_to_config
+ gather_facts: no
+ roles:
+ - role: openshift_excluder
+ r_openshift_excluder_action: disable
+ r_openshift_excluder_service_type: "{{ openshift.common.service_type }}"
+
- name: Gather and set facts for master hosts
hosts: oo_masters_to_config
vars:
@@ -27,7 +35,9 @@
file:
path: "/etc/origin/{{ item }}"
state: absent
- when: rpmgenerated_config.stat.exists == true and deployment_type in ['openshift-enterprise', 'atomic-enterprise']
+ when:
+ - rpmgenerated_config.stat.exists == true
+ - deployment_type == 'openshift-enterprise'
with_items:
- master
- node
@@ -171,27 +181,36 @@
openshift_master_count: "{{ openshift.master.master_count }}"
openshift_master_session_auth_secrets: "{{ hostvars[groups.oo_first_master.0].openshift.master.session_auth_secrets }}"
openshift_master_session_encryption_secrets: "{{ hostvars[groups.oo_first_master.0].openshift.master.session_encryption_secrets }}"
- openshift_no_proxy_internal_hostnames: "{{ hostvars | oo_select_keys(groups['oo_nodes_to_config']
- | union(groups['oo_masters_to_config'])
- | union(groups['oo_etcd_to_config'] | default([])))
- | oo_collect('openshift.common.hostname') | default([]) | join (',')
- }}"
- openshift_no_proxy_etcd_host_ips: "{{ hostvars | oo_select_keys(groups['oo_etcd_to_config'] | default([]))
- | oo_collect('openshift.common.ip') | default([]) | join(',')
- }}"
- roles:
- - role: openshift_master
openshift_ca_host: "{{ groups.oo_first_master.0 }}"
openshift_master_etcd_hosts: "{{ hostvars
| oo_select_keys(groups['oo_etcd_to_config'] | default([]))
| oo_collect('openshift.common.hostname')
| default(none, true) }}"
- openshift_master_hosts: "{{ groups.oo_masters_to_config }}"
- r_etcd_common_etcd_runtime: "{{ openshift.common.etcd_runtime }}"
- etcd_ca_host: "{{ groups.oo_etcd_to_config.0 }}"
+ openshift_no_proxy_etcd_host_ips: "{{ hostvars | oo_select_keys(groups['oo_etcd_to_config'] | default([]))
+ | oo_collect('openshift.common.ip') | default([]) | join(',')
+ }}"
+ roles:
+ - role: os_firewall
+ - role: openshift_master_facts
+ - role: openshift_hosted_facts
+ - role: openshift_master_certificates
+ - role: openshift_etcd_client_certificates
etcd_cert_subdir: "openshift-master-{{ openshift.common.hostname }}"
etcd_cert_config_dir: "{{ openshift.common.config_base }}/master"
etcd_cert_prefix: "master.etcd-"
+ r_etcd_common_etcd_runtime: "{{ openshift.common.etcd_runtime }}"
+ etcd_ca_host: "{{ groups.oo_etcd_to_config.0 }}"
+ when: groups.oo_etcd_to_config | default([]) | length != 0
+ - role: openshift_clock
+ - role: openshift_cloud_provider
+ - role: openshift_builddefaults
+ - role: openshift_buildoverrides
+ - role: nickhammond.logrotate
+ - role: contiv
+ contiv_role: netmaster
+ when: openshift_use_contiv | default(False) | bool
+ - role: openshift_master
+ openshift_master_hosts: "{{ groups.oo_masters_to_config }}"
r_openshift_master_clean_install: "{{ hostvars[groups.oo_first_master.0].l_clean_install }}"
r_openshift_master_etcd3_storage: "{{ hostvars[groups.oo_first_master.0].l_etcd3_enabled }}"
openshift_master_is_scaleup_host: "{{ g_openshift_master_is_scaleup | default(false) }}"
@@ -199,11 +218,18 @@
openshift_master_default_registry_value_api: "{{ hostvars[groups.oo_first_master.0].l_default_registry_value_api }}"
openshift_master_default_registry_value_controllers: "{{ hostvars[groups.oo_first_master.0].l_default_registry_value_controllers }}"
- role: nuage_master
- when: openshift.common.use_nuage | bool
+ when: openshift_use_nuage | default(false) | bool
- role: calico_master
- when: openshift.common.use_calico | bool
-
+ when: openshift_use_calico | default(false) | bool
post_tasks:
- name: Create group for deployment type
group_by: key=oo_masters_deployment_type_{{ openshift.common.deployment_type }}
changed_when: False
+
+- name: Re-enable excluder if it was previously enabled
+ hosts: oo_masters_to_config
+ gather_facts: no
+ roles:
+ - role: openshift_excluder
+ r_openshift_excluder_action: enable
+ r_openshift_excluder_service_type: "{{ openshift.common.service_type }}"
diff --git a/playbooks/common/openshift-master/restart.yml b/playbooks/common/openshift-master/restart.yml
index 6fec346c3..4d73b8124 100644
--- a/playbooks/common/openshift-master/restart.yml
+++ b/playbooks/common/openshift-master/restart.yml
@@ -7,7 +7,7 @@
openshift_master_ha: "{{ groups.oo_masters_to_config | length > 1 }}"
serial: 1
handlers:
- - include: roles/openshift_master/handlers/main.yml
+ - include: ../../../roles/openshift_master/handlers/main.yml
static: yes
roles:
- openshift_facts
diff --git a/playbooks/common/openshift-master/scaleup.yml b/playbooks/common/openshift-master/scaleup.yml
index bc61ee9bb..17f9ef4bc 100644
--- a/playbooks/common/openshift-master/scaleup.yml
+++ b/playbooks/common/openshift-master/scaleup.yml
@@ -1,11 +1,4 @@
---
-- include: ../openshift-cluster/evaluate_groups.yml
-
-- name: Gather facts
- hosts: oo_etcd_to_config:oo_masters_to_config:oo_nodes_to_config
- roles:
- - openshift_facts
-
- name: Update master count
hosts: oo_masters:!oo_masters_to_config
serial: 1
@@ -50,38 +43,8 @@
delay: 1
changed_when: false
-- name: Configure docker hosts
- hosts: oo_masters_to_config:oo_nodes_to_config
- vars:
- docker_additional_registries: "{{ lookup('oo_option', 'docker_additional_registries') | oo_split }}"
- docker_insecure_registries: "{{ lookup('oo_option', 'docker_insecure_registries') | oo_split }}"
- docker_blocked_registries: "{{ lookup('oo_option', 'docker_blocked_registries') | oo_split }}"
- roles:
- - openshift_facts
- - openshift_docker
-
-- name: Disable excluders
- hosts: oo_masters_to_config
- tags:
- - always
- gather_facts: no
- roles:
- - role: openshift_excluder
- r_openshift_excluder_action: disable
- r_openshift_excluder_service_type: "{{ openshift.common.service_type }}"
-
- include: ../openshift-master/config.yml
- include: ../openshift-loadbalancer/config.yml
- include: ../openshift-node/config.yml
-
-- name: Re-enable excluder if it was previously enabled
- hosts: oo_masters_to_config
- tags:
- - always
- gather_facts: no
- roles:
- - role: openshift_excluder
- r_openshift_excluder_action: enable
- r_openshift_excluder_service_type: "{{ openshift.common.service_type }}"
diff --git a/playbooks/common/openshift-master/service.yml b/playbooks/common/openshift-master/service.yml
deleted file mode 100644
index 48a2731aa..000000000
--- a/playbooks/common/openshift-master/service.yml
+++ /dev/null
@@ -1,23 +0,0 @@
----
-- name: Populate g_service_masters host group if needed
- hosts: localhost
- gather_facts: no
- connection: local
- become: no
- tasks:
- - fail: msg="new_cluster_state is required to be injected in this playbook"
- when: new_cluster_state is not defined
-
- - name: Evaluate g_service_masters
- add_host:
- name: "{{ item }}"
- groups: g_service_masters
- with_items: "{{ oo_host_group_exp | default([]) }}"
- changed_when: False
-
-- name: Change state on master instance(s)
- hosts: g_service_masters
- connection: ssh
- gather_facts: no
- tasks:
- - service: name={{ openshift.common.service_type }}-master state="{{ new_cluster_state }}"
diff --git a/playbooks/common/openshift-nfs/config.yml b/playbooks/common/openshift-nfs/config.yml
index 000e46e80..64ea0d3c4 100644
--- a/playbooks/common/openshift-nfs/config.yml
+++ b/playbooks/common/openshift-nfs/config.yml
@@ -2,5 +2,5 @@
- name: Configure nfs
hosts: oo_nfs_to_config
roles:
- - role: openshift_facts
+ - role: os_firewall
- role: openshift_storage_nfs
diff --git a/playbooks/common/openshift-nfs/service.yml b/playbooks/common/openshift-nfs/service.yml
deleted file mode 100644
index b1e35e4b1..000000000
--- a/playbooks/common/openshift-nfs/service.yml
+++ /dev/null
@@ -1,21 +0,0 @@
----
-- name: Populate g_service_nfs host group if needed
- hosts: localhost
- gather_facts: no
- tasks:
- - fail: msg="new_cluster_state is required to be injected in this playbook"
- when: new_cluster_state is not defined
-
- - name: Evaluate g_service_nfs
- add_host:
- name: "{{ item }}"
- groups: g_service_nfs
- with_items: "{{ oo_host_group_exp | default([]) }}"
- changed_when: False
-
-- name: Change state on nfs instance(s)
- hosts: g_service_nfs
- connection: ssh
- gather_facts: no
- tasks:
- - service: name=nfs-server state="{{ new_cluster_state }}"
diff --git a/playbooks/common/openshift-node/config.yml b/playbooks/common/openshift-node/config.yml
index ef7d54f9f..0801c41ff 100644
--- a/playbooks/common/openshift-node/config.yml
+++ b/playbooks/common/openshift-node/config.yml
@@ -1,4 +1,12 @@
---
+- name: Disable excluders
+ hosts: oo_nodes_to_config
+ gather_facts: no
+ roles:
+ - role: openshift_excluder
+ r_openshift_excluder_action: disable
+ r_openshift_excluder_service_type: "{{ openshift.common.service_type }}"
+
- name: Evaluate node groups
hosts: localhost
become: no
@@ -32,6 +40,7 @@
}}"
roles:
+ - role: os_firewall
- role: openshift_node
openshift_ca_host: "{{ groups.oo_first_master.0 }}"
@@ -47,6 +56,7 @@
| oo_collect('openshift.common.hostname') | default([]) | join (',')
}}"
roles:
+ - role: os_firewall
- role: openshift_node
openshift_ca_host: "{{ groups.oo_first_master.0 }}"
@@ -61,18 +71,27 @@
etcd_ca_host: "{{ groups.oo_etcd_to_config.0 }}"
etcd_cert_subdir: "openshift-node-{{ openshift.common.hostname }}"
etcd_cert_config_dir: "{{ openshift.common.config_base }}/node"
- when: openshift.common.use_flannel | bool
+ when: openshift_use_flannel | default(false) | bool
- role: calico
- when: openshift.common.use_calico | bool
+ when: openshift_use_calico | default(false) | bool
- role: nuage_node
- when: openshift.common.use_nuage | bool
+ when: openshift_use_nuage | default(false) | bool
- role: contiv
contiv_role: netplugin
- when: openshift.common.use_contiv | bool
+ when: openshift_use_contiv | default(false) | bool
- role: nickhammond.logrotate
- role: openshift_manage_node
openshift_master_host: "{{ groups.oo_first_master.0 }}"
+ when: not openshift_node_bootstrap | default(False)
tasks:
- name: Create group for deployment type
group_by: key=oo_nodes_deployment_type_{{ openshift.common.deployment_type }}
changed_when: False
+
+- name: Re-enable excluder if it was previously enabled
+ hosts: oo_nodes_to_config
+ gather_facts: no
+ roles:
+ - role: openshift_excluder
+ r_openshift_excluder_action: enable
+ r_openshift_excluder_service_type: "{{ openshift.common.service_type }}"
diff --git a/playbooks/common/openshift-node/scaleup.yml b/playbooks/common/openshift-node/scaleup.yml
deleted file mode 100644
index 40da8990d..000000000
--- a/playbooks/common/openshift-node/scaleup.yml
+++ /dev/null
@@ -1,50 +0,0 @@
----
-- include: ../openshift-cluster/evaluate_groups.yml
-
-- name: Gather facts
- hosts: oo_etcd_to_config:oo_masters_to_config:oo_nodes_to_config
- roles:
- - openshift_facts
-
-- name: Gather and set facts for first master
- hosts: oo_first_master
- vars:
- openshift_master_count: "{{ groups.oo_masters | length }}"
- pre_tasks:
- - set_fact:
- openshift_master_default_subdomain: "{{ lookup('oo_option', 'openshift_master_default_subdomain') | default(None, true) }}"
- when: openshift_master_default_subdomain is not defined
- roles:
- - openshift_master_facts
-
-- name: Configure docker hosts
- hosts: oo_nodes_to_config
- vars:
- docker_additional_registries: "{{ lookup('oo_option', 'docker_additional_registries') | oo_split }}"
- docker_insecure_registries: "{{ lookup('oo_option', 'docker_insecure_registries') | oo_split }}"
- docker_blocked_registries: "{{ lookup('oo_option', 'docker_blocked_registries') | oo_split }}"
- roles:
- - openshift_facts
- - openshift_docker
-
-- name: Disable excluders
- hosts: oo_nodes_to_config
- tags:
- - always
- gather_facts: no
- roles:
- - role: openshift_excluder
- r_openshift_excluder_action: disable
- r_openshift_excluder_service_type: "{{ openshift.common.service_type }}"
-
-- include: ../openshift-node/config.yml
-
-- name: Re-enable excluder if it was previously enabled
- hosts: oo_nodes_to_config
- tags:
- - always
- gather_facts: no
- roles:
- - role: openshift_excluder
- r_openshift_excluder_action: enable
- r_openshift_excluder_service_type: "{{ openshift.common.service_type }}"
diff --git a/playbooks/common/openshift-node/service.yml b/playbooks/common/openshift-node/service.yml
deleted file mode 100644
index 130a5416f..000000000
--- a/playbooks/common/openshift-node/service.yml
+++ /dev/null
@@ -1,26 +0,0 @@
----
-- name: Populate g_service_nodes host group if needed
- hosts: localhost
- connection: local
- become: no
- gather_facts: no
- tasks:
- - fail: msg="new_cluster_state is required to be injected in this playbook"
- when: new_cluster_state is not defined
-
- - name: Evaluate g_service_nodes
- add_host:
- name: "{{ item }}"
- groups: g_service_nodes
- with_items: "{{ oo_host_group_exp | default([]) }}"
- changed_when: False
-
-- name: Change state on node instance(s)
- hosts: g_service_nodes
- connection: ssh
- gather_facts: no
- tasks:
- - name: Change state on node instance(s)
- service:
- name: "{{ service_type }}-node"
- state: "{{ new_cluster_state }}"
diff --git a/playbooks/gce/README.md b/playbooks/gce/README.md
deleted file mode 100644
index 0514d6f50..000000000
--- a/playbooks/gce/README.md
+++ /dev/null
@@ -1,4 +0,0 @@
-# GCE playbooks
-
-This playbook directory is meant to be driven by [`bin/cluster`](../../bin),
-which is community supported and most use is considered deprecated.
diff --git a/playbooks/gce/openshift-cluster/add_nodes.yml b/playbooks/gce/openshift-cluster/add_nodes.yml
deleted file mode 100644
index 765e03fdc..000000000
--- a/playbooks/gce/openshift-cluster/add_nodes.yml
+++ /dev/null
@@ -1,43 +0,0 @@
----
-- name: Launch instance(s)
- hosts: localhost
- connection: local
- become: no
- gather_facts: no
- vars_files:
- - vars.yml
- vars:
- oo_extend_env: True
- tasks:
- - fail:
- msg: Deployment type not supported for gce provider yet
- when: deployment_type == 'enterprise'
-
- - include: ../../common/openshift-cluster/tasks/set_node_launch_facts.yml
- vars:
- type: "compute"
- count: "{{ num_nodes }}"
- - include: tasks/launch_instances.yml
- vars:
- instances: "{{ node_names }}"
- cluster: "{{ cluster_id }}"
- type: "{{ k8s_type }}"
- g_sub_host_type: "{{ sub_host_type }}"
- gce_machine_type: "{{ lookup('env', 'gce_machine_node_type') | default(lookup('env', 'gce_machine_type'), true) }}"
- gce_machine_image: "{{ lookup('env', 'gce_machine_node_image') | default(lookup('env', 'gce_machine_image'), true) }}"
-
- - include: ../../common/openshift-cluster/tasks/set_node_launch_facts.yml
- vars:
- type: "infra"
- count: "{{ num_infra }}"
- - include: tasks/launch_instances.yml
- vars:
- instances: "{{ node_names }}"
- cluster: "{{ cluster_id }}"
- type: "{{ k8s_type }}"
- g_sub_host_type: "{{ sub_host_type }}"
- gce_machine_type: "{{ lookup('env', 'gce_machine_node_type') | default(lookup('env', 'gce_machine_type'), true) }}"
- gce_machine_image: "{{ lookup('env', 'gce_machine_node_image') | default(lookup('env', 'gce_machine_image'), true) }}"
-
-- include: scaleup.yml
-- include: list.yml
diff --git a/playbooks/gce/openshift-cluster/cluster_hosts.yml b/playbooks/gce/openshift-cluster/cluster_hosts.yml
deleted file mode 100644
index e5f41382b..000000000
--- a/playbooks/gce/openshift-cluster/cluster_hosts.yml
+++ /dev/null
@@ -1,25 +0,0 @@
----
-g_all_hosts: "{{ groups['tag_clusterid-' ~ cluster_id] | default([])
- | intersect(groups['tag_environment-' ~ cluster_env] | default([])) }}"
-
-g_etcd_hosts: "{{ g_all_hosts | intersect(groups['tag_host-type-etcd'] | default([])) }}"
-
-g_new_etcd_hosts: "{{ g_all_hosts | intersect(groups['tag_host-type-new_etcd'] | default([])) }}"
-
-g_lb_hosts: "{{ g_all_hosts | intersect(groups['tag_host-type-lb'] | default([])) }}"
-
-g_nfs_hosts: "{{ g_all_hosts | intersect(groups['tag_host-type-nfs'] | default([])) }}"
-
-g_glusterfs_hosts: "{{ g_all_hosts | intersect(groups['tag_host-type-glusterfs'] | default([])) }}"
-
-g_master_hosts: "{{ g_all_hosts | intersect(groups['tag_host-type-master'] | default([])) }}"
-
-g_new_master_hosts: "{{ g_all_hosts | intersect(groups['tag_host-type-new-master'] | default([])) }}"
-
-g_node_hosts: "{{ g_all_hosts | intersect(groups['tag_host-type-node'] | default([])) }}"
-
-g_new_node_hosts: "{{ g_all_hosts | intersect(groups['tag_host-type-new-node'] | default([])) }}"
-
-g_infra_hosts: "{{ g_node_hosts | intersect(groups['tag_sub-host-type-infra'] | default([])) }}"
-
-g_compute_hosts: "{{ g_node_hosts | intersect(groups['tag_sub-host-type-compute'] | default([])) }}"
diff --git a/playbooks/gce/openshift-cluster/config.yml b/playbooks/gce/openshift-cluster/config.yml
deleted file mode 100644
index 2625d4d05..000000000
--- a/playbooks/gce/openshift-cluster/config.yml
+++ /dev/null
@@ -1,36 +0,0 @@
----
-- hosts: localhost
- gather_facts: no
- tasks:
- - include_vars: vars.yml
- - include_vars: cluster_hosts.yml
- - add_host:
- name: "{{ item }}"
- groups: l_oo_all_hosts
- ansible_ssh_user: "{{ deployment_vars[deployment_type].ssh_user }}"
- ansible_become: "{{ deployment_vars[deployment_type].become }}"
- with_items: "{{ g_all_hosts | default([]) }}"
-
-- hosts: l_oo_all_hosts
- gather_facts: no
- tasks:
- - include_vars: vars.yml
- - include_vars: cluster_hosts.yml
-
-- include: ../../common/openshift-cluster/config.yml
- vars:
- g_ssh_user: "{{ deployment_vars[deployment_type].ssh_user }}"
- g_sudo: "{{ deployment_vars[deployment_type].become }}"
- g_nodeonmaster: true
- openshift_cluster_id: "{{ cluster_id }}"
- openshift_debug_level: "{{ debug_level }}"
- openshift_deployment_type: "{{ deployment_type }}"
- openshift_hostname: "{{ gce_private_ip }}"
- openshift_hosted_registry_selector: 'type=infra'
- openshift_hosted_router_selector: 'type=infra'
- openshift_master_cluster_method: 'native'
- openshift_use_openshift_sdn: "{{ lookup('oo_option', 'use_openshift_sdn') }}"
- os_sdn_network_plugin_name: "{{ lookup('oo_option', 'sdn_network_plugin_name') }}"
- openshift_use_flannel: "{{ lookup('oo_option', 'use_flannel') }}"
- openshift_use_calico: "{{ lookup('oo_option', 'use_calico') }}"
- openshift_use_fluentd: "{{ lookup('oo_option', 'use_fluentd') }}"
diff --git a/playbooks/gce/openshift-cluster/filter_plugins b/playbooks/gce/openshift-cluster/filter_plugins
deleted file mode 120000
index 99a95e4ca..000000000
--- a/playbooks/gce/openshift-cluster/filter_plugins
+++ /dev/null
@@ -1 +0,0 @@
-../../../filter_plugins \ No newline at end of file
diff --git a/playbooks/gce/openshift-cluster/launch.yml b/playbooks/gce/openshift-cluster/launch.yml
deleted file mode 100644
index 7532a678b..000000000
--- a/playbooks/gce/openshift-cluster/launch.yml
+++ /dev/null
@@ -1,67 +0,0 @@
----
-- name: Launch instance(s)
- hosts: localhost
- connection: local
- become: no
- gather_facts: no
- vars_files:
- - vars.yml
- tasks:
- - fail: msg="Deployment type not supported for gce provider yet"
- when: deployment_type == 'enterprise'
-
- - include: ../../common/openshift-cluster/tasks/set_etcd_launch_facts.yml
- - include: tasks/launch_instances.yml
- vars:
- instances: "{{ etcd_names }}"
- cluster: "{{ cluster_id }}"
- type: "{{ k8s_type }}"
- g_sub_host_type: "default"
- gce_machine_type: "{{ lookup('env', 'gce_machine_etcd_type') | default(lookup('env', 'gce_machine_type'), true) }}"
- gce_machine_image: "{{ lookup('env', 'gce_machine_etcd_image') | default(lookup('env', 'gce_machine_image'), true) }}"
-
-
- - include: ../../common/openshift-cluster/tasks/set_master_launch_facts.yml
- - include: tasks/launch_instances.yml
- vars:
- instances: "{{ master_names }}"
- cluster: "{{ cluster_id }}"
- type: "{{ k8s_type }}"
- g_sub_host_type: "default"
- gce_machine_type: "{{ lookup('env', 'gce_machine_master_type') | default(lookup('env', 'gce_machine_type'), true) }}"
- gce_machine_image: "{{ lookup('env', 'gce_machine_master_image') | default(lookup('env', 'gce_machine_image'), true) }}"
-
- - include: ../../common/openshift-cluster/tasks/set_node_launch_facts.yml
- vars:
- type: "compute"
- count: "{{ num_nodes }}"
- - include: tasks/launch_instances.yml
- vars:
- instances: "{{ node_names }}"
- cluster: "{{ cluster_id }}"
- type: "{{ k8s_type }}"
- g_sub_host_type: "{{ sub_host_type }}"
- gce_machine_type: "{{ lookup('env', 'gce_machine_node_type') | default(lookup('env', 'gce_machine_type'), true) }}"
- gce_machine_image: "{{ lookup('env', 'gce_machine_node_image') | default(lookup('env', 'gce_machine_image'), true) }}"
-
- - include: ../../common/openshift-cluster/tasks/set_node_launch_facts.yml
- vars:
- type: "infra"
- count: "{{ num_infra }}"
- - include: tasks/launch_instances.yml
- vars:
- instances: "{{ node_names }}"
- cluster: "{{ cluster_id }}"
- type: "{{ k8s_type }}"
- g_sub_host_type: "{{ sub_host_type }}"
- gce_machine_type: "{{ lookup('env', 'gce_machine_node_type') | default(lookup('env', 'gce_machine_type'), true) }}"
- gce_machine_image: "{{ lookup('env', 'gce_machine_node_image') | default(lookup('env', 'gce_machine_image'), true) }}"
-
- - add_host:
- name: "{{ master_names.0 }}"
- groups: service_master
- when: master_names is defined and master_names.0 is defined
-
-- include: update.yml
-
-- include: list.yml
diff --git a/playbooks/gce/openshift-cluster/list.yml b/playbooks/gce/openshift-cluster/list.yml
deleted file mode 100644
index 34ab09533..000000000
--- a/playbooks/gce/openshift-cluster/list.yml
+++ /dev/null
@@ -1,23 +0,0 @@
----
-- name: Generate oo_list_hosts group
- hosts: localhost
- connection: local
- become: no
- gather_facts: no
- vars_files:
- - vars.yml
- tasks:
- - set_fact: scratch_group=tag_clusterid-{{ cluster_id }}
- when: cluster_id != ''
- - set_fact: scratch_group=all
- when: cluster_id == ''
- - add_host:
- name: "{{ item }}"
- groups: oo_list_hosts
- ansible_ssh_user: "{{ deployment_vars[deployment_type].ssh_user }}"
- ansible_become: "{{ deployment_vars[deployment_type].become }}"
- oo_public_ipv4: "{{ hostvars[item].gce_public_ip }}"
- oo_private_ipv4: "{{ hostvars[item].gce_private_ip }}"
- with_items: "{{ groups[scratch_group] | default([], true) | difference(['localhost']) | difference(groups.status_terminated | default([], true)) }}"
- - debug:
- msg: "{{ hostvars | oo_select_keys(groups[scratch_group] | default([])) | oo_pretty_print_cluster }}"
diff --git a/playbooks/gce/openshift-cluster/lookup_plugins b/playbooks/gce/openshift-cluster/lookup_plugins
deleted file mode 120000
index ac79701db..000000000
--- a/playbooks/gce/openshift-cluster/lookup_plugins
+++ /dev/null
@@ -1 +0,0 @@
-../../../lookup_plugins \ No newline at end of file
diff --git a/playbooks/gce/openshift-cluster/service.yml b/playbooks/gce/openshift-cluster/service.yml
deleted file mode 100644
index 13b267976..000000000
--- a/playbooks/gce/openshift-cluster/service.yml
+++ /dev/null
@@ -1,29 +0,0 @@
----
-- name: Call same systemctl command for openshift on all instance(s)
- hosts: localhost
- connection: local
- become: no
- gather_facts: no
- vars_files:
- - vars.yml
- - cluster_hosts.yml
- tasks:
- - fail: msg="cluster_id is required to be injected in this playbook"
- when: cluster_id is not defined
-
- - add_host:
- name: "{{ item }}"
- groups: g_service_nodes
- ansible_ssh_user: "{{ deployment_vars[deployment_type].ssh_user }}"
- ansible_become: "{{ deployment_vars[deployment_type].become }}"
- with_items: "{{ node_hosts | default([]) | difference(['localhost']) | difference(groups.status_terminated) }}"
-
- - add_host:
- name: "{{ item }}"
- groups: g_service_masters
- ansible_ssh_user: "{{ deployment_vars[deployment_type].ssh_user }}"
- ansible_become: "{{ deployment_vars[deployment_type].become }}"
- with_items: "{{ master_hosts | default([]) | difference(['localhost']) | difference(groups.status_terminated) }}"
-
-- include: ../../common/openshift-node/service.yml
-- include: ../../common/openshift-master/service.yml
diff --git a/playbooks/gce/openshift-cluster/tasks/launch_instances.yml b/playbooks/gce/openshift-cluster/tasks/launch_instances.yml
deleted file mode 100644
index 65dd2b71e..000000000
--- a/playbooks/gce/openshift-cluster/tasks/launch_instances.yml
+++ /dev/null
@@ -1,65 +0,0 @@
----
-- name: Launch instance(s)
- gce:
- instance_names: "{{ instances|join(',') }}"
- machine_type: "{{ gce_machine_type | default(deployment_vars[deployment_type].machine_type, true) }}"
- image: "{{ gce_machine_image | default(deployment_vars[deployment_type].image, true) }}"
- service_account_email: "{{ lookup('env', 'gce_service_account_email_address') }}"
- pem_file: "{{ lookup('env', 'gce_service_account_pem_file_path') }}"
- project_id: "{{ lookup('env', 'gce_project_id') }}"
- zone: "{{ lookup('env', 'zone') }}"
- network: "{{ lookup('env', 'network') }}"
- subnetwork: "{{ lookup('env', 'subnetwork') | default(omit, True) }}"
- # unsupported in 1.9.+
- #service_account_permissions: "datastore,logging-write"
- tags:
- - created-by-{{ lookup('env', 'LOGNAME') | regex_replace('[^a-z0-9]+', '') | default(cluster, true) }}
- - environment-{{ cluster_env }}
- - clusterid-{{ cluster_id }}
- - host-type-{{ type }}
- - sub-host-type-{{ g_sub_host_type }}
- metadata:
- startup-script: |
- #!/bin/bash
- echo "Defaults:{{ deployment_vars[deployment_type].ssh_user }} !requiretty" > /etc/sudoers.d/99-{{ deployment_vars[deployment_type].ssh_user }}
-
- when: instances |length > 0
- register: gce
-
-- set_fact:
- node_label:
- # There doesn't seem to be a way to get the region directly, so parse it out of the zone.
- region: "{{ gce.zone | regex_replace('^(.*)-.*$', '\\\\1') }}"
- type: "{{ g_sub_host_type }}"
- when: instances |length > 0 and type == "node"
-
-- set_fact:
- node_label:
- # There doesn't seem to be a way to get the region directly, so parse it out of the zone.
- region: "{{ gce.zone | regex_replace('^(.*)-.*$', '\\\\1') }}"
- type: "{{ type }}"
- when: instances |length > 0 and type != "node"
-
-- name: Add new instances to groups and set variables needed
- add_host:
- hostname: "{{ item.name }}"
- ansible_ssh_host: "{{ item.public_ip }}"
- ansible_ssh_user: "{{ deployment_vars[deployment_type].ssh_user }}"
- ansible_become: "{{ deployment_vars[deployment_type].become }}"
- groups: "{{ item.tags | oo_prepend_strings_in_list('tag_') | join(',') }}"
- gce_public_ip: "{{ item.public_ip }}"
- gce_private_ip: "{{ item.private_ip }}"
- openshift_node_labels: "{{ node_label }}"
- with_items: "{{ gce.instance_data | default([], true) }}"
-
-- name: Wait for ssh
- wait_for: port=22 host={{ item.public_ip }}
- with_items: "{{ gce.instance_data | default([], true) }}"
-
-- name: Wait for user setup
- command: "ssh -o StrictHostKeyChecking=no -o PasswordAuthentication=no -o ConnectTimeout=10 -o UserKnownHostsFile=/dev/null {{ hostvars[item.name].ansible_ssh_user }}@{{ item.public_ip }} echo {{ hostvars[item.name].ansible_ssh_user }} user is setup"
- register: result
- until: result.rc == 0
- retries: 30
- delay: 5
- with_items: "{{ gce.instance_data | default([], true) }}"
diff --git a/playbooks/gce/openshift-cluster/terminate.yml b/playbooks/gce/openshift-cluster/terminate.yml
deleted file mode 100644
index afe269b7c..000000000
--- a/playbooks/gce/openshift-cluster/terminate.yml
+++ /dev/null
@@ -1,58 +0,0 @@
----
-- name: Terminate instance(s)
- hosts: localhost
- connection: local
- become: no
- gather_facts: no
- vars_files:
- - vars.yml
- tasks:
- - add_host:
- name: "{{ item }}"
- groups: oo_hosts_to_terminate
- ansible_ssh_user: "{{ deployment_vars[deployment_type].ssh_user }}"
- ansible_become: "{{ deployment_vars[deployment_type].become }}"
- with_items: "{{ (groups['tag_clusterid-' ~ cluster_id] | default([])) | difference(['localhost']) }}"
-
-- name: Unsubscribe VMs
- hosts: oo_hosts_to_terminate
- vars_files:
- - vars.yml
- roles:
- - role: rhel_unsubscribe
- when: deployment_type in ['atomic-enterprise', 'enterprise', 'openshift-enterprise'] and
- ansible_distribution == "RedHat" and
- lookup('oo_option', 'rhel_skip_subscription') | default(rhsub_skip, True) |
- default('no', True) | lower in ['no', 'false']
-
-- name: Terminate instances(s)
- hosts: localhost
- become: no
- connection: local
- gather_facts: no
- vars_files:
- - vars.yml
- tasks:
- - name: Terminate instances that were previously launched
- local_action:
- module: gce
- state: 'absent'
- name: "{{ item }}"
- service_account_email: "{{ lookup('env', 'gce_service_account_email_address') }}"
- pem_file: "{{ lookup('env', 'gce_service_account_pem_file_path') }}"
- project_id: "{{ lookup('env', 'gce_project_id') }}"
- zone: "{{ lookup('env', 'zone') }}"
- with_items: "{{ groups['oo_hosts_to_terminate'] | default([], true) }}"
- when: item is defined
-
-#- include: ../openshift-node/terminate.yml
-# vars:
-# gce_service_account_email: "{{ lookup('env', 'gce_service_account_email_address') }}"
-# gce_pem_file: "{{ lookup('env', 'gce_service_account_pem_file_path') }}"
-# gce_project_id: "{{ lookup('env', 'gce_project_id') }}"
-#
-#- include: ../openshift-master/terminate.yml
-# vars:
-# gce_service_account_email: "{{ lookup('env', 'gce_service_account_email_address') }}"
-# gce_pem_file: "{{ lookup('env', 'gce_service_account_pem_file_path') }}"
-# gce_project_id: "{{ lookup('env', 'gce_project_id') }}"
diff --git a/playbooks/gce/openshift-cluster/update.yml b/playbooks/gce/openshift-cluster/update.yml
deleted file mode 100644
index 6d2af3d26..000000000
--- a/playbooks/gce/openshift-cluster/update.yml
+++ /dev/null
@@ -1,34 +0,0 @@
----
-- hosts: localhost
- gather_facts: no
- tasks:
- - include_vars: vars.yml
- - include_vars: cluster_hosts.yml
- - add_host:
- name: "{{ item }}"
- groups: l_oo_all_hosts
- with_items: "{{ g_all_hosts }}"
-
-- hosts: l_oo_all_hosts
- gather_facts: no
- tasks:
- - include_vars: vars.yml
- - include_vars: cluster_hosts.yml
-
-- name: Populate oo_hosts_to_update group
- hosts: localhost
- connection: local
- become: no
- gather_facts: no
- tasks:
- - name: Evaluate oo_hosts_to_update
- add_host:
- name: "{{ item }}"
- groups: oo_hosts_to_update
- ansible_ssh_user: "{{ deployment_vars[deployment_type].ssh_user }}"
- ansible_become: "{{ deployment_vars[deployment_type].become }}"
- with_items: "{{ g_all_hosts | default([]) }}"
-
-- include: ../../common/openshift-cluster/update_repos_and_packages.yml
-
-- include: config.yml
diff --git a/playbooks/gce/openshift-cluster/vars.yml b/playbooks/gce/openshift-cluster/vars.yml
deleted file mode 100644
index 13c754c1e..000000000
--- a/playbooks/gce/openshift-cluster/vars.yml
+++ /dev/null
@@ -1,18 +0,0 @@
----
-debug_level: 2
-
-deployment_rhel7_ent_base:
- image: "{{ lookup('oo_option', 'image_name') | default('rhel-7', True) }}"
- machine_type: "{{ lookup('oo_option', 'machine_type') | default('n1-standard-1', True) }}"
- ssh_user: "{{ lookup('env', 'gce_ssh_user') | default(ansible_ssh_user, true) }}"
- become: yes
-
-deployment_vars:
- origin:
- image: "{{ lookup('oo_option', 'image_name') | default('centos-7', True) }}"
- machine_type: "{{ lookup('oo_option', 'machine_type') | default('n1-standard-1', True) }}"
- ssh_user: "{{ lookup('env', 'gce_ssh_user') | default(ansible_ssh_user, true) }}"
- become: yes
- enterprise: "{{ deployment_rhel7_ent_base }}"
- openshift-enterprise: "{{ deployment_rhel7_ent_base }}"
- atomic-enterprise: "{{ deployment_rhel7_ent_base }}"
diff --git a/playbooks/gcp/openshift-cluster/provision.yml b/playbooks/gcp/openshift-cluster/provision.yml
new file mode 100644
index 000000000..a3d1d46a6
--- /dev/null
+++ b/playbooks/gcp/openshift-cluster/provision.yml
@@ -0,0 +1,19 @@
+---
+- name: Ensure all cloud resources necessary for the cluster, including instances, have been started
+ hosts: localhost
+ connection: local
+ gather_facts: no
+ tasks:
+
+ - name: provision a GCP cluster in the specified project
+ include_role:
+ name: openshift_gcp
+
+- name: normalize groups
+ include: ../../byo/openshift-cluster/initialize_groups.yml
+
+- name: run the std_include
+ include: ../../common/openshift-cluster/std_include.yml
+
+- name: run the config
+ include: ../../common/openshift-cluster/config.yml
diff --git a/playbooks/libvirt/README.md b/playbooks/libvirt/README.md
deleted file mode 100644
index 3ce46a76f..000000000
--- a/playbooks/libvirt/README.md
+++ /dev/null
@@ -1,4 +0,0 @@
-# libvirt playbooks
-
-This playbook directory is meant to be driven by [`bin/cluster`](../../bin),
-which is community supported and most use is considered deprecated.
diff --git a/playbooks/libvirt/openshift-cluster/cluster_hosts.yml b/playbooks/libvirt/openshift-cluster/cluster_hosts.yml
deleted file mode 100644
index e5f41382b..000000000
--- a/playbooks/libvirt/openshift-cluster/cluster_hosts.yml
+++ /dev/null
@@ -1,25 +0,0 @@
----
-g_all_hosts: "{{ groups['tag_clusterid-' ~ cluster_id] | default([])
- | intersect(groups['tag_environment-' ~ cluster_env] | default([])) }}"
-
-g_etcd_hosts: "{{ g_all_hosts | intersect(groups['tag_host-type-etcd'] | default([])) }}"
-
-g_new_etcd_hosts: "{{ g_all_hosts | intersect(groups['tag_host-type-new_etcd'] | default([])) }}"
-
-g_lb_hosts: "{{ g_all_hosts | intersect(groups['tag_host-type-lb'] | default([])) }}"
-
-g_nfs_hosts: "{{ g_all_hosts | intersect(groups['tag_host-type-nfs'] | default([])) }}"
-
-g_glusterfs_hosts: "{{ g_all_hosts | intersect(groups['tag_host-type-glusterfs'] | default([])) }}"
-
-g_master_hosts: "{{ g_all_hosts | intersect(groups['tag_host-type-master'] | default([])) }}"
-
-g_new_master_hosts: "{{ g_all_hosts | intersect(groups['tag_host-type-new-master'] | default([])) }}"
-
-g_node_hosts: "{{ g_all_hosts | intersect(groups['tag_host-type-node'] | default([])) }}"
-
-g_new_node_hosts: "{{ g_all_hosts | intersect(groups['tag_host-type-new-node'] | default([])) }}"
-
-g_infra_hosts: "{{ g_node_hosts | intersect(groups['tag_sub-host-type-infra'] | default([])) }}"
-
-g_compute_hosts: "{{ g_node_hosts | intersect(groups['tag_sub-host-type-compute'] | default([])) }}"
diff --git a/playbooks/libvirt/openshift-cluster/config.yml b/playbooks/libvirt/openshift-cluster/config.yml
deleted file mode 100644
index 569e00da2..000000000
--- a/playbooks/libvirt/openshift-cluster/config.yml
+++ /dev/null
@@ -1,39 +0,0 @@
----
-# TODO: need to figure out a plan for setting hostname, currently the default
-# is localhost, so no hostname value (or public_hostname) value is getting
-# assigned
-
-- include: ../../common/openshift-cluster/std_include.yml
-
-- hosts: localhost
- gather_facts: no
- tasks:
- - include_vars: vars.yml
- - include_vars: cluster_hosts.yml
- - add_host:
- name: "{{ item }}"
- groups: l_oo_all_hosts
- with_items: "{{ g_all_hosts | default([]) }}"
-
-- hosts: l_oo_all_hosts
- gather_facts: no
- tasks:
- - include_vars: vars.yml
- - include_vars: cluster_hosts.yml
-
-- include: ../../common/openshift-cluster/config.yml
- vars:
- g_ssh_user: "{{ deployment_vars[deployment_type].ssh_user }}"
- g_sudo: "{{ deployment_vars[deployment_type].become }}"
- g_nodeonmaster: true
- openshift_cluster_id: "{{ cluster_id }}"
- openshift_debug_level: "{{ debug_level }}"
- openshift_deployment_type: "{{ deployment_type }}"
- openshift_hosted_registry_selector: 'type=infra'
- openshift_hosted_router_selector: 'type=infra'
- openshift_master_cluster_method: 'native'
- openshift_use_openshift_sdn: "{{ lookup('oo_option', 'use_openshift_sdn') }}"
- os_sdn_network_plugin_name: "{{ lookup('oo_option', 'sdn_network_plugin_name') }}"
- openshift_use_flannel: "{{ lookup('oo_option', 'use_flannel') }}"
- openshift_use_calico: "{{ lookup('oo_option', 'use_calico') }}"
- openshift_use_fluentd: "{{ lookup('oo_option', 'use_fluentd') }}"
diff --git a/playbooks/libvirt/openshift-cluster/filter_plugins b/playbooks/libvirt/openshift-cluster/filter_plugins
deleted file mode 120000
index 99a95e4ca..000000000
--- a/playbooks/libvirt/openshift-cluster/filter_plugins
+++ /dev/null
@@ -1 +0,0 @@
-../../../filter_plugins \ No newline at end of file
diff --git a/playbooks/libvirt/openshift-cluster/launch.yml b/playbooks/libvirt/openshift-cluster/launch.yml
deleted file mode 100644
index 2475b9d6b..000000000
--- a/playbooks/libvirt/openshift-cluster/launch.yml
+++ /dev/null
@@ -1,57 +0,0 @@
----
-- name: Launch instance(s)
- hosts: localhost
- become: no
- connection: local
- gather_facts: no
- vars_files:
- - vars.yml
- vars:
- image_url: "{{ deployment_vars[deployment_type].image.url }}"
- image_sha256: "{{ deployment_vars[deployment_type].image.sha256 }}"
- image_name: "{{ deployment_vars[deployment_type].image.name }}"
- image_compression: "{{ deployment_vars[deployment_type].image.compression }}"
- tasks:
- - include: tasks/configure_libvirt.yml
-
- - include: ../../common/openshift-cluster/tasks/set_etcd_launch_facts.yml
- - include: tasks/launch_instances.yml
- vars:
- instances: "{{ etcd_names }}"
- cluster: "{{ cluster_id }}"
- type: "{{ k8s_type }}"
- g_sub_host_type: "default"
-
- - include: ../../common/openshift-cluster/tasks/set_master_launch_facts.yml
- - include: tasks/launch_instances.yml
- vars:
- instances: "{{ master_names }}"
- cluster: "{{ cluster_id }}"
- type: "{{ k8s_type }}"
- g_sub_host_type: "default"
-
- - include: ../../common/openshift-cluster/tasks/set_node_launch_facts.yml
- vars:
- type: "compute"
- count: "{{ num_nodes }}"
- - include: tasks/launch_instances.yml
- vars:
- instances: "{{ node_names }}"
- cluster: "{{ cluster_id }}"
- type: "{{ k8s_type }}"
- g_sub_host_type: "{{ sub_host_type }}"
-
- - include: ../../common/openshift-cluster/tasks/set_node_launch_facts.yml
- vars:
- type: "infra"
- count: "{{ num_infra }}"
- - include: tasks/launch_instances.yml
- vars:
- instances: "{{ node_names }}"
- cluster: "{{ cluster_id }}"
- type: "{{ k8s_type }}"
- g_sub_host_type: "{{ sub_host_type }}"
-
-- include: update.yml
-
-- include: list.yml
diff --git a/playbooks/libvirt/openshift-cluster/list.yml b/playbooks/libvirt/openshift-cluster/list.yml
deleted file mode 100644
index 579cd7ac6..000000000
--- a/playbooks/libvirt/openshift-cluster/list.yml
+++ /dev/null
@@ -1,23 +0,0 @@
----
-- name: Generate oo_list_hosts group
- hosts: localhost
- become: no
- connection: local
- gather_facts: no
- vars_files:
- - vars.yml
- tasks:
- - set_fact: scratch_group=tag_clusterid-{{ cluster_id }}
- when: cluster_id != ''
- - set_fact: scratch_group=all
- when: cluster_id == ''
- - add_host:
- name: "{{ item }}"
- groups: oo_list_hosts
- ansible_ssh_user: "{{ deployment_vars[deployment_type].ssh_user }}"
- ansible_become: "{{ deployment_vars[deployment_type].become }}"
- oo_public_ipv4: ""
- oo_private_ipv4: "{{ hostvars[item].libvirt_ip_address }}"
- with_items: "{{ groups[scratch_group] | default([]) | difference(['localhost']) }}"
- - debug:
- msg: "{{ hostvars | oo_select_keys(groups[scratch_group] | default([])) | oo_pretty_print_cluster }}"
diff --git a/playbooks/libvirt/openshift-cluster/lookup_plugins b/playbooks/libvirt/openshift-cluster/lookup_plugins
deleted file mode 120000
index ac79701db..000000000
--- a/playbooks/libvirt/openshift-cluster/lookup_plugins
+++ /dev/null
@@ -1 +0,0 @@
-../../../lookup_plugins \ No newline at end of file
diff --git a/playbooks/libvirt/openshift-cluster/roles b/playbooks/libvirt/openshift-cluster/roles
deleted file mode 120000
index 20c4c58cf..000000000
--- a/playbooks/libvirt/openshift-cluster/roles
+++ /dev/null
@@ -1 +0,0 @@
-../../../roles \ No newline at end of file
diff --git a/playbooks/libvirt/openshift-cluster/service.yml b/playbooks/libvirt/openshift-cluster/service.yml
deleted file mode 100644
index 8bd24a8cf..000000000
--- a/playbooks/libvirt/openshift-cluster/service.yml
+++ /dev/null
@@ -1,34 +0,0 @@
----
-# TODO: need to figure out a plan for setting hostname, currently the default
-# is localhost, so no hostname value (or public_hostname) value is getting
-# assigned
-
-- name: Call same systemctl command for openshift on all instance(s)
- hosts: localhost
- become: no
- connection: local
- gather_facts: no
- vars_files:
- - vars.yml
- tasks:
- - fail: msg="cluster_id is required to be injected in this playbook"
- when: cluster_id is not defined
-
- - name: Evaluate g_service_masters
- add_host:
- name: "{{ item }}"
- ansible_ssh_user: "{{ deployment_vars[deployment_type].ssh_user }}"
- ansible_become: "{{ deployment_vars[deployment_type].become }}"
- groups: g_service_masters
- with_items: "{{ g_master_hosts | default([]) }}"
-
- - name: Evaluate g_service_nodes
- add_host:
- name: "{{ item }}"
- ansible_ssh_user: "{{ deployment_vars[deployment_type].ssh_user }}"
- ansible_become: "{{ deployment_vars[deployment_type].become }}"
- groups: g_service_nodes
- with_items: "{{ g_node_hosts | default([]) }}"
-
-- include: ../../common/openshift-node/service.yml
-- include: ../../common/openshift-master/service.yml
diff --git a/playbooks/libvirt/openshift-cluster/tasks/configure_libvirt.yml b/playbooks/libvirt/openshift-cluster/tasks/configure_libvirt.yml
deleted file mode 100644
index f237c1a60..000000000
--- a/playbooks/libvirt/openshift-cluster/tasks/configure_libvirt.yml
+++ /dev/null
@@ -1,6 +0,0 @@
----
-- include: configure_libvirt_storage_pool.yml
- when: libvirt_storage_pool is defined and libvirt_storage_pool_path is defined
-
-- include: configure_libvirt_network.yml
- when: libvirt_network is defined
diff --git a/playbooks/libvirt/openshift-cluster/tasks/configure_libvirt_network.yml b/playbooks/libvirt/openshift-cluster/tasks/configure_libvirt_network.yml
deleted file mode 100644
index b42ca83af..000000000
--- a/playbooks/libvirt/openshift-cluster/tasks/configure_libvirt_network.yml
+++ /dev/null
@@ -1,11 +0,0 @@
----
-- name: Create the libvirt network for OpenShift
- virt_net:
- name: '{{ libvirt_network }}'
- state: '{{ item }}'
- autostart: 'yes'
- xml: "{{ lookup('template', 'network.xml') }}"
- uri: '{{ libvirt_uri }}'
- with_items:
- - present
- - active
diff --git a/playbooks/libvirt/openshift-cluster/tasks/configure_libvirt_storage_pool.yml b/playbooks/libvirt/openshift-cluster/tasks/configure_libvirt_storage_pool.yml
deleted file mode 100644
index 8685624ec..000000000
--- a/playbooks/libvirt/openshift-cluster/tasks/configure_libvirt_storage_pool.yml
+++ /dev/null
@@ -1,30 +0,0 @@
----
-- name: Create libvirt storage directory for openshift
- file:
- dest: "{{ libvirt_storage_pool_path }}"
- state: directory
-
-# We need to set permissions on the directory and any items created under the directory, so we need to call the acl module with and without default set.
-- acl:
- default: '{{ item.default }}'
- entity: kvm
- etype: group
- name: "{{ libvirt_storage_pool_path }}"
- permissions: '{{ item.permissions }}'
- state: present
- with_items:
- - default: no
- permissions: x
- - default: yes
- permissions: rwx
-
-- name: Create the libvirt storage pool for OpenShift
- virt_pool:
- name: '{{ libvirt_storage_pool }}'
- state: '{{ item }}'
- autostart: 'yes'
- xml: "{{ lookup('template', 'storage-pool.xml') }}"
- uri: '{{ libvirt_uri }}'
- with_items:
- - present
- - active
diff --git a/playbooks/libvirt/openshift-cluster/tasks/launch_instances.yml b/playbooks/libvirt/openshift-cluster/tasks/launch_instances.yml
deleted file mode 100644
index 4df86effa..000000000
--- a/playbooks/libvirt/openshift-cluster/tasks/launch_instances.yml
+++ /dev/null
@@ -1,142 +0,0 @@
----
-# TODO: Add support for choosing base image based on deployment_type and os
-# wanted (os wanted needs support added in bin/cluster with sane defaults:
-# fedora/centos for origin, rhel for enterprise)
-
-# TODO: create a role to encapsulate some of this complexity, possibly also
-# create a module to manage the storage tasks, network tasks, and possibly
-# even handle the libvirt tasks to set metadata in the domain xml and be able
-# to create/query data about vms without having to use xml the python libvirt
-# bindings look like a good candidate for this
-
-- name: Download Base Cloud image
- get_url:
- url: '{{ image_url }}'
- sha256sum: '{{ image_sha256 }}'
- dest: '{{ libvirt_storage_pool_path }}/{{ [image_name, image_compression] | difference([""]) | join(".") }}'
- when: ( lookup("oo_option", "skip_image_download") | default("no", True) | lower ) in ["false", "no"]
- register: downloaded_image
-
-- name: Uncompress xz compressed base cloud image
- command: 'unxz -kf {{ libvirt_storage_pool_path }}/{{ [image_name, image_compression] | join(".") }}'
- args:
- creates: '{{ libvirt_storage_pool_path }}/{{ image_name }}'
- when: image_compression in ["xz"] and downloaded_image.changed
-
-- name: Uncompress tgz compressed base cloud image
- command: 'tar zxvf {{ libvirt_storage_pool_path }}/{{ [image_name, image_compression] | join(".") }}'
- args:
- creates: '{{ libvirt_storage_pool_path }}/{{ image_name }}'
- when: image_compression in ["tgz"] and downloaded_image.changed
-
-- name: Uncompress gzip compressed base cloud image
- command: 'gunzip {{ libvirt_storage_pool_path }}/{{ [image_name, image_compression] | join(".") }}'
- args:
- creates: '{{ libvirt_storage_pool_path }}/{{ image_name }}'
- when: image_compression in ["gz"] and downloaded_image.changed
-
-- name: Create the cloud-init config drive path
- file:
- dest: '{{ libvirt_storage_pool_path }}/{{ item }}_configdrive/'
- state: directory
- with_items: '{{ instances }}'
-
-- name: Create the cloud-init config drive files
- template:
- src: '{{ item[1] }}'
- dest: '{{ libvirt_storage_pool_path }}/{{ item[0] }}_configdrive/{{ item[1] }}'
- with_nested:
- - '{{ instances }}'
- - [ user-data, meta-data ]
-
-- name: Check for genisoimage
- command: which genisoimage
- register: which_genisoimage
-
-- name: Create the cloud-init config drive
- command: "{{ 'genisoimage' if which_genisoimage.rc == 0 else 'mkisofs' }} -output {{ libvirt_storage_pool_path }}/{{ item }}_cloud-init.iso -volid cidata -joliet -rock user-data meta-data"
- args:
- chdir: "{{ libvirt_storage_pool_path }}/{{ item }}_configdrive/"
- creates: "{{ libvirt_storage_pool_path }}/{{ item }}_cloud-init.iso"
- with_items: '{{ instances }}'
-
-- name: Refresh the libvirt storage pool for openshift
- command: 'virsh -c {{ libvirt_uri }} pool-refresh {{ libvirt_storage_pool }}'
-
-- name: Create VM drives
- command: 'virsh -c {{ libvirt_uri }} vol-create-as {{ libvirt_storage_pool }} {{ item }}.qcow2 10G --format qcow2 --backing-vol {{ image_name }} --backing-vol-format qcow2'
- with_items: '{{ instances }}'
-
-- name: Create VM docker drives
- command: 'virsh -c {{ libvirt_uri }} vol-create-as {{ libvirt_storage_pool }} {{ item }}-docker.qcow2 10G --format qcow2 --allocation 0'
- with_items: '{{ instances }}'
-
-- name: Create VMs
- virt:
- name: '{{ item }}'
- command: define
- xml: "{{ lookup('template', '../templates/domain.xml') }}"
- uri: '{{ libvirt_uri }}'
- with_items: '{{ instances }}'
-
-- name: Start VMs
- virt:
- name: '{{ item }}'
- state: running
- uri: '{{ libvirt_uri }}'
- with_items: '{{ instances }}'
-
-- name: Wait for the VMs to get an IP
- shell: 'virsh -c {{ libvirt_uri }} net-dhcp-leases {{ libvirt_network }} | egrep -c ''{{ instances | join("|") }}'''
- register: nb_allocated_ips
- until: nb_allocated_ips.stdout == '{{ instances | length }}'
- retries: 60
- delay: 3
- when: instances | length != 0
-
-- name: Collect IP addresses of the VMs
- shell: 'virsh -c {{ libvirt_uri }} net-dhcp-leases {{ libvirt_network }} | awk ''$6 == "{{ item }}" {gsub(/\/.*/, "", $5); print $5}'''
- register: scratch_ip
- with_items: '{{ instances }}'
-
-- set_fact:
- ips: "{{ scratch_ip.results | default([]) | oo_collect('stdout') }}"
-
-- set_fact:
- node_label:
- type: "{{ g_sub_host_type }}"
- when: instances | length > 0 and type == "node"
-
-- set_fact:
- node_label:
- type: "{{ type }}"
- when: instances | length > 0 and type != "node"
-
-- name: Add new instances
- add_host:
- hostname: '{{ item.0 }}'
- ansible_ssh_host: '{{ item.1 }}'
- ansible_ssh_user: "{{ deployment_vars[deployment_type].ssh_user }}"
- ansible_become: "{{ deployment_vars[deployment_type].become }}"
- groups: "tag_environment-{{ cluster_env }}, tag_host-type-{{ type }}, tag_sub-host-type-{{ g_sub_host_type }}, tag_clusterid-{{ cluster_id }}"
- openshift_node_labels: "{{ node_label }}"
- libvirt_ip_address: "{{ item.1 }}"
- with_together:
- - '{{ instances }}'
- - '{{ ips }}'
-
-- name: Wait for ssh
- wait_for:
- host: '{{ item }}'
- port: 22
- with_items: '{{ ips }}'
-
-- name: Wait for openshift user setup
- command: 'ssh -o StrictHostKeyChecking=no -o PasswordAuthentication=no -o ConnectTimeout=10 -o UserKnownHostsFile=/dev/null openshift@{{ item.1 }} echo openshift user is setup'
- register: result
- until: result.rc == 0
- retries: 30
- delay: 1
- with_together:
- - '{{ instances }}'
- - '{{ ips }}'
diff --git a/playbooks/libvirt/openshift-cluster/templates/domain.xml b/playbooks/libvirt/openshift-cluster/templates/domain.xml
deleted file mode 100644
index 88504a5f6..000000000
--- a/playbooks/libvirt/openshift-cluster/templates/domain.xml
+++ /dev/null
@@ -1,65 +0,0 @@
-<domain type='kvm' id='8'>
- <name>{{ item }}</name>
- <memory unit='MiB'>{{ libvirt_instance_memory_mib }}</memory>
- <metadata xmlns:ansible="https://github.com/ansible/ansible">
- <ansible:tags>
- <ansible:tag>environment-{{ cluster_env }}</ansible:tag>
- <ansible:tag>clusterid-{{ cluster }}</ansible:tag>
- <ansible:tag>host-type-{{ type }}</ansible:tag>
- <ansible:tag>sub-host-type-{{ g_sub_host_type }}</ansible:tag>
- </ansible:tags>
- </metadata>
- <vcpu placement='static'>{{ libvirt_instance_vcpu }}</vcpu>
- <os>
- <type arch='x86_64' machine='pc'>hvm</type>
- <boot dev='hd'/>
- </os>
- <features>
- <acpi/>
- <apic/>
- <pae/>
- </features>
- <cpu mode='host-model'>
- <model fallback='allow'/>
- </cpu>
- <clock offset='utc'>
- <timer name='rtc' tickpolicy='catchup'/>
- <timer name='pit' tickpolicy='delay'/>
- <timer name='hpet' present='no'/>
- </clock>
- <on_poweroff>destroy</on_poweroff>
- <on_reboot>restart</on_reboot>
- <on_crash>restart</on_crash>
- <devices>
- <emulator>/usr/bin/qemu-system-x86_64</emulator>
- <disk type='file' device='disk'>
- <driver name='qemu' type='qcow2' discard='unmap'/>
- <source file='{{ libvirt_storage_pool_path }}/{{ item }}.qcow2'/>
- <target dev='sda' bus='scsi'/>
- </disk>
- <disk type='file' device='disk'>
- <driver name='qemu' type='qcow2' discard='unmap'/>
- <source file='{{ libvirt_storage_pool_path }}/{{ item }}-docker.qcow2'/>
- <target dev='sdb' bus='scsi'/>
- </disk>
- <disk type='file' device='cdrom'>
- <driver name='qemu' type='raw'/>
- <source file='{{ libvirt_storage_pool_path }}/{{ item }}_cloud-init.iso'/>
- <target dev='sdc' bus='scsi'/>
- <readonly/>
- </disk>
- <controller type='scsi' model='virtio-scsi' />
- <interface type='network'>
- <source network='{{ libvirt_network }}'/>
- <model type='virtio'/>
- </interface>
- <serial type='pty'>
- <target port='0'/>
- </serial>
- <console type='pty'>
- <target type='serial' port='0'/>
- </console>
- <memballoon model='virtio'>
- </memballoon>
- </devices>
-</domain>
diff --git a/playbooks/libvirt/openshift-cluster/templates/meta-data b/playbooks/libvirt/openshift-cluster/templates/meta-data
deleted file mode 100644
index 6b421770d..000000000
--- a/playbooks/libvirt/openshift-cluster/templates/meta-data
+++ /dev/null
@@ -1,3 +0,0 @@
-instance-id: {{ item[0] }}
-hostname: {{ item[0] }}
-local-hostname: {{ item[0] }}.example.com
diff --git a/playbooks/libvirt/openshift-cluster/templates/network.xml b/playbooks/libvirt/openshift-cluster/templates/network.xml
deleted file mode 100644
index 0ce2a8342..000000000
--- a/playbooks/libvirt/openshift-cluster/templates/network.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<network>
- <name>{{ libvirt_network }}</name>
- <forward mode='nat'>
- <nat>
- <port start='1024' end='65535'/>
- </nat>
- </forward>
- <!-- TODO: query for first available virbr interface available -->
- <bridge name='virbr3' stp='on' delay='0'/>
- <!-- TODO: make overridable -->
- <domain name='example.com' localOnly='yes' />
- <dns>
- <!-- TODO: automatically add host entries -->
- </dns>
- <!-- TODO: query for available address space -->
- <ip address='192.168.55.1' netmask='255.255.255.0'>
- <dhcp>
- <range start='192.168.55.2' end='192.168.55.254'/>
- <!-- TODO: add static entries addresses for the hosts to be created -->
- </dhcp>
- </ip>
-</network>
-
diff --git a/playbooks/libvirt/openshift-cluster/templates/storage-pool.xml b/playbooks/libvirt/openshift-cluster/templates/storage-pool.xml
deleted file mode 100644
index da139afd0..000000000
--- a/playbooks/libvirt/openshift-cluster/templates/storage-pool.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<pool type='dir'>
- <name>{{ libvirt_storage_pool }}</name>
- <target>
- <path>{{ libvirt_storage_pool_path }}</path>
- </target>
-</pool>
diff --git a/playbooks/libvirt/openshift-cluster/templates/user-data b/playbooks/libvirt/openshift-cluster/templates/user-data
deleted file mode 100644
index fbcf7c886..000000000
--- a/playbooks/libvirt/openshift-cluster/templates/user-data
+++ /dev/null
@@ -1,43 +0,0 @@
-#cloud-config
-disable_root: true
-
-hostname: {{ item[0] }}
-fqdn: {{ item[0] }}.example.com
-
-mounts:
-- [ sdb ]
-
-users:
- - default
- - name: root
- ssh_authorized_keys:
- - {{ lookup('file', '~/.ssh/id_rsa.pub') }}
-
-system_info:
- default_user:
- name: openshift
- sudo: ["ALL=(ALL) NOPASSWD: ALL"]
-
-ssh_authorized_keys:
- - {{ lookup('file', '~/.ssh/id_rsa.pub') }}
-
-write_files:
- - path: /etc/sudoers.d/00-openshift-no-requiretty
- permissions: 440
- content: |
- Defaults:openshift !requiretty
- - path: /etc/sysconfig/docker-storage-setup
- owner: root:root
- permissions: '0644'
- content: |
- DEVS=/dev/sdb
- VG=docker_vg
- EXTRA_DOCKER_STORAGE_OPTIONS='--storage-opt dm.blkdiscard=true'
- - path: /etc/systemd/system/fstrim.timer.d/hourly.conf
- content: |
- [Timer]
- OnCalendar=hourly
-
-runcmd:
- - NETWORK_CONFIG=/etc/sysconfig/network-scripts/ifcfg-eth0; if ! grep DHCP_HOSTNAME ${NETWORK_CONFIG}; then echo 'DHCP_HOSTNAME="{{ item[0] }}.example.com"' >> ${NETWORK_CONFIG}; fi; pkill -9 dhclient; service network restart
- - systemctl enable --now fstrim.timer
diff --git a/playbooks/libvirt/openshift-cluster/terminate.yml b/playbooks/libvirt/openshift-cluster/terminate.yml
deleted file mode 100644
index 8a63d11a5..000000000
--- a/playbooks/libvirt/openshift-cluster/terminate.yml
+++ /dev/null
@@ -1,70 +0,0 @@
----
-# TODO: does not handle a non-existent cluster gracefully
-
-- name: Terminate instance(s)
- hosts: localhost
- become: no
- connection: local
- gather_facts: no
- vars_files:
- - vars.yml
- tasks:
- - set_fact: cluster_group=tag_clusterid-{{ cluster_id }}
- - add_host:
- name: "{{ item }}"
- groups: oo_hosts_to_terminate
- ansible_ssh_user: "{{ deployment_vars[deployment_type].ssh_user }}"
- ansible_become: "{{ deployment_vars[deployment_type].become }}"
- with_items: '{{ groups[cluster_group] | default([]) }}'
-
-- name: Unsubscribe VMs
- hosts: oo_hosts_to_terminate
- vars_files:
- - vars.yml
- roles:
- - role: rhel_unsubscribe
- when: deployment_type in ['atomic-enterprise', 'enterprise', 'openshift-enterprise'] and
- ansible_distribution == "RedHat" and
- lookup('oo_option', 'rhel_skip_subscription') | default(rhsub_skip, True) |
- default('no', True) | lower in ['no', 'false']
-
-- name: Terminate instance(s)
- hosts: localhost
- become: no
- connection: local
- gather_facts: no
- vars_files:
- - vars.yml
- tasks:
- - name: Destroy VMs
- virt:
- name: '{{ item[0] }}'
- command: '{{ item[1] }}'
- uri: '{{ libvirt_uri }}'
- with_nested:
- - "{{ groups['oo_hosts_to_terminate'] }}"
- - [ destroy, undefine ]
-
- - name: Delete VM drives
- command: 'virsh -c {{ libvirt_uri }} vol-delete --pool {{ libvirt_storage_pool }} {{ item }}.qcow2'
- args:
- removes: '{{ libvirt_storage_pool_path }}/{{ item }}.qcow2'
- with_items: "{{ groups['oo_hosts_to_terminate'] }}"
-
- - name: Delete VM docker drives
- command: 'virsh -c {{ libvirt_uri }} vol-delete --pool {{ libvirt_storage_pool }} {{ item }}-docker.qcow2'
- args:
- removes: '{{ libvirt_storage_pool_path }}/{{ item }}-docker.qcow2'
- with_items: "{{ groups['oo_hosts_to_terminate'] }}"
-
- - name: Delete the VM cloud-init image
- file:
- path: '{{ libvirt_storage_pool_path }}/{{ item }}_cloud-init.iso'
- state: absent
- with_items: "{{ groups['oo_hosts_to_terminate'] }}"
-
- - name: Remove the cloud-init config directory
- file:
- path: '{{ libvirt_storage_pool_path }}/{{ item }}_configdrive/'
- state: absent
- with_items: "{{ groups['oo_hosts_to_terminate'] }}"
diff --git a/playbooks/libvirt/openshift-cluster/update.yml b/playbooks/libvirt/openshift-cluster/update.yml
deleted file mode 100644
index a152135fc..000000000
--- a/playbooks/libvirt/openshift-cluster/update.yml
+++ /dev/null
@@ -1,37 +0,0 @@
----
-- hosts: localhost
- gather_facts: no
- tasks:
- - include_vars: vars.yml
- - include_vars: cluster_hosts.yml
- - add_host:
- name: "{{ item }}"
- groups: l_oo_all_hosts
- with_items: '{{ g_all_hosts }}'
-
-- hosts: l_oo_all_hosts
- gather_facts: no
- tasks:
- - include_vars: vars.yml
- - include_vars: cluster_hosts.yml
-
-- name: Populate oo_hosts_to_update group
- hosts: localhost
- connection: local
- become: no
- gather_facts: no
- vars_files:
- - vars.yml
- - cluster_hosts.yml
- tasks:
- - name: Evaluate oo_hosts_to_update
- add_host:
- name: "{{ item }}"
- groups: oo_hosts_to_update
- ansible_ssh_user: "{{ deployment_vars[deployment_type].ssh_user }}"
- ansible_become: "{{ deployment_vars[deployment_type].become }}"
- with_items: '{{ g_all_hosts | default([]) }}'
-
-- include: ../../common/openshift-cluster/update_repos_and_packages.yml
-
-- include: config.yml
diff --git a/playbooks/libvirt/openshift-cluster/vars.yml b/playbooks/libvirt/openshift-cluster/vars.yml
deleted file mode 100644
index 5156789e7..000000000
--- a/playbooks/libvirt/openshift-cluster/vars.yml
+++ /dev/null
@@ -1,40 +0,0 @@
----
-default_pool_path: "{{ lookup('env','HOME') }}/libvirt-storage-pool-openshift-ansible"
-libvirt_storage_pool_path: "{{ lookup('oo_option', 'libvirt_storage_pool_path') | default(default_pool_path, True) }}"
-libvirt_storage_pool: "{{ lookup('oo_option', 'libvirt_storage_pool') | default('openshift-ansible', True) }}"
-libvirt_network: "{{ lookup('oo_option', 'libvirt_network') | default('openshift-ansible', True) }}"
-libvirt_instance_memory_mib: "{{ lookup('oo_option', 'libvirt_instance_memory_mib') | default(1024, True) }}"
-libvirt_instance_vcpu: "{{ lookup('oo_option', 'libvirt_instance_vcpu') | default(2, True) }}"
-libvirt_uri: "{{ lookup('oo_option', 'libvirt_uri') | default('qemu:///system', True) }}"
-debug_level: 2
-
-# Automatic download of the qcow2 image for RHEL cannot be done directly from the RedHat portal because it requires authentication.
-# The default value of image_url for enterprise and openshift-enterprise deployment types below won't work.
-deployment_rhel7_ent_base:
- image:
- url: "{{ lookup('oo_option', 'image_url') |
- default('https://access.cdn.redhat.com//content/origin/files/sha256/25/25f880767ec6bf71beb532e17f1c45231640bbfdfbbb1dffb79d2c1b328388e0/rhel-guest-image-7.2-20151102.0.x86_64.qcow2', True) }}"
- name: "{{ lookup('oo_option', 'image_name') |
- default('rhel-guest-image-7.2-20151102.0.x86_64.qcow2', True) }}"
- sha256: "{{ lookup('oo_option', 'image_sha256') |
- default('25f880767ec6bf71beb532e17f1c45231640bbfdfbbb1dffb79d2c1b328388e0', True) }}"
- compression: ""
- ssh_user: openshift
- become: yes
-
-deployment_vars:
- origin:
- image:
- url: "{{ lookup('oo_option', 'image_url') |
- default('http://cloud.centos.org/centos/7/images/CentOS-7-x86_64-GenericCloud-1602.qcow2.xz', True) }}"
- compression: "{{ lookup('oo_option', 'image_compression') |
- default('xz', True) }}"
- name: "{{ lookup('oo_option', 'image_name') |
- default('CentOS-7-x86_64-GenericCloud.qcow2', True) }}"
- sha256: "{{ lookup('oo_option', 'image_sha256') |
- default('dd0f5e610e7c5ffacaca35ed7a78a19142a588f4543da77b61c1fb0d74400471', True) }}"
- ssh_user: openshift
- become: yes
- enterprise: "{{ deployment_rhel7_ent_base }}"
- openshift-enterprise: "{{ deployment_rhel7_ent_base }}"
- atomic-enterprise: "{{ deployment_rhel7_ent_base }}"
diff --git a/playbooks/openstack/README.md b/playbooks/openstack/README.md
deleted file mode 100644
index a6d8d6995..000000000
--- a/playbooks/openstack/README.md
+++ /dev/null
@@ -1,4 +0,0 @@
-# OpenStack playbooks
-
-This playbook directory is meant to be driven by [`bin/cluster`](../../bin),
-which is community supported and most use is considered deprecated.
diff --git a/playbooks/openstack/openshift-cluster/cluster_hosts.yml b/playbooks/openstack/openshift-cluster/cluster_hosts.yml
deleted file mode 100644
index 12c9fd442..000000000
--- a/playbooks/openstack/openshift-cluster/cluster_hosts.yml
+++ /dev/null
@@ -1,25 +0,0 @@
----
-g_all_hosts: "{{ groups['meta-clusterid_' ~ cluster_id] | default([])
- | intersect(groups['meta-environment_' ~ cluster_env] | default([])) }}"
-
-g_etcd_hosts: "{{ g_all_hosts | intersect(groups['meta-host-type_etcd'] | default([])) }}"
-
-g_new_etcd_hosts: "{{ g_all_hosts | intersect(groups['meta-host-type_new_etcd'] | default([])) }}"
-
-g_lb_hosts: "{{ g_all_hosts | intersect(groups['meta-host-type_lb'] | default([])) }}"
-
-g_nfs_hosts: "{{ g_all_hosts | intersect(groups['meta-host-type_nfs'] | default([])) }}"
-
-g_glusterfs_hosts: "{{ g_all_hosts | intersect(groups['tag_host-type-glusterfs'] | default([])) }}"
-
-g_master_hosts: "{{ g_all_hosts | intersect(groups['meta-host-type_master'] | default([])) }}"
-
-g_new_master_hosts: "{{ g_all_hosts | intersect(groups['meta-host-type_new_master'] | default([])) }}"
-
-g_node_hosts: "{{ g_all_hosts | intersect(groups['meta-host-type_node'] | default([])) }}"
-
-g_new_node_hosts: "{{ g_all_hosts | intersect(groups['meta-host-type_new_node'] | default([])) }}"
-
-g_infra_hosts: "{{ g_node_hosts | intersect(groups['meta-sub-host-type_infra'] | default([])) }}"
-
-g_compute_hosts: "{{ g_node_hosts | intersect(groups['meta-sub-host-type_compute'] | default([])) }}"
diff --git a/playbooks/openstack/openshift-cluster/config.yml b/playbooks/openstack/openshift-cluster/config.yml
deleted file mode 100644
index f9ddb9469..000000000
--- a/playbooks/openstack/openshift-cluster/config.yml
+++ /dev/null
@@ -1,33 +0,0 @@
----
-- hosts: localhost
- gather_facts: no
- tasks:
- - include_vars: vars.yml
- - include_vars: cluster_hosts.yml
- - add_host:
- name: "{{ item }}"
- groups: l_oo_all_hosts
- with_items: "{{ g_all_hosts | default([]) }}"
-
-- hosts: l_oo_all_hosts
- gather_facts: no
- tasks:
- - include_vars: vars.yml
- - include_vars: cluster_hosts.yml
-
-- include: ../../common/openshift-cluster/config.yml
- vars:
- g_nodeonmaster: true
- g_ssh_user: "{{ deployment_vars[deployment_type].ssh_user }}"
- g_sudo: "{{ deployment_vars[deployment_type].become }}"
- openshift_cluster_id: "{{ cluster_id }}"
- openshift_debug_level: "{{ debug_level }}"
- openshift_deployment_type: "{{ deployment_type }}"
- openshift_hosted_registry_selector: 'type=infra'
- openshift_hosted_router_selector: 'type=infra'
- openshift_master_cluster_method: 'native'
- openshift_use_openshift_sdn: "{{ lookup('oo_option', 'use_openshift_sdn') }}"
- os_sdn_network_plugin_name: "{{ lookup('oo_option', 'sdn_network_plugin_name') }}"
- openshift_use_flannel: "{{ lookup('oo_option', 'use_flannel') }}"
- openshift_use_calico: "{{ lookup('oo_option', 'use_calico') }}"
- openshift_use_fluentd: "{{ lookup('oo_option', 'use_fluentd') }}"
diff --git a/playbooks/openstack/openshift-cluster/files/heat_stack.yaml b/playbooks/openstack/openshift-cluster/files/heat_stack.yaml
deleted file mode 100644
index 82329eac1..000000000
--- a/playbooks/openstack/openshift-cluster/files/heat_stack.yaml
+++ /dev/null
@@ -1,508 +0,0 @@
-heat_template_version: 2014-10-16
-
-description: OpenShift cluster
-
-parameters:
-
- cluster_env:
- type: string
- label: Cluster environment
- description: Environment of the cluster
-
- cluster_id:
- type: string
- label: Cluster ID
- description: Identifier of the cluster
-
- subnet_24_prefix:
- type: string
- label: subnet /24 prefix
- description: /24 subnet prefix of the network of the cluster (dot separated number triplet)
-
- dns_nameservers:
- type: comma_delimited_list
- label: DNS nameservers list
- description: List of DNS nameservers
-
- external_net:
- type: string
- label: External network
- description: Name of the external network
- default: external
-
- ssh_public_key:
- type: string
- label: SSH public key
- description: SSH public key
- hidden: true
-
- ssh_incoming:
- type: string
- label: Source of ssh connections
- description: Source of legitimate ssh connections
- default: 0.0.0.0/0
-
- node_port_incoming:
- type: string
- label: Source of node port connections
- description: Authorized sources targeting node ports
- default: 0.0.0.0/0
-
- num_etcd:
- type: number
- label: Number of etcd nodes
- description: Number of etcd nodes
-
- num_masters:
- type: number
- label: Number of masters
- description: Number of masters
-
- num_nodes:
- type: number
- label: Number of compute nodes
- description: Number of compute nodes
-
- num_infra:
- type: number
- label: Number of infrastructure nodes
- description: Number of infrastructure nodes
-
- etcd_image:
- type: string
- label: Etcd image
- description: Name of the image for the etcd servers
-
- master_image:
- type: string
- label: Master image
- description: Name of the image for the master servers
-
- node_image:
- type: string
- label: Node image
- description: Name of the image for the compute node servers
-
- infra_image:
- type: string
- label: Infra image
- description: Name of the image for the infra node servers
-
- etcd_flavor:
- type: string
- label: Etcd flavor
- description: Flavor of the etcd servers
-
- master_flavor:
- type: string
- label: Master flavor
- description: Flavor of the master servers
-
- node_flavor:
- type: string
- label: Node flavor
- description: Flavor of the compute node servers
-
- infra_flavor:
- type: string
- label: Infra flavor
- description: Flavor of the infra node servers
-
-outputs:
-
- etcd_names:
- description: Name of the etcds
- value: { get_attr: [ etcd, name ] }
-
- etcd_ips:
- description: IPs of the etcds
- value: { get_attr: [ etcd, private_ip ] }
-
- etcd_floating_ips:
- description: Floating IPs of the etcds
- value: { get_attr: [ etcd, floating_ip ] }
-
- master_names:
- description: Name of the masters
- value: { get_attr: [ masters, name ] }
-
- master_ips:
- description: IPs of the masters
- value: { get_attr: [ masters, private_ip ] }
-
- master_floating_ips:
- description: Floating IPs of the masters
- value: { get_attr: [ masters, floating_ip ] }
-
- node_names:
- description: Name of the nodes
- value: { get_attr: [ compute_nodes, name ] }
-
- node_ips:
- description: IPs of the nodes
- value: { get_attr: [ compute_nodes, private_ip ] }
-
- node_floating_ips:
- description: Floating IPs of the nodes
- value: { get_attr: [ compute_nodes, floating_ip ] }
-
- infra_names:
- description: Name of the nodes
- value: { get_attr: [ infra_nodes, name ] }
-
- infra_ips:
- description: IPs of the nodes
- value: { get_attr: [ infra_nodes, private_ip ] }
-
- infra_floating_ips:
- description: Floating IPs of the nodes
- value: { get_attr: [ infra_nodes, floating_ip ] }
-
-resources:
-
- net:
- type: OS::Neutron::Net
- properties:
- name:
- str_replace:
- template: openshift-ansible-cluster_id-net
- params:
- cluster_id: { get_param: cluster_id }
-
- subnet:
- type: OS::Neutron::Subnet
- properties:
- name:
- str_replace:
- template: openshift-ansible-cluster_id-subnet
- params:
- cluster_id: { get_param: cluster_id }
- network: { get_resource: net }
- cidr:
- str_replace:
- template: subnet_24_prefix.0/24
- params:
- subnet_24_prefix: { get_param: subnet_24_prefix }
- dns_nameservers: { get_param: dns_nameservers }
-
- router:
- type: OS::Neutron::Router
- properties:
- name:
- str_replace:
- template: openshift-ansible-cluster_id-router
- params:
- cluster_id: { get_param: cluster_id }
- external_gateway_info:
- network: { get_param: external_net }
-
- interface:
- type: OS::Neutron::RouterInterface
- properties:
- router_id: { get_resource: router }
- subnet_id: { get_resource: subnet }
-
- keypair:
- type: OS::Nova::KeyPair
- properties:
- name:
- str_replace:
- template: openshift-ansible-cluster_id-keypair
- params:
- cluster_id: { get_param: cluster_id }
- public_key: { get_param: ssh_public_key }
-
- master-secgrp:
- type: OS::Neutron::SecurityGroup
- properties:
- name:
- str_replace:
- template: openshift-ansible-cluster_id-master-secgrp
- params:
- cluster_id: { get_param: cluster_id }
- description:
- str_replace:
- template: Security group for cluster_id OpenShift cluster master
- params:
- cluster_id: { get_param: cluster_id }
- rules:
- - direction: ingress
- protocol: tcp
- port_range_min: 22
- port_range_max: 22
- remote_ip_prefix: { get_param: ssh_incoming }
- - direction: ingress
- protocol: tcp
- port_range_min: 4001
- port_range_max: 4001
- - direction: ingress
- protocol: tcp
- port_range_min: 8443
- port_range_max: 8443
- - direction: ingress
- protocol: tcp
- port_range_min: 8444
- port_range_max: 8444
- - direction: ingress
- protocol: tcp
- port_range_min: 53
- port_range_max: 53
- - direction: ingress
- protocol: udp
- port_range_min: 53
- port_range_max: 53
- - direction: ingress
- protocol: tcp
- port_range_min: 8053
- port_range_max: 8053
- - direction: ingress
- protocol: udp
- port_range_min: 8053
- port_range_max: 8053
- - direction: ingress
- protocol: tcp
- port_range_min: 24224
- port_range_max: 24224
- - direction: ingress
- protocol: udp
- port_range_min: 24224
- port_range_max: 24224
- - direction: ingress
- protocol: tcp
- port_range_min: 2224
- port_range_max: 2224
- - direction: ingress
- protocol: udp
- port_range_min: 5404
- port_range_max: 5404
- - direction: ingress
- protocol: udp
- port_range_min: 5405
- port_range_max: 5405
- - direction: ingress
- protocol: tcp
- port_range_min: 9090
- port_range_max: 9090
-
- etcd-secgrp:
- type: OS::Neutron::SecurityGroup
- properties:
- name:
- str_replace:
- template: openshift-ansible-cluster_id-etcd-secgrp
- params:
- cluster_id: { get_param: cluster_id }
- description:
- str_replace:
- template: Security group for cluster_id etcd cluster
- params:
- cluster_id: { get_param: cluster_id }
- rules:
- - direction: ingress
- protocol: tcp
- port_range_min: 22
- port_range_max: 22
- remote_ip_prefix: { get_param: ssh_incoming }
- - direction: ingress
- protocol: tcp
- port_range_min: 2379
- port_range_max: 2379
- remote_mode: remote_group_id
- remote_group_id: { get_resource: master-secgrp }
- - direction: ingress
- protocol: tcp
- port_range_min: 2380
- port_range_max: 2380
- remote_mode: remote_group_id
-
- node-secgrp:
- type: OS::Neutron::SecurityGroup
- properties:
- name:
- str_replace:
- template: openshift-ansible-cluster_id-node-secgrp
- params:
- cluster_id: { get_param: cluster_id }
- description:
- str_replace:
- template: Security group for cluster_id OpenShift cluster nodes
- params:
- cluster_id: { get_param: cluster_id }
- rules:
- - direction: ingress
- protocol: tcp
- port_range_min: 22
- port_range_max: 22
- remote_ip_prefix: { get_param: ssh_incoming }
- - direction: ingress
- protocol: tcp
- port_range_min: 10250
- port_range_max: 10250
- remote_mode: remote_group_id
- - direction: ingress
- protocol: udp
- port_range_min: 4789
- port_range_max: 4789
- remote_mode: remote_group_id
- - direction: ingress
- protocol: tcp
- port_range_min: 30000
- port_range_max: 32767
- remote_ip_prefix: { get_param: node_port_incoming }
-
- infra-secgrp:
- type: OS::Neutron::SecurityGroup
- properties:
- name:
- str_replace:
- template: openshift-ansible-cluster_id-infra-secgrp
- params:
- cluster_id: { get_param: cluster_id }
- description:
- str_replace:
- template: Security group for cluster_id OpenShift infrastructure cluster nodes
- params:
- cluster_id: { get_param: cluster_id }
- rules:
- - direction: ingress
- protocol: tcp
- port_range_min: 80
- port_range_max: 80
- - direction: ingress
- protocol: tcp
- port_range_min: 443
- port_range_max: 443
-
- etcd:
- type: OS::Heat::ResourceGroup
- properties:
- count: { get_param: num_etcd }
- resource_def:
- type: heat_stack_server.yaml
- properties:
- name:
- str_replace:
- template: cluster_id-k8s_type-%index%
- params:
- cluster_id: { get_param: cluster_id }
- k8s_type: etcd
- cluster_env: { get_param: cluster_env }
- cluster_id: { get_param: cluster_id }
- type: etcd
- image: { get_param: etcd_image }
- flavor: { get_param: etcd_flavor }
- key_name: { get_resource: keypair }
- net: { get_resource: net }
- subnet: { get_resource: subnet }
- secgrp:
- - { get_resource: etcd-secgrp }
- floating_network: { get_param: external_net }
- net_name:
- str_replace:
- template: openshift-ansible-cluster_id-net
- params:
- cluster_id: { get_param: cluster_id }
- depends_on:
- - interface
-
- masters:
- type: OS::Heat::ResourceGroup
- properties:
- count: { get_param: num_masters }
- resource_def:
- type: heat_stack_server.yaml
- properties:
- name:
- str_replace:
- template: cluster_id-k8s_type-%index%
- params:
- cluster_id: { get_param: cluster_id }
- k8s_type: master
- cluster_env: { get_param: cluster_env }
- cluster_id: { get_param: cluster_id }
- type: master
- image: { get_param: master_image }
- flavor: { get_param: master_flavor }
- key_name: { get_resource: keypair }
- net: { get_resource: net }
- subnet: { get_resource: subnet }
- secgrp:
- - { get_resource: master-secgrp }
- - { get_resource: node-secgrp }
- floating_network: { get_param: external_net }
- net_name:
- str_replace:
- template: openshift-ansible-cluster_id-net
- params:
- cluster_id: { get_param: cluster_id }
- depends_on:
- - interface
-
- compute_nodes:
- type: OS::Heat::ResourceGroup
- properties:
- count: { get_param: num_nodes }
- resource_def:
- type: heat_stack_server.yaml
- properties:
- name:
- str_replace:
- template: cluster_id-k8s_type-sub_host_type-%index%
- params:
- cluster_id: { get_param: cluster_id }
- k8s_type: node
- sub_host_type: compute
- cluster_env: { get_param: cluster_env }
- cluster_id: { get_param: cluster_id }
- type: node
- subtype: compute
- image: { get_param: node_image }
- flavor: { get_param: node_flavor }
- key_name: { get_resource: keypair }
- net: { get_resource: net }
- subnet: { get_resource: subnet }
- secgrp:
- - { get_resource: node-secgrp }
- floating_network: { get_param: external_net }
- net_name:
- str_replace:
- template: openshift-ansible-cluster_id-net
- params:
- cluster_id: { get_param: cluster_id }
- depends_on:
- - interface
-
- infra_nodes:
- type: OS::Heat::ResourceGroup
- properties:
- count: { get_param: num_infra }
- resource_def:
- type: heat_stack_server.yaml
- properties:
- name:
- str_replace:
- template: cluster_id-k8s_type-sub_host_type-%index%
- params:
- cluster_id: { get_param: cluster_id }
- k8s_type: node
- sub_host_type: infra
- cluster_env: { get_param: cluster_env }
- cluster_id: { get_param: cluster_id }
- type: node
- subtype: infra
- image: { get_param: infra_image }
- flavor: { get_param: infra_flavor }
- key_name: { get_resource: keypair }
- net: { get_resource: net }
- subnet: { get_resource: subnet }
- secgrp:
- - { get_resource: node-secgrp }
- - { get_resource: infra-secgrp }
- floating_network: { get_param: external_net }
- net_name:
- str_replace:
- template: openshift-ansible-cluster_id-net
- params:
- cluster_id: { get_param: cluster_id }
- depends_on:
- - interface
diff --git a/playbooks/openstack/openshift-cluster/files/heat_stack_server.yaml b/playbooks/openstack/openshift-cluster/files/heat_stack_server.yaml
deleted file mode 100644
index 435139849..000000000
--- a/playbooks/openstack/openshift-cluster/files/heat_stack_server.yaml
+++ /dev/null
@@ -1,152 +0,0 @@
-heat_template_version: 2014-10-16
-
-description: OpenShift cluster server
-
-parameters:
-
- name:
- type: string
- label: Name
- description: Name
-
- cluster_env:
- type: string
- label: Cluster environment
- description: Environment of the cluster
-
- cluster_id:
- type: string
- label: Cluster ID
- description: Identifier of the cluster
-
- type:
- type: string
- label: Type
- description: Type master or node
-
- subtype:
- type: string
- label: Sub-type
- description: Sub-type compute or infra for nodes, default otherwise
- default: default
-
- key_name:
- type: string
- label: Key name
- description: Key name of keypair
-
- image:
- type: string
- label: Image
- description: Name of the image
-
- flavor:
- type: string
- label: Flavor
- description: Name of the flavor
-
- net:
- type: string
- label: Net ID
- description: Net resource
-
- net_name:
- type: string
- label: Net name
- description: Net name
-
- subnet:
- type: string
- label: Subnet ID
- description: Subnet resource
-
- secgrp:
- type: comma_delimited_list
- label: Security groups
- description: Security group resources
-
- floating_network:
- type: string
- label: Floating network
- description: Network to allocate floating IP from
-
-outputs:
-
- name:
- description: Name of the server
- value: { get_attr: [ server, name ] }
-
- private_ip:
- description: Private IP of the server
- value:
- get_attr:
- - server
- - addresses
- - { get_param: net_name }
- - 0
- - addr
-
- floating_ip:
- description: Floating IP of the server
- value:
- get_attr:
- - server
- - addresses
- - { get_param: net_name }
- - 1
- - addr
-
-resources:
-
- server:
- type: OS::Nova::Server
- properties:
- name: { get_param: name }
- key_name: { get_param: key_name }
- image: { get_param: image }
- flavor: { get_param: flavor }
- networks:
- - port: { get_resource: port }
- user_data: { get_resource: config }
- user_data_format: RAW
- metadata:
- environment: { get_param: cluster_env }
- clusterid: { get_param: cluster_id }
- host-type: { get_param: type }
- sub-host-type: { get_param: subtype }
-
- port:
- type: OS::Neutron::Port
- properties:
- network: { get_param: net }
- fixed_ips:
- - subnet: { get_param: subnet }
- security_groups: { get_param: secgrp }
-
- floating-ip:
- type: OS::Neutron::FloatingIP
- properties:
- floating_network: { get_param: floating_network }
- port_id: { get_resource: port }
-
- config:
- type: OS::Heat::CloudConfig
- properties:
- cloud_config:
- disable_root: true
-
- hostname: { get_param: name }
-
- system_info:
- default_user:
- name: openshift
- sudo: ["ALL=(ALL) NOPASSWD: ALL"]
-
- write_files:
- - path: /etc/sudoers.d/00-openshift-no-requiretty
- permissions: 440
- # content: Defaults:openshift !requiretty
- # Encoded in base64 to be sure that we do not forget the trailing newline or
- # sudo will not be able to parse that file
- encoding: b64
- content: RGVmYXVsdHM6b3BlbnNoaWZ0ICFyZXF1aXJldHR5Cg==
diff --git a/playbooks/openstack/openshift-cluster/filter_plugins b/playbooks/openstack/openshift-cluster/filter_plugins
deleted file mode 120000
index 99a95e4ca..000000000
--- a/playbooks/openstack/openshift-cluster/filter_plugins
+++ /dev/null
@@ -1 +0,0 @@
-../../../filter_plugins \ No newline at end of file
diff --git a/playbooks/openstack/openshift-cluster/launch.yml b/playbooks/openstack/openshift-cluster/launch.yml
deleted file mode 100644
index c0bc12f55..000000000
--- a/playbooks/openstack/openshift-cluster/launch.yml
+++ /dev/null
@@ -1,191 +0,0 @@
----
-- name: Launch instance(s)
- hosts: localhost
- become: no
- connection: local
- gather_facts: no
- vars_files:
- - vars.yml
- tasks:
- # TODO: Write an Ansible module for dealing with HEAT stacks
- # Dealing with the outputs is currently terrible
-
- - name: Check OpenStack stack
- command: 'heat stack-show openshift-ansible-{{ cluster_id }}-stack'
- register: stack_show_result
- changed_when: false
- failed_when: stack_show_result.rc != 0 and 'Stack not found' not in stack_show_result.stderr
-
- - set_fact:
- heat_stack_action: 'stack-create'
- when: stack_show_result.rc == 1
- - set_fact:
- heat_stack_action: 'stack-update'
- when: stack_show_result.rc == 0
-
- - name: Create or Update OpenStack Stack
- command: 'heat {{ heat_stack_action }} -f {{ openstack_infra_heat_stack }}
- --timeout {{ openstack_heat_timeout }}
- -P cluster_env={{ cluster_env }}
- -P cluster_id={{ cluster_id }}
- -P subnet_24_prefix={{ openstack_subnet_24_prefix }}
- -P dns_nameservers={{ openstack_network_dns | join(",") }}
- -P external_net={{ openstack_network_external_net }}
- -P ssh_public_key="{{ openstack_ssh_public_key }}"
- -P ssh_incoming={{ openstack_ssh_access_from }}
- -P node_port_incoming={{ openstack_node_port_access_from }}
- -P num_etcd={{ num_etcd }}
- -P num_masters={{ num_masters }}
- -P num_nodes={{ num_nodes }}
- -P num_infra={{ num_infra }}
- -P etcd_image={{ deployment_vars[deployment_type].image }}
- -P master_image={{ deployment_vars[deployment_type].image }}
- -P node_image={{ deployment_vars[deployment_type].image }}
- -P infra_image={{ deployment_vars[deployment_type].image }}
- -P etcd_flavor={{ openstack_flavor["etcd"] }}
- -P master_flavor={{ openstack_flavor["master"] }}
- -P node_flavor={{ openstack_flavor["node"] }}
- -P infra_flavor={{ openstack_flavor["infra"] }}
- openshift-ansible-{{ cluster_id }}-stack'
- args:
- chdir: '{{ playbook_dir }}'
-
- - name: Wait for OpenStack Stack readiness
- shell: 'heat stack-show openshift-ansible-{{ cluster_id }}-stack | awk ''$2 == "stack_status" {print $4}'''
- register: stack_show_status_result
- until: stack_show_status_result.stdout not in ['CREATE_IN_PROGRESS', 'UPDATE_IN_PROGRESS']
- retries: 30
- delay: 5
-
- - name: Display the stack resources
- command: 'heat resource-list openshift-ansible-{{ cluster_id }}-stack'
- register: stack_resource_list_result
- when: stack_show_status_result.stdout not in ['CREATE_COMPLETE', 'UPDATE_COMPLETE']
-
- - name: Display the stack status
- command: 'heat stack-show openshift-ansible-{{ cluster_id }}-stack'
- register: stack_show_result
- when: stack_show_status_result.stdout not in ['CREATE_COMPLETE', 'UPDATE_COMPLETE']
-
- - name: Delete the stack
- command: 'heat stack-delete openshift-ansible-{{ cluster_id }}-stack'
- when: stack_show_status_result.stdout not in ['CREATE_COMPLETE', 'UPDATE_COMPLETE']
-
- - fail:
- msg: |
-
- +--------------------------------------+
- | ^ |
- | /!\ Failed to create the heat stack |
- | /___\ |
- +--------------------------------------+
-
- Here is the list of stack resources and their status:
- {{ stack_resource_list_result.stdout }}
-
- Here is the status of the stack:
- {{ stack_show_result.stdout }}
-
- ^ Failed to create the heat stack
- /!\
- /___\ Please check the `stack_status_reason` line in the above array to know why.
- when: stack_show_status_result.stdout not in ['CREATE_COMPLETE', 'UPDATE_COMPLETE']
-
- - name: Read OpenStack Stack outputs
- command: 'heat stack-show openshift-ansible-{{ cluster_id }}-stack'
- register: stack_show_result
-
- - set_fact:
- parsed_outputs: "{{ stack_show_result | oo_parse_heat_stack_outputs }}"
-
- - name: Add new etcd instances groups and variables
- add_host:
- hostname: '{{ item[0] }}'
- ansible_ssh_host: '{{ item[2] }}'
- ansible_ssh_user: "{{ deployment_vars[deployment_type].ssh_user }}"
- ansible_become: "{{ deployment_vars[deployment_type].become }}"
- groups: 'meta-environment_{{ cluster_env }}, meta-host-type_etcd, meta-sub-host-type_default, meta-clusterid_{{ cluster_id }}'
- openshift_node_labels:
- type: "etcd"
- openstack:
- public_v4: '{{ item[2] }}'
- private_v4: '{{ item[1] }}'
- with_together:
- - '{{ parsed_outputs.etcd_names }}'
- - '{{ parsed_outputs.etcd_ips }}'
- - '{{ parsed_outputs.etcd_floating_ips }}'
-
- - name: Add new master instances groups and variables
- add_host:
- hostname: '{{ item[0] }}'
- ansible_ssh_host: '{{ item[2] }}'
- ansible_ssh_user: "{{ deployment_vars[deployment_type].ssh_user }}"
- ansible_become: "{{ deployment_vars[deployment_type].become }}"
- groups: 'meta-environment_{{ cluster_env }}, meta-host-type_master, meta-sub-host-type_default, meta-clusterid_{{ cluster_id }}'
- openshift_node_labels:
- type: "master"
- openstack:
- public_v4: '{{ item[2] }}'
- private_v4: '{{ item[1] }}'
- with_together:
- - '{{ parsed_outputs.master_names }}'
- - '{{ parsed_outputs.master_ips }}'
- - '{{ parsed_outputs.master_floating_ips }}'
-
- - name: Add new node instances groups and variables
- add_host:
- hostname: '{{ item[0] }}'
- ansible_ssh_host: '{{ item[2] }}'
- ansible_ssh_user: "{{ deployment_vars[deployment_type].ssh_user }}"
- ansible_become: "{{ deployment_vars[deployment_type].become }}"
- groups: 'meta-environment_{{ cluster_env }}, meta-host-type_node, meta-sub-host-type_compute, meta-clusterid_{{ cluster_id }}'
- openshift_node_labels:
- type: "compute"
- openstack:
- public_v4: '{{ item[2] }}'
- private_v4: '{{ item[1] }}'
- with_together:
- - '{{ parsed_outputs.node_names }}'
- - '{{ parsed_outputs.node_ips }}'
- - '{{ parsed_outputs.node_floating_ips }}'
-
- - name: Add new infra instances groups and variables
- add_host:
- hostname: '{{ item[0] }}'
- ansible_ssh_host: '{{ item[2] }}'
- ansible_ssh_user: "{{ deployment_vars[deployment_type].ssh_user }}"
- ansible_become: "{{ deployment_vars[deployment_type].become }}"
- groups: 'meta-environment_{{ cluster_env }}, meta-host-type_node, meta-sub-host-type_infra, meta-clusterid_{{ cluster_id }}'
- openshift_node_labels:
- type: "infra"
- openstack:
- public_v4: '{{ item[2] }}'
- private_v4: '{{ item[1] }}'
- with_together:
- - '{{ parsed_outputs.infra_names }}'
- - '{{ parsed_outputs.infra_ips }}'
- - '{{ parsed_outputs.infra_floating_ips }}'
-
- - name: Wait for ssh
- wait_for:
- host: '{{ item }}'
- port: 22
- with_flattened:
- - '{{ parsed_outputs.master_floating_ips }}'
- - '{{ parsed_outputs.node_floating_ips }}'
- - '{{ parsed_outputs.infra_floating_ips }}'
-
- - name: Wait for user setup
- command: 'ssh -o StrictHostKeyChecking=no -o PasswordAuthentication=no -o ConnectTimeout=10 -o UserKnownHostsFile=/dev/null {{ deployment_vars[deployment_type].ssh_user }}@{{ item }} echo {{ deployment_vars[deployment_type].ssh_user }} user is setup'
- register: result
- until: result.rc == 0
- retries: 30
- delay: 1
- with_flattened:
- - '{{ parsed_outputs.master_floating_ips }}'
- - '{{ parsed_outputs.node_floating_ips }}'
- - '{{ parsed_outputs.infra_floating_ips }}'
-
-- include: update.yml
-
-- include: list.yml
diff --git a/playbooks/openstack/openshift-cluster/list.yml b/playbooks/openstack/openshift-cluster/list.yml
deleted file mode 100644
index 6c6f671be..000000000
--- a/playbooks/openstack/openshift-cluster/list.yml
+++ /dev/null
@@ -1,24 +0,0 @@
----
-- name: Generate oo_list_hosts group
- hosts: localhost
- become: no
- connection: local
- gather_facts: no
- vars_files:
- - vars.yml
- tasks:
- - set_fact: scratch_group=meta-clusterid_{{ cluster_id }}
- when: cluster_id != ''
- - set_fact: scratch_group=all
- when: cluster_id == ''
- - add_host:
- name: "{{ item }}"
- groups: oo_list_hosts
- ansible_ssh_user: "{{ deployment_vars[deployment_type].ssh_user }}"
- ansible_ssh_host: "{{ hostvars[item].ansible_ssh_host | default(item) }}"
- ansible_become: "{{ deployment_vars[deployment_type].become }}"
- oo_public_ipv4: "{{ hostvars[item].openstack.public_v4 }}"
- oo_private_ipv4: "{{ hostvars[item].openstack.private_v4 }}"
- with_items: "{{ groups[scratch_group] | default([]) | difference(['localhost']) }}"
- - debug:
- msg: "{{ hostvars | oo_select_keys(groups[scratch_group] | default([])) | oo_pretty_print_cluster('meta-') }}"
diff --git a/playbooks/openstack/openshift-cluster/lookup_plugins b/playbooks/openstack/openshift-cluster/lookup_plugins
deleted file mode 120000
index ac79701db..000000000
--- a/playbooks/openstack/openshift-cluster/lookup_plugins
+++ /dev/null
@@ -1 +0,0 @@
-../../../lookup_plugins \ No newline at end of file
diff --git a/playbooks/openstack/openshift-cluster/roles b/playbooks/openstack/openshift-cluster/roles
deleted file mode 120000
index 20c4c58cf..000000000
--- a/playbooks/openstack/openshift-cluster/roles
+++ /dev/null
@@ -1 +0,0 @@
-../../../roles \ No newline at end of file
diff --git a/playbooks/openstack/openshift-cluster/terminate.yml b/playbooks/openstack/openshift-cluster/terminate.yml
deleted file mode 100644
index affb57117..000000000
--- a/playbooks/openstack/openshift-cluster/terminate.yml
+++ /dev/null
@@ -1,49 +0,0 @@
----
-- name: Terminate instance(s)
- hosts: localhost
- become: no
- connection: local
- gather_facts: no
- vars_files:
- - vars.yml
- tasks:
- - add_host:
- name: "{{ item }}"
- groups: oo_hosts_to_terminate
- ansible_ssh_user: "{{ deployment_vars[deployment_type].ssh_user }}"
- ansible_become: "{{ deployment_vars[deployment_type].become }}"
- with_items: "{{ (groups['meta-environment_' ~ cluster_env]|default([])) | intersect(groups['meta-clusterid_' ~ cluster_id ]|default([])) }}"
-
-- name: Unsubscribe VMs
- hosts: oo_hosts_to_terminate
- vars_files:
- - vars.yml
- roles:
- - role: rhel_unsubscribe
- when: deployment_type in ['atomic-enterprise', 'enterprise', 'openshift-enterprise'] and
- ansible_distribution == "RedHat" and
- lookup('oo_option', 'rhel_skip_subscription') | default(rhsub_skip, True) |
- default('no', True) | lower in ['no', 'false']
-
-- hosts: localhost
- become: no
- connection: local
- gather_facts: no
- vars_files:
- - vars.yml
- tasks:
- - name: Delete the OpenStack Stack
- command: 'heat stack-delete openshift-ansible-{{ cluster_id }}-stack'
- register: stack_delete_result
- changed_when: stack_delete_result.rc == 0
- failed_when: stack_delete_result.rc != 0 and 'could not be found' not in stack_delete_result.stdout
-
- - name: Wait for the completion of the OpenStack Stack deletion
- shell: 'heat stack-show openshift-ansible-{{ cluster_id }}-stack | awk ''$2 == "stack_status" {print $4}'''
- when: stack_delete_result.changed
- register: stack_show_result
- until: stack_show_result.stdout != 'DELETE_IN_PROGRESS'
- retries: 60
- delay: 5
- failed_when: '"Stack not found" not in stack_show_result.stderr and
- stack_show_result.stdout != "DELETE_COMPLETE"'
diff --git a/playbooks/openstack/openshift-cluster/update.yml b/playbooks/openstack/openshift-cluster/update.yml
deleted file mode 100644
index 6d2af3d26..000000000
--- a/playbooks/openstack/openshift-cluster/update.yml
+++ /dev/null
@@ -1,34 +0,0 @@
----
-- hosts: localhost
- gather_facts: no
- tasks:
- - include_vars: vars.yml
- - include_vars: cluster_hosts.yml
- - add_host:
- name: "{{ item }}"
- groups: l_oo_all_hosts
- with_items: "{{ g_all_hosts }}"
-
-- hosts: l_oo_all_hosts
- gather_facts: no
- tasks:
- - include_vars: vars.yml
- - include_vars: cluster_hosts.yml
-
-- name: Populate oo_hosts_to_update group
- hosts: localhost
- connection: local
- become: no
- gather_facts: no
- tasks:
- - name: Evaluate oo_hosts_to_update
- add_host:
- name: "{{ item }}"
- groups: oo_hosts_to_update
- ansible_ssh_user: "{{ deployment_vars[deployment_type].ssh_user }}"
- ansible_become: "{{ deployment_vars[deployment_type].become }}"
- with_items: "{{ g_all_hosts | default([]) }}"
-
-- include: ../../common/openshift-cluster/update_repos_and_packages.yml
-
-- include: config.yml
diff --git a/playbooks/openstack/openshift-cluster/vars.yml b/playbooks/openstack/openshift-cluster/vars.yml
deleted file mode 100644
index ba2855b73..000000000
--- a/playbooks/openstack/openshift-cluster/vars.yml
+++ /dev/null
@@ -1,38 +0,0 @@
-# yamllint disable rule:colons
----
-debug_level: 2
-openstack_infra_heat_stack: "{{ lookup('oo_option', 'infra_heat_stack' ) |
- default('files/heat_stack.yaml', True) }}"
-openstack_subnet_24_prefix: "{{ lookup('oo_option', 'subnet_24_prefix' ) |
- default('192.168.' + ( ( 1048576 | random % 256 ) | string() ), True) }}"
-openstack_network_external_net: "{{ lookup('oo_option', 'external_net' ) |
- default('external', True) }}"
-openstack_network_dns: "{{ lookup('oo_option', 'dns' ) |
- default('8.8.8.8,8.8.4.4', True) | oo_split() }}"
-openstack_ssh_public_key: "{{ lookup('file', lookup('oo_option', 'public_key') |
- default('~/.ssh/id_rsa.pub', True)) }}"
-openstack_ssh_access_from: "{{ lookup('oo_option', 'ssh_from') |
- default('0.0.0.0/0', True) }}"
-openstack_node_port_access_from: "{{ lookup('oo_option', 'node_port_from') |
- default('0.0.0.0/0', True) }}"
-openstack_heat_timeout: "{{ lookup('oo_option', 'heat_timeout') |
- default('3', True) }}"
-openstack_flavor:
- etcd: "{{ lookup('oo_option', 'etcd_flavor' ) | default('m1.small', True) }}"
- master: "{{ lookup('oo_option', 'master_flavor' ) | default('m1.small', True) }}"
- infra: "{{ lookup('oo_option', 'infra_flavor' ) | default('m1.small', True) }}"
- node: "{{ lookup('oo_option', 'node_flavor' ) | default('m1.medium', True) }}"
-
-deployment_rhel7_ent_base:
- image: "{{ lookup('oo_option', 'image_name') | default('rhel-guest-image-7.2-20151102.0.x86_64', True) }}"
- ssh_user: openshift
- become: yes
-
-deployment_vars:
- origin:
- image: "{{ lookup('oo_option', 'image_name') | default('centos-70-raw', True) }}"
- ssh_user: openshift
- become: yes
- enterprise: "{{ deployment_rhel7_ent_base }}"
- openshift-enterprise: "{{ deployment_rhel7_ent_base }}"
- atomic-enterprise: "{{ deployment_rhel7_ent_base }}"
diff --git a/roles/ansible_service_broker/vars/openshift-enterprise.yml b/roles/ansible_service_broker/vars/openshift-enterprise.yml
index 0b3a2a69d..ce2ae8365 100644
--- a/roles/ansible_service_broker/vars/openshift-enterprise.yml
+++ b/roles/ansible_service_broker/vars/openshift-enterprise.yml
@@ -1,7 +1,7 @@
---
__ansible_service_broker_image_prefix: registry.access.redhat.com/openshift3/ose-
-__ansible_service_broker_image_tag: latest
+__ansible_service_broker_image_tag: v3.6
__ansible_service_broker_etcd_image_prefix: rhel7/
__ansible_service_broker_etcd_image_tag: latest
diff --git a/roles/calico/defaults/main.yaml b/roles/calico/defaults/main.yaml
index 03c96be36..be73e8a73 100644
--- a/roles/calico/defaults/main.yaml
+++ b/roles/calico/defaults/main.yaml
@@ -1,5 +1,5 @@
---
-kubeconfig: "{{openshift.common.config_base}}/node/{{ 'system:node:' + openshift.common.hostname }}.kubeconfig"
+kubeconfig: "{{ openshift.common.config_base }}/node/{{ 'system:node:' + openshift.common.hostname }}.kubeconfig"
cni_conf_dir: "/etc/cni/net.d/"
cni_bin_dir: "/opt/cni/bin/"
@@ -11,4 +11,4 @@ calico_url_ipam: "https://github.com/projectcalico/cni-plugin/releases/download/
calico_ipv4pool_ipip: "always"
calico_log_dir: "/var/log/calico"
-calico_node_image: "calico/node:v2.4.1"
+calico_node_image: "calico/node:v2.5.0"
diff --git a/roles/calico/tasks/main.yml b/roles/calico/tasks/main.yml
index e62378532..39f730462 100644
--- a/roles/calico/tasks/main.yml
+++ b/roles/calico/tasks/main.yml
@@ -38,7 +38,7 @@
path: "{{ item }}"
with_items:
- "{{ calico_etcd_ca_cert_file }}"
- - "{{ calico_etcd_cert_file}}"
+ - "{{ calico_etcd_cert_file }}"
- "{{ calico_etcd_key_file }}"
- name: Calico Node | Configure Calico service unit file
diff --git a/roles/calico_master/defaults/main.yaml b/roles/calico_master/defaults/main.yaml
index d40286aba..01a2b9529 100644
--- a/roles/calico_master/defaults/main.yaml
+++ b/roles/calico_master/defaults/main.yaml
@@ -3,5 +3,5 @@ kubeconfig: "{{ openshift.common.config_base }}/master/openshift-master.kubeconf
calicoctl_bin_dir: "/usr/local/bin/"
-calico_url_calicoctl: "https://github.com/projectcalico/calicoctl/releases/download/v1.4.0/calicoctl"
+calico_url_calicoctl: "https://github.com/projectcalico/calicoctl/releases/download/v1.5.0/calicoctl"
calico_url_policy_controller: "quay.io/calico/kube-policy-controller:v0.7.0"
diff --git a/roles/cockpit/defaults/main.yml b/roles/cockpit/defaults/main.yml
index cbe5bb92b..15c40e3b5 100644
--- a/roles/cockpit/defaults/main.yml
+++ b/roles/cockpit/defaults/main.yml
@@ -1,6 +1,6 @@
---
-r_cockpit_firewall_enabled: True
-r_cockpit_use_firewalld: False
+r_cockpit_firewall_enabled: "{{ os_firewall_enabled | default(True) }}"
+r_cockpit_use_firewalld: "{{ os_firewall_use_firewalld | default(False) }}"
r_cockpit_os_firewall_deny: []
r_cockpit_os_firewall_allow:
diff --git a/roles/dns/README.md b/roles/dns/README.md
deleted file mode 100644
index 9a88ce97c..000000000
--- a/roles/dns/README.md
+++ /dev/null
@@ -1,45 +0,0 @@
-dns
-===
-
-Configure a DNS server serving IPs of all the nodes of the cluster
-
-Requirements
-------------
-
-Ansible 2.2
-
-Role Variables
---------------
-
-| Name | Mandatory / Optional | Description |
-|------|----------------------|-------------|
-| `dns_zones` | Mandatory | DNS zones in which we must find the hosts |
-| `dns_forwarders` | If not set, the DNS will be a recursive non-forwarding DNS server | DNS forwarders to delegate the requests for hosts outside of `dns_zones` |
-| `dns_all_hosts` | Mandatory | Exhaustive list of hosts |
-| `base_docker_image` | Optional | Base docker image to build Bind image from, used only in containerized deployments |
-
-Dependencies
-------------
-
-None
-
-Example Playbook
-----------------
-
- - hosts: dns_hosts
- roles:
- - role: dns
- dns_forwarders: [ '8.8.8.8', '8.8.4.4' ]
- dns_zones: [ novalocal, openstacklocal ]
- dns_all_hosts: "{{ g_all_hosts }}"
- base_docker_image: 'centos:centos7'
-
-License
--------
-
-ASL 2.0
-
-Author Information
-------------------
-
-OpenShift operations, Red Hat, Inc
diff --git a/roles/dns/defaults/main.yml b/roles/dns/defaults/main.yml
deleted file mode 100644
index 82055c8cd..000000000
--- a/roles/dns/defaults/main.yml
+++ /dev/null
@@ -1,2 +0,0 @@
----
-base_docker_image: "{{ 'centos:centos7' if openshift.common.deployment_type == 'origin' else 'rhel7' }}"
diff --git a/roles/dns/handlers/main.yml b/roles/dns/handlers/main.yml
deleted file mode 100644
index 61fd7a10e..000000000
--- a/roles/dns/handlers/main.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-- name: restart bind
- systemd:
- name: named
- state: restarted
diff --git a/roles/dns/meta/main.yml b/roles/dns/meta/main.yml
deleted file mode 100644
index 64d56114e..000000000
--- a/roles/dns/meta/main.yml
+++ /dev/null
@@ -1,9 +0,0 @@
----
-galaxy_info:
- author: Lénaïc Huard
- description: Deploy and configure a DNS server
- company: Amadeus SAS
- license: ASL 2.0
- min_ansible_version: 2.2
-dependencies:
-- { role: openshift_facts }
diff --git a/roles/dns/tasks/main.yml b/roles/dns/tasks/main.yml
deleted file mode 100644
index c5ab53b4d..000000000
--- a/roles/dns/tasks/main.yml
+++ /dev/null
@@ -1,46 +0,0 @@
----
-- name: Install Bind
- package: name=bind state=present
- when: not openshift.common.is_containerized | bool
-
-- name: Create docker build dir
- file: path=/tmp/dockerbuild state=directory
- when: openshift.common.is_containerized | bool
-
-- name: Install dockerfile
- template:
- dest: "/tmp/dockerbuild/Dockerfile"
- src: Dockerfile
- when: openshift.common.is_containerized | bool
-
-- name: Build Bind image
- docker_image: path="/tmp/dockerbuild" name="bind" state=present
- when: openshift.common.is_containerized | bool
-
-- name: Install bind service file
- template:
- dest: "/etc/systemd/system/named.service"
- src: named.service.j2
- when: openshift.common.is_containerized | bool
-
-- name: Create bind zone dir
- file: path=/var/named state=directory
- when: openshift.common.is_containerized | bool
-
-- name: Configure Bind
- template:
- src: "{{ item.src }}"
- dest: "{{ item.dest }}"
- with_items:
- - src: openshift-cluster.zone
- dest: /var/named/openshift-cluster.zone
- - src: named.conf
- dest: /etc/named.conf
- notify: restart bind
-
-- name: Enable Bind
- systemd:
- name: named
- state: started
- enabled: yes
- daemon_reload: yes
diff --git a/roles/dns/templates/Dockerfile b/roles/dns/templates/Dockerfile
deleted file mode 100644
index cdff0a228..000000000
--- a/roles/dns/templates/Dockerfile
+++ /dev/null
@@ -1,11 +0,0 @@
-FROM {{ base_docker_image }}
-MAINTAINER Jan Provaznik <jprovazn@redhat.com>
-
-# install main packages:
-RUN yum -y update; yum clean all;
-RUN yum -y install bind-utils bind
-
-EXPOSE 53
-
-# start services:
-CMD ["/usr/sbin/named", "-f"]
diff --git a/roles/dns/templates/named.conf b/roles/dns/templates/named.conf
deleted file mode 100644
index 22c1ff935..000000000
--- a/roles/dns/templates/named.conf
+++ /dev/null
@@ -1,23 +0,0 @@
-options
-{
- directory "/var/named";
-
- allow-query { {{ ansible_default_ipv4.network }}/24; };
-
- recursion yes;
-
-{% if dns_forwarders is defined %}
- forwarders {
- {% for dns in dns_forwarders %}
- {{ dns }};
- {% endfor %}
- };
-{% endif %}
-};
-{% for zone in dns_zones %}
-
-zone "{{ zone }}" IN {
- type master;
- file "openshift-cluster.zone";
-};
-{% endfor %}
diff --git a/roles/dns/templates/named.service.j2 b/roles/dns/templates/named.service.j2
deleted file mode 100644
index 6e0a7a640..000000000
--- a/roles/dns/templates/named.service.j2
+++ /dev/null
@@ -1,15 +0,0 @@
-[Unit]
-Requires={{ openshift.docker.service_name }}.service
-After={{ openshift.docker.service_name }}.service
-PartOf={{ openshift.docker.service_name }}.service
-
-[Service]
-Type=simple
-TimeoutStartSec=5m
-ExecStartPre=/usr/bin/docker run --rm -v /etc/named.conf:/etc/named.conf -v /var/named:/var/named:z bind named-checkconf -z /etc/named.conf
-ExecStartPre=-/usr/bin/docker rm -f bind
-ExecStart=/usr/bin/docker run --name bind -p 53:53/udp -v /var/log:/var/log -v /etc/named.conf:/etc/named.conf -v /var/named:/var/named:z bind
-ExecStop=/usr/bin/docker stop bind
-
-[Install]
-WantedBy={{ openshift.docker.service_name }}.service
diff --git a/roles/dns/templates/openshift-cluster.zone b/roles/dns/templates/openshift-cluster.zone
deleted file mode 100644
index 03f5dc089..000000000
--- a/roles/dns/templates/openshift-cluster.zone
+++ /dev/null
@@ -1,14 +0,0 @@
-$TTL 1d
-@ IN SOA {{ ansible_hostname }} openshift (
- {{ ansible_date_time.epoch }} ; Serial (To be fixed before 2039)
- 12h ; Refresh
- 3m ; Retry
- 4w ; Expire
- 3h ; TTL for negative replies
- )
-
- IN NS {{ ansible_hostname }}
-{{ ansible_hostname }} IN A {{ ansible_default_ipv4.address }}
-{% for host in dns_all_hosts %}
-{{ hostvars[host].ansible_hostname }} IN A {{ hostvars[host]['ansible_default_ipv4'].address }}
-{% endfor %}
diff --git a/roles/docker/defaults/main.yml b/roles/docker/defaults/main.yml
index ed97d539c..7e206ded1 100644
--- a/roles/docker/defaults/main.yml
+++ b/roles/docker/defaults/main.yml
@@ -1 +1,6 @@
---
+docker_cli_auth_config_path: '/root/.docker'
+
+oreg_url: ''
+oreg_host: "{{ oreg_url.split('/')[0] if '.' in oreg_url.split('/')[0] else '' }}"
+oreg_auth_credentials_replace: False
diff --git a/roles/docker/tasks/main.yml b/roles/docker/tasks/main.yml
index 1f9ac5059..78c6671d8 100644
--- a/roles/docker/tasks/main.yml
+++ b/roles/docker/tasks/main.yml
@@ -7,8 +7,8 @@
- set_fact:
l_use_system_container: "{{ openshift.docker.use_system_container | default(False) }}"
- l_use_crio: "{{ openshift.docker.use_crio | default(False) }}"
- l_use_crio_only: "{{ openshift.docker.use_crio_only | default(False) }}"
+ l_use_crio: "{{ openshift_use_crio | default(False) }}"
+ l_use_crio_only: "{{ openshift_use_crio_only | default(False) }}"
- name: Use Package Docker if Requested
include: package_docker.yml
diff --git a/roles/docker/tasks/package_docker.yml b/roles/docker/tasks/package_docker.yml
index bc52ab60c..16aea5067 100644
--- a/roles/docker/tasks/package_docker.yml
+++ b/roles/docker/tasks/package_docker.yml
@@ -3,6 +3,8 @@
command: "{{ repoquery_cmd }} --installed --qf '%{version}' docker"
when: not openshift.common.is_atomic | bool
register: curr_docker_version
+ retries: 4
+ until: curr_docker_version | succeeded
changed_when: false
- name: Error out if Docker pre-installed but too old
@@ -117,6 +119,18 @@
notify:
- restart docker
+- name: Check for credentials file for registry auth
+ stat:
+ path: "{{ docker_cli_auth_config_path }}/config.json"
+ when: oreg_auth_user is defined
+ register: docker_cli_auth_credentials_stat
+
+- name: Create credentials for docker cli registry auth
+ command: "docker --config={{ docker_cli_auth_config_path }} login -u {{ oreg_auth_user }} -p {{ oreg_auth_password }} {{ oreg_host }}"
+ when:
+ - oreg_auth_user is defined
+ - (not docker_cli_auth_credentials_stat.stat.exists or oreg_auth_credentials_replace) | bool
+
- name: Start the Docker service
systemd:
name: docker
diff --git a/roles/docker/tasks/systemcontainer_crio.yml b/roles/docker/tasks/systemcontainer_crio.yml
index 787f51f94..0bab0899c 100644
--- a/roles/docker/tasks/systemcontainer_crio.yml
+++ b/roles/docker/tasks/systemcontainer_crio.yml
@@ -3,6 +3,15 @@
- set_fact:
l_insecure_crio_registries: "{{ '\"{}\"'.format('\", \"'.join(openshift.docker.insecure_registries)) }}"
when: openshift.docker.insecure_registries
+- set_fact:
+ l_crio_registries: "{{ openshift.docker.additional_registries + ['docker.io'] }}"
+ when: openshift.docker.additional_registries
+- set_fact:
+ l_crio_registries: "{{ ['docker.io'] }}"
+ when: not openshift.docker.additional_registries
+- set_fact:
+ l_additional_crio_registries: "{{ '\"{}\"'.format('\", \"'.join(l_crio_registries)) }}"
+ when: openshift.docker.additional_registries
- name: Ensure container-selinux is installed
package:
@@ -86,12 +95,18 @@
- name: Set to default prepend
set_fact:
l_crio_image_prepend: "docker.io/gscrivano"
- l_crio_image_name: "crio-o-fedora"
+ l_crio_image_name: "cri-o-fedora"
- - name: Use Centos based image when distribution is Red Hat or CentOS
+ - name: Use Centos based image when distribution is CentOS
set_fact:
l_crio_image_name: "cri-o-centos"
- when: ansible_distribution in ['RedHat', 'CentOS']
+ when: ansible_distribution == "CentOS"
+
+ - name: Use RHEL based image when distribution is Red Hat
+ set_fact:
+ l_crio_image_prepend: "registry.access.redhat.com"
+ l_crio_image_name: "cri-o"
+ when: ansible_distribution == "RedHat"
# For https://github.com/openshift/openshift-ansible/pull/4049#discussion_r114478504
- name: Use a testing registry if requested
diff --git a/roles/docker/tasks/systemcontainer_docker.yml b/roles/docker/tasks/systemcontainer_docker.yml
index 57a84bc2c..146e5f430 100644
--- a/roles/docker/tasks/systemcontainer_docker.yml
+++ b/roles/docker/tasks/systemcontainer_docker.yml
@@ -100,18 +100,22 @@
l_docker_image_prepend: "registry.fedoraproject.org/f25"
when: ansible_distribution == 'Fedora'
- # For https://github.com/openshift/openshift-ansible/pull/4049#discussion_r114478504
- - name: Use a testing registry if requested
- set_fact:
- l_docker_image_prepend: "{{ openshift_docker_systemcontainer_image_registry_override }}"
- when:
- - openshift_docker_systemcontainer_image_registry_override is defined
- - openshift_docker_systemcontainer_image_registry_override != ""
-
- name: Set the full image name
set_fact:
l_docker_image: "{{ l_docker_image_prepend }}/{{ openshift.docker.service_name }}:latest"
+ # For https://github.com/openshift/openshift-ansible/pull/5354#issuecomment-328552959
+ - name: Use a specific image if requested
+ set_fact:
+ l_docker_image: "{{ openshift_docker_systemcontainer_image_override }}"
+ when:
+ - openshift_docker_systemcontainer_image_override is defined
+ - openshift_docker_systemcontainer_image_override != ""
+
+ # Be nice and let the user see the variable result
+ - debug:
+ var: l_docker_image
+
# NOTE: no_proxy added as a workaround until https://github.com/projectatomic/atomic/pull/999 is released
- name: Pre-pull Container Engine System Container image
command: "atomic pull --storage ostree {{ l_docker_image }}"
diff --git a/roles/docker/templates/crio.conf.j2 b/roles/docker/templates/crio.conf.j2
index eae1759ab..b4ee84fd0 100644
--- a/roles/docker/templates/crio.conf.j2
+++ b/roles/docker/templates/crio.conf.j2
@@ -43,7 +43,7 @@ stream_port = "10010"
# This is a mandatory setting as this runtime will be the default one
# and will also be used for untrusted container workloads if
# runtime_untrusted_workload is not set.
-runtime = "/usr/libexec/crio/runc"
+runtime = "/usr/bin/runc"
# runtime_untrusted_workload is the OCI compatible runtime used for untrusted
# container workloads. This is an optional setting, except if
@@ -120,6 +120,11 @@ insecure_registries = [
{{ l_insecure_crio_registries|default("") }}
]
+# registries is used to specify a comma separated list of registries to be used
+# when pulling an unqualified image (e.g. fedora:rawhide).
+registries = [
+{{ l_additional_crio_registries|default("") }}
+]
# The "crio.network" table contains settings pertaining to the
# management of CNI plugins.
[crio.network]
diff --git a/roles/etcd/defaults/main.yaml b/roles/etcd/defaults/main.yaml
index d12d7a358..3cc2bbb18 100644
--- a/roles/etcd/defaults/main.yaml
+++ b/roles/etcd/defaults/main.yaml
@@ -1,6 +1,6 @@
---
-r_etcd_firewall_enabled: True
-r_etcd_use_firewalld: False
+r_etcd_firewall_enabled: "{{ os_firewall_enabled | default(True) }}"
+r_etcd_use_firewalld: "{{ os_firewall_use_firewalld | default(Falsel) }}"
etcd_initial_cluster_state: new
etcd_initial_cluster_token: etcd-cluster-1
diff --git a/roles/etcd/templates/etcd.conf.j2 b/roles/etcd/templates/etcd.conf.j2
index ce362c743..2c2803aee 100644
--- a/roles/etcd/templates/etcd.conf.j2
+++ b/roles/etcd/templates/etcd.conf.j2
@@ -11,7 +11,8 @@
ETCD_NAME={{ etcd_hostname }}
ETCD_LISTEN_PEER_URLS={{ etcd_listen_peer_urls }}
ETCD_DATA_DIR={{ etcd_data_dir }}
-#ETCD_SNAPSHOT_COUNTER=10000
+#ETCD_WAL_DIR=""
+#ETCD_SNAPSHOT_COUNT=10000
ETCD_HEARTBEAT_INTERVAL=500
ETCD_ELECTION_TIMEOUT=2500
ETCD_LISTEN_CLIENT_URLS={{ etcd_listen_client_urls }}
@@ -41,24 +42,43 @@ ETCD_INITIAL_CLUSTER_TOKEN={{ etcd_initial_cluster_token }}
#ETCD_DISCOVERY_PROXY=
{% endif %}
ETCD_ADVERTISE_CLIENT_URLS={{ etcd_advertise_client_urls }}
+#ETCD_STRICT_RECONFIG_CHECK="false"
+#ETCD_AUTO_COMPACTION_RETENTION="0"
+#ETCD_ENABLE_V2="true"
#[proxy]
#ETCD_PROXY=off
+#ETCD_PROXY_FAILURE_WAIT="5000"
+#ETCD_PROXY_REFRESH_INTERVAL="30000"
+#ETCD_PROXY_DIAL_TIMEOUT="1000"
+#ETCD_PROXY_WRITE_TIMEOUT="5000"
+#ETCD_PROXY_READ_TIMEOUT="0"
#[security]
{% if etcd_url_scheme == 'https' -%}
-ETCD_CA_FILE={{ etcd_ca_file }}
+ETCD_TRUSTED_CA_FILE={{ etcd_ca_file }}
+ETCD_CLIENT_CERT_AUTH="true"
ETCD_CERT_FILE={{ etcd_cert_file }}
ETCD_KEY_FILE={{ etcd_key_file }}
{% endif -%}
+#ETCD_AUTO_TLS="false"
{% if etcd_peer_url_scheme == 'https' -%}
-ETCD_PEER_CA_FILE={{ etcd_peer_ca_file }}
+ETCD_PEER_TRUSTED_CA_FILE={{ etcd_peer_ca_file }}
+ETCD_PEER_CLIENT_CERT_AUTH="true"
ETCD_PEER_CERT_FILE={{ etcd_peer_cert_file }}
ETCD_PEER_KEY_FILE={{ etcd_peer_key_file }}
{% endif -%}
+#ETCD_PEER_AUTO_TLS="false"
#[logging]
ETCD_DEBUG="{{ etcd_debug | default(false) | bool | string }}"
{% if etcd_log_package_levels is defined %}
ETCD_LOG_PACKAGE_LEVELS="{{ etcd_log_package_levels }}"
{% endif %}
+
+#[profiling]
+#ETCD_ENABLE_PPROF="false"
+#ETCD_METRICS="basic"
+#
+#[auth]
+#ETCD_AUTH_TOKEN="simple"
diff --git a/roles/etcd_common/defaults/main.yml b/roles/etcd_common/defaults/main.yml
index b1bfa4592..b67411f40 100644
--- a/roles/etcd_common/defaults/main.yml
+++ b/roles/etcd_common/defaults/main.yml
@@ -56,10 +56,20 @@ etcd_is_containerized: False
etcd_is_thirdparty: False
# etcd dir vars
-etcd_data_dir: "{{ '/var/lib/origin/openshift.local.etcd' if r_etcd_common_embedded_etcd | bool else '/var/lib/etcd/' if openshift.common.etcd_runtime != 'runc' else '/var/lib/etcd/etcd.etcd/' }}"
+etcd_data_dir: "{{ '/var/lib/origin/openshift.local.etcd' if r_etcd_common_embedded_etcd | bool else '/var/lib/etcd/' if r_etcd_common_etcd_runtime != 'runc' else '/var/lib/etcd/etcd.etcd/' }}"
# etcd ports and protocols
etcd_client_port: 2379
etcd_peer_port: 2380
etcd_url_scheme: http
etcd_peer_url_scheme: http
+
+etcd_initial_cluster_state: new
+etcd_initial_cluster_token: etcd-cluster-1
+
+etcd_initial_advertise_peer_urls: "{{ etcd_peer_url_scheme }}://{{ etcd_ip }}:{{ etcd_peer_port }}"
+etcd_listen_peer_urls: "{{ etcd_peer_url_scheme }}://{{ etcd_ip }}:{{ etcd_peer_port }}"
+etcd_advertise_client_urls: "{{ etcd_url_scheme }}://{{ etcd_ip }}:{{ etcd_client_port }}"
+etcd_listen_client_urls: "{{ etcd_url_scheme }}://{{ etcd_ip }}:{{ etcd_client_port }}"
+
+etcd_systemd_dir: "/etc/systemd/system/{{ etcd_service }}.service.d"
diff --git a/roles/etcd_common/tasks/backup.yml b/roles/etcd_common/tasks/backup.yml
index 2bc486d3f..42d27c081 100644
--- a/roles/etcd_common/tasks/backup.yml
+++ b/roles/etcd_common/tasks/backup.yml
@@ -29,7 +29,6 @@
- name: Check current etcd disk usage
shell: du --exclude='*openshift-backup*' -k {{ l_etcd_data_dir }} | tail -n 1 | cut -f1
register: l_etcd_disk_usage
- when: r_etcd_common_embedded_etcd | bool
# AUDIT:changed_when: `false` because we are only inspecting
# state, not manipulating anything
changed_when: false
@@ -37,9 +36,9 @@
- name: Abort if insufficient disk space for etcd backup
fail:
msg: >
- {{ l_etcd_disk_usage.stdout }} Kb disk space required for etcd backup,
+ {{ l_etcd_disk_usage.stdout|int*2 }} Kb disk space required for etcd backup,
{{ l_avail_disk.stdout }} Kb available.
- when: (r_etcd_common_embedded_etcd | bool) and (l_etcd_disk_usage.stdout|int > l_avail_disk.stdout|int)
+ when: l_etcd_disk_usage.stdout|int*2 > l_avail_disk.stdout|int
# For non containerized and non embedded we should have the correct version of
# etcd installed already. So don't do anything.
diff --git a/roles/etcd_common/tasks/main.yml b/roles/etcd_common/tasks/main.yml
index f5bcd03ee..6ed87e6c7 100644
--- a/roles/etcd_common/tasks/main.yml
+++ b/roles/etcd_common/tasks/main.yml
@@ -6,4 +6,4 @@
- name: Include main action task file
include: "{{ r_etcd_common_action }}.yml"
- when: '"noop" not in r_etcd_common_action'
+ when: r_etcd_common_action != "noop"
diff --git a/roles/etcd_common/tasks/noop.yml b/roles/etcd_common/tasks/noop.yml
new file mode 100644
index 000000000..a88d78235
--- /dev/null
+++ b/roles/etcd_common/tasks/noop.yml
@@ -0,0 +1,4 @@
+---
+# This is file is here because the usage of tags, specifically `pre_upgrade`
+# breaks the functionality of this role.
+# See https://bugzilla.redhat.com/show_bug.cgi?id=1464025
diff --git a/roles/etcd_migrate/tasks/add_ttls.yml b/roles/etcd_migrate/tasks/add_ttls.yml
new file mode 100644
index 000000000..c10465af9
--- /dev/null
+++ b/roles/etcd_migrate/tasks/add_ttls.yml
@@ -0,0 +1,33 @@
+---
+# To be executed on first master
+- slurp:
+ src: "{{ openshift.common.config_base }}/master/master-config.yaml"
+ register: g_master_config_output
+
+- set_fact:
+ accessTokenMaxAgeSeconds: "{{ (g_master_config_output.content|b64decode|from_yaml).oauthConfig.tokenConfig.accessTokenMaxAgeSeconds | default(86400) }}"
+ authroizeTokenMaxAgeSeconds: "{{ (g_master_config_output.content|b64decode|from_yaml).oauthConfig.tokenConfig.authroizeTokenMaxAgeSeconds | default(500) }}"
+ controllerLeaseTTL: "{{ (g_master_config_output.content|b64decode|from_yaml).controllerLeaseTTL | default(30) }}"
+- name: Re-introduce leases (as a replacement for key TTLs)
+ command: >
+ oadm migrate etcd-ttl \
+ --cert {{ r_etcd_common_master_peer_cert_file }} \
+ --key {{ r_etcd_common_master_peer_key_file }} \
+ --cacert {{ r_etcd_common_master_peer_ca_file }} \
+ --etcd-address 'https://{{ etcd_peer }}:{{ etcd_client_port }}' \
+ --ttl-keys-prefix {{ item.keys }} \
+ --lease-duration {{ item.ttl }}
+ environment:
+ ETCDCTL_API: 3
+ PATH: "/usr/local/bin:/var/usrlocal/bin:{{ ansible_env.PATH }}"
+ with_items:
+ - keys: "/kubernetes.io/events"
+ ttl: "1h"
+ - keys: "/kubernetes.io/masterleases"
+ ttl: "10s"
+ - keys: "/openshift.io/oauth/accesstokens"
+ ttl: "{{ accessTokenMaxAgeSeconds }}s"
+ - keys: "/openshift.io/oauth/authorizetokens"
+ ttl: "{{ authroizeTokenMaxAgeSeconds }}s"
+ - keys: "/openshift.io/leases/controllers"
+ ttl: "{{ controllerLeaseTTL }}s"
diff --git a/roles/etcd_migrate/tasks/check.yml b/roles/etcd_migrate/tasks/check.yml
index b66696b55..0804d9e1c 100644
--- a/roles/etcd_migrate/tasks/check.yml
+++ b/roles/etcd_migrate/tasks/check.yml
@@ -1,7 +1,4 @@
---
-- fail:
- msg: "Currently etcd v3 migration is unsupported while we test it more thoroughly"
- when: not openshift_enable_unsupported_configurations | default(false) | bool
# Check the cluster is healthy
- include: check_cluster_health.yml
diff --git a/roles/etcd_migrate/tasks/clean_data.yml b/roles/etcd_migrate/tasks/clean_data.yml
new file mode 100644
index 000000000..95a0e7c0a
--- /dev/null
+++ b/roles/etcd_migrate/tasks/clean_data.yml
@@ -0,0 +1,5 @@
+---
+- name: Remove member data
+ file:
+ path: /var/lib/etcd/member
+ state: absent
diff --git a/roles/etcd_migrate/tasks/main.yml b/roles/etcd_migrate/tasks/main.yml
index 409b0b613..e82f6a6b4 100644
--- a/roles/etcd_migrate/tasks/main.yml
+++ b/roles/etcd_migrate/tasks/main.yml
@@ -1,8 +1,8 @@
---
- name: Fail if invalid r_etcd_migrate_action provided
fail:
- msg: "etcd_migrate role can only be called with 'check' or 'migrate' or 'configure'"
- when: r_etcd_migrate_action not in ['check', 'migrate', 'configure']
+ msg: "etcd_migrate role can only be called with 'check', 'migrate', 'configure', 'add_ttls', or 'clean_data'"
+ when: r_etcd_migrate_action not in ['check', 'migrate', 'configure', 'add_ttls', 'clean_data']
- name: Include main action task file
include: "{{ r_etcd_migrate_action }}.yml"
diff --git a/roles/etcd_migrate/tasks/migrate.yml b/roles/etcd_migrate/tasks/migrate.yml
index b2cf6d20a..54a9c74ff 100644
--- a/roles/etcd_migrate/tasks/migrate.yml
+++ b/roles/etcd_migrate/tasks/migrate.yml
@@ -3,62 +3,54 @@
- set_fact:
l_etcd_service: "{{ 'etcd_container' if openshift.common.is_containerized else 'etcd' }}"
-- name: Disable etcd members
- service:
- name: "{{ l_etcd_service }}"
- state: stopped
-
-# Should we skip all TTL keys? https://bugzilla.redhat.com/show_bug.cgi?id=1389773
- name: Migrate etcd data
command: >
etcdctl migrate --data-dir={{ etcd_data_dir }}
environment:
ETCDCTL_API: 3
register: l_etcdctl_migrate
-
# TODO(jchaloup): If any of the members fails, we need to restore all members to v2 from the pre-migrate backup
- name: Check the etcd v2 data are correctly migrated
fail:
msg: "Failed to migrate a member"
when: "'finished transforming keys' not in l_etcdctl_migrate.stdout and 'no v2 keys to migrate' not in l_etcdctl_migrate.stdout"
-
- name: Migration message
debug:
msg: "Etcd migration finished with: {{ l_etcdctl_migrate.stdout }}"
-
-- name: Enable etcd member
- service:
+- name: Set ETCD_FORCE_NEW_CLUSTER=true on first etcd host
+ lineinfile:
+ line: "ETCD_FORCE_NEW_CLUSTER=true"
+ dest: /etc/etcd/etcd.conf
+ backup: true
+- name: Start etcd
+ systemd:
name: "{{ l_etcd_service }}"
state: started
-
-- name: Wait for cluster to become healthy after migration
+- name: Wait for cluster to become healthy after bringing up first member
command: >
etcdctl --cert-file {{ etcd_peer_cert_file }} --key-file {{ etcd_peer_key_file }} --ca-file {{ etcd_peer_ca_file }} --endpoint https://{{ etcd_peer }}:{{ etcd_client_port }} cluster-health
register: l_etcd_migrate_health
until: l_etcd_migrate_health.rc == 0
retries: 3
delay: 30
- run_once: true
+- name: Unset ETCD_FORCE_NEW_CLUSTER=true on first etcd host
+ lineinfile:
+ line: "ETCD_FORCE_NEW_CLUSTER=true"
+ dest: /etc/etcd/etcd.conf
+ state: absent
+ backup: true
+- name: Restart first etcd host
+ systemd:
+ name: "{{ l_etcd_service }}"
+ state: restarted
-# NOTE: /usr/local/bin may be removed from the PATH by ansible hence why
-# it's added to the environment in this task.
-- name: Re-introduce leases (as a replacement for key TTLs)
+- name: Wait for cluster to become healthy after bringing up first member
command: >
- oadm migrate etcd-ttl \
- --cert {{ r_etcd_common_master_peer_cert_file }} \
- --key {{ r_etcd_common_master_peer_key_file }} \
- --cacert {{ r_etcd_common_master_peer_ca_file }} \
- --etcd-address 'https://{{ etcd_peer }}:{{ etcd_client_port }}' \
- --ttl-keys-prefix {{ item }} \
- --lease-duration 1h
- environment:
- ETCDCTL_API: 3
- PATH: "/usr/local/bin:/var/usrlocal/bin:{{ ansible_env.PATH }}"
- with_items:
- - "/kubernetes.io/events"
- - "/kubernetes.io/masterleases"
- delegate_to: "{{ groups.oo_first_master[0] }}"
- run_once: true
+ etcdctl --cert-file {{ etcd_peer_cert_file }} --key-file {{ etcd_peer_key_file }} --ca-file {{ etcd_peer_ca_file }} --endpoint https://{{ etcd_peer }}:{{ etcd_client_port }} cluster-health
+ register: l_etcd_migrate_health
+ until: l_etcd_migrate_health.rc == 0
+ retries: 3
+ delay: 30
- set_fact:
r_etcd_migrate_success: true
diff --git a/roles/flannel_register/defaults/main.yaml b/roles/flannel_register/defaults/main.yaml
index ddf8230ec..71c8f38c3 100644
--- a/roles/flannel_register/defaults/main.yaml
+++ b/roles/flannel_register/defaults/main.yaml
@@ -1,7 +1,6 @@
---
-flannel_network: "{{ openshift.common.portal_net | default('172.30.0.0/16', true) }}"
-flannel_min_network: 172.30.5.0
-flannel_subnet_len: 24
+flannel_network: "{{ openshift.master.sdn_cluster_network_cidr }}"
+flannel_subnet_len: "{{ 32 - openshift.master.sdn_host_subnet_length }}"
flannel_etcd_key: /openshift.com/network
etcd_hosts: "{{ etcd_urls }}"
etcd_conf_dir: "{{ openshift.common.config_base }}/master"
diff --git a/roles/flannel_register/templates/flannel-config.json b/roles/flannel_register/templates/flannel-config.json
index 89ce4c30b..bba3729fa 100644
--- a/roles/flannel_register/templates/flannel-config.json
+++ b/roles/flannel_register/templates/flannel-config.json
@@ -1,7 +1,6 @@
{
"Network": "{{ flannel_network }}",
"SubnetLen": {{ flannel_subnet_len }},
- "SubnetMin": "{{ flannel_min_network }}",
"Backend": {
"Type": "host-gw"
}
diff --git a/roles/lib_openshift/library/oc_adm_ca_server_cert.py b/roles/lib_openshift/library/oc_adm_ca_server_cert.py
index 1b73bfd0e..45d7444a4 100644
--- a/roles/lib_openshift/library/oc_adm_ca_server_cert.py
+++ b/roles/lib_openshift/library/oc_adm_ca_server_cert.py
@@ -1288,13 +1288,12 @@ class Utils(object): # pragma: no cover
@staticmethod
def openshift_installed():
''' check if openshift is installed '''
- import yum
+ import rpm
- yum_base = yum.YumBase()
- if yum_base.rpmdb.searchNevra(name='atomic-openshift'):
- return True
+ transaction_set = rpm.TransactionSet()
+ rpmquery = transaction_set.dbMatch("name", "atomic-openshift")
- return False
+ return rpmquery.count() > 0
# Disabling too-many-branches. This is a yaml dictionary comparison function
# pylint: disable=too-many-branches,too-many-return-statements,too-many-statements
diff --git a/roles/lib_openshift/library/oc_adm_csr.py b/roles/lib_openshift/library/oc_adm_csr.py
new file mode 100644
index 000000000..231857cca
--- /dev/null
+++ b/roles/lib_openshift/library/oc_adm_csr.py
@@ -0,0 +1,1649 @@
+#!/usr/bin/env python
+# pylint: disable=missing-docstring
+# flake8: noqa: T001
+# ___ ___ _ _ ___ ___ _ _____ ___ ___
+# / __| __| \| | __| _ \ /_\_ _| __| \
+# | (_ | _|| .` | _|| / / _ \| | | _|| |) |
+# \___|___|_|\_|___|_|_\/_/_\_\_|_|___|___/_ _____
+# | \ / _ \ | \| |/ _ \_ _| | __| \_ _|_ _|
+# | |) | (_) | | .` | (_) || | | _|| |) | | | |
+# |___/ \___/ |_|\_|\___/ |_| |___|___/___| |_|
+#
+# Copyright 2016 Red Hat, Inc. and/or its affiliates
+# and other contributors as indicated by the @author tags.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# -*- -*- -*- Begin included fragment: lib/import.py -*- -*- -*-
+'''
+ OpenShiftCLI class that wraps the oc commands in a subprocess
+'''
+# pylint: disable=too-many-lines
+
+from __future__ import print_function
+import atexit
+import copy
+import json
+import os
+import re
+import shutil
+import subprocess
+import tempfile
+# pylint: disable=import-error
+try:
+ import ruamel.yaml as yaml
+except ImportError:
+ import yaml
+
+from ansible.module_utils.basic import AnsibleModule
+
+# -*- -*- -*- End included fragment: lib/import.py -*- -*- -*-
+
+# -*- -*- -*- Begin included fragment: doc/csr -*- -*- -*-
+
+DOCUMENTATION = '''
+---
+module: oc_adm_csr
+short_description: Module to approve or deny openshift certificate signing requests
+description:
+ - Wrapper around the openshift `oc adm certificate approve|deny <csr>` command.
+options:
+ state:
+ description:
+ - approve|deny|list Approve, deny, and list are the only supported states for certificates
+ required: false
+ default: present
+ choices:
+ - present
+ aliases: []
+ kubeconfig:
+ description:
+ - The path for the kubeconfig file to use for authentication
+ required: false
+ default: /etc/origin/master/admin.kubeconfig
+ aliases: []
+ debug:
+ description:
+ - Turn on debug output.
+ required: false
+ default: False
+ aliases: []
+ nodes:
+ description:
+ - A list of the names of the nodes in which to accept the certificates
+ required: false
+ default: None
+ aliases: []
+ timeout:
+ description:
+ - This flag allows for a timeout value when approving nodes.
+ required: false
+ default: 30
+ aliases: []
+ timeout:
+ description:
+ - This flag allows for a timeout value when doing node approvals.
+ - A zero value for the timeout will block until the nodes have been accepted
+ required: false
+ default: 30
+ aliases: []
+ approve_all:
+ description:
+ - This flag allows for the module to approve all CSRs that are found.
+ - This facilitates testing.
+ required: false
+ default: False
+ aliases: []
+ service_account:
+ description:
+ - This parameter tells the approval process which service account is being used for the requests
+ required: false
+ default: node-bootstrapper
+ aliases: []
+author:
+- "Kenny Woodson <kwoodson@redhat.com>"
+extends_documentation_fragment: []
+'''
+
+EXAMPLES = '''
+- name: Approve certificates for node xyz
+ oc_adm_scr:
+ nodes:
+ - xyz
+ timeout: 300
+
+- name: Approve certificates for node xyz
+ oc_adm_scr:
+ nodes:
+ - xyz
+ timeout: 0
+'''
+
+# -*- -*- -*- End included fragment: doc/csr -*- -*- -*-
+
+# -*- -*- -*- Begin included fragment: ../../lib_utils/src/class/yedit.py -*- -*- -*-
+
+
+class YeditException(Exception): # pragma: no cover
+ ''' Exception class for Yedit '''
+ pass
+
+
+# pylint: disable=too-many-public-methods
+class Yedit(object): # pragma: no cover
+ ''' Class to modify yaml files '''
+ re_valid_key = r"(((\[-?\d+\])|([0-9a-zA-Z%s/_-]+)).?)+$"
+ re_key = r"(?:\[(-?\d+)\])|([0-9a-zA-Z{}/_-]+)"
+ com_sep = set(['.', '#', '|', ':'])
+
+ # pylint: disable=too-many-arguments
+ def __init__(self,
+ filename=None,
+ content=None,
+ content_type='yaml',
+ separator='.',
+ backup=False):
+ self.content = content
+ self._separator = separator
+ self.filename = filename
+ self.__yaml_dict = content
+ self.content_type = content_type
+ self.backup = backup
+ self.load(content_type=self.content_type)
+ if self.__yaml_dict is None:
+ self.__yaml_dict = {}
+
+ @property
+ def separator(self):
+ ''' getter method for separator '''
+ return self._separator
+
+ @separator.setter
+ def separator(self, inc_sep):
+ ''' setter method for separator '''
+ self._separator = inc_sep
+
+ @property
+ def yaml_dict(self):
+ ''' getter method for yaml_dict '''
+ return self.__yaml_dict
+
+ @yaml_dict.setter
+ def yaml_dict(self, value):
+ ''' setter method for yaml_dict '''
+ self.__yaml_dict = value
+
+ @staticmethod
+ def parse_key(key, sep='.'):
+ '''parse the key allowing the appropriate separator'''
+ common_separators = list(Yedit.com_sep - set([sep]))
+ return re.findall(Yedit.re_key.format(''.join(common_separators)), key)
+
+ @staticmethod
+ def valid_key(key, sep='.'):
+ '''validate the incoming key'''
+ common_separators = list(Yedit.com_sep - set([sep]))
+ if not re.match(Yedit.re_valid_key.format(''.join(common_separators)), key):
+ return False
+
+ return True
+
+ @staticmethod
+ def remove_entry(data, key, sep='.'):
+ ''' remove data at location key '''
+ if key == '' and isinstance(data, dict):
+ data.clear()
+ return True
+ elif key == '' and isinstance(data, list):
+ del data[:]
+ return True
+
+ if not (key and Yedit.valid_key(key, sep)) and \
+ isinstance(data, (list, dict)):
+ return None
+
+ key_indexes = Yedit.parse_key(key, sep)
+ for arr_ind, dict_key in key_indexes[:-1]:
+ if dict_key and isinstance(data, dict):
+ data = data.get(dict_key)
+ elif (arr_ind and isinstance(data, list) and
+ int(arr_ind) <= len(data) - 1):
+ data = data[int(arr_ind)]
+ else:
+ return None
+
+ # process last index for remove
+ # expected list entry
+ if key_indexes[-1][0]:
+ if isinstance(data, list) and int(key_indexes[-1][0]) <= len(data) - 1: # noqa: E501
+ del data[int(key_indexes[-1][0])]
+ return True
+
+ # expected dict entry
+ elif key_indexes[-1][1]:
+ if isinstance(data, dict):
+ del data[key_indexes[-1][1]]
+ return True
+
+ @staticmethod
+ def add_entry(data, key, item=None, sep='.'):
+ ''' Get an item from a dictionary with key notation a.b.c
+ d = {'a': {'b': 'c'}}}
+ key = a#b
+ return c
+ '''
+ if key == '':
+ pass
+ elif (not (key and Yedit.valid_key(key, sep)) and
+ isinstance(data, (list, dict))):
+ return None
+
+ key_indexes = Yedit.parse_key(key, sep)
+ for arr_ind, dict_key in key_indexes[:-1]:
+ if dict_key:
+ if isinstance(data, dict) and dict_key in data and data[dict_key]: # noqa: E501
+ data = data[dict_key]
+ continue
+
+ elif data and not isinstance(data, dict):
+ raise YeditException("Unexpected item type found while going through key " +
+ "path: {} (at key: {})".format(key, dict_key))
+
+ data[dict_key] = {}
+ data = data[dict_key]
+
+ elif (arr_ind and isinstance(data, list) and
+ int(arr_ind) <= len(data) - 1):
+ data = data[int(arr_ind)]
+ else:
+ raise YeditException("Unexpected item type found while going through key path: {}".format(key))
+
+ if key == '':
+ data = item
+
+ # process last index for add
+ # expected list entry
+ elif key_indexes[-1][0] and isinstance(data, list) and int(key_indexes[-1][0]) <= len(data) - 1: # noqa: E501
+ data[int(key_indexes[-1][0])] = item
+
+ # expected dict entry
+ elif key_indexes[-1][1] and isinstance(data, dict):
+ data[key_indexes[-1][1]] = item
+
+ # didn't add/update to an existing list, nor add/update key to a dict
+ # so we must have been provided some syntax like a.b.c[<int>] = "data" for a
+ # non-existent array
+ else:
+ raise YeditException("Error adding to object at path: {}".format(key))
+
+ return data
+
+ @staticmethod
+ def get_entry(data, key, sep='.'):
+ ''' Get an item from a dictionary with key notation a.b.c
+ d = {'a': {'b': 'c'}}}
+ key = a.b
+ return c
+ '''
+ if key == '':
+ pass
+ elif (not (key and Yedit.valid_key(key, sep)) and
+ isinstance(data, (list, dict))):
+ return None
+
+ key_indexes = Yedit.parse_key(key, sep)
+ for arr_ind, dict_key in key_indexes:
+ if dict_key and isinstance(data, dict):
+ data = data.get(dict_key)
+ elif (arr_ind and isinstance(data, list) and
+ int(arr_ind) <= len(data) - 1):
+ data = data[int(arr_ind)]
+ else:
+ return None
+
+ return data
+
+ @staticmethod
+ def _write(filename, contents):
+ ''' Actually write the file contents to disk. This helps with mocking. '''
+
+ tmp_filename = filename + '.yedit'
+
+ with open(tmp_filename, 'w') as yfd:
+ yfd.write(contents)
+
+ os.rename(tmp_filename, filename)
+
+ def write(self):
+ ''' write to file '''
+ if not self.filename:
+ raise YeditException('Please specify a filename.')
+
+ if self.backup and self.file_exists():
+ shutil.copy(self.filename, self.filename + '.orig')
+
+ # Try to set format attributes if supported
+ try:
+ self.yaml_dict.fa.set_block_style()
+ except AttributeError:
+ pass
+
+ # Try to use RoundTripDumper if supported.
+ try:
+ Yedit._write(self.filename, yaml.dump(self.yaml_dict, Dumper=yaml.RoundTripDumper))
+ except AttributeError:
+ Yedit._write(self.filename, yaml.safe_dump(self.yaml_dict, default_flow_style=False))
+
+ return (True, self.yaml_dict)
+
+ def read(self):
+ ''' read from file '''
+ # check if it exists
+ if self.filename is None or not self.file_exists():
+ return None
+
+ contents = None
+ with open(self.filename) as yfd:
+ contents = yfd.read()
+
+ return contents
+
+ def file_exists(self):
+ ''' return whether file exists '''
+ if os.path.exists(self.filename):
+ return True
+
+ return False
+
+ def load(self, content_type='yaml'):
+ ''' return yaml file '''
+ contents = self.read()
+
+ if not contents and not self.content:
+ return None
+
+ if self.content:
+ if isinstance(self.content, dict):
+ self.yaml_dict = self.content
+ return self.yaml_dict
+ elif isinstance(self.content, str):
+ contents = self.content
+
+ # check if it is yaml
+ try:
+ if content_type == 'yaml' and contents:
+ # Try to set format attributes if supported
+ try:
+ self.yaml_dict.fa.set_block_style()
+ except AttributeError:
+ pass
+
+ # Try to use RoundTripLoader if supported.
+ try:
+ self.yaml_dict = yaml.safe_load(contents, yaml.RoundTripLoader)
+ except AttributeError:
+ self.yaml_dict = yaml.safe_load(contents)
+
+ # Try to set format attributes if supported
+ try:
+ self.yaml_dict.fa.set_block_style()
+ except AttributeError:
+ pass
+
+ elif content_type == 'json' and contents:
+ self.yaml_dict = json.loads(contents)
+ except yaml.YAMLError as err:
+ # Error loading yaml or json
+ raise YeditException('Problem with loading yaml file. {}'.format(err))
+
+ return self.yaml_dict
+
+ def get(self, key):
+ ''' get a specified key'''
+ try:
+ entry = Yedit.get_entry(self.yaml_dict, key, self.separator)
+ except KeyError:
+ entry = None
+
+ return entry
+
+ def pop(self, path, key_or_item):
+ ''' remove a key, value pair from a dict or an item for a list'''
+ try:
+ entry = Yedit.get_entry(self.yaml_dict, path, self.separator)
+ except KeyError:
+ entry = None
+
+ if entry is None:
+ return (False, self.yaml_dict)
+
+ if isinstance(entry, dict):
+ # AUDIT:maybe-no-member makes sense due to fuzzy types
+ # pylint: disable=maybe-no-member
+ if key_or_item in entry:
+ entry.pop(key_or_item)
+ return (True, self.yaml_dict)
+ return (False, self.yaml_dict)
+
+ elif isinstance(entry, list):
+ # AUDIT:maybe-no-member makes sense due to fuzzy types
+ # pylint: disable=maybe-no-member
+ ind = None
+ try:
+ ind = entry.index(key_or_item)
+ except ValueError:
+ return (False, self.yaml_dict)
+
+ entry.pop(ind)
+ return (True, self.yaml_dict)
+
+ return (False, self.yaml_dict)
+
+ def delete(self, path):
+ ''' remove path from a dict'''
+ try:
+ entry = Yedit.get_entry(self.yaml_dict, path, self.separator)
+ except KeyError:
+ entry = None
+
+ if entry is None:
+ return (False, self.yaml_dict)
+
+ result = Yedit.remove_entry(self.yaml_dict, path, self.separator)
+ if not result:
+ return (False, self.yaml_dict)
+
+ return (True, self.yaml_dict)
+
+ def exists(self, path, value):
+ ''' check if value exists at path'''
+ try:
+ entry = Yedit.get_entry(self.yaml_dict, path, self.separator)
+ except KeyError:
+ entry = None
+
+ if isinstance(entry, list):
+ if value in entry:
+ return True
+ return False
+
+ elif isinstance(entry, dict):
+ if isinstance(value, dict):
+ rval = False
+ for key, val in value.items():
+ if entry[key] != val:
+ rval = False
+ break
+ else:
+ rval = True
+ return rval
+
+ return value in entry
+
+ return entry == value
+
+ def append(self, path, value):
+ '''append value to a list'''
+ try:
+ entry = Yedit.get_entry(self.yaml_dict, path, self.separator)
+ except KeyError:
+ entry = None
+
+ if entry is None:
+ self.put(path, [])
+ entry = Yedit.get_entry(self.yaml_dict, path, self.separator)
+ if not isinstance(entry, list):
+ return (False, self.yaml_dict)
+
+ # AUDIT:maybe-no-member makes sense due to loading data from
+ # a serialized format.
+ # pylint: disable=maybe-no-member
+ entry.append(value)
+ return (True, self.yaml_dict)
+
+ # pylint: disable=too-many-arguments
+ def update(self, path, value, index=None, curr_value=None):
+ ''' put path, value into a dict '''
+ try:
+ entry = Yedit.get_entry(self.yaml_dict, path, self.separator)
+ except KeyError:
+ entry = None
+
+ if isinstance(entry, dict):
+ # AUDIT:maybe-no-member makes sense due to fuzzy types
+ # pylint: disable=maybe-no-member
+ if not isinstance(value, dict):
+ raise YeditException('Cannot replace key, value entry in dict with non-dict type. ' +
+ 'value=[{}] type=[{}]'.format(value, type(value)))
+
+ entry.update(value)
+ return (True, self.yaml_dict)
+
+ elif isinstance(entry, list):
+ # AUDIT:maybe-no-member makes sense due to fuzzy types
+ # pylint: disable=maybe-no-member
+ ind = None
+ if curr_value:
+ try:
+ ind = entry.index(curr_value)
+ except ValueError:
+ return (False, self.yaml_dict)
+
+ elif index is not None:
+ ind = index
+
+ if ind is not None and entry[ind] != value:
+ entry[ind] = value
+ return (True, self.yaml_dict)
+
+ # see if it exists in the list
+ try:
+ ind = entry.index(value)
+ except ValueError:
+ # doesn't exist, append it
+ entry.append(value)
+ return (True, self.yaml_dict)
+
+ # already exists, return
+ if ind is not None:
+ return (False, self.yaml_dict)
+ return (False, self.yaml_dict)
+
+ def put(self, path, value):
+ ''' put path, value into a dict '''
+ try:
+ entry = Yedit.get_entry(self.yaml_dict, path, self.separator)
+ except KeyError:
+ entry = None
+
+ if entry == value:
+ return (False, self.yaml_dict)
+
+ # deepcopy didn't work
+ # Try to use ruamel.yaml and fallback to pyyaml
+ try:
+ tmp_copy = yaml.load(yaml.round_trip_dump(self.yaml_dict,
+ default_flow_style=False),
+ yaml.RoundTripLoader)
+ except AttributeError:
+ tmp_copy = copy.deepcopy(self.yaml_dict)
+
+ # set the format attributes if available
+ try:
+ tmp_copy.fa.set_block_style()
+ except AttributeError:
+ pass
+
+ result = Yedit.add_entry(tmp_copy, path, value, self.separator)
+ if result is None:
+ return (False, self.yaml_dict)
+
+ # When path equals "" it is a special case.
+ # "" refers to the root of the document
+ # Only update the root path (entire document) when its a list or dict
+ if path == '':
+ if isinstance(result, list) or isinstance(result, dict):
+ self.yaml_dict = result
+ return (True, self.yaml_dict)
+
+ return (False, self.yaml_dict)
+
+ self.yaml_dict = tmp_copy
+
+ return (True, self.yaml_dict)
+
+ def create(self, path, value):
+ ''' create a yaml file '''
+ if not self.file_exists():
+ # deepcopy didn't work
+ # Try to use ruamel.yaml and fallback to pyyaml
+ try:
+ tmp_copy = yaml.load(yaml.round_trip_dump(self.yaml_dict,
+ default_flow_style=False),
+ yaml.RoundTripLoader)
+ except AttributeError:
+ tmp_copy = copy.deepcopy(self.yaml_dict)
+
+ # set the format attributes if available
+ try:
+ tmp_copy.fa.set_block_style()
+ except AttributeError:
+ pass
+
+ result = Yedit.add_entry(tmp_copy, path, value, self.separator)
+ if result is not None:
+ self.yaml_dict = tmp_copy
+ return (True, self.yaml_dict)
+
+ return (False, self.yaml_dict)
+
+ @staticmethod
+ def get_curr_value(invalue, val_type):
+ '''return the current value'''
+ if invalue is None:
+ return None
+
+ curr_value = invalue
+ if val_type == 'yaml':
+ curr_value = yaml.load(invalue)
+ elif val_type == 'json':
+ curr_value = json.loads(invalue)
+
+ return curr_value
+
+ @staticmethod
+ def parse_value(inc_value, vtype=''):
+ '''determine value type passed'''
+ true_bools = ['y', 'Y', 'yes', 'Yes', 'YES', 'true', 'True', 'TRUE',
+ 'on', 'On', 'ON', ]
+ false_bools = ['n', 'N', 'no', 'No', 'NO', 'false', 'False', 'FALSE',
+ 'off', 'Off', 'OFF']
+
+ # It came in as a string but you didn't specify value_type as string
+ # we will convert to bool if it matches any of the above cases
+ if isinstance(inc_value, str) and 'bool' in vtype:
+ if inc_value not in true_bools and inc_value not in false_bools:
+ raise YeditException('Not a boolean type. str=[{}] vtype=[{}]'.format(inc_value, vtype))
+ elif isinstance(inc_value, bool) and 'str' in vtype:
+ inc_value = str(inc_value)
+
+ # There is a special case where '' will turn into None after yaml loading it so skip
+ if isinstance(inc_value, str) and inc_value == '':
+ pass
+ # If vtype is not str then go ahead and attempt to yaml load it.
+ elif isinstance(inc_value, str) and 'str' not in vtype:
+ try:
+ inc_value = yaml.safe_load(inc_value)
+ except Exception:
+ raise YeditException('Could not determine type of incoming value. ' +
+ 'value=[{}] vtype=[{}]'.format(type(inc_value), vtype))
+
+ return inc_value
+
+ @staticmethod
+ def process_edits(edits, yamlfile):
+ '''run through a list of edits and process them one-by-one'''
+ results = []
+ for edit in edits:
+ value = Yedit.parse_value(edit['value'], edit.get('value_type', ''))
+ if edit.get('action') == 'update':
+ # pylint: disable=line-too-long
+ curr_value = Yedit.get_curr_value(
+ Yedit.parse_value(edit.get('curr_value')),
+ edit.get('curr_value_format'))
+
+ rval = yamlfile.update(edit['key'],
+ value,
+ edit.get('index'),
+ curr_value)
+
+ elif edit.get('action') == 'append':
+ rval = yamlfile.append(edit['key'], value)
+
+ else:
+ rval = yamlfile.put(edit['key'], value)
+
+ if rval[0]:
+ results.append({'key': edit['key'], 'edit': rval[1]})
+
+ return {'changed': len(results) > 0, 'results': results}
+
+ # pylint: disable=too-many-return-statements,too-many-branches
+ @staticmethod
+ def run_ansible(params):
+ '''perform the idempotent crud operations'''
+ yamlfile = Yedit(filename=params['src'],
+ backup=params['backup'],
+ separator=params['separator'])
+
+ state = params['state']
+
+ if params['src']:
+ rval = yamlfile.load()
+
+ if yamlfile.yaml_dict is None and state != 'present':
+ return {'failed': True,
+ 'msg': 'Error opening file [{}]. Verify that the '.format(params['src']) +
+ 'file exists, that it is has correct permissions, and is valid yaml.'}
+
+ if state == 'list':
+ if params['content']:
+ content = Yedit.parse_value(params['content'], params['content_type'])
+ yamlfile.yaml_dict = content
+
+ if params['key']:
+ rval = yamlfile.get(params['key']) or {}
+
+ return {'changed': False, 'result': rval, 'state': state}
+
+ elif state == 'absent':
+ if params['content']:
+ content = Yedit.parse_value(params['content'], params['content_type'])
+ yamlfile.yaml_dict = content
+
+ if params['update']:
+ rval = yamlfile.pop(params['key'], params['value'])
+ else:
+ rval = yamlfile.delete(params['key'])
+
+ if rval[0] and params['src']:
+ yamlfile.write()
+
+ return {'changed': rval[0], 'result': rval[1], 'state': state}
+
+ elif state == 'present':
+ # check if content is different than what is in the file
+ if params['content']:
+ content = Yedit.parse_value(params['content'], params['content_type'])
+
+ # We had no edits to make and the contents are the same
+ if yamlfile.yaml_dict == content and \
+ params['value'] is None:
+ return {'changed': False, 'result': yamlfile.yaml_dict, 'state': state}
+
+ yamlfile.yaml_dict = content
+
+ # If we were passed a key, value then
+ # we enapsulate it in a list and process it
+ # Key, Value passed to the module : Converted to Edits list #
+ edits = []
+ _edit = {}
+ if params['value'] is not None:
+ _edit['value'] = params['value']
+ _edit['value_type'] = params['value_type']
+ _edit['key'] = params['key']
+
+ if params['update']:
+ _edit['action'] = 'update'
+ _edit['curr_value'] = params['curr_value']
+ _edit['curr_value_format'] = params['curr_value_format']
+ _edit['index'] = params['index']
+
+ elif params['append']:
+ _edit['action'] = 'append'
+
+ edits.append(_edit)
+
+ elif params['edits'] is not None:
+ edits = params['edits']
+
+ if edits:
+ results = Yedit.process_edits(edits, yamlfile)
+
+ # if there were changes and a src provided to us we need to write
+ if results['changed'] and params['src']:
+ yamlfile.write()
+
+ return {'changed': results['changed'], 'result': results['results'], 'state': state}
+
+ # no edits to make
+ if params['src']:
+ # pylint: disable=redefined-variable-type
+ rval = yamlfile.write()
+ return {'changed': rval[0],
+ 'result': rval[1],
+ 'state': state}
+
+ # We were passed content but no src, key or value, or edits. Return contents in memory
+ return {'changed': False, 'result': yamlfile.yaml_dict, 'state': state}
+ return {'failed': True, 'msg': 'Unkown state passed'}
+
+# -*- -*- -*- End included fragment: ../../lib_utils/src/class/yedit.py -*- -*- -*-
+
+# -*- -*- -*- Begin included fragment: lib/base.py -*- -*- -*-
+# pylint: disable=too-many-lines
+# noqa: E301,E302,E303,T001
+
+
+class OpenShiftCLIError(Exception):
+ '''Exception class for openshiftcli'''
+ pass
+
+
+ADDITIONAL_PATH_LOOKUPS = ['/usr/local/bin', os.path.expanduser('~/bin')]
+
+
+def locate_oc_binary():
+ ''' Find and return oc binary file '''
+ # https://github.com/openshift/openshift-ansible/issues/3410
+ # oc can be in /usr/local/bin in some cases, but that may not
+ # be in $PATH due to ansible/sudo
+ paths = os.environ.get("PATH", os.defpath).split(os.pathsep) + ADDITIONAL_PATH_LOOKUPS
+
+ oc_binary = 'oc'
+
+ # Use shutil.which if it is available, otherwise fallback to a naive path search
+ try:
+ which_result = shutil.which(oc_binary, path=os.pathsep.join(paths))
+ if which_result is not None:
+ oc_binary = which_result
+ except AttributeError:
+ for path in paths:
+ if os.path.exists(os.path.join(path, oc_binary)):
+ oc_binary = os.path.join(path, oc_binary)
+ break
+
+ return oc_binary
+
+
+# pylint: disable=too-few-public-methods
+class OpenShiftCLI(object):
+ ''' Class to wrap the command line tools '''
+ def __init__(self,
+ namespace,
+ kubeconfig='/etc/origin/master/admin.kubeconfig',
+ verbose=False,
+ all_namespaces=False):
+ ''' Constructor for OpenshiftCLI '''
+ self.namespace = namespace
+ self.verbose = verbose
+ self.kubeconfig = Utils.create_tmpfile_copy(kubeconfig)
+ self.all_namespaces = all_namespaces
+ self.oc_binary = locate_oc_binary()
+
+ # Pylint allows only 5 arguments to be passed.
+ # pylint: disable=too-many-arguments
+ def _replace_content(self, resource, rname, content, force=False, sep='.'):
+ ''' replace the current object with the content '''
+ res = self._get(resource, rname)
+ if not res['results']:
+ return res
+
+ fname = Utils.create_tmpfile(rname + '-')
+
+ yed = Yedit(fname, res['results'][0], separator=sep)
+ changes = []
+ for key, value in content.items():
+ changes.append(yed.put(key, value))
+
+ if any([change[0] for change in changes]):
+ yed.write()
+
+ atexit.register(Utils.cleanup, [fname])
+
+ return self._replace(fname, force)
+
+ return {'returncode': 0, 'updated': False}
+
+ def _replace(self, fname, force=False):
+ '''replace the current object with oc replace'''
+ # We are removing the 'resourceVersion' to handle
+ # a race condition when modifying oc objects
+ yed = Yedit(fname)
+ results = yed.delete('metadata.resourceVersion')
+ if results[0]:
+ yed.write()
+
+ cmd = ['replace', '-f', fname]
+ if force:
+ cmd.append('--force')
+ return self.openshift_cmd(cmd)
+
+ def _create_from_content(self, rname, content):
+ '''create a temporary file and then call oc create on it'''
+ fname = Utils.create_tmpfile(rname + '-')
+ yed = Yedit(fname, content=content)
+ yed.write()
+
+ atexit.register(Utils.cleanup, [fname])
+
+ return self._create(fname)
+
+ def _create(self, fname):
+ '''call oc create on a filename'''
+ return self.openshift_cmd(['create', '-f', fname])
+
+ def _delete(self, resource, name=None, selector=None):
+ '''call oc delete on a resource'''
+ cmd = ['delete', resource]
+ if selector is not None:
+ cmd.append('--selector={}'.format(selector))
+ elif name is not None:
+ cmd.append(name)
+ else:
+ raise OpenShiftCLIError('Either name or selector is required when calling delete.')
+
+ return self.openshift_cmd(cmd)
+
+ def _process(self, template_name, create=False, params=None, template_data=None): # noqa: E501
+ '''process a template
+
+ template_name: the name of the template to process
+ create: whether to send to oc create after processing
+ params: the parameters for the template
+ template_data: the incoming template's data; instead of a file
+ '''
+ cmd = ['process']
+ if template_data:
+ cmd.extend(['-f', '-'])
+ else:
+ cmd.append(template_name)
+ if params:
+ param_str = ["{}={}".format(key, str(value).replace("'", r'"')) for key, value in params.items()]
+ cmd.append('-v')
+ cmd.extend(param_str)
+
+ results = self.openshift_cmd(cmd, output=True, input_data=template_data)
+
+ if results['returncode'] != 0 or not create:
+ return results
+
+ fname = Utils.create_tmpfile(template_name + '-')
+ yed = Yedit(fname, results['results'])
+ yed.write()
+
+ atexit.register(Utils.cleanup, [fname])
+
+ return self.openshift_cmd(['create', '-f', fname])
+
+ def _get(self, resource, name=None, selector=None):
+ '''return a resource by name '''
+ cmd = ['get', resource]
+ if selector is not None:
+ cmd.append('--selector={}'.format(selector))
+ elif name is not None:
+ cmd.append(name)
+
+ cmd.extend(['-o', 'json'])
+
+ rval = self.openshift_cmd(cmd, output=True)
+
+ # Ensure results are retuned in an array
+ if 'items' in rval:
+ rval['results'] = rval['items']
+ elif not isinstance(rval['results'], list):
+ rval['results'] = [rval['results']]
+
+ return rval
+
+ def _schedulable(self, node=None, selector=None, schedulable=True):
+ ''' perform oadm manage-node scheduable '''
+ cmd = ['manage-node']
+ if node:
+ cmd.extend(node)
+ else:
+ cmd.append('--selector={}'.format(selector))
+
+ cmd.append('--schedulable={}'.format(schedulable))
+
+ return self.openshift_cmd(cmd, oadm=True, output=True, output_type='raw') # noqa: E501
+
+ def _list_pods(self, node=None, selector=None, pod_selector=None):
+ ''' perform oadm list pods
+
+ node: the node in which to list pods
+ selector: the label selector filter if provided
+ pod_selector: the pod selector filter if provided
+ '''
+ cmd = ['manage-node']
+ if node:
+ cmd.extend(node)
+ else:
+ cmd.append('--selector={}'.format(selector))
+
+ if pod_selector:
+ cmd.append('--pod-selector={}'.format(pod_selector))
+
+ cmd.extend(['--list-pods', '-o', 'json'])
+
+ return self.openshift_cmd(cmd, oadm=True, output=True, output_type='raw')
+
+ # pylint: disable=too-many-arguments
+ def _evacuate(self, node=None, selector=None, pod_selector=None, dry_run=False, grace_period=None, force=False):
+ ''' perform oadm manage-node evacuate '''
+ cmd = ['manage-node']
+ if node:
+ cmd.extend(node)
+ else:
+ cmd.append('--selector={}'.format(selector))
+
+ if dry_run:
+ cmd.append('--dry-run')
+
+ if pod_selector:
+ cmd.append('--pod-selector={}'.format(pod_selector))
+
+ if grace_period:
+ cmd.append('--grace-period={}'.format(int(grace_period)))
+
+ if force:
+ cmd.append('--force')
+
+ cmd.append('--evacuate')
+
+ return self.openshift_cmd(cmd, oadm=True, output=True, output_type='raw')
+
+ def _version(self):
+ ''' return the openshift version'''
+ return self.openshift_cmd(['version'], output=True, output_type='raw')
+
+ def _import_image(self, url=None, name=None, tag=None):
+ ''' perform image import '''
+ cmd = ['import-image']
+
+ image = '{0}'.format(name)
+ if tag:
+ image += ':{0}'.format(tag)
+
+ cmd.append(image)
+
+ if url:
+ cmd.append('--from={0}/{1}'.format(url, image))
+
+ cmd.append('-n{0}'.format(self.namespace))
+
+ cmd.append('--confirm')
+ return self.openshift_cmd(cmd)
+
+ def _run(self, cmds, input_data):
+ ''' Actually executes the command. This makes mocking easier. '''
+ curr_env = os.environ.copy()
+ curr_env.update({'KUBECONFIG': self.kubeconfig})
+ proc = subprocess.Popen(cmds,
+ stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ env=curr_env)
+
+ stdout, stderr = proc.communicate(input_data)
+
+ return proc.returncode, stdout.decode('utf-8'), stderr.decode('utf-8')
+
+ # pylint: disable=too-many-arguments,too-many-branches
+ def openshift_cmd(self, cmd, oadm=False, output=False, output_type='json', input_data=None):
+ '''Base command for oc '''
+ cmds = [self.oc_binary]
+
+ if oadm:
+ cmds.append('adm')
+
+ cmds.extend(cmd)
+
+ if self.all_namespaces:
+ cmds.extend(['--all-namespaces'])
+ elif self.namespace is not None and self.namespace.lower() not in ['none', 'emtpy']: # E501
+ cmds.extend(['-n', self.namespace])
+
+ if self.verbose:
+ print(' '.join(cmds))
+
+ try:
+ returncode, stdout, stderr = self._run(cmds, input_data)
+ except OSError as ex:
+ returncode, stdout, stderr = 1, '', 'Failed to execute {}: {}'.format(subprocess.list2cmdline(cmds), ex)
+
+ rval = {"returncode": returncode,
+ "cmd": ' '.join(cmds)}
+
+ if output_type == 'json':
+ rval['results'] = {}
+ if output and stdout:
+ try:
+ rval['results'] = json.loads(stdout)
+ except ValueError as verr:
+ if "No JSON object could be decoded" in verr.args:
+ rval['err'] = verr.args
+ elif output_type == 'raw':
+ rval['results'] = stdout if output else ''
+
+ if self.verbose:
+ print("STDOUT: {0}".format(stdout))
+ print("STDERR: {0}".format(stderr))
+
+ if 'err' in rval or returncode != 0:
+ rval.update({"stderr": stderr,
+ "stdout": stdout})
+
+ return rval
+
+
+class Utils(object): # pragma: no cover
+ ''' utilities for openshiftcli modules '''
+
+ @staticmethod
+ def _write(filename, contents):
+ ''' Actually write the file contents to disk. This helps with mocking. '''
+
+ with open(filename, 'w') as sfd:
+ sfd.write(contents)
+
+ @staticmethod
+ def create_tmp_file_from_contents(rname, data, ftype='yaml'):
+ ''' create a file in tmp with name and contents'''
+
+ tmp = Utils.create_tmpfile(prefix=rname)
+
+ if ftype == 'yaml':
+ # AUDIT:no-member makes sense here due to ruamel.YAML/PyYAML usage
+ # pylint: disable=no-member
+ if hasattr(yaml, 'RoundTripDumper'):
+ Utils._write(tmp, yaml.dump(data, Dumper=yaml.RoundTripDumper))
+ else:
+ Utils._write(tmp, yaml.safe_dump(data, default_flow_style=False))
+
+ elif ftype == 'json':
+ Utils._write(tmp, json.dumps(data))
+ else:
+ Utils._write(tmp, data)
+
+ # Register cleanup when module is done
+ atexit.register(Utils.cleanup, [tmp])
+ return tmp
+
+ @staticmethod
+ def create_tmpfile_copy(inc_file):
+ '''create a temporary copy of a file'''
+ tmpfile = Utils.create_tmpfile('lib_openshift-')
+ Utils._write(tmpfile, open(inc_file).read())
+
+ # Cleanup the tmpfile
+ atexit.register(Utils.cleanup, [tmpfile])
+
+ return tmpfile
+
+ @staticmethod
+ def create_tmpfile(prefix='tmp'):
+ ''' Generates and returns a temporary file name '''
+
+ with tempfile.NamedTemporaryFile(prefix=prefix, delete=False) as tmp:
+ return tmp.name
+
+ @staticmethod
+ def create_tmp_files_from_contents(content, content_type=None):
+ '''Turn an array of dict: filename, content into a files array'''
+ if not isinstance(content, list):
+ content = [content]
+ files = []
+ for item in content:
+ path = Utils.create_tmp_file_from_contents(item['path'] + '-',
+ item['data'],
+ ftype=content_type)
+ files.append({'name': os.path.basename(item['path']),
+ 'path': path})
+ return files
+
+ @staticmethod
+ def cleanup(files):
+ '''Clean up on exit '''
+ for sfile in files:
+ if os.path.exists(sfile):
+ if os.path.isdir(sfile):
+ shutil.rmtree(sfile)
+ elif os.path.isfile(sfile):
+ os.remove(sfile)
+
+ @staticmethod
+ def exists(results, _name):
+ ''' Check to see if the results include the name '''
+ if not results:
+ return False
+
+ if Utils.find_result(results, _name):
+ return True
+
+ return False
+
+ @staticmethod
+ def find_result(results, _name):
+ ''' Find the specified result by name'''
+ rval = None
+ for result in results:
+ if 'metadata' in result and result['metadata']['name'] == _name:
+ rval = result
+ break
+
+ return rval
+
+ @staticmethod
+ def get_resource_file(sfile, sfile_type='yaml'):
+ ''' return the service file '''
+ contents = None
+ with open(sfile) as sfd:
+ contents = sfd.read()
+
+ if sfile_type == 'yaml':
+ # AUDIT:no-member makes sense here due to ruamel.YAML/PyYAML usage
+ # pylint: disable=no-member
+ if hasattr(yaml, 'RoundTripLoader'):
+ contents = yaml.load(contents, yaml.RoundTripLoader)
+ else:
+ contents = yaml.safe_load(contents)
+ elif sfile_type == 'json':
+ contents = json.loads(contents)
+
+ return contents
+
+ @staticmethod
+ def filter_versions(stdout):
+ ''' filter the oc version output '''
+
+ version_dict = {}
+ version_search = ['oc', 'openshift', 'kubernetes']
+
+ for line in stdout.strip().split('\n'):
+ for term in version_search:
+ if not line:
+ continue
+ if line.startswith(term):
+ version_dict[term] = line.split()[-1]
+
+ # horrible hack to get openshift version in Openshift 3.2
+ # By default "oc version in 3.2 does not return an "openshift" version
+ if "openshift" not in version_dict:
+ version_dict["openshift"] = version_dict["oc"]
+
+ return version_dict
+
+ @staticmethod
+ def add_custom_versions(versions):
+ ''' create custom versions strings '''
+
+ versions_dict = {}
+
+ for tech, version in versions.items():
+ # clean up "-" from version
+ if "-" in version:
+ version = version.split("-")[0]
+
+ if version.startswith('v'):
+ versions_dict[tech + '_numeric'] = version[1:].split('+')[0]
+ # "v3.3.0.33" is what we have, we want "3.3"
+ versions_dict[tech + '_short'] = version[1:4]
+
+ return versions_dict
+
+ @staticmethod
+ def openshift_installed():
+ ''' check if openshift is installed '''
+ import rpm
+
+ transaction_set = rpm.TransactionSet()
+ rpmquery = transaction_set.dbMatch("name", "atomic-openshift")
+
+ return rpmquery.count() > 0
+
+ # Disabling too-many-branches. This is a yaml dictionary comparison function
+ # pylint: disable=too-many-branches,too-many-return-statements,too-many-statements
+ @staticmethod
+ def check_def_equal(user_def, result_def, skip_keys=None, debug=False):
+ ''' Given a user defined definition, compare it with the results given back by our query. '''
+
+ # Currently these values are autogenerated and we do not need to check them
+ skip = ['metadata', 'status']
+ if skip_keys:
+ skip.extend(skip_keys)
+
+ for key, value in result_def.items():
+ if key in skip:
+ continue
+
+ # Both are lists
+ if isinstance(value, list):
+ if key not in user_def:
+ if debug:
+ print('User data does not have key [%s]' % key)
+ print('User data: %s' % user_def)
+ return False
+
+ if not isinstance(user_def[key], list):
+ if debug:
+ print('user_def[key] is not a list key=[%s] user_def[key]=%s' % (key, user_def[key]))
+ return False
+
+ if len(user_def[key]) != len(value):
+ if debug:
+ print("List lengths are not equal.")
+ print("key=[%s]: user_def[%s] != value[%s]" % (key, len(user_def[key]), len(value)))
+ print("user_def: %s" % user_def[key])
+ print("value: %s" % value)
+ return False
+
+ for values in zip(user_def[key], value):
+ if isinstance(values[0], dict) and isinstance(values[1], dict):
+ if debug:
+ print('sending list - list')
+ print(type(values[0]))
+ print(type(values[1]))
+ result = Utils.check_def_equal(values[0], values[1], skip_keys=skip_keys, debug=debug)
+ if not result:
+ print('list compare returned false')
+ return False
+
+ elif value != user_def[key]:
+ if debug:
+ print('value should be identical')
+ print(user_def[key])
+ print(value)
+ return False
+
+ # recurse on a dictionary
+ elif isinstance(value, dict):
+ if key not in user_def:
+ if debug:
+ print("user_def does not have key [%s]" % key)
+ return False
+ if not isinstance(user_def[key], dict):
+ if debug:
+ print("dict returned false: not instance of dict")
+ return False
+
+ # before passing ensure keys match
+ api_values = set(value.keys()) - set(skip)
+ user_values = set(user_def[key].keys()) - set(skip)
+ if api_values != user_values:
+ if debug:
+ print("keys are not equal in dict")
+ print(user_values)
+ print(api_values)
+ return False
+
+ result = Utils.check_def_equal(user_def[key], value, skip_keys=skip_keys, debug=debug)
+ if not result:
+ if debug:
+ print("dict returned false")
+ print(result)
+ return False
+
+ # Verify each key, value pair is the same
+ else:
+ if key not in user_def or value != user_def[key]:
+ if debug:
+ print("value not equal; user_def does not have key")
+ print(key)
+ print(value)
+ if key in user_def:
+ print(user_def[key])
+ return False
+
+ if debug:
+ print('returning true')
+ return True
+
+class OpenShiftCLIConfig(object):
+ '''Generic Config'''
+ def __init__(self, rname, namespace, kubeconfig, options):
+ self.kubeconfig = kubeconfig
+ self.name = rname
+ self.namespace = namespace
+ self._options = options
+
+ @property
+ def config_options(self):
+ ''' return config options '''
+ return self._options
+
+ def to_option_list(self, ascommalist=''):
+ '''return all options as a string
+ if ascommalist is set to the name of a key, and
+ the value of that key is a dict, format the dict
+ as a list of comma delimited key=value pairs'''
+ return self.stringify(ascommalist)
+
+ def stringify(self, ascommalist=''):
+ ''' return the options hash as cli params in a string
+ if ascommalist is set to the name of a key, and
+ the value of that key is a dict, format the dict
+ as a list of comma delimited key=value pairs '''
+ rval = []
+ for key in sorted(self.config_options.keys()):
+ data = self.config_options[key]
+ if data['include'] \
+ and (data['value'] or isinstance(data['value'], int)):
+ if key == ascommalist:
+ val = ','.join(['{}={}'.format(kk, vv) for kk, vv in sorted(data['value'].items())])
+ else:
+ val = data['value']
+ rval.append('--{}={}'.format(key.replace('_', '-'), val))
+
+ return rval
+
+
+# -*- -*- -*- End included fragment: lib/base.py -*- -*- -*-
+
+# -*- -*- -*- Begin included fragment: class/oc_adm_csr.py -*- -*- -*-
+
+
+class OCcsr(OpenShiftCLI):
+ ''' Class to wrap the oc adm certificate command line'''
+ kind = 'csr'
+
+ # pylint: disable=too-many-arguments
+ def __init__(self,
+ nodes=None,
+ approve_all=False,
+ service_account=None,
+ kubeconfig='/etc/origin/master/admin.kubeconfig',
+ verbose=False):
+ ''' Constructor for oc adm certificate '''
+ super(OCcsr, self).__init__(None, kubeconfig, verbose)
+ self.service_account = service_account
+ self.nodes = self.create_nodes(nodes)
+ self._csrs = []
+ self.approve_all = approve_all
+ self.verbose = verbose
+
+ @property
+ def csrs(self):
+ '''property for managing csrs'''
+ # any processing needed??
+ self._csrs = self._get(resource=self.kind)['results'][0]['items']
+ return self._csrs
+
+ def create_nodes(self, nodes):
+ '''create a node object to track csr signing status'''
+ nodes_list = []
+
+ if nodes is None:
+ return nodes_list
+
+ results = self._get(resource='nodes')['results'][0]['items']
+
+ for node in nodes:
+ nodes_list.append(dict(name=node, csrs={}, accepted=False, denied=False))
+
+ for ocnode in results:
+ if node in ocnode['metadata']['name']:
+ nodes_list[-1]['accepted'] = True
+
+ return nodes_list
+
+ def get(self):
+ '''get the current certificate signing requests'''
+ return self.csrs
+
+ @staticmethod
+ def action_needed(csr, action):
+ '''check to see if csr is in desired state'''
+ if csr['status'] == {}:
+ return True
+
+ state = csr['status']['conditions'][0]['type']
+
+ if action == 'approve' and state != 'Approved':
+ return True
+
+ elif action == 'deny' and state != 'Denied':
+ return True
+
+ return False
+
+ def match_node(self, csr):
+ '''match an inc csr to a node in self.nodes'''
+ for node in self.nodes:
+ # we have a match
+ if node['name'] in csr['metadata']['name']:
+ node['csrs'][csr['metadata']['name']] = csr
+
+ # check that the username is the node and type is 'Approved'
+ if node['name'] in csr['spec']['username'] and csr['status']:
+ if csr['status']['conditions'][0]['type'] == 'Approved':
+ node['accepted'] = True
+ # check type is 'Denied' and mark node as such
+ if csr['status'] and csr['status']['conditions'][0]['type'] == 'Denied':
+ node['denied'] = True
+
+ return node
+
+ return None
+
+ def finished(self):
+ '''determine if there are more csrs to sign'''
+ # if nodes is set and we have nodes then return if all nodes are 'accepted'
+ if self.nodes is not None and len(self.nodes) > 0:
+ return all([node['accepted'] or node['denied'] for node in self.nodes])
+
+ # we are approving everything or we still have nodes outstanding
+ return False
+
+ def manage(self, action):
+ '''run openshift oc adm ca create-server-cert cmd and store results into self.nodes
+
+ we attempt to verify if the node is one that was given to us to accept.
+
+ action - (allow | deny)
+ '''
+
+ results = []
+ # There are 2 types of requests:
+ # - node-bootstrapper-client-ip-172-31-51-246-ec2-internal
+ # The client request allows the client to talk to the api/controller
+ # - node-bootstrapper-server-ip-172-31-51-246-ec2-internal
+ # The server request allows the server to join the cluster
+ # Here we need to determine how to approve/deny
+ # we should query the csrs and verify they are from the nodes we thought
+ for csr in self.csrs:
+ node = self.match_node(csr)
+ # oc adm certificate <approve|deny> csr
+ # there are 3 known states: Denied, Aprroved, {}
+ # verify something is needed by OCcsr.action_needed
+ # if approve_all, then do it
+ # if you passed in nodes, you must have a node that matches
+ if self.approve_all or (node and OCcsr.action_needed(csr, action)):
+ result = self.openshift_cmd(['certificate', action, csr['metadata']['name']], oadm=True)
+ # client should have service account name in username field
+ # server should have node name in username field
+ if node and csr['metadata']['name'] not in node['csrs']:
+ node['csrs'][csr['metadata']['name']] = csr
+
+ # accept node in cluster
+ if node['name'] in csr['spec']['username']:
+ node['accepted'] = True
+
+ results.append(result)
+
+ return results
+
+ @staticmethod
+ def run_ansible(params, check_mode=False):
+ '''run the idempotent ansible code'''
+
+ client = OCcsr(params['nodes'],
+ params['approve_all'],
+ params['service_account'],
+ params['kubeconfig'],
+ params['debug'])
+
+ state = params['state']
+
+ api_rval = client.get()
+
+ if state == 'list':
+ return {'changed': False, 'results': api_rval, 'state': state}
+
+ if state in ['approve', 'deny']:
+ if check_mode:
+ return {'changed': True,
+ 'msg': "CHECK_MODE: Would have {} the certificate.".format(params['state']),
+ 'state': state}
+
+ all_results = []
+ finished = False
+ timeout = False
+ import time
+ # loop for timeout or block until all nodes pass
+ ctr = 0
+ while True:
+
+ all_results.extend(client.manage(params['state']))
+ if client.finished():
+ finished = True
+ break
+
+ if params['timeout'] == 0:
+ if not params['approve_all']:
+ ctr = 0
+
+ if ctr * 2 > params['timeout']:
+ timeout = True
+ break
+
+ # This provides time for the nodes to send their csr requests between approvals
+ time.sleep(2)
+
+ ctr += 1
+
+ for result in all_results:
+ if result['returncode'] != 0:
+ return {'failed': True, 'msg': all_results}
+
+ return dict(changed=len(all_results) > 0,
+ results=all_results,
+ nodes=client.nodes,
+ state=state,
+ finished=finished,
+ timeout=timeout)
+
+ return {'failed': True,
+ 'msg': 'Unknown state passed. %s' % state}
+
+
+# -*- -*- -*- End included fragment: class/oc_adm_csr.py -*- -*- -*-
+
+# -*- -*- -*- Begin included fragment: ansible/oc_adm_csr.py -*- -*- -*-
+
+def main():
+ '''
+ ansible oc module for approving certificate signing requests
+ '''
+
+ module = AnsibleModule(
+ argument_spec=dict(
+ kubeconfig=dict(default='/etc/origin/master/admin.kubeconfig', type='str'),
+ state=dict(default='approve', type='str',
+ choices=['approve', 'deny', 'list']),
+ debug=dict(default=False, type='bool'),
+ nodes=dict(default=None, type='list'),
+ timeout=dict(default=30, type='int'),
+ approve_all=dict(default=False, type='bool'),
+ service_account=dict(default='node-bootstrapper', type='str'),
+ ),
+ supports_check_mode=True,
+ mutually_exclusive=[['approve_all', 'nodes']],
+ )
+
+ if module.params['nodes'] == []:
+ module.fail_json(**dict(failed=True, msg='Please specify hosts.'))
+
+ rval = OCcsr.run_ansible(module.params, module.check_mode)
+
+ if 'failed' in rval:
+ return module.fail_json(**rval)
+
+ return module.exit_json(**rval)
+
+
+if __name__ == '__main__':
+ main()
+
+# -*- -*- -*- End included fragment: ansible/oc_adm_csr.py -*- -*- -*-
diff --git a/roles/lib_openshift/library/oc_adm_manage_node.py b/roles/lib_openshift/library/oc_adm_manage_node.py
index b09321a5b..44f3f57d8 100644
--- a/roles/lib_openshift/library/oc_adm_manage_node.py
+++ b/roles/lib_openshift/library/oc_adm_manage_node.py
@@ -1274,13 +1274,12 @@ class Utils(object): # pragma: no cover
@staticmethod
def openshift_installed():
''' check if openshift is installed '''
- import yum
+ import rpm
- yum_base = yum.YumBase()
- if yum_base.rpmdb.searchNevra(name='atomic-openshift'):
- return True
+ transaction_set = rpm.TransactionSet()
+ rpmquery = transaction_set.dbMatch("name", "atomic-openshift")
- return False
+ return rpmquery.count() > 0
# Disabling too-many-branches. This is a yaml dictionary comparison function
# pylint: disable=too-many-branches,too-many-return-statements,too-many-statements
diff --git a/roles/lib_openshift/library/oc_adm_policy_group.py b/roles/lib_openshift/library/oc_adm_policy_group.py
index 7154fd839..687cff579 100644
--- a/roles/lib_openshift/library/oc_adm_policy_group.py
+++ b/roles/lib_openshift/library/oc_adm_policy_group.py
@@ -1260,13 +1260,12 @@ class Utils(object): # pragma: no cover
@staticmethod
def openshift_installed():
''' check if openshift is installed '''
- import yum
+ import rpm
- yum_base = yum.YumBase()
- if yum_base.rpmdb.searchNevra(name='atomic-openshift'):
- return True
+ transaction_set = rpm.TransactionSet()
+ rpmquery = transaction_set.dbMatch("name", "atomic-openshift")
- return False
+ return rpmquery.count() > 0
# Disabling too-many-branches. This is a yaml dictionary comparison function
# pylint: disable=too-many-branches,too-many-return-statements,too-many-statements
diff --git a/roles/lib_openshift/library/oc_adm_policy_user.py b/roles/lib_openshift/library/oc_adm_policy_user.py
index 3fcf49799..ddf5d90b7 100644
--- a/roles/lib_openshift/library/oc_adm_policy_user.py
+++ b/roles/lib_openshift/library/oc_adm_policy_user.py
@@ -1260,13 +1260,12 @@ class Utils(object): # pragma: no cover
@staticmethod
def openshift_installed():
''' check if openshift is installed '''
- import yum
+ import rpm
- yum_base = yum.YumBase()
- if yum_base.rpmdb.searchNevra(name='atomic-openshift'):
- return True
+ transaction_set = rpm.TransactionSet()
+ rpmquery = transaction_set.dbMatch("name", "atomic-openshift")
- return False
+ return rpmquery.count() > 0
# Disabling too-many-branches. This is a yaml dictionary comparison function
# pylint: disable=too-many-branches,too-many-return-statements,too-many-statements
diff --git a/roles/lib_openshift/library/oc_adm_registry.py b/roles/lib_openshift/library/oc_adm_registry.py
index bf2650460..c00eee381 100644
--- a/roles/lib_openshift/library/oc_adm_registry.py
+++ b/roles/lib_openshift/library/oc_adm_registry.py
@@ -1378,13 +1378,12 @@ class Utils(object): # pragma: no cover
@staticmethod
def openshift_installed():
''' check if openshift is installed '''
- import yum
+ import rpm
- yum_base = yum.YumBase()
- if yum_base.rpmdb.searchNevra(name='atomic-openshift'):
- return True
+ transaction_set = rpm.TransactionSet()
+ rpmquery = transaction_set.dbMatch("name", "atomic-openshift")
- return False
+ return rpmquery.count() > 0
# Disabling too-many-branches. This is a yaml dictionary comparison function
# pylint: disable=too-many-branches,too-many-return-statements,too-many-statements
diff --git a/roles/lib_openshift/library/oc_adm_router.py b/roles/lib_openshift/library/oc_adm_router.py
index a2b7d12c0..0c925ab0b 100644
--- a/roles/lib_openshift/library/oc_adm_router.py
+++ b/roles/lib_openshift/library/oc_adm_router.py
@@ -1403,13 +1403,12 @@ class Utils(object): # pragma: no cover
@staticmethod
def openshift_installed():
''' check if openshift is installed '''
- import yum
+ import rpm
- yum_base = yum.YumBase()
- if yum_base.rpmdb.searchNevra(name='atomic-openshift'):
- return True
+ transaction_set = rpm.TransactionSet()
+ rpmquery = transaction_set.dbMatch("name", "atomic-openshift")
- return False
+ return rpmquery.count() > 0
# Disabling too-many-branches. This is a yaml dictionary comparison function
# pylint: disable=too-many-branches,too-many-return-statements,too-many-statements
diff --git a/roles/lib_openshift/library/oc_atomic_container.py b/roles/lib_openshift/library/oc_atomic_container.py
index 955c6313e..79bd08f4e 100644
--- a/roles/lib_openshift/library/oc_atomic_container.py
+++ b/roles/lib_openshift/library/oc_atomic_container.py
@@ -83,7 +83,7 @@ def _install(module, container, image, values_list):
if rc != 0:
return rc, out, err, False
else:
- changed = "Extracting" in out
+ changed = "Extracting" in out or "Copying blob" in out
return rc, out, err, changed
def _uninstall(module, name):
@@ -127,7 +127,7 @@ def do_update(module, container, old_image, image, values_list):
if rc != 0:
module.fail_json(rc=rc, msg=err)
else:
- changed = "Extracting" in out
+ changed = "Extracting" in out or "Copying blob" in out
module.exit_json(msg=out, changed=changed)
diff --git a/roles/lib_openshift/library/oc_clusterrole.py b/roles/lib_openshift/library/oc_clusterrole.py
index d101eac1c..567ecfd4e 100644
--- a/roles/lib_openshift/library/oc_clusterrole.py
+++ b/roles/lib_openshift/library/oc_clusterrole.py
@@ -1252,13 +1252,12 @@ class Utils(object): # pragma: no cover
@staticmethod
def openshift_installed():
''' check if openshift is installed '''
- import yum
+ import rpm
- yum_base = yum.YumBase()
- if yum_base.rpmdb.searchNevra(name='atomic-openshift'):
- return True
+ transaction_set = rpm.TransactionSet()
+ rpmquery = transaction_set.dbMatch("name", "atomic-openshift")
- return False
+ return rpmquery.count() > 0
# Disabling too-many-branches. This is a yaml dictionary comparison function
# pylint: disable=too-many-branches,too-many-return-statements,too-many-statements
diff --git a/roles/lib_openshift/library/oc_configmap.py b/roles/lib_openshift/library/oc_configmap.py
index 7cd29215f..9515de569 100644
--- a/roles/lib_openshift/library/oc_configmap.py
+++ b/roles/lib_openshift/library/oc_configmap.py
@@ -1258,13 +1258,12 @@ class Utils(object): # pragma: no cover
@staticmethod
def openshift_installed():
''' check if openshift is installed '''
- import yum
+ import rpm
- yum_base = yum.YumBase()
- if yum_base.rpmdb.searchNevra(name='atomic-openshift'):
- return True
+ transaction_set = rpm.TransactionSet()
+ rpmquery = transaction_set.dbMatch("name", "atomic-openshift")
- return False
+ return rpmquery.count() > 0
# Disabling too-many-branches. This is a yaml dictionary comparison function
# pylint: disable=too-many-branches,too-many-return-statements,too-many-statements
diff --git a/roles/lib_openshift/library/oc_edit.py b/roles/lib_openshift/library/oc_edit.py
index 5b11f45ba..d461e5ae9 100644
--- a/roles/lib_openshift/library/oc_edit.py
+++ b/roles/lib_openshift/library/oc_edit.py
@@ -1302,13 +1302,12 @@ class Utils(object): # pragma: no cover
@staticmethod
def openshift_installed():
''' check if openshift is installed '''
- import yum
+ import rpm
- yum_base = yum.YumBase()
- if yum_base.rpmdb.searchNevra(name='atomic-openshift'):
- return True
+ transaction_set = rpm.TransactionSet()
+ rpmquery = transaction_set.dbMatch("name", "atomic-openshift")
- return False
+ return rpmquery.count() > 0
# Disabling too-many-branches. This is a yaml dictionary comparison function
# pylint: disable=too-many-branches,too-many-return-statements,too-many-statements
diff --git a/roles/lib_openshift/library/oc_env.py b/roles/lib_openshift/library/oc_env.py
index d3834ce0c..22ad58725 100644
--- a/roles/lib_openshift/library/oc_env.py
+++ b/roles/lib_openshift/library/oc_env.py
@@ -1269,13 +1269,12 @@ class Utils(object): # pragma: no cover
@staticmethod
def openshift_installed():
''' check if openshift is installed '''
- import yum
+ import rpm
- yum_base = yum.YumBase()
- if yum_base.rpmdb.searchNevra(name='atomic-openshift'):
- return True
+ transaction_set = rpm.TransactionSet()
+ rpmquery = transaction_set.dbMatch("name", "atomic-openshift")
- return False
+ return rpmquery.count() > 0
# Disabling too-many-branches. This is a yaml dictionary comparison function
# pylint: disable=too-many-branches,too-many-return-statements,too-many-statements
diff --git a/roles/lib_openshift/library/oc_group.py b/roles/lib_openshift/library/oc_group.py
index 0d751fe28..b6c6e47d9 100644
--- a/roles/lib_openshift/library/oc_group.py
+++ b/roles/lib_openshift/library/oc_group.py
@@ -1242,13 +1242,12 @@ class Utils(object): # pragma: no cover
@staticmethod
def openshift_installed():
''' check if openshift is installed '''
- import yum
+ import rpm
- yum_base = yum.YumBase()
- if yum_base.rpmdb.searchNevra(name='atomic-openshift'):
- return True
+ transaction_set = rpm.TransactionSet()
+ rpmquery = transaction_set.dbMatch("name", "atomic-openshift")
- return False
+ return rpmquery.count() > 0
# Disabling too-many-branches. This is a yaml dictionary comparison function
# pylint: disable=too-many-branches,too-many-return-statements,too-many-statements
diff --git a/roles/lib_openshift/library/oc_image.py b/roles/lib_openshift/library/oc_image.py
index 3a6ba3e56..f7fc286e0 100644
--- a/roles/lib_openshift/library/oc_image.py
+++ b/roles/lib_openshift/library/oc_image.py
@@ -1261,13 +1261,12 @@ class Utils(object): # pragma: no cover
@staticmethod
def openshift_installed():
''' check if openshift is installed '''
- import yum
+ import rpm
- yum_base = yum.YumBase()
- if yum_base.rpmdb.searchNevra(name='atomic-openshift'):
- return True
+ transaction_set = rpm.TransactionSet()
+ rpmquery = transaction_set.dbMatch("name", "atomic-openshift")
- return False
+ return rpmquery.count() > 0
# Disabling too-many-branches. This is a yaml dictionary comparison function
# pylint: disable=too-many-branches,too-many-return-statements,too-many-statements
diff --git a/roles/lib_openshift/library/oc_label.py b/roles/lib_openshift/library/oc_label.py
index 5db036b23..2206878a4 100644
--- a/roles/lib_openshift/library/oc_label.py
+++ b/roles/lib_openshift/library/oc_label.py
@@ -1278,13 +1278,12 @@ class Utils(object): # pragma: no cover
@staticmethod
def openshift_installed():
''' check if openshift is installed '''
- import yum
+ import rpm
- yum_base = yum.YumBase()
- if yum_base.rpmdb.searchNevra(name='atomic-openshift'):
- return True
+ transaction_set = rpm.TransactionSet()
+ rpmquery = transaction_set.dbMatch("name", "atomic-openshift")
- return False
+ return rpmquery.count() > 0
# Disabling too-many-branches. This is a yaml dictionary comparison function
# pylint: disable=too-many-branches,too-many-return-statements,too-many-statements
diff --git a/roles/lib_openshift/library/oc_obj.py b/roles/lib_openshift/library/oc_obj.py
index 7d9392af9..126d7a617 100644
--- a/roles/lib_openshift/library/oc_obj.py
+++ b/roles/lib_openshift/library/oc_obj.py
@@ -1281,13 +1281,12 @@ class Utils(object): # pragma: no cover
@staticmethod
def openshift_installed():
''' check if openshift is installed '''
- import yum
+ import rpm
- yum_base = yum.YumBase()
- if yum_base.rpmdb.searchNevra(name='atomic-openshift'):
- return True
+ transaction_set = rpm.TransactionSet()
+ rpmquery = transaction_set.dbMatch("name", "atomic-openshift")
- return False
+ return rpmquery.count() > 0
# Disabling too-many-branches. This is a yaml dictionary comparison function
# pylint: disable=too-many-branches,too-many-return-statements,too-many-statements
diff --git a/roles/lib_openshift/library/oc_objectvalidator.py b/roles/lib_openshift/library/oc_objectvalidator.py
index 130521761..d20904d0d 100644
--- a/roles/lib_openshift/library/oc_objectvalidator.py
+++ b/roles/lib_openshift/library/oc_objectvalidator.py
@@ -1213,13 +1213,12 @@ class Utils(object): # pragma: no cover
@staticmethod
def openshift_installed():
''' check if openshift is installed '''
- import yum
+ import rpm
- yum_base = yum.YumBase()
- if yum_base.rpmdb.searchNevra(name='atomic-openshift'):
- return True
+ transaction_set = rpm.TransactionSet()
+ rpmquery = transaction_set.dbMatch("name", "atomic-openshift")
- return False
+ return rpmquery.count() > 0
# Disabling too-many-branches. This is a yaml dictionary comparison function
# pylint: disable=too-many-branches,too-many-return-statements,too-many-statements
diff --git a/roles/lib_openshift/library/oc_process.py b/roles/lib_openshift/library/oc_process.py
index c6568d520..91199d093 100644
--- a/roles/lib_openshift/library/oc_process.py
+++ b/roles/lib_openshift/library/oc_process.py
@@ -1270,13 +1270,12 @@ class Utils(object): # pragma: no cover
@staticmethod
def openshift_installed():
''' check if openshift is installed '''
- import yum
+ import rpm
- yum_base = yum.YumBase()
- if yum_base.rpmdb.searchNevra(name='atomic-openshift'):
- return True
+ transaction_set = rpm.TransactionSet()
+ rpmquery = transaction_set.dbMatch("name", "atomic-openshift")
- return False
+ return rpmquery.count() > 0
# Disabling too-many-branches. This is a yaml dictionary comparison function
# pylint: disable=too-many-branches,too-many-return-statements,too-many-statements
diff --git a/roles/lib_openshift/library/oc_project.py b/roles/lib_openshift/library/oc_project.py
index bf65ef603..f9b2d81fa 100644
--- a/roles/lib_openshift/library/oc_project.py
+++ b/roles/lib_openshift/library/oc_project.py
@@ -1267,13 +1267,12 @@ class Utils(object): # pragma: no cover
@staticmethod
def openshift_installed():
''' check if openshift is installed '''
- import yum
+ import rpm
- yum_base = yum.YumBase()
- if yum_base.rpmdb.searchNevra(name='atomic-openshift'):
- return True
+ transaction_set = rpm.TransactionSet()
+ rpmquery = transaction_set.dbMatch("name", "atomic-openshift")
- return False
+ return rpmquery.count() > 0
# Disabling too-many-branches. This is a yaml dictionary comparison function
# pylint: disable=too-many-branches,too-many-return-statements,too-many-statements
diff --git a/roles/lib_openshift/library/oc_pvc.py b/roles/lib_openshift/library/oc_pvc.py
index a21540962..895322ba5 100644
--- a/roles/lib_openshift/library/oc_pvc.py
+++ b/roles/lib_openshift/library/oc_pvc.py
@@ -1274,13 +1274,12 @@ class Utils(object): # pragma: no cover
@staticmethod
def openshift_installed():
''' check if openshift is installed '''
- import yum
+ import rpm
- yum_base = yum.YumBase()
- if yum_base.rpmdb.searchNevra(name='atomic-openshift'):
- return True
+ transaction_set = rpm.TransactionSet()
+ rpmquery = transaction_set.dbMatch("name", "atomic-openshift")
- return False
+ return rpmquery.count() > 0
# Disabling too-many-branches. This is a yaml dictionary comparison function
# pylint: disable=too-many-branches,too-many-return-statements,too-many-statements
diff --git a/roles/lib_openshift/library/oc_route.py b/roles/lib_openshift/library/oc_route.py
index 0c0bc9386..8f8e46e1e 100644
--- a/roles/lib_openshift/library/oc_route.py
+++ b/roles/lib_openshift/library/oc_route.py
@@ -1312,13 +1312,12 @@ class Utils(object): # pragma: no cover
@staticmethod
def openshift_installed():
''' check if openshift is installed '''
- import yum
+ import rpm
- yum_base = yum.YumBase()
- if yum_base.rpmdb.searchNevra(name='atomic-openshift'):
- return True
+ transaction_set = rpm.TransactionSet()
+ rpmquery = transaction_set.dbMatch("name", "atomic-openshift")
- return False
+ return rpmquery.count() > 0
# Disabling too-many-branches. This is a yaml dictionary comparison function
# pylint: disable=too-many-branches,too-many-return-statements,too-many-statements
@@ -1666,9 +1665,6 @@ class OCRoute(OpenShiftCLI):
@staticmethod
def get_cert_data(path, content):
'''get the data for a particular value'''
- if not path and not content:
- return None
-
rval = None
if path and os.path.exists(path) and os.access(path, os.R_OK):
rval = open(path).read()
@@ -1707,14 +1703,14 @@ class OCRoute(OpenShiftCLI):
if params['tls_termination'] and params['tls_termination'].lower() != 'passthrough': # E501
for key, option in files.items():
- if key == 'destcacert' and params['tls_termination'] != 'reencrypt':
+ if not option['path'] and not option['content']:
continue
option['value'] = OCRoute.get_cert_data(option['path'], option['content']) # E501
if not option['value']:
return {'failed': True,
- 'msg': 'Verify that you pass a value for %s' % key}
+ 'msg': 'Verify that you pass a correct value for %s' % key}
rconfig = RouteConfig(params['name'],
params['namespace'],
diff --git a/roles/lib_openshift/library/oc_scale.py b/roles/lib_openshift/library/oc_scale.py
index f112b6dd0..7130cc5fc 100644
--- a/roles/lib_openshift/library/oc_scale.py
+++ b/roles/lib_openshift/library/oc_scale.py
@@ -1256,13 +1256,12 @@ class Utils(object): # pragma: no cover
@staticmethod
def openshift_installed():
''' check if openshift is installed '''
- import yum
+ import rpm
- yum_base = yum.YumBase()
- if yum_base.rpmdb.searchNevra(name='atomic-openshift'):
- return True
+ transaction_set = rpm.TransactionSet()
+ rpmquery = transaction_set.dbMatch("name", "atomic-openshift")
- return False
+ return rpmquery.count() > 0
# Disabling too-many-branches. This is a yaml dictionary comparison function
# pylint: disable=too-many-branches,too-many-return-statements,too-many-statements
diff --git a/roles/lib_openshift/library/oc_secret.py b/roles/lib_openshift/library/oc_secret.py
index d762e0c38..0c4b99e30 100644
--- a/roles/lib_openshift/library/oc_secret.py
+++ b/roles/lib_openshift/library/oc_secret.py
@@ -1308,13 +1308,12 @@ class Utils(object): # pragma: no cover
@staticmethod
def openshift_installed():
''' check if openshift is installed '''
- import yum
+ import rpm
- yum_base = yum.YumBase()
- if yum_base.rpmdb.searchNevra(name='atomic-openshift'):
- return True
+ transaction_set = rpm.TransactionSet()
+ rpmquery = transaction_set.dbMatch("name", "atomic-openshift")
- return False
+ return rpmquery.count() > 0
# Disabling too-many-branches. This is a yaml dictionary comparison function
# pylint: disable=too-many-branches,too-many-return-statements,too-many-statements
diff --git a/roles/lib_openshift/library/oc_service.py b/roles/lib_openshift/library/oc_service.py
index 769b75e15..7ab139e85 100644
--- a/roles/lib_openshift/library/oc_service.py
+++ b/roles/lib_openshift/library/oc_service.py
@@ -1315,13 +1315,12 @@ class Utils(object): # pragma: no cover
@staticmethod
def openshift_installed():
''' check if openshift is installed '''
- import yum
+ import rpm
- yum_base = yum.YumBase()
- if yum_base.rpmdb.searchNevra(name='atomic-openshift'):
- return True
+ transaction_set = rpm.TransactionSet()
+ rpmquery = transaction_set.dbMatch("name", "atomic-openshift")
- return False
+ return rpmquery.count() > 0
# Disabling too-many-branches. This is a yaml dictionary comparison function
# pylint: disable=too-many-branches,too-many-return-statements,too-many-statements
diff --git a/roles/lib_openshift/library/oc_serviceaccount.py b/roles/lib_openshift/library/oc_serviceaccount.py
index 446987eff..5d539ced4 100644
--- a/roles/lib_openshift/library/oc_serviceaccount.py
+++ b/roles/lib_openshift/library/oc_serviceaccount.py
@@ -1254,13 +1254,12 @@ class Utils(object): # pragma: no cover
@staticmethod
def openshift_installed():
''' check if openshift is installed '''
- import yum
+ import rpm
- yum_base = yum.YumBase()
- if yum_base.rpmdb.searchNevra(name='atomic-openshift'):
- return True
+ transaction_set = rpm.TransactionSet()
+ rpmquery = transaction_set.dbMatch("name", "atomic-openshift")
- return False
+ return rpmquery.count() > 0
# Disabling too-many-branches. This is a yaml dictionary comparison function
# pylint: disable=too-many-branches,too-many-return-statements,too-many-statements
diff --git a/roles/lib_openshift/library/oc_serviceaccount_secret.py b/roles/lib_openshift/library/oc_serviceaccount_secret.py
index c7eb1986a..97e213f46 100644
--- a/roles/lib_openshift/library/oc_serviceaccount_secret.py
+++ b/roles/lib_openshift/library/oc_serviceaccount_secret.py
@@ -1254,13 +1254,12 @@ class Utils(object): # pragma: no cover
@staticmethod
def openshift_installed():
''' check if openshift is installed '''
- import yum
+ import rpm
- yum_base = yum.YumBase()
- if yum_base.rpmdb.searchNevra(name='atomic-openshift'):
- return True
+ transaction_set = rpm.TransactionSet()
+ rpmquery = transaction_set.dbMatch("name", "atomic-openshift")
- return False
+ return rpmquery.count() > 0
# Disabling too-many-branches. This is a yaml dictionary comparison function
# pylint: disable=too-many-branches,too-many-return-statements,too-many-statements
diff --git a/roles/lib_openshift/library/oc_storageclass.py b/roles/lib_openshift/library/oc_storageclass.py
index 686119c65..9339a85e5 100644
--- a/roles/lib_openshift/library/oc_storageclass.py
+++ b/roles/lib_openshift/library/oc_storageclass.py
@@ -1272,13 +1272,12 @@ class Utils(object): # pragma: no cover
@staticmethod
def openshift_installed():
''' check if openshift is installed '''
- import yum
+ import rpm
- yum_base = yum.YumBase()
- if yum_base.rpmdb.searchNevra(name='atomic-openshift'):
- return True
+ transaction_set = rpm.TransactionSet()
+ rpmquery = transaction_set.dbMatch("name", "atomic-openshift")
- return False
+ return rpmquery.count() > 0
# Disabling too-many-branches. This is a yaml dictionary comparison function
# pylint: disable=too-many-branches,too-many-return-statements,too-many-statements
diff --git a/roles/lib_openshift/library/oc_user.py b/roles/lib_openshift/library/oc_user.py
index 3a98693b7..2fa349547 100644
--- a/roles/lib_openshift/library/oc_user.py
+++ b/roles/lib_openshift/library/oc_user.py
@@ -1314,13 +1314,12 @@ class Utils(object): # pragma: no cover
@staticmethod
def openshift_installed():
''' check if openshift is installed '''
- import yum
+ import rpm
- yum_base = yum.YumBase()
- if yum_base.rpmdb.searchNevra(name='atomic-openshift'):
- return True
+ transaction_set = rpm.TransactionSet()
+ rpmquery = transaction_set.dbMatch("name", "atomic-openshift")
- return False
+ return rpmquery.count() > 0
# Disabling too-many-branches. This is a yaml dictionary comparison function
# pylint: disable=too-many-branches,too-many-return-statements,too-many-statements
diff --git a/roles/lib_openshift/library/oc_version.py b/roles/lib_openshift/library/oc_version.py
index 939261526..55e1054e7 100644
--- a/roles/lib_openshift/library/oc_version.py
+++ b/roles/lib_openshift/library/oc_version.py
@@ -1226,13 +1226,12 @@ class Utils(object): # pragma: no cover
@staticmethod
def openshift_installed():
''' check if openshift is installed '''
- import yum
+ import rpm
- yum_base = yum.YumBase()
- if yum_base.rpmdb.searchNevra(name='atomic-openshift'):
- return True
+ transaction_set = rpm.TransactionSet()
+ rpmquery = transaction_set.dbMatch("name", "atomic-openshift")
- return False
+ return rpmquery.count() > 0
# Disabling too-many-branches. This is a yaml dictionary comparison function
# pylint: disable=too-many-branches,too-many-return-statements,too-many-statements
diff --git a/roles/lib_openshift/library/oc_volume.py b/roles/lib_openshift/library/oc_volume.py
index 41e7d0ab8..63bad57b4 100644
--- a/roles/lib_openshift/library/oc_volume.py
+++ b/roles/lib_openshift/library/oc_volume.py
@@ -1303,13 +1303,12 @@ class Utils(object): # pragma: no cover
@staticmethod
def openshift_installed():
''' check if openshift is installed '''
- import yum
+ import rpm
- yum_base = yum.YumBase()
- if yum_base.rpmdb.searchNevra(name='atomic-openshift'):
- return True
+ transaction_set = rpm.TransactionSet()
+ rpmquery = transaction_set.dbMatch("name", "atomic-openshift")
- return False
+ return rpmquery.count() > 0
# Disabling too-many-branches. This is a yaml dictionary comparison function
# pylint: disable=too-many-branches,too-many-return-statements,too-many-statements
diff --git a/roles/lib_openshift/src/ansible/oc_adm_csr.py b/roles/lib_openshift/src/ansible/oc_adm_csr.py
new file mode 100644
index 000000000..9e43a810b
--- /dev/null
+++ b/roles/lib_openshift/src/ansible/oc_adm_csr.py
@@ -0,0 +1,36 @@
+# pylint: skip-file
+# flake8: noqa
+
+def main():
+ '''
+ ansible oc module for approving certificate signing requests
+ '''
+
+ module = AnsibleModule(
+ argument_spec=dict(
+ kubeconfig=dict(default='/etc/origin/master/admin.kubeconfig', type='str'),
+ state=dict(default='approve', type='str',
+ choices=['approve', 'deny', 'list']),
+ debug=dict(default=False, type='bool'),
+ nodes=dict(default=None, type='list'),
+ timeout=dict(default=30, type='int'),
+ approve_all=dict(default=False, type='bool'),
+ service_account=dict(default='node-bootstrapper', type='str'),
+ ),
+ supports_check_mode=True,
+ mutually_exclusive=[['approve_all', 'nodes']],
+ )
+
+ if module.params['nodes'] == []:
+ module.fail_json(**dict(failed=True, msg='Please specify hosts.'))
+
+ rval = OCcsr.run_ansible(module.params, module.check_mode)
+
+ if 'failed' in rval:
+ return module.fail_json(**rval)
+
+ return module.exit_json(**rval)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/roles/lib_openshift/src/ansible/oc_atomic_container.py b/roles/lib_openshift/src/ansible/oc_atomic_container.py
index 7b81760df..454d7c4b2 100644
--- a/roles/lib_openshift/src/ansible/oc_atomic_container.py
+++ b/roles/lib_openshift/src/ansible/oc_atomic_container.py
@@ -19,7 +19,7 @@ def _install(module, container, image, values_list):
if rc != 0:
return rc, out, err, False
else:
- changed = "Extracting" in out
+ changed = "Extracting" in out or "Copying blob" in out
return rc, out, err, changed
def _uninstall(module, name):
@@ -63,7 +63,7 @@ def do_update(module, container, old_image, image, values_list):
if rc != 0:
module.fail_json(rc=rc, msg=err)
else:
- changed = "Extracting" in out
+ changed = "Extracting" in out or "Copying blob" in out
module.exit_json(msg=out, changed=changed)
diff --git a/roles/lib_openshift/src/class/oc_adm_csr.py b/roles/lib_openshift/src/class/oc_adm_csr.py
new file mode 100644
index 000000000..ea11c6ca9
--- /dev/null
+++ b/roles/lib_openshift/src/class/oc_adm_csr.py
@@ -0,0 +1,197 @@
+# pylint: skip-file
+# flake8: noqa
+
+
+class OCcsr(OpenShiftCLI):
+ ''' Class to wrap the oc adm certificate command line'''
+ kind = 'csr'
+
+ # pylint: disable=too-many-arguments
+ def __init__(self,
+ nodes=None,
+ approve_all=False,
+ service_account=None,
+ kubeconfig='/etc/origin/master/admin.kubeconfig',
+ verbose=False):
+ ''' Constructor for oc adm certificate '''
+ super(OCcsr, self).__init__(None, kubeconfig, verbose)
+ self.service_account = service_account
+ self.nodes = self.create_nodes(nodes)
+ self._csrs = []
+ self.approve_all = approve_all
+ self.verbose = verbose
+
+ @property
+ def csrs(self):
+ '''property for managing csrs'''
+ # any processing needed??
+ self._csrs = self._get(resource=self.kind)['results'][0]['items']
+ return self._csrs
+
+ def create_nodes(self, nodes):
+ '''create a node object to track csr signing status'''
+ nodes_list = []
+
+ if nodes is None:
+ return nodes_list
+
+ results = self._get(resource='nodes')['results'][0]['items']
+
+ for node in nodes:
+ nodes_list.append(dict(name=node, csrs={}, accepted=False, denied=False))
+
+ for ocnode in results:
+ if node in ocnode['metadata']['name']:
+ nodes_list[-1]['accepted'] = True
+
+ return nodes_list
+
+ def get(self):
+ '''get the current certificate signing requests'''
+ return self.csrs
+
+ @staticmethod
+ def action_needed(csr, action):
+ '''check to see if csr is in desired state'''
+ if csr['status'] == {}:
+ return True
+
+ state = csr['status']['conditions'][0]['type']
+
+ if action == 'approve' and state != 'Approved':
+ return True
+
+ elif action == 'deny' and state != 'Denied':
+ return True
+
+ return False
+
+ def match_node(self, csr):
+ '''match an inc csr to a node in self.nodes'''
+ for node in self.nodes:
+ # we have a match
+ if node['name'] in csr['metadata']['name']:
+ node['csrs'][csr['metadata']['name']] = csr
+
+ # check that the username is the node and type is 'Approved'
+ if node['name'] in csr['spec']['username'] and csr['status']:
+ if csr['status']['conditions'][0]['type'] == 'Approved':
+ node['accepted'] = True
+ # check type is 'Denied' and mark node as such
+ if csr['status'] and csr['status']['conditions'][0]['type'] == 'Denied':
+ node['denied'] = True
+
+ return node
+
+ return None
+
+ def finished(self):
+ '''determine if there are more csrs to sign'''
+ # if nodes is set and we have nodes then return if all nodes are 'accepted'
+ if self.nodes is not None and len(self.nodes) > 0:
+ return all([node['accepted'] or node['denied'] for node in self.nodes])
+
+ # we are approving everything or we still have nodes outstanding
+ return False
+
+ def manage(self, action):
+ '''run openshift oc adm ca create-server-cert cmd and store results into self.nodes
+
+ we attempt to verify if the node is one that was given to us to accept.
+
+ action - (allow | deny)
+ '''
+
+ results = []
+ # There are 2 types of requests:
+ # - node-bootstrapper-client-ip-172-31-51-246-ec2-internal
+ # The client request allows the client to talk to the api/controller
+ # - node-bootstrapper-server-ip-172-31-51-246-ec2-internal
+ # The server request allows the server to join the cluster
+ # Here we need to determine how to approve/deny
+ # we should query the csrs and verify they are from the nodes we thought
+ for csr in self.csrs:
+ node = self.match_node(csr)
+ # oc adm certificate <approve|deny> csr
+ # there are 3 known states: Denied, Aprroved, {}
+ # verify something is needed by OCcsr.action_needed
+ # if approve_all, then do it
+ # if you passed in nodes, you must have a node that matches
+ if self.approve_all or (node and OCcsr.action_needed(csr, action)):
+ result = self.openshift_cmd(['certificate', action, csr['metadata']['name']], oadm=True)
+ # client should have service account name in username field
+ # server should have node name in username field
+ if node and csr['metadata']['name'] not in node['csrs']:
+ node['csrs'][csr['metadata']['name']] = csr
+
+ # accept node in cluster
+ if node['name'] in csr['spec']['username']:
+ node['accepted'] = True
+
+ results.append(result)
+
+ return results
+
+ @staticmethod
+ def run_ansible(params, check_mode=False):
+ '''run the idempotent ansible code'''
+
+ client = OCcsr(params['nodes'],
+ params['approve_all'],
+ params['service_account'],
+ params['kubeconfig'],
+ params['debug'])
+
+ state = params['state']
+
+ api_rval = client.get()
+
+ if state == 'list':
+ return {'changed': False, 'results': api_rval, 'state': state}
+
+ if state in ['approve', 'deny']:
+ if check_mode:
+ return {'changed': True,
+ 'msg': "CHECK_MODE: Would have {} the certificate.".format(params['state']),
+ 'state': state}
+
+ all_results = []
+ finished = False
+ timeout = False
+ import time
+ # loop for timeout or block until all nodes pass
+ ctr = 0
+ while True:
+
+ all_results.extend(client.manage(params['state']))
+ if client.finished():
+ finished = True
+ break
+
+ if params['timeout'] == 0:
+ if not params['approve_all']:
+ ctr = 0
+
+ if ctr * 2 > params['timeout']:
+ timeout = True
+ break
+
+ # This provides time for the nodes to send their csr requests between approvals
+ time.sleep(2)
+
+ ctr += 1
+
+ for result in all_results:
+ if result['returncode'] != 0:
+ return {'failed': True, 'msg': all_results}
+
+ return dict(changed=len(all_results) > 0,
+ results=all_results,
+ nodes=client.nodes,
+ state=state,
+ finished=finished,
+ timeout=timeout)
+
+ return {'failed': True,
+ 'msg': 'Unknown state passed. %s' % state}
+
diff --git a/roles/lib_openshift/src/class/oc_route.py b/roles/lib_openshift/src/class/oc_route.py
index 3935525f1..3a1bd732f 100644
--- a/roles/lib_openshift/src/class/oc_route.py
+++ b/roles/lib_openshift/src/class/oc_route.py
@@ -68,9 +68,6 @@ class OCRoute(OpenShiftCLI):
@staticmethod
def get_cert_data(path, content):
'''get the data for a particular value'''
- if not path and not content:
- return None
-
rval = None
if path and os.path.exists(path) and os.access(path, os.R_OK):
rval = open(path).read()
@@ -109,14 +106,14 @@ class OCRoute(OpenShiftCLI):
if params['tls_termination'] and params['tls_termination'].lower() != 'passthrough': # E501
for key, option in files.items():
- if key == 'destcacert' and params['tls_termination'] != 'reencrypt':
+ if not option['path'] and not option['content']:
continue
option['value'] = OCRoute.get_cert_data(option['path'], option['content']) # E501
if not option['value']:
return {'failed': True,
- 'msg': 'Verify that you pass a value for %s' % key}
+ 'msg': 'Verify that you pass a correct value for %s' % key}
rconfig = RouteConfig(params['name'],
params['namespace'],
diff --git a/roles/lib_openshift/src/doc/csr b/roles/lib_openshift/src/doc/csr
new file mode 100644
index 000000000..db72dbda3
--- /dev/null
+++ b/roles/lib_openshift/src/doc/csr
@@ -0,0 +1,80 @@
+# flake8: noqa
+# pylint: skip-file
+
+DOCUMENTATION = '''
+---
+module: oc_adm_csr
+short_description: Module to approve or deny openshift certificate signing requests
+description:
+ - Wrapper around the openshift `oc adm certificate approve|deny <csr>` command.
+options:
+ state:
+ description:
+ - approve|deny|list Approve, deny, and list are the only supported states for certificates
+ required: false
+ default: present
+ choices:
+ - present
+ aliases: []
+ kubeconfig:
+ description:
+ - The path for the kubeconfig file to use for authentication
+ required: false
+ default: /etc/origin/master/admin.kubeconfig
+ aliases: []
+ debug:
+ description:
+ - Turn on debug output.
+ required: false
+ default: False
+ aliases: []
+ nodes:
+ description:
+ - A list of the names of the nodes in which to accept the certificates
+ required: false
+ default: None
+ aliases: []
+ timeout:
+ description:
+ - This flag allows for a timeout value when approving nodes.
+ required: false
+ default: 30
+ aliases: []
+ timeout:
+ description:
+ - This flag allows for a timeout value when doing node approvals.
+ - A zero value for the timeout will block until the nodes have been accepted
+ required: false
+ default: 30
+ aliases: []
+ approve_all:
+ description:
+ - This flag allows for the module to approve all CSRs that are found.
+ - This facilitates testing.
+ required: false
+ default: False
+ aliases: []
+ service_account:
+ description:
+ - This parameter tells the approval process which service account is being used for the requests
+ required: false
+ default: node-bootstrapper
+ aliases: []
+author:
+- "Kenny Woodson <kwoodson@redhat.com>"
+extends_documentation_fragment: []
+'''
+
+EXAMPLES = '''
+- name: Approve certificates for node xyz
+ oc_adm_scr:
+ nodes:
+ - xyz
+ timeout: 300
+
+- name: Approve certificates for node xyz
+ oc_adm_scr:
+ nodes:
+ - xyz
+ timeout: 0
+'''
diff --git a/roles/lib_openshift/src/lib/base.py b/roles/lib_openshift/src/lib/base.py
index 16770b22d..5a307cdb3 100644
--- a/roles/lib_openshift/src/lib/base.py
+++ b/roles/lib_openshift/src/lib/base.py
@@ -464,13 +464,12 @@ class Utils(object):
@staticmethod
def openshift_installed():
''' check if openshift is installed '''
- import yum
+ import rpm
- yum_base = yum.YumBase()
- if yum_base.rpmdb.searchNevra(name='atomic-openshift'):
- return True
+ transaction_set = rpm.TransactionSet()
+ rpmquery = transaction_set.dbMatch("name", "atomic-openshift")
- return False
+ return rpmquery.count() > 0
# Disabling too-many-branches. This is a yaml dictionary comparison function
# pylint: disable=too-many-branches,too-many-return-statements,too-many-statements
diff --git a/roles/lib_openshift/src/sources.yml b/roles/lib_openshift/src/sources.yml
index e9b6bf261..4636f6b9b 100644
--- a/roles/lib_openshift/src/sources.yml
+++ b/roles/lib_openshift/src/sources.yml
@@ -9,6 +9,16 @@ oc_adm_ca_server_cert.py:
- class/oc_adm_ca_server_cert.py
- ansible/oc_adm_ca_server_cert.py
+oc_adm_csr.py:
+- doc/generated
+- doc/license
+- lib/import.py
+- doc/csr
+- ../../lib_utils/src/class/yedit.py
+- lib/base.py
+- class/oc_adm_csr.py
+- ansible/oc_adm_csr.py
+
oc_adm_manage_node.py:
- doc/generated
- doc/license
diff --git a/roles/lib_openshift/src/test/integration/oc_adm_csr.yml b/roles/lib_openshift/src/test/integration/oc_adm_csr.yml
new file mode 100755
index 000000000..cad8e36f5
--- /dev/null
+++ b/roles/lib_openshift/src/test/integration/oc_adm_csr.yml
@@ -0,0 +1,28 @@
+#!/usr/bin/ansible-playbook --module-path=../../../library/
+# ./oc_adm_csr.yml -M ../../../library -e "cli_master_test=$OPENSHIFT_MASTER
+---
+- hosts: masters
+ gather_facts: no
+ user: root
+ tasks:
+ - name: list csrs
+ oc_adm_csr:
+ state: list
+ register: csrout
+
+ - debug: var=csrout
+
+ - name: list csrs
+ oc_adm_csr:
+ state: approve
+ nodes:
+ - ip-172-31-51-0-ec2-internal
+ - ip-172-31-51-246-ec2-internal
+ - ip-172-31-54-12-ec2-internal
+ - ip-172-31-58-173-ec2-internal
+ - ip-172-31-58-212-ec2-internal
+ - ip-172-31-51-246-ec2-internal
+ - ip-172-31-54-12-ec2-internal
+
+ register: csrout
+ - debug: var=csrout
diff --git a/roles/lib_openshift/src/test/integration/oc_configmap.yml b/roles/lib_openshift/src/test/integration/oc_configmap.yml
index c0d200e73..6a452ccec 100755
--- a/roles/lib_openshift/src/test/integration/oc_configmap.yml
+++ b/roles/lib_openshift/src/test/integration/oc_configmap.yml
@@ -55,7 +55,7 @@
config: "{{ filename }}"
from_literal:
foo: notbar
- deployment_type: online
+ deployment_type: openshift-enterprise
- name: fetch the updated configmap
oc_configmap:
@@ -70,7 +70,7 @@
assert:
that:
- cmout.results.results[0].metadata.name == 'configmaptest'
- - cmout.results.results[0].data.deployment_type == 'online'
+ - cmout.results.results[0].data.deployment_type == 'openshift-enterprise'
- cmout.results.results[0].data.foo == 'notbar'
###### end update test ###########
diff --git a/roles/lib_openshift/src/test/unit/test_oc_configmap.py b/roles/lib_openshift/src/test/unit/test_oc_configmap.py
index 318fd6167..27042c64b 100755
--- a/roles/lib_openshift/src/test/unit/test_oc_configmap.py
+++ b/roles/lib_openshift/src/test/unit/test_oc_configmap.py
@@ -79,7 +79,7 @@ class OCConfigMapTest(unittest.TestCase):
''' Testing a configmap create '''
params = copy.deepcopy(OCConfigMapTest.params)
params['from_file'] = {'test': '/root/file'}
- params['from_literal'] = {'foo': 'bar', 'deployment_type': 'online'}
+ params['from_literal'] = {'foo': 'bar', 'deployment_type': 'openshift-enterprise'}
configmap = '''{
"apiVersion": "v1",
@@ -100,7 +100,7 @@ class OCConfigMapTest(unittest.TestCase):
"apiVersion": "v1",
"data": {
"foo": "bar",
- "deployment_type": "online",
+ "deployment_type": "openshift-enterprise",
"test": "this is a file\\n"
},
"kind": "ConfigMap",
@@ -128,7 +128,7 @@ class OCConfigMapTest(unittest.TestCase):
self.assertTrue(results['changed'])
self.assertEqual(results['results']['results'][0]['metadata']['name'], 'configmap')
- self.assertEqual(results['results']['results'][0]['data']['deployment_type'], 'online')
+ self.assertEqual(results['results']['results'][0]['data']['deployment_type'], 'openshift-enterprise')
@unittest.skipIf(six.PY3, 'py2 test only')
@mock.patch('os.path.exists')
diff --git a/roles/lib_utils/library/iam_cert23.py b/roles/lib_utils/library/iam_cert23.py
new file mode 100644
index 000000000..07b3d3bdf
--- /dev/null
+++ b/roles/lib_utils/library/iam_cert23.py
@@ -0,0 +1,314 @@
+#!/usr/bin/python
+# pylint: skip-file
+# flake8: noqa
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+ANSIBLE_METADATA = {'metadata_version': '1.1',
+ 'status': ['preview'],
+ 'supported_by': 'community'}
+
+
+DOCUMENTATION = '''
+---
+module: iam_cert
+short_description: Manage server certificates for use on ELBs and CloudFront
+description:
+ - Allows for the management of server certificates
+version_added: "2.0"
+options:
+ name:
+ description:
+ - Name of certificate to add, update or remove.
+ required: true
+ new_name:
+ description:
+ - When state is present, this will update the name of the cert.
+ - The cert, key and cert_chain parameters will be ignored if this is defined.
+ new_path:
+ description:
+ - When state is present, this will update the path of the cert.
+ - The cert, key and cert_chain parameters will be ignored if this is defined.
+ state:
+ description:
+ - Whether to create(or update) or delete certificate.
+ - If new_path or new_name is defined, specifying present will attempt to make an update these.
+ required: true
+ choices: [ "present", "absent" ]
+ path:
+ description:
+ - When creating or updating, specify the desired path of the certificate.
+ default: "/"
+ cert_chain:
+ description:
+ - The path to, or content of the CA certificate chain in PEM encoded format.
+ As of 2.4 content is accepted. If the parameter is not a file, it is assumed to be content.
+ cert:
+ description:
+ - The path to, or content of the certificate body in PEM encoded format.
+ As of 2.4 content is accepted. If the parameter is not a file, it is assumed to be content.
+ key:
+ description:
+ - The path to, or content of the private key in PEM encoded format.
+ As of 2.4 content is accepted. If the parameter is not a file, it is assumed to be content.
+ dup_ok:
+ description:
+ - By default the module will not upload a certificate that is already uploaded into AWS.
+ If set to True, it will upload the certificate as long as the name is unique.
+ default: False
+
+
+requirements: [ "boto" ]
+author: Jonathan I. Davila
+extends_documentation_fragment:
+ - aws
+ - ec2
+'''
+
+EXAMPLES = '''
+# Basic server certificate upload from local file
+- iam_cert:
+ name: very_ssl
+ state: present
+ cert: "{{ lookup('file', 'path/to/cert') }}"
+ key: "{{ lookup('file', 'path/to/key') }}"
+ cert_chain: "{{ lookup('file', 'path/to/certchain') }}"
+
+# Basic server certificate upload
+- iam_cert:
+ name: very_ssl
+ state: present
+ cert: path/to/cert
+ key: path/to/key
+ cert_chain: path/to/certchain
+
+# Server certificate upload using key string
+- iam_cert:
+ name: very_ssl
+ state: present
+ path: "/a/cert/path/"
+ cert: body_of_somecert
+ key: vault_body_of_privcertkey
+ cert_chain: body_of_myverytrustedchain
+
+# Basic rename of existing certificate
+- iam_cert:
+ name: very_ssl
+ new_name: new_very_ssl
+ state: present
+
+'''
+from ansible.module_utils.basic import AnsibleModule
+from ansible.module_utils.ec2 import ec2_argument_spec, get_aws_connection_info, connect_to_aws
+import os
+
+try:
+ import boto
+ import boto.iam
+ import boto.ec2
+ HAS_BOTO = True
+except ImportError:
+ HAS_BOTO = False
+
+
+def boto_exception(err):
+ '''generic error message handler'''
+ if hasattr(err, 'error_message'):
+ error = err.error_message
+ elif hasattr(err, 'message'):
+ error = err.message
+ else:
+ error = '%s: %s' % (Exception, err)
+
+ return error
+
+
+def cert_meta(iam, name):
+ certificate = iam.get_server_certificate(name).get_server_certificate_result.server_certificate
+ ocert = certificate.certificate_body
+ opath = certificate.server_certificate_metadata.path
+ ocert_id = certificate.server_certificate_metadata.server_certificate_id
+ upload_date = certificate.server_certificate_metadata.upload_date
+ exp = certificate.server_certificate_metadata.expiration
+ arn = certificate.server_certificate_metadata.arn
+ return opath, ocert, ocert_id, upload_date, exp, arn
+
+
+def dup_check(module, iam, name, new_name, cert, orig_cert_names, orig_cert_bodies, dup_ok):
+ update = False
+
+ # IAM cert names are case insensitive
+ names_lower = [n.lower() for n in [name, new_name] if n is not None]
+ orig_cert_names_lower = [ocn.lower() for ocn in orig_cert_names]
+
+ if any(ct in orig_cert_names_lower for ct in names_lower):
+ for i_name in names_lower:
+ if cert is not None:
+ try:
+ c_index = orig_cert_names_lower.index(i_name)
+ except NameError:
+ continue
+ else:
+ # NOTE: remove the carriage return to strictly compare the cert bodies.
+ slug_cert = cert.replace('\r', '')
+ slug_orig_cert_bodies = orig_cert_bodies[c_index].replace('\r', '')
+ if slug_orig_cert_bodies == slug_cert:
+ update = True
+ break
+ elif slug_cert.startswith(slug_orig_cert_bodies):
+ update = True
+ break
+ elif slug_orig_cert_bodies != slug_cert:
+ module.fail_json(changed=False, msg='A cert with the name %s already exists and'
+ ' has a different certificate body associated'
+ ' with it. Certificates cannot have the same name' % orig_cert_names[c_index])
+ else:
+ update = True
+ break
+ elif cert in orig_cert_bodies and not dup_ok:
+ for crt_name, crt_body in zip(orig_cert_names, orig_cert_bodies):
+ if crt_body == cert:
+ module.fail_json(changed=False, msg='This certificate already'
+ ' exists under the name %s' % crt_name)
+
+ return update
+
+
+def cert_action(module, iam, name, cpath, new_name, new_path, state,
+ cert, key, cert_chain, orig_cert_names, orig_cert_bodies, dup_ok):
+ if state == 'present':
+ update = dup_check(module, iam, name, new_name, cert, orig_cert_names,
+ orig_cert_bodies, dup_ok)
+ if update:
+ opath, ocert, ocert_id, upload_date, exp, arn = cert_meta(iam, name)
+ changed = True
+ if new_name and new_path:
+ iam.update_server_cert(name, new_cert_name=new_name, new_path=new_path)
+ module.exit_json(changed=changed, original_name=name, new_name=new_name,
+ original_path=opath, new_path=new_path, cert_body=ocert,
+ upload_date=upload_date, expiration_date=exp, arn=arn)
+ elif new_name and not new_path:
+ iam.update_server_cert(name, new_cert_name=new_name)
+ module.exit_json(changed=changed, original_name=name, new_name=new_name,
+ cert_path=opath, cert_body=ocert,
+ upload_date=upload_date, expiration_date=exp, arn=arn)
+ elif not new_name and new_path:
+ iam.update_server_cert(name, new_path=new_path)
+ module.exit_json(changed=changed, name=new_name,
+ original_path=opath, new_path=new_path, cert_body=ocert,
+ upload_date=upload_date, expiration_date=exp, arn=arn)
+ else:
+ changed = False
+ module.exit_json(changed=changed, name=name, cert_path=opath, cert_body=ocert,
+ upload_date=upload_date, expiration_date=exp, arn=arn,
+ msg='No new path or name specified. No changes made')
+ else:
+ changed = True
+ iam.upload_server_cert(name, cert, key, cert_chain=cert_chain, path=cpath)
+ opath, ocert, ocert_id, upload_date, exp, arn = cert_meta(iam, name)
+ module.exit_json(changed=changed, name=name, cert_path=opath, cert_body=ocert,
+ upload_date=upload_date, expiration_date=exp, arn=arn)
+ elif state == 'absent':
+ if name in orig_cert_names:
+ changed = True
+ iam.delete_server_cert(name)
+ module.exit_json(changed=changed, deleted_cert=name)
+ else:
+ changed = False
+ module.exit_json(changed=changed, msg='Certificate with the name %s already absent' % name)
+
+
+def load_data(cert, key, cert_chain):
+ # if paths are provided rather than lookups read the files and return the contents
+ if cert and os.path.isfile(cert):
+ cert = open(cert, 'r').read().rstrip()
+ if key and os.path.isfile(key):
+ key = open(key, 'r').read().rstrip()
+ if cert_chain and os.path.isfile(cert_chain):
+ cert_chain = open(cert_chain, 'r').read()
+ return cert, key, cert_chain
+
+
+def main():
+ argument_spec = ec2_argument_spec()
+ argument_spec.update(dict(
+ state=dict(required=True, choices=['present', 'absent']),
+ name=dict(),
+ cert=dict(),
+ key=dict(no_log=True),
+ cert_chain=dict(),
+ new_name=dict(),
+ path=dict(default='/'),
+ new_path=dict(),
+ dup_ok=dict(type='bool')
+ )
+ )
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ mutually_exclusive=[
+ ['new_path', 'key'],
+ ['new_path', 'cert'],
+ ['new_path', 'cert_chain'],
+ ['new_name', 'key'],
+ ['new_name', 'cert'],
+ ['new_name', 'cert_chain'],
+ ],
+ )
+
+ if not HAS_BOTO:
+ module.fail_json(msg="Boto is required for this module")
+
+ region, ec2_url, aws_connect_kwargs = get_aws_connection_info(module)
+
+ try:
+ if region:
+ iam = connect_to_aws(boto.iam, region, **aws_connect_kwargs)
+ else:
+ iam = boto.iam.connection.IAMConnection(**aws_connect_kwargs)
+ except boto.exception.NoAuthHandlerFound as e:
+ module.fail_json(msg=str(e))
+
+ state = module.params.get('state')
+ name = module.params.get('name')
+ path = module.params.get('path')
+ new_name = module.params.get('new_name')
+ new_path = module.params.get('new_path')
+ dup_ok = module.params.get('dup_ok')
+ if state == 'present' and not new_name and not new_path:
+ cert, key, cert_chain = load_data(cert=module.params.get('cert'),
+ key=module.params.get('key'),
+ cert_chain=module.params.get('cert_chain'))
+ else:
+ cert = key = cert_chain = None
+
+ orig_cert_names = [ctb['server_certificate_name'] for ctb in
+ iam.get_all_server_certs().list_server_certificates_result.server_certificate_metadata_list]
+ orig_cert_bodies = [iam.get_server_certificate(thing).get_server_certificate_result.certificate_body
+ for thing in orig_cert_names]
+ if new_name == name:
+ new_name = None
+ if new_path == path:
+ new_path = None
+
+ changed = False
+ try:
+ cert_action(module, iam, name, path, new_name, new_path, state,
+ cert, key, cert_chain, orig_cert_names, orig_cert_bodies, dup_ok)
+ except boto.exception.BotoServerError as err:
+ module.fail_json(changed=changed, msg=str(err), debug=[cert, key])
+
+
+if __name__ == '__main__':
+ main()
diff --git a/roles/lib_utils/library/oo_iam_kms.py b/roles/lib_utils/library/oo_iam_kms.py
new file mode 100644
index 000000000..c85745f01
--- /dev/null
+++ b/roles/lib_utils/library/oo_iam_kms.py
@@ -0,0 +1,172 @@
+#!/usr/bin/env python
+'''
+ansible module for creating AWS IAM KMS keys
+'''
+# vim: expandtab:tabstop=4:shiftwidth=4
+#
+# AWS IAM KMS ansible module
+#
+#
+# Copyright 2016 Red Hat Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# Jenkins environment doesn't have all the required libraries
+# pylint: disable=import-error
+import time
+import boto3
+# Ansible modules need this wildcard import
+# pylint: disable=unused-wildcard-import, wildcard-import, redefined-builtin
+from ansible.module_utils.basic import AnsibleModule
+
+AWS_ALIAS_URL = "http://docs.aws.amazon.com/kms/latest/developerguide/programming-aliases.html"
+
+
+class AwsIamKms(object):
+ '''
+ ansible module for AWS IAM KMS
+ '''
+
+ def __init__(self):
+ ''' constructor '''
+ self.module = None
+ self.kms_client = None
+ self.aliases = None
+
+ @staticmethod
+ def valid_alias_name(user_alias):
+ ''' AWS KMS aliases must start with 'alias/' '''
+ valid_start = 'alias/'
+ if user_alias.startswith(valid_start):
+ return True
+
+ return False
+
+ def get_all_kms_info(self):
+ '''fetch all kms info and return them
+
+ list_keys doesn't have information regarding aliases
+ list_aliases doesn't have the full kms arn
+
+ fetch both and join them on the targetKeyId
+ '''
+ aliases = self.kms_client.list_aliases()['Aliases']
+ keys = self.kms_client.list_keys()['Keys']
+
+ for alias in aliases:
+ for key in keys:
+ if 'TargetKeyId' in alias and 'KeyId' in key:
+ if alias['TargetKeyId'] == key['KeyId']:
+ alias.update(key)
+
+ return aliases
+
+ def get_kms_entry(self, user_alias, alias_list):
+ ''' return single alias details from list of aliases '''
+ for alias in alias_list:
+ if user_alias == alias.get('AliasName', False):
+ return alias
+
+ msg = "Did not find alias {}".format(user_alias)
+ self.module.exit_json(failed=True, results=msg)
+
+ @staticmethod
+ def exists(user_alias, alias_list):
+ ''' Check if KMS alias already exists '''
+ for alias in alias_list:
+ if user_alias == alias.get('AliasName'):
+ return True
+
+ return False
+
+ def main(self):
+ ''' entry point for module '''
+
+ self.module = AnsibleModule(
+ argument_spec=dict(
+ state=dict(default='list', choices=['list', 'present'], type='str'),
+ region=dict(default=None, required=True, type='str'),
+ alias=dict(default=None, type='str'),
+ # description default cannot be None
+ description=dict(default='', type='str'),
+ aws_access_key=dict(default=None, type='str'),
+ aws_secret_key=dict(default=None, type='str'),
+ ),
+ )
+
+ state = self.module.params['state']
+ aws_access_key = self.module.params['aws_access_key']
+ aws_secret_key = self.module.params['aws_secret_key']
+ if aws_access_key and aws_secret_key:
+ boto3.setup_default_session(aws_access_key_id=aws_access_key,
+ aws_secret_access_key=aws_secret_key,
+ region_name=self.module.params['region'])
+ else:
+ boto3.setup_default_session(region_name=self.module.params['region'])
+
+ self.kms_client = boto3.client('kms')
+
+ aliases = self.get_all_kms_info()
+
+ if state == 'list':
+ if self.module.params['alias'] is not None:
+ user_kms = self.get_kms_entry(self.module.params['alias'],
+ aliases)
+ self.module.exit_json(changed=False, results=user_kms,
+ state="list")
+ else:
+ self.module.exit_json(changed=False, results=aliases,
+ state="list")
+
+ if state == 'present':
+
+ # early sanity check to make sure the alias name conforms with
+ # AWS alias name requirements
+ if not self.valid_alias_name(self.module.params['alias']):
+ self.module.exit_json(failed=True, changed=False,
+ results="Alias must start with the prefix " +
+ "'alias/'. Please see " + AWS_ALIAS_URL,
+ state='present')
+
+ if not self.exists(self.module.params['alias'], aliases):
+ # if we didn't find it, create it
+ response = self.kms_client.create_key(KeyUsage='ENCRYPT_DECRYPT',
+ Description=self.module.params['description'])
+ kid = response['KeyMetadata']['KeyId']
+ response = self.kms_client.create_alias(AliasName=self.module.params['alias'],
+ TargetKeyId=kid)
+ # sleep for a bit so that the KMS data can be queried
+ time.sleep(10)
+ # get details for newly created KMS entry
+ new_alias_list = self.kms_client.list_aliases()['Aliases']
+ user_kms = self.get_kms_entry(self.module.params['alias'],
+ new_alias_list)
+
+ self.module.exit_json(changed=True, results=user_kms,
+ state='present')
+
+ # already exists, normally we would check whether we need to update it
+ # but this module isn't written to allow changing the alias name
+ # or changing whether the key is enabled/disabled
+ user_kms = self.get_kms_entry(self.module.params['alias'], aliases)
+ self.module.exit_json(changed=False, results=user_kms,
+ state="present")
+
+ self.module.exit_json(failed=True,
+ changed=False,
+ results='Unknown state passed. %s' % state,
+ state="unknown")
+
+
+if __name__ == '__main__':
+ AwsIamKms().main()
diff --git a/roles/lib_utils/library/repoquery.py b/roles/lib_utils/library/repoquery.py
index 95a305b58..e5ac1f74f 100644
--- a/roles/lib_utils/library/repoquery.py
+++ b/roles/lib_utils/library/repoquery.py
@@ -35,6 +35,7 @@ import os # noqa: F401
import re # noqa: F401
import shutil # noqa: F401
import tempfile # noqa: F401
+import time # noqa: F401
try:
import ruamel.yaml as yaml # noqa: F401
@@ -618,17 +619,22 @@ def main():
show_duplicates=dict(default=False, required=False, type='bool'),
match_version=dict(default=None, required=False, type='str'),
ignore_excluders=dict(default=False, required=False, type='bool'),
+ retries=dict(default=4, required=False, type='int'),
+ retry_interval=dict(default=5, required=False, type='int'),
),
supports_check_mode=False,
required_if=[('show_duplicates', True, ['name'])],
)
- rval = Repoquery.run_ansible(module.params, module.check_mode)
-
- if 'failed' in rval:
- module.fail_json(**rval)
-
- module.exit_json(**rval)
+ tries = 1
+ while True:
+ rval = Repoquery.run_ansible(module.params, module.check_mode)
+ if 'failed' not in rval:
+ module.exit_json(**rval)
+ elif tries > module.params['retries']:
+ module.fail_json(**rval)
+ tries += 1
+ time.sleep(module.params['retry_interval'])
if __name__ == "__main__":
diff --git a/roles/lib_utils/library/yedit.py b/roles/lib_utils/library/yedit.py
index baf72fe47..921bca074 100644
--- a/roles/lib_utils/library/yedit.py
+++ b/roles/lib_utils/library/yedit.py
@@ -35,6 +35,7 @@ import os # noqa: F401
import re # noqa: F401
import shutil # noqa: F401
import tempfile # noqa: F401
+import time # noqa: F401
try:
import ruamel.yaml as yaml # noqa: F401
diff --git a/roles/lib_utils/src/ansible/repoquery.py b/roles/lib_utils/src/ansible/repoquery.py
index 40773b1c1..5f5b93639 100644
--- a/roles/lib_utils/src/ansible/repoquery.py
+++ b/roles/lib_utils/src/ansible/repoquery.py
@@ -19,17 +19,22 @@ def main():
show_duplicates=dict(default=False, required=False, type='bool'),
match_version=dict(default=None, required=False, type='str'),
ignore_excluders=dict(default=False, required=False, type='bool'),
+ retries=dict(default=4, required=False, type='int'),
+ retry_interval=dict(default=5, required=False, type='int'),
),
supports_check_mode=False,
required_if=[('show_duplicates', True, ['name'])],
)
- rval = Repoquery.run_ansible(module.params, module.check_mode)
-
- if 'failed' in rval:
- module.fail_json(**rval)
-
- module.exit_json(**rval)
+ tries = 1
+ while True:
+ rval = Repoquery.run_ansible(module.params, module.check_mode)
+ if 'failed' not in rval:
+ module.exit_json(**rval)
+ elif tries > module.params['retries']:
+ module.fail_json(**rval)
+ tries += 1
+ time.sleep(module.params['retry_interval'])
if __name__ == "__main__":
diff --git a/roles/lib_utils/src/lib/import.py b/roles/lib_utils/src/lib/import.py
index 567f8c9e0..07a04b7ae 100644
--- a/roles/lib_utils/src/lib/import.py
+++ b/roles/lib_utils/src/lib/import.py
@@ -10,6 +10,7 @@ import os # noqa: F401
import re # noqa: F401
import shutil # noqa: F401
import tempfile # noqa: F401
+import time # noqa: F401
try:
import ruamel.yaml as yaml # noqa: F401
diff --git a/roles/lib_utils/tasks/main.yml b/roles/lib_utils/tasks/main.yml
deleted file mode 100644
index ed97d539c..000000000
--- a/roles/lib_utils/tasks/main.yml
+++ /dev/null
@@ -1 +0,0 @@
----
diff --git a/roles/nuage_common/defaults/main.yaml b/roles/nuage_common/defaults/main.yaml
index a7803c0ee..919e3aa7b 100644
--- a/roles/nuage_common/defaults/main.yaml
+++ b/roles/nuage_common/defaults/main.yaml
@@ -10,5 +10,8 @@ nuage_ca_serial: "{{ nuage_ca_dir }}/nuageMonCA.serial.txt"
nuage_master_mon_dir: /usr/share/nuage-openshift-monitor
nuage_node_plugin_dir: /usr/share/vsp-openshift
+nuage_node_cni_bin_dir: /opt/cni/bin
+nuage_node_cni_netconf_dir: /etc/cni/net.d
+
nuage_mon_rest_server_port: "{{ nuage_openshift_monitor_rest_server_port | default('9443') }}"
nuage_mon_cert_validity_period: "{{ nuage_cert_validity_period | default('3650') }}"
diff --git a/roles/nuage_common/tasks/main.yml b/roles/nuage_common/tasks/main.yml
new file mode 100644
index 000000000..6c8c9f8d2
--- /dev/null
+++ b/roles/nuage_common/tasks/main.yml
@@ -0,0 +1,27 @@
+---
+- name: Set the Nuage plugin openshift directory fact to handle Atomic host install
+ set_fact:
+ nuage_node_plugin_dir: /var/usr/share/vsp-openshift
+ when: openshift.common.is_atomic | bool
+
+- name: Set the Nuage CNI network config directory fact to handle Atomic host install
+ set_fact:
+ nuage_node_cni_netconf_dir: /var/etc/cni/net.d/
+ when: openshift.common.is_atomic | bool
+
+- name: Set the Nuage CNI binary directory fact to handle Atomic host install
+ set_fact:
+ nuage_node_cni_bin_dir: /var/opt/cni/bin/
+ when: openshift.common.is_atomic | bool
+
+- name: Assure CNI plugin config dir exists before daemon set install
+ become: yes
+ file: path="{{ nuage_node_plugin_dir }}" state=directory
+
+- name: Assure CNI netconf directory exists before daemon set install
+ become: yes
+ file: path="{{ nuage_node_cni_netconf_dir }}" state=directory
+
+- name: Assure CNI plugin binary directory exists before daemon set install
+ become: yes
+ file: path="{{ nuage_node_cni_bin_dir }}" state=directory
diff --git a/roles/nuage_master/defaults/main.yml b/roles/nuage_master/defaults/main.yml
index ffab25775..5f1d8686a 100644
--- a/roles/nuage_master/defaults/main.yml
+++ b/roles/nuage_master/defaults/main.yml
@@ -1,6 +1,6 @@
---
-r_nuage_master_firewall_enabled: True
-r_nuage_master_use_firewalld: False
+r_nuage_master_firewall_enabled: "{{ os_firewall_enabled | default(True) }}"
+r_nuage_master_use_firewalld: "{{ os_firewall_use_firewalld | default(False) }}"
nuage_mon_rest_server_port: '9443'
diff --git a/roles/nuage_master/handlers/main.yaml b/roles/nuage_master/handlers/main.yaml
index ad7bbb111..21da6b953 100644
--- a/roles/nuage_master/handlers/main.yaml
+++ b/roles/nuage_master/handlers/main.yaml
@@ -1,8 +1,4 @@
---
-- name: restart nuage-openshift-monitor
- become: yes
- systemd: name=nuage-openshift-monitor state=restarted
-
- name: restart master api
systemd: name={{ openshift.common.service_type }}-master-api state=restarted
when: >
diff --git a/roles/nuage_master/tasks/main.yaml b/roles/nuage_master/tasks/main.yaml
index d0363c981..f3c487132 100644
--- a/roles/nuage_master/tasks/main.yaml
+++ b/roles/nuage_master/tasks/main.yaml
@@ -3,17 +3,64 @@
include: firewall.yml
static: yes
+- name: Set the Nuage certificate directory fact for Atomic hosts
+ set_fact:
+ cert_output_dir: /var/usr/share/nuage-openshift-monitor
+ when: openshift.common.is_atomic | bool
+
+- name: Set the Nuage kubeconfig file path fact for Atomic hosts
+ set_fact:
+ kube_config: /var/usr/share/nuage-openshift-monitor/nuage.kubeconfig
+ when: openshift.common.is_atomic | bool
+
+- name: Set the Nuage monitor yaml location fact for Atomic hosts
+ set_fact:
+ kubemon_yaml: /var/usr/share/nuage-openshift-monitor/nuage-openshift-monitor.yaml
+ when: openshift.common.is_atomic | bool
+
+- name: Set the Nuage monitor certs location fact for Atomic hosts
+ set_fact:
+ nuage_master_crt_dir: /var/usr/share/nuage-openshift-monitor/
+ when: openshift.common.is_atomic | bool
+
+- name: Set the Nuage master config directory for daemon sets install
+ set_fact:
+ nuage_master_config_dsets_mount_dir: /var/usr/share/
+ when: master_host_type == "is_atomic"
+
+- name: Set the Nuage node config directory for daemon sets install
+ set_fact:
+ nuage_node_config_dsets_mount_dir: /var/usr/share/
+ when: slave_host_type == "is_atomic"
+
+- name: Set the Nuage CNI plugin binary directory for daemon sets install
+ set_fact:
+ nuage_cni_bin_dsets_mount_dir: /var/opt/cni/bin
+ when: openshift.common.is_atomic | bool
+
- name: Create directory /usr/share/nuage-openshift-monitor
become: yes
file: path=/usr/share/nuage-openshift-monitor state=directory
+ when: not openshift.common.is_atomic | bool
-- name: Create the log directory
+- name: Create directory /var/usr/share/nuage-openshift-monitor
become: yes
- file: path={{ nuage_mon_rest_server_logdir }} state=directory
+ file: path=/var/usr/share/nuage-openshift-monitor state=directory
+ when: openshift.common.is_atomic | bool
+
+- name: Create directory /var/usr/bin for monitor binary on atomic
+ become: yes
+ file: path=/var/usr/bin state=directory
+ when: openshift.common.is_atomic | bool
-- name: Install Nuage Openshift Monitor
+- name: Create CNI bin directory /var/opt/cni/bin
become: yes
- yum: name={{ nuage_openshift_rpm }} state=present
+ file: path=/var/opt/cni/bin state=directory
+ when: openshift.common.is_atomic | bool
+
+- name: Create the log directory
+ become: yes
+ file: path={{ nuage_mon_rest_server_logdir }} state=directory
- include: serviceaccount.yml
@@ -45,10 +92,32 @@
become: yes
copy: src="{{ vsd_user_key_file }}" dest="{{ cert_output_dir }}/{{ vsd_user_key_file | basename }}"
-- name: Create nuage-openshift-monitor.yaml
+- name: Create Nuage master daemon set yaml file
+ become: yes
+ template: src=nuage-master-config-daemonset.j2 dest=/etc/nuage-master-config-daemonset.yaml owner=root mode=0644
+
+- name: Create Nuage node daemon set yaml file
become: yes
- template: src=nuage-openshift-monitor.j2 dest=/usr/share/nuage-openshift-monitor/nuage-openshift-monitor.yaml owner=root mode=0644
+ template: src=nuage-node-config-daemonset.j2 dest=/etc/nuage-node-config-daemonset.yaml owner=root mode=0644
+
+- name: Add the service account to the privileged scc to have root permissions
+ shell: oc adm policy add-scc-to-user privileged system:serviceaccount:openshift-infra:daemonset-controller
+ ignore_errors: true
+ when: inventory_hostname == groups.oo_first_master.0
+
+- name: Spawn Nuage Master monitor daemon sets pod
+ shell: oc create -f /etc/nuage-master-config-daemonset.yaml
+ ignore_errors: true
+ when: inventory_hostname == groups.oo_first_master.0
+
+- name: Spawn Nuage CNI daemon sets pod
+ shell: oc create -f /etc/nuage-node-config-daemonset.yaml
+ ignore_errors: true
+ when: inventory_hostname == groups.oo_first_master.0
+
+- name: Restart daemons
+ command: /bin/true
notify:
- restart master api
- restart master controllers
- - restart nuage-openshift-monitor
+ ignore_errors: true
diff --git a/roles/nuage_master/templates/nuage-master-config-daemonset.j2 b/roles/nuage_master/templates/nuage-master-config-daemonset.j2
new file mode 100755
index 000000000..612d689c2
--- /dev/null
+++ b/roles/nuage_master/templates/nuage-master-config-daemonset.j2
@@ -0,0 +1,111 @@
+# This ConfigMap is used to configure Nuage VSP configuration on master nodes
+kind: ConfigMap
+apiVersion: v1
+metadata:
+ name: nuage-master-config
+ namespace: kube-system
+data:
+ # This will generate the required Nuage configuration
+ # on master nodes
+ monitor_yaml_config: |
+
+ # .kubeconfig that includes the nuage service account
+ kubeConfig: {{ nuage_master_crt_dir }}/nuage.kubeconfig
+ # name of the nuage service account, or another account with 'cluster-reader'
+ # permissions
+ # Openshift master config file
+ masterConfig: /etc/origin/master/master-config.yaml
+ # URL of the VSD Architect
+ vsdApiUrl: {{ vsd_api_url }}
+ # API version to query against. Usually "v3_2"
+ vspVersion: {{ vsp_version }}
+ # Name of the enterprise in which pods will reside
+ enterpriseName: {{ enterprise }}
+ # Name of the domain in which pods will reside
+ domainName: {{ domain }}
+ # VSD generated user certificate file location on master node
+ userCertificateFile: {{ nuage_master_crt_dir }}/{{ vsd_user }}.pem
+ # VSD generated user key file location on master node
+ userKeyFile: {{ nuage_master_crt_dir }}/{{ vsd_user }}-Key.pem
+ # Location where logs should be saved
+ log_dir: /var/log/nuage-openshift-monitor
+ # Monitor rest server parameters
+ # Logging level for the nuage openshift monitor
+ # allowed options are: 0 => INFO, 1 => WARNING, 2 => ERROR, 3 => FATAL
+ logLevel: 0
+ # Parameters related to the nuage monitor REST server
+ nuageMonServer:
+ URL: 0.0.0.0:9443
+ certificateDirectory: {{ nuage_master_crt_dir }}
+ # etcd config required for HA
+ etcdClientConfig:
+ ca: {{ nuage_master_crt_dir }}/nuageMonCA.crt
+ certFile: {{ nuage_master_crt_dir }}/nuageMonServer.crt
+ keyFile: {{ nuage_master_crt_dir }}/master.etcd-client.key
+ urls:
+ {% for etcd_url in openshift.master.etcd_urls %}
+ - {{ etcd_url }}
+ {% endfor %}
+
+---
+
+# This manifest installs Nuage master node configuration on
+# each Nuage master node in a cluster.
+kind: DaemonSet
+apiVersion: extensions/v1beta1
+metadata:
+ name: nuage-master-config
+ namespace: kube-system
+ labels:
+ k8s-app: nuage-master-config
+spec:
+ selector:
+ matchLabels:
+ k8s-app: nuage-master-config
+ template:
+ metadata:
+ labels:
+ k8s-app: nuage-master-config
+ spec:
+ hostNetwork: true
+ tolerations:
+ - key: node-role.kubernetes.io/master
+ effect: NoSchedule
+ operator: Exists
+ nodeSelector:
+ install-monitor: "true"
+ containers:
+ # This container configures Nuage Master node
+ - name: install-nuage-master-config
+ image: nuage/master:{{ nuage_monitor_container_image_version }}
+ ports:
+ - containerPort: 9443
+ hostPort: 9443
+ command: ["/configure-master.sh"]
+ args: ["ose", "{{ master_host_type }}"]
+ securityContext:
+ privileged: true
+ env:
+ # nuage-openshift-monitor.yaml config to install on each slave node.
+ - name: NUAGE_MASTER_VSP_CONFIG
+ valueFrom:
+ configMapKeyRef:
+ name: nuage-master-config
+ key: monitor_yaml_config
+ volumeMounts:
+ - mountPath: /var/log
+ name: cni-log-dir
+ - mountPath: {{ nuage_master_config_dsets_mount_dir }}
+ name: usr-share-dir
+ - mountPath: /etc/origin/
+ name: master-config-dir
+ volumes:
+ - name: cni-log-dir
+ hostPath:
+ path: /var/log
+ - name: usr-share-dir
+ hostPath:
+ path: {{ nuage_master_config_dsets_mount_dir }}
+ - name: master-config-dir
+ hostPath:
+ path: /etc/origin/
diff --git a/roles/nuage_master/templates/nuage-node-config-daemonset.j2 b/roles/nuage_master/templates/nuage-node-config-daemonset.j2
new file mode 100755
index 000000000..02e9a1563
--- /dev/null
+++ b/roles/nuage_master/templates/nuage-node-config-daemonset.j2
@@ -0,0 +1,206 @@
+# This ConfigMap is used to configure Nuage VSP configuration
+kind: ConfigMap
+apiVersion: v1
+metadata:
+ name: nuage-config
+ namespace: kube-system
+data:
+ # This will generate the required Nuage vsp-openshift.yaml
+ # config on each slave node
+ plugin_yaml_config: |
+ clientCert: {{ nuage_node_config_dsets_mount_dir }}/vsp-openshift/client.crt
+ # The key to the certificate in clientCert above
+ clientKey: {{ nuage_node_config_dsets_mount_dir }}/vsp-openshift/client.key
+ # The certificate authority's certificate for the local kubelet. Usually the
+ # same as the CA cert used to create the client Cert/Key pair.
+ CACert: {{ nuage_node_config_dsets_mount_dir }}/vsp-openshift/ca.crt
+ # Name of the enterprise in which pods will reside
+ enterpriseName: {{ enterprise }}
+ # Name of the domain in which pods will reside
+ domainName: {{ domain }}
+ # Name of the VSD user in admin group
+ vsdUser: {{ vsd_user }}
+ # IP address and port number of master API server
+ masterApiServer: {{ api_server_url }}
+ # REST server URL
+ nuageMonRestServer: {{ nuage_mon_rest_server_url }}
+ # Bridge name for the docker bridge
+ dockerBridgeName: docker0
+ # Certificate for connecting to the openshift monitor REST api
+ nuageMonClientCert: {{ nuage_node_config_dsets_mount_dir }}/vsp-openshift/nuageMonClient.crt
+ # Key to the certificate in restClientCert
+ nuageMonClientKey: {{ nuage_node_config_dsets_mount_dir }}/vsp-openshift/nuageMonClient.key
+ # CA certificate for verifying the master's rest server
+ nuageMonServerCA: {{ nuage_node_config_dsets_mount_dir }}/vsp-openshift/nuageMonCA.crt
+ # Nuage vport mtu size
+ interfaceMTU: {{ nuage_vport_mtu }}
+ # Logging level for the plugin
+ # allowed options are: "dbg", "info", "warn", "err", "emer", "off"
+ logLevel: 3
+
+ # This will generate the required Nuage CNI yaml configuration
+ cni_yaml_config: |
+ vrsendpoint: "/var/run/openvswitch/db.sock"
+ vrsbridge: "alubr0"
+ monitorinterval: 60
+ cniversion: 0.2.0
+ loglevel: "info"
+ portresolvetimer: 60
+ logfilesize: 1
+ vrsconnectionchecktimer: 180
+ mtu: 1450
+ staleentrytimeout: 600
+
+---
+
+# This manifest installs Nuage CNI plugins and network config on
+# each worker node in Openshift cluster
+kind: DaemonSet
+apiVersion: extensions/v1beta1
+metadata:
+ name: nuage-cni-ds
+ namespace: kube-system
+ labels:
+ k8s-app: nuage-cni-ds
+spec:
+ selector:
+ matchLabels:
+ k8s-app: nuage-cni-ds
+ template:
+ metadata:
+ labels:
+ k8s-app: nuage-cni-ds
+ spec:
+ hostNetwork: true
+ tolerations:
+ - key: node-role.kubernetes.io/master
+ effect: NoSchedule
+ operator: Exists
+ containers:
+ # This container installs Nuage CNI binaries
+ # and CNI network config file on each node.
+ - name: install-nuage-cni
+ image: nuage/cni:{{ nuage_cni_container_image_version }}
+ command: ["/install-cni.sh"]
+ args: ["nuage-cni-openshift", "{{ slave_host_type }}"]
+ securityContext:
+ privileged: true
+ env:
+ # Nuage vsp-openshift.yaml config to install on each slave node.
+ - name: NUAGE_VSP_CONFIG
+ valueFrom:
+ configMapKeyRef:
+ name: nuage-config
+ key: plugin_yaml_config
+ # Nuage nuage-cni.yaml config to install on each slave node.
+ - name: NUAGE_CNI_YAML_CONFIG
+ valueFrom:
+ configMapKeyRef:
+ name: nuage-config
+ key: cni_yaml_config
+ # Nuage cluster network CIDR for iptables configuration
+ - name: NUAGE_CLUSTER_NW_CIDR
+ value: "{{ hostvars[groups.oo_first_master.0].openshift.master.sdn_cluster_network_cidr }}"
+ volumeMounts:
+ - mountPath: /host/opt/cni/bin
+ name: cni-bin-dir
+ - mountPath: /host/etc/cni/net.d
+ name: cni-net-dir
+ - mountPath: /etc/default
+ name: cni-yaml-dir
+ - mountPath: /var/run
+ name: var-run-dir
+ - mountPath: /var/log
+ name: cni-log-dir
+ - mountPath: {{ nuage_node_config_dsets_mount_dir }}
+ name: usr-share-dir
+ volumes:
+ - name: cni-bin-dir
+ hostPath:
+ path: {{ nuage_cni_bin_dsets_mount_dir }}
+ - name: cni-net-dir
+ hostPath:
+ path: {{ nuage_cni_netconf_dsets_mount_dir }}
+ - name: cni-yaml-dir
+ hostPath:
+ path: /etc/default
+ - name: var-run-dir
+ hostPath:
+ path: /var/run
+ - name: cni-log-dir
+ hostPath:
+ path: /var/log
+ - name: usr-share-dir
+ hostPath:
+ path: {{ nuage_node_config_dsets_mount_dir }}
+
+---
+
+# This manifest installs Nuage VRS on
+# each worker node in an Openshift cluster.
+kind: DaemonSet
+apiVersion: extensions/v1beta1
+metadata:
+ name: nuage-vrs-ds
+ namespace: kube-system
+ labels:
+ k8s-app: nuage-vrs-ds
+spec:
+ selector:
+ matchLabels:
+ k8s-app: nuage-vrs-ds
+ updateStrategy:
+ type: RollingUpdate
+ template:
+ metadata:
+ labels:
+ k8s-app: nuage-vrs-ds
+ spec:
+ hostNetwork: true
+ tolerations:
+ - key: node-role.kubernetes.io/master
+ effect: NoSchedule
+ operator: Exists
+ containers:
+ # This container installs Nuage VRS running as a
+ # container on each worker node
+ - name: install-nuage-vrs
+ image: nuage/vrs:{{ nuage_vrs_container_image_version }}
+ securityContext:
+ privileged: true
+ env:
+ # Configure parameters for VRS openvswitch file
+ - name: NUAGE_ACTIVE_CONTROLLER
+ value: "{{ vsc_active_ip }}"
+ - name: NUAGE_STANDBY_CONTROLLER
+ value: "{{ vsc_standby_ip }}"
+ - name: NUAGE_PLATFORM
+ value: '"kvm, k8s"'
+ - name: NUAGE_K8S_SERVICE_IPV4_SUBNET
+ value: '192.168.0.0\/16'
+ - name: NUAGE_NETWORK_UPLINK_INTF
+ value: "eth0"
+ volumeMounts:
+ - mountPath: /var/run
+ name: vrs-run-dir
+ - mountPath: /var/log
+ name: vrs-log-dir
+ - mountPath: /sys/module
+ name: sys-mod-dir
+ readOnly: true
+ - mountPath: /lib/modules
+ name: lib-mod-dir
+ readOnly: true
+ volumes:
+ - name: vrs-run-dir
+ hostPath:
+ path: /var/run
+ - name: vrs-log-dir
+ hostPath:
+ path: /var/log
+ - name: sys-mod-dir
+ hostPath:
+ path: /sys/module
+ - name: lib-mod-dir
+ hostPath:
+ path: /lib/modules
diff --git a/roles/nuage_master/templates/nuage-openshift-monitor.j2 b/roles/nuage_master/templates/nuage-openshift-monitor.j2
deleted file mode 100644
index e077128a4..000000000
--- a/roles/nuage_master/templates/nuage-openshift-monitor.j2
+++ /dev/null
@@ -1,41 +0,0 @@
-# .kubeconfig that includes the nuage service account
-kubeConfig: {{ kube_config }}
-# name of the nuage service account, or another account with 'cluster-reader'
-# permissions
-# Openshift master config file
-masterConfig: {{ master_config_yaml }}
-# URL of the VSD Architect
-vsdApiUrl: {{ vsd_api_url }}
-# API version to query against. Usually "v3_2"
-vspVersion: {{ vsp_version }}
-# File containing a VSP license to install. Only necessary if no license has
-# been installed on the VSD Architect before, only valid for standalone vsd install
-# licenseFile: "/path/to/base_vsp_license.txt"
-# Name of the enterprise in which pods will reside
-enterpriseName: {{ enterprise }}
-# Name of the domain in which pods will reside
-domainName: {{ domain }}
-# VSD generated user certificate file location on master node
-userCertificateFile: {{ cert_output_dir }}/{{ vsd_user_cert_file | basename }}
-# VSD generated user key file location on master node
-userKeyFile: {{ cert_output_dir }}/{{ vsd_user_key_file | basename }}
-# Location where logs should be saved
-log_dir: {{ nuage_mon_rest_server_logdir }}
-# Monitor rest server parameters
-# Logging level for the nuage openshift monitor
-# allowed options are: 0 => INFO, 1 => WARNING, 2 => ERROR, 3 => FATAL
-logLevel: {{ nuage_mon_log_level }}
-# Parameters related to the nuage monitor REST server
-nuageMonServer:
- URL: {{ nuage_mon_rest_server_url }}
- certificateDirectory: {{ cert_output_dir }}
-# etcd config required for HA
-etcdClientConfig:
- ca: {{ openshift_master_config_dir }}/{{ "ca.crt" if (openshift.master.embedded_etcd | bool) else "master.etcd-ca.crt" }}
- certFile: {{ openshift_master_config_dir }}/master.etcd-client.crt
- keyFile: {{ openshift_master_config_dir }}/master.etcd-client.key
- urls:
-{% for etcd_url in openshift.master.etcd_urls %}
- - {{ etcd_url }}
-{% endfor %}
-
diff --git a/roles/nuage_master/vars/main.yaml b/roles/nuage_master/vars/main.yaml
index 57d5d2595..114514d7c 100644
--- a/roles/nuage_master/vars/main.yaml
+++ b/roles/nuage_master/vars/main.yaml
@@ -22,6 +22,18 @@ nuage_mon_rest_server_host: "{{ openshift.master.cluster_hostname | default(open
nuage_master_crt_dir: /usr/share/nuage-openshift-monitor
nuage_service_account: system:serviceaccount:default:nuage
+nuage_master_config_dsets_mount_dir: /usr/share/
+nuage_node_config_dsets_mount_dir: /usr/share/
+nuage_cni_bin_dsets_mount_dir: /opt/cni/bin
+nuage_cni_netconf_dsets_mount_dir: /etc/cni/net.d
+nuage_monitor_container_image_version: "{{ nuage_monitor_image_version | default('v5.1.1') }}"
+nuage_vrs_container_image_version: "{{ nuage_vrs_image_version | default('v5.1.1') }}"
+nuage_cni_container_image_version: "{{ nuage_cni_image_version | default('v5.1.1') }}"
+api_server_url: "{{ hostvars[groups.oo_first_master.0].openshift.master.api_url }}"
+nuage_vport_mtu: "{{ nuage_interface_mtu | default('1460') }}"
+master_host_type: "{{ master_base_host_type | default('is_rhel_server') }}"
+slave_host_type: "{{ slave_base_host_type | default('is_rhel_server') }}"
+
nuage_tasks:
- resource_kind: cluster-role
resource_name: cluster-reader
diff --git a/roles/nuage_node/defaults/main.yml b/roles/nuage_node/defaults/main.yml
index b3d2e3cec..9a2e34387 100644
--- a/roles/nuage_node/defaults/main.yml
+++ b/roles/nuage_node/defaults/main.yml
@@ -1,6 +1,6 @@
---
-r_nuage_node_firewall_enabled: True
-r_nuage_node_use_firewalld: False
+r_nuage_node_firewall_enabled: "{{ os_firewall_enabled | default(True) }}"
+r_nuage_node_use_firewalld: "{{ os_firewall_use_firewalld | default(False) }}"
nuage_mon_rest_server_port: '9443'
diff --git a/roles/nuage_node/handlers/main.yaml b/roles/nuage_node/handlers/main.yaml
index 8384856ff..e68ae74bd 100644
--- a/roles/nuage_node/handlers/main.yaml
+++ b/roles/nuage_node/handlers/main.yaml
@@ -1,11 +1,7 @@
---
-- name: restart vrs
- become: yes
- systemd: name=openvswitch state=restarted
-
- name: restart node
become: yes
- systemd: name={{ openshift.common.service_type }}-node state=restarted
+ systemd: name={{ openshift.common.service_type }}-node daemon-reload=yes state=restarted
- name: save iptable rules
become: yes
diff --git a/roles/nuage_node/tasks/main.yaml b/roles/nuage_node/tasks/main.yaml
index 66d6ef4ca..9db9dbb6a 100644
--- a/roles/nuage_node/tasks/main.yaml
+++ b/roles/nuage_node/tasks/main.yaml
@@ -1,28 +1,18 @@
---
-- name: Install Nuage VRS
- become: yes
- yum: name={{ vrs_rpm }} state=present
-
-- name: Set the uplink interface
- become: yes
- lineinfile: dest={{ vrs_config }} regexp=^NETWORK_UPLINK_INTF line='NETWORK_UPLINK_INTF={{ uplink_interface }}'
-
-- name: Set the Active Controller
- become: yes
- lineinfile: dest={{ vrs_config }} regexp=^ACTIVE_CONTROLLER line='ACTIVE_CONTROLLER={{ vsc_active_ip }}'
-
-- name: Set the K8S/OSE Cluster service CIDR
- become: yes
- lineinfile: dest={{ vrs_config }} regexp=^K8S_SERVICE_IPV4_SUBNET line='K8S_SERVICE_IPV4_SUBNET={{ k8s_cluster_service_cidr }}'
+- name: Set the Nuage plugin openshift directory fact for Atomic hosts
+ set_fact:
+ vsp_openshift_dir: /var/usr/share/vsp-openshift
+ when: openshift.common.is_atomic | bool
-- name: Set the Standby Controller
- become: yes
- lineinfile: dest={{ vrs_config }} regexp=^STANDBY_CONTROLLER line='STANDBY_CONTROLLER={{ vsc_standby_ip }}'
- when: vsc_standby_ip is defined
+- name: Set the Nuage CNI binary directory fact for Atomic hosts
+ set_fact:
+ cni_bin_dir: /var/opt/cni/bin/
+ when: openshift.common.is_atomic | bool
-- name: Install plugin rpm
- become: yes
- yum: name={{ plugin_rpm }} state=present
+- name: Set the Nuage plugin certs directory fact for Atomic hosts
+ set_fact:
+ nuage_plugin_crt_dir: /var/usr/share/vsp-openshift
+ when: openshift.common.is_atomic | bool
- name: Assure CNI conf dir exists
become: yes
@@ -32,13 +22,6 @@
become: yes
file: path="{{ cni_bin_dir }}" state=directory
-- name: Install CNI loopback plugin
- become: yes
- copy:
- src: "{{ k8s_cni_loopback_plugin }}"
- dest: "{{ cni_bin_dir }}/{{ k8s_cni_loopback_plugin | basename }}"
- mode: 0755
-
- name: Copy the certificates and keys
become: yes
copy: src="/tmp/{{ item }}" dest="{{ vsp_openshift_dir }}/{{ item }}"
@@ -50,12 +33,16 @@
- include: certificates.yml
-- name: Set the vsp-openshift.yaml
+- name: Add additional Docker mounts for Nuage for atomic hosts
become: yes
- template: src=vsp-openshift.j2 dest={{ vsp_openshift_yaml }} owner=root mode=0644
+ lineinfile: dest="{{ openshift_atomic_node_config_file }}" line="{{ nuage_atomic_docker_additional_mounts }}"
+ when: openshift.common.is_atomic | bool
+
+- name: Restart node services
+ command: /bin/true
notify:
- - restart vrs
- restart node
+ ignore_errors: true
- include: iptables.yml
diff --git a/roles/nuage_node/templates/vsp-openshift.j2 b/roles/nuage_node/templates/vsp-openshift.j2
deleted file mode 100644
index f6bccebc2..000000000
--- a/roles/nuage_node/templates/vsp-openshift.j2
+++ /dev/null
@@ -1,29 +0,0 @@
-clientCert: {{ client_cert }}
-# The key to the certificate in clientCert above
-clientKey: {{ client_key }}
-# The certificate authority's certificate for the local kubelet. Usually the
-# same as the CA cert used to create the client Cert/Key pair.
-CACert: {{ ca_cert }}
-# Name of the enterprise in which pods will reside
-enterpriseName: {{ enterprise }}
-# Name of the domain in which pods will reside
-domainName: {{ domain }}
-# Name of the VSD user in admin group
-vsdUser: {{ vsd_user }}
-# IP address and port number of master API server
-masterApiServer: {{ api_server }}
-# REST server URL
-nuageMonRestServer: {{ nuage_mon_rest_server_url }}
-# Bridge name for the docker bridge
-dockerBridgeName: {{ docker_bridge }}
-# Certificate for connecting to the kubemon REST API
-nuageMonClientCert: {{ rest_client_cert }}
-# Key to the certificate in restClientCert
-nuageMonClientKey: {{ rest_client_key }}
-# CA certificate for verifying the master's rest server
-nuageMonServerCA: {{ rest_server_ca_cert }}
-# Nuage vport mtu size
-interfaceMTU: {{ vport_mtu }}
-# Logging level for the plugin
-# allowed options are: "dbg", "info", "warn", "err", "emer", "off"
-logLevel: {{ plugin_log_level }}
diff --git a/roles/nuage_node/vars/main.yaml b/roles/nuage_node/vars/main.yaml
index 4cf68411f..d8bfca62a 100644
--- a/roles/nuage_node/vars/main.yaml
+++ b/roles/nuage_node/vars/main.yaml
@@ -23,3 +23,5 @@ cni_conf_dir: "/etc/cni/net.d/"
cni_bin_dir: "/opt/cni/bin/"
nuage_plugin_crt_dir: /usr/share/vsp-openshift
+openshift_atomic_node_config_file: /etc/sysconfig/{{ openshift.common.service_type }}-node
+nuage_atomic_docker_additional_mounts: "DOCKER_ADDTL_BIND_MOUNTS=-v /var/usr/share/vsp-openshift:/var/usr/share/vsp-openshift -v /etc/default:/etc/default -v /var/run:/var/run -v /opt/cni/bin:/opt/cni/bin -v /etc/cni/net.d:/etc/cni/net.d"
diff --git a/roles/openshift_aws/README.md b/roles/openshift_aws/README.md
new file mode 100644
index 000000000..696efbea5
--- /dev/null
+++ b/roles/openshift_aws/README.md
@@ -0,0 +1,84 @@
+openshift_aws
+==================================
+
+Provision AWS infrastructure helpers.
+
+Requirements
+------------
+
+* Ansible 2.3
+* Boto
+
+Role Variables
+--------------
+
+From this role:
+
+| Name | Default value
+|---------------------------------------------------|-----------------------
+| openshift_aws_clusterid | default
+| openshift_aws_elb_scheme | internet-facing
+| openshift_aws_launch_config_bootstrap_token | ''
+| openshift_aws_node_group_config | {'master': {'ami': '{{ openshift_aws_ami }}', 'health_check': {'type': 'EC2', 'period': 60}, 'volumes': '{{ openshift_aws_node_group_config_master_volumes }}', 'tags': {'host-type': 'master', 'sub-host-type': 'default'}, 'min_size': 3, 'instance_type': 'm4.xlarge', 'desired_size': 3, 'wait_for_instances': True, 'max_size': 3}, 'tags': '{{ openshift_aws_node_group_config_tags }}', 'compute': {'ami': '{{ openshift_aws_ami }}', 'health_check': {'type': 'EC2', 'period': 60}, 'volumes': '{{ openshift_aws_node_group_config_node_volumes }}', 'tags': {'host-type': 'node', 'sub-host-type': 'compute'}, 'min_size': 3, 'instance_type': 'm4.xlarge', 'desired_size': 3, 'max_size': 100}, 'infra': {'ami': '{{ openshift_aws_ami }}', 'health_check': {'type': 'EC2', 'period': 60}, 'volumes': '{{ openshift_aws_node_group_config_node_volumes }}', 'tags': {'host-type': 'node', 'sub-host-type': 'infra'}, 'min_size': 2, 'instance_type': 'm4.xlarge', 'desired_size': 2, 'max_size': 20}}
+| openshift_aws_ami_copy_wait | False
+| openshift_aws_users | []
+| openshift_aws_launch_config_name | {{ openshift_aws_clusterid }}-{{ openshift_aws_node_group_type }}
+| openshift_aws_create_vpc | False
+| openshift_aws_node_group_type | master
+| openshift_aws_elb_cert_arn | ''
+| openshift_aws_kubernetes_cluster_status | owned
+| openshift_aws_s3_mode | create
+| openshift_aws_vpc | {'subnets': {'us-east-1': [{'cidr': '172.31.48.0/20', 'az': 'us-east-1c'}, {'cidr': '172.31.32.0/20', 'az': 'us-east-1e'}, {'cidr': '172.31.16.0/20', 'az': 'us-east-1a'}]}, 'cidr': '172.31.0.0/16', 'name': '{{ openshift_aws_vpc_name }}'}
+| openshift_aws_create_ssh_keys | False
+| openshift_aws_iam_kms_alias | alias/{{ openshift_aws_clusterid }}_kms
+| openshift_aws_use_custom_ami | False
+| openshift_aws_ami_copy_src_region | {{ openshift_aws_region }}
+| openshift_aws_s3_bucket_name | {{ openshift_aws_clusterid }}
+| openshift_aws_elb_health_check | {'response_timeout': 5, 'ping_port': 443, 'ping_protocol': 'tcp', 'interval': 30, 'healthy_threshold': 2, 'unhealthy_threshold': 2}
+| openshift_aws_node_security_groups | {'default': {'rules': [{'to_port': 22, 'from_port': 22, 'cidr_ip': '0.0.0.0/0', 'proto': 'tcp'}, {'to_port': 'all', 'from_port': 'all', 'proto': 'all', 'group_name': '{{ openshift_aws_clusterid }}'}], 'name': '{{ openshift_aws_clusterid }}', 'desc': '{{ openshift_aws_clusterid }} default'}, 'master': {'rules': [{'to_port': 80, 'from_port': 80, 'cidr_ip': '0.0.0.0/0', 'proto': 'tcp'}, {'to_port': 443, 'from_port': 443, 'cidr_ip': '0.0.0.0/0', 'proto': 'tcp'}], 'name': '{{ openshift_aws_clusterid }}_master', 'desc': '{{ openshift_aws_clusterid }} master instances'}, 'compute': {'name': '{{ openshift_aws_clusterid }}_compute', 'desc': '{{ openshift_aws_clusterid }} compute node instances'}, 'etcd': {'name': '{{ openshift_aws_clusterid }}_etcd', 'desc': '{{ openshift_aws_clusterid }} etcd instances'}, 'infra': {'rules': [{'to_port': 80, 'from_port': 80, 'cidr_ip': '0.0.0.0/0', 'proto': 'tcp'}, {'to_port': 443, 'from_port': 443, 'cidr_ip': '0.0.0.0/0', 'proto': 'tcp'}, {'to_port': 32000, 'from_port': 30000, 'cidr_ip': '0.0.0.0/0', 'proto': 'tcp'}], 'name': '{{ openshift_aws_clusterid }}_infra', 'desc': '{{ openshift_aws_clusterid }} infra node instances'}}
+| openshift_aws_elb_security_groups | ['{{ openshift_aws_clusterid }}', '{{ openshift_aws_clusterid }}_{{ openshift_aws_node_group_type }}']
+| openshift_aws_vpc_tags | {'Name': '{{ openshift_aws_vpc_name }}'}
+| openshift_aws_create_security_groups | False
+| openshift_aws_create_iam_cert | False
+| openshift_aws_create_scale_group | True
+| openshift_aws_ami_encrypt | False
+| openshift_aws_node_group_config_node_volumes | [{'volume_size': 100, 'delete_on_termination': True, 'device_type': 'gp2', 'device_name': '/dev/sdb'}]
+| openshift_aws_elb_instance_filter | {'tag:host-type': '{{ openshift_aws_node_group_type }}', 'tag:clusterid': '{{ openshift_aws_clusterid }}', 'instance-state-name': 'running'}
+| openshift_aws_region | us-east-1
+| openshift_aws_elb_name | {{ openshift_aws_clusterid }}-{{ openshift_aws_node_group_type }}
+| openshift_aws_elb_idle_timout | 400
+| openshift_aws_subnet_name | us-east-1c
+| openshift_aws_node_group_config_tags | {{ openshift_aws_clusterid | openshift_aws_build_instance_tags(openshift_aws_kubernetes_cluster_status) }}
+| openshift_aws_create_launch_config | True
+| openshift_aws_ami_tags | {'bootstrap': 'true', 'clusterid': '{{ openshift_aws_clusterid }}', 'openshift-created': 'true'}
+| openshift_aws_ami_name | openshift-gi
+| openshift_aws_node_group_config_master_volumes | [{'volume_size': 100, 'delete_on_termination': False, 'device_type': 'gp2', 'device_name': '/dev/sdb'}]
+| openshift_aws_vpc_name | {{ openshift_aws_clusterid }}
+| openshift_aws_elb_listeners | {'master': {'internal': [{'instance_port': 80, 'instance_protocol': 'tcp', 'load_balancer_port': 80, 'protocol': 'tcp'}, {'instance_port': 443, 'instance_protocol': 'tcp', 'load_balancer_port': 443, 'protocol': 'tcp'}], 'external': [{'instance_port': 443, 'instance_protocol': 'ssl', 'load_balancer_port': 80, 'protocol': 'tcp'}, {'instance_port': 443, 'instance_protocol': 'ssl', 'load_balancer_port': 443, 'ssl_certificate_id': '{{ openshift_aws_elb_cert_arn }}', 'protocol': 'ssl'}]}}
+|
+
+
+Dependencies
+------------
+
+
+Example Playbook
+----------------
+
+```yaml
+- include_role:
+ name: openshift_aws
+ tasks_from: vpc.yml
+ vars:
+ openshift_aws_clusterid: test
+ openshift_aws_region: us-east-1
+ openshift_aws_create_vpc: true
+```
+
+License
+-------
+
+Apache License, Version 2.0
+
+Author Information
+------------------
diff --git a/roles/openshift_aws/defaults/main.yml b/roles/openshift_aws/defaults/main.yml
new file mode 100644
index 000000000..4e7f54f79
--- /dev/null
+++ b/roles/openshift_aws/defaults/main.yml
@@ -0,0 +1,209 @@
+---
+openshift_aws_create_vpc: True
+openshift_aws_create_s3: True
+openshift_aws_create_iam_cert: True
+openshift_aws_create_security_groups: True
+openshift_aws_create_launch_config: True
+openshift_aws_create_scale_group: True
+openshift_aws_kubernetes_cluster_status: owned # or shared
+openshift_aws_node_group_type: master
+
+openshift_aws_wait_for_ssh: True
+
+openshift_aws_clusterid: default
+openshift_aws_region: us-east-1
+openshift_aws_vpc_name: "{{ openshift_aws_clusterid }}"
+
+openshift_aws_iam_cert_name: "{{ openshift_aws_clusterid }}-master-external"
+openshift_aws_iam_cert_path: ''
+openshift_aws_iam_cert_chain_path: ''
+openshift_aws_iam_cert_key_path: ''
+openshift_aws_scale_group_name: "{{ openshift_aws_clusterid }} openshift {{ openshift_aws_node_group_type }}"
+
+openshift_aws_iam_kms_alias: "alias/{{ openshift_aws_clusterid }}_kms"
+openshift_aws_ami: ''
+openshift_aws_ami_copy_wait: False
+openshift_aws_ami_encrypt: False
+openshift_aws_ami_copy_src_region: "{{ openshift_aws_region }}"
+openshift_aws_ami_name: openshift-gi
+openshift_aws_base_ami_name: ami_base
+
+openshift_aws_launch_config_bootstrap_token: ''
+openshift_aws_launch_config_name: "{{ openshift_aws_clusterid }}-{{ openshift_aws_node_group_type }}-{{ ansible_date_time.epoch }}"
+
+openshift_aws_users: []
+
+openshift_aws_ami_tags:
+ bootstrap: "true"
+ openshift-created: "true"
+ clusterid: "{{ openshift_aws_clusterid }}"
+
+openshift_aws_s3_mode: create
+openshift_aws_s3_bucket_name: "{{ openshift_aws_clusterid }}-docker-registry"
+
+openshift_aws_elb_health_check:
+ ping_protocol: tcp
+ ping_port: 443
+ response_timeout: 5
+ interval: 30
+ unhealthy_threshold: 2
+ healthy_threshold: 2
+
+openshift_aws_elb_name: "{{ openshift_aws_clusterid }}-{{ openshift_aws_node_group_type }}"
+openshift_aws_elb_idle_timout: 400
+openshift_aws_elb_scheme: internet-facing
+openshift_aws_elb_cert_arn: ''
+
+openshift_aws_elb_listeners:
+ master:
+ external:
+ - protocol: tcp
+ load_balancer_port: 80
+ instance_protocol: ssl
+ instance_port: 443
+ - protocol: ssl
+ load_balancer_port: 443
+ instance_protocol: ssl
+ instance_port: 443
+ # ssl certificate required for https or ssl
+ ssl_certificate_id: "{{ openshift_aws_elb_cert_arn }}"
+ internal:
+ - protocol: tcp
+ load_balancer_port: 80
+ instance_protocol: tcp
+ instance_port: 80
+ - protocol: tcp
+ load_balancer_port: 443
+ instance_protocol: tcp
+ instance_port: 443
+
+openshift_aws_node_group_config_master_volumes:
+- device_name: /dev/sdb
+ volume_size: 100
+ device_type: gp2
+ delete_on_termination: False
+
+openshift_aws_node_group_config_node_volumes:
+- device_name: /dev/sdb
+ volume_size: 100
+ device_type: gp2
+ delete_on_termination: True
+
+openshift_aws_node_group_config_tags: "{{ openshift_aws_clusterid | build_instance_tags(openshift_aws_kubernetes_cluster_status) }}"
+
+openshift_aws_node_group_config:
+ tags: "{{ openshift_aws_node_group_config_tags }}"
+ master:
+ instance_type: m4.xlarge
+ ami: "{{ openshift_aws_ami }}"
+ volumes: "{{ openshift_aws_node_group_config_master_volumes }}"
+ health_check:
+ period: 60
+ type: EC2
+ min_size: 3
+ max_size: 3
+ desired_size: 3
+ tags:
+ host-type: master
+ sub-host-type: default
+ wait_for_instances: True
+ compute:
+ instance_type: m4.xlarge
+ ami: "{{ openshift_aws_ami }}"
+ volumes: "{{ openshift_aws_node_group_config_node_volumes }}"
+ health_check:
+ period: 60
+ type: EC2
+ min_size: 3
+ max_size: 100
+ desired_size: 3
+ tags:
+ host-type: node
+ sub-host-type: compute
+ infra:
+ instance_type: m4.xlarge
+ ami: "{{ openshift_aws_ami }}"
+ volumes: "{{ openshift_aws_node_group_config_node_volumes }}"
+ health_check:
+ period: 60
+ type: EC2
+ min_size: 2
+ max_size: 20
+ desired_size: 2
+ tags:
+ host-type: node
+ sub-host-type: infra
+
+openshift_aws_elb_security_groups:
+- "{{ openshift_aws_clusterid }}"
+- "{{ openshift_aws_clusterid }}_{{ openshift_aws_node_group_type }}"
+
+openshift_aws_elb_instance_filter:
+ "tag:clusterid": "{{ openshift_aws_clusterid }}"
+ "tag:host-type": "{{ openshift_aws_node_group_type }}"
+ instance-state-name: running
+
+openshift_aws_node_security_groups:
+ default:
+ name: "{{ openshift_aws_clusterid }}"
+ desc: "{{ openshift_aws_clusterid }} default"
+ rules:
+ - proto: tcp
+ from_port: 22
+ to_port: 22
+ cidr_ip: 0.0.0.0/0
+ - proto: all
+ from_port: all
+ to_port: all
+ group_name: "{{ openshift_aws_clusterid }}"
+ master:
+ name: "{{ openshift_aws_clusterid }}_master"
+ desc: "{{ openshift_aws_clusterid }} master instances"
+ rules:
+ - proto: tcp
+ from_port: 80
+ to_port: 80
+ cidr_ip: 0.0.0.0/0
+ - proto: tcp
+ from_port: 443
+ to_port: 443
+ cidr_ip: 0.0.0.0/0
+ compute:
+ name: "{{ openshift_aws_clusterid }}_compute"
+ desc: "{{ openshift_aws_clusterid }} compute node instances"
+ infra:
+ name: "{{ openshift_aws_clusterid }}_infra"
+ desc: "{{ openshift_aws_clusterid }} infra node instances"
+ rules:
+ - proto: tcp
+ from_port: 80
+ to_port: 80
+ cidr_ip: 0.0.0.0/0
+ - proto: tcp
+ from_port: 443
+ to_port: 443
+ cidr_ip: 0.0.0.0/0
+ - proto: tcp
+ from_port: 30000
+ to_port: 32000
+ cidr_ip: 0.0.0.0/0
+ etcd:
+ name: "{{ openshift_aws_clusterid }}_etcd"
+ desc: "{{ openshift_aws_clusterid }} etcd instances"
+
+openshift_aws_vpc_tags:
+ Name: "{{ openshift_aws_vpc_name }}"
+
+openshift_aws_subnet_name: us-east-1c
+
+openshift_aws_vpc:
+ name: "{{ openshift_aws_vpc_name }}"
+ cidr: 172.31.0.0/16
+ subnets:
+ us-east-1:
+ - cidr: 172.31.48.0/20
+ az: "us-east-1c"
+ - cidr: 172.31.32.0/20
+ az: "us-east-1e"
+ - cidr: 172.31.16.0/20
+ az: "us-east-1a"
diff --git a/roles/openshift_aws/filter_plugins/filters.py b/roles/openshift_aws/filter_plugins/filters.py
new file mode 100644
index 000000000..06e1f9602
--- /dev/null
+++ b/roles/openshift_aws/filter_plugins/filters.py
@@ -0,0 +1,28 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+'''
+Custom filters for use in openshift_aws
+'''
+
+
+class FilterModule(object):
+ ''' Custom ansible filters for use by openshift_aws role'''
+
+ @staticmethod
+ def build_instance_tags(clusterid, status='owned'):
+ ''' This function will return a dictionary of the instance tags.
+
+ The main desire to have this inside of a filter_plugin is that we
+ need to build the following key.
+
+ {"kubernetes.io/cluster/{{ openshift_aws_clusterid }}": 'owned'}
+
+ '''
+ tags = {'clusterid': clusterid,
+ 'kubernetes.io/cluster/{}'.format(clusterid): status}
+
+ return tags
+
+ def filters(self):
+ ''' returns a mapping of filters to methods '''
+ return {'build_instance_tags': self.build_instance_tags}
diff --git a/roles/openshift_aws/meta/main.yml b/roles/openshift_aws/meta/main.yml
new file mode 100644
index 000000000..875efcb8f
--- /dev/null
+++ b/roles/openshift_aws/meta/main.yml
@@ -0,0 +1,3 @@
+---
+dependencies:
+- lib_utils
diff --git a/roles/openshift_aws/tasks/ami_copy.yml b/roles/openshift_aws/tasks/ami_copy.yml
new file mode 100644
index 000000000..07020dd62
--- /dev/null
+++ b/roles/openshift_aws/tasks/ami_copy.yml
@@ -0,0 +1,34 @@
+---
+- fail:
+ msg: "{{ item }} needs to be defined"
+ when: item is not defined
+ with_items:
+ - openshift_aws_ami_copy_src_ami
+ - openshift_aws_ami_copy_name
+
+- name: Create IAM KMS key with alias
+ oo_iam_kms:
+ state: present
+ alias: "{{ openshift_aws_iam_kms_alias }}"
+ region: "{{ openshift_aws_region }}"
+ register: created_kms
+
+- debug: var=created_kms.results
+
+- name: "Create copied AMI image and wait: {{ openshift_aws_ami_copy_wait }}"
+ ec2_ami_copy:
+ name: "{{ openshift_aws_ami_copy_name }}"
+ region: "{{ openshift_aws_region }}"
+ source_region: "{{ openshift_aws_ami_copy_src_region }}"
+ source_image_id: "{{ openshift_aws_ami_copy_src_ami }}"
+ encrypted: "{{ openshift_aws_ami_encrypt | bool }}"
+ kms_key_id: "{{ created_kms.results.KeyArn | default(omit) }}"
+ wait: "{{ openshift_aws_ami_copy_wait | default(omit) }}"
+ tags: "{{ openshift_aws_ami_tags }}"
+ register: copy_result
+
+- debug: var=copy_result
+
+- name: return AMI ID with setfact
+ set_fact:
+ openshift_aws_ami_copy_custom_ami: "{{ copy_result.image_id }}"
diff --git a/roles/openshift_aws/tasks/build_ami.yml b/roles/openshift_aws/tasks/build_ami.yml
new file mode 100644
index 000000000..8d4e5ac43
--- /dev/null
+++ b/roles/openshift_aws/tasks/build_ami.yml
@@ -0,0 +1,48 @@
+---
+- when: openshift_aws_create_vpc | bool
+ name: create a vpc
+ include: vpc.yml
+
+- when: openshift_aws_users | length > 0
+ name: create aws ssh keypair
+ include: ssh_keys.yml
+
+- when: openshift_aws_create_security_groups | bool
+ name: Create compute security_groups
+ include: security_group.yml
+
+- name: query vpc
+ ec2_vpc_net_facts:
+ region: "{{ openshift_aws_region }}"
+ filters:
+ 'tag:Name': "{{ openshift_aws_vpc_name }}"
+ register: vpcout
+
+- name: fetch the default subnet id
+ ec2_vpc_subnet_facts:
+ region: "{{ openshift_aws_region }}"
+ filters:
+ "tag:Name": "{{ openshift_aws_subnet_name }}"
+ vpc-id: "{{ vpcout.vpcs[0].id }}"
+ register: subnetout
+
+- name: create instance for ami creation
+ ec2:
+ assign_public_ip: yes
+ region: "{{ openshift_aws_region }}"
+ key_name: "{{ openshift_aws_ssh_key_name }}"
+ group: "{{ openshift_aws_clusterid }}"
+ instance_type: m4.xlarge
+ vpc_subnet_id: "{{ subnetout.subnets[0].id }}"
+ image: "{{ openshift_aws_base_ami }}"
+ volumes:
+ - device_name: /dev/sdb
+ volume_type: gp2
+ volume_size: 100
+ delete_on_termination: true
+ wait: yes
+ exact_count: 1
+ count_tag:
+ Name: "{{ openshift_aws_base_ami_name }}"
+ instance_tags:
+ Name: "{{ openshift_aws_base_ami_name }}"
diff --git a/roles/openshift_aws/tasks/build_node_group.yml b/roles/openshift_aws/tasks/build_node_group.yml
new file mode 100644
index 000000000..0dac1c23d
--- /dev/null
+++ b/roles/openshift_aws/tasks/build_node_group.yml
@@ -0,0 +1,34 @@
+---
+# When openshift_aws_use_custom_ami is '' then
+# we retrieve the latest build AMI.
+# Then set openshift_aws_ami to the ami.
+- when: openshift_aws_ami == ''
+ block:
+ - name: fetch recently created AMI
+ ec2_ami_find:
+ region: "{{ openshift_aws_region }}"
+ sort: creationDate
+ sort_order: descending
+ name: "{{ openshift_aws_ami_name }}*"
+ ami_tags: "{{ openshift_aws_ami_tags }}"
+ no_result_action: fail
+ register: amiout
+
+ - name: Set the openshift_aws_ami
+ set_fact:
+ openshift_aws_ami: "{{ amiout.results[0].ami_id }}"
+ when:
+ - "'results' in amiout"
+ - amiout.results|length > 0
+
+- when: openshift_aws_create_security_groups
+ name: "Create {{ openshift_aws_node_group_type }} security groups"
+ include: security_group.yml
+
+- when: openshift_aws_create_launch_config
+ name: "Create {{ openshift_aws_node_group_type }} launch config"
+ include: launch_config.yml
+
+- when: openshift_aws_create_scale_group
+ name: "Create {{ openshift_aws_node_group_type }} node group"
+ include: scale_group.yml
diff --git a/roles/openshift_aws/tasks/elb.yml b/roles/openshift_aws/tasks/elb.yml
new file mode 100644
index 000000000..a1fdd66fc
--- /dev/null
+++ b/roles/openshift_aws/tasks/elb.yml
@@ -0,0 +1,68 @@
+---
+- name: query vpc
+ ec2_vpc_net_facts:
+ region: "{{ openshift_aws_region }}"
+ filters:
+ 'tag:Name': "{{ openshift_aws_vpc_name }}"
+ register: vpcout
+
+- name: debug
+ debug: var=vpcout
+
+- name: fetch the remote instances
+ ec2_remote_facts:
+ region: "{{ openshift_aws_region }}"
+ filters: "{{ openshift_aws_elb_instance_filter }}"
+ register: instancesout
+
+- name: fetch the default subnet id
+ ec2_vpc_subnet_facts:
+ region: "{{ openshift_aws_region }}"
+ filters:
+ "tag:Name": "{{ openshift_aws_subnet_name }}"
+ vpc-id: "{{ vpcout.vpcs[0].id }}"
+ register: subnetout
+
+- name:
+ debug:
+ msg: "{{ openshift_aws_elb_listeners[openshift_aws_node_group_type][openshift_aws_elb_direction]
+ if 'master' in openshift_aws_node_group_type or 'infra' in openshift_aws_node_group_type
+ else openshift_aws_elb_listeners }}"
+
+- name: "Create ELB {{ openshift_aws_elb_name }}"
+ ec2_elb_lb:
+ name: "{{ openshift_aws_elb_name }}"
+ state: present
+ security_group_names: "{{ openshift_aws_elb_security_groups }}"
+ idle_timeout: "{{ openshift_aws_elb_idle_timout }}"
+ region: "{{ openshift_aws_region }}"
+ subnets:
+ - "{{ subnetout.subnets[0].id }}"
+ health_check: "{{ openshift_aws_elb_health_check }}"
+ listeners: "{{ openshift_aws_elb_listeners[openshift_aws_node_group_type][openshift_aws_elb_direction]
+ if 'master' in openshift_aws_node_group_type or 'infra' in openshift_aws_node_group_type
+ else openshift_aws_elb_listeners }}"
+ scheme: "{{ openshift_aws_elb_scheme }}"
+ tags:
+ KubernetesCluster: "{{ openshift_aws_clusterid }}"
+ register: new_elb
+
+# It is necessary to ignore_errors here because the instances are not in 'ready'
+# state when first added to ELB
+- name: "Add instances to ELB {{ openshift_aws_elb_name }}"
+ ec2_elb:
+ instance_id: "{{ item.id }}"
+ ec2_elbs: "{{ openshift_aws_elb_name }}"
+ state: present
+ region: "{{ openshift_aws_region }}"
+ wait: False
+ with_items: "{{ instancesout.instances }}"
+ ignore_errors: True
+ retries: 10
+ register: elb_call
+ until: elb_call|succeeded
+
+- debug:
+ msg: "{{ item }}"
+ with_items:
+ - "{{ new_elb }}"
diff --git a/roles/openshift_aws/tasks/iam_cert.yml b/roles/openshift_aws/tasks/iam_cert.yml
new file mode 100644
index 000000000..cd9772a25
--- /dev/null
+++ b/roles/openshift_aws/tasks/iam_cert.yml
@@ -0,0 +1,29 @@
+---
+- name: upload certificates to AWS IAM
+ iam_cert23:
+ state: present
+ name: "{{ openshift_aws_iam_cert_name }}"
+ cert: "{{ openshift_aws_iam_cert_path }}"
+ key: "{{ openshift_aws_iam_cert_key_path }}"
+ cert_chain: "{{ openshift_aws_iam_cert_chain_path | default(omit) }}"
+ register: elb_cert_chain
+ failed_when:
+ - "'failed' in elb_cert_chain"
+ - elb_cert_chain.failed
+ - "'msg' in elb_cert_chain"
+ - "'already exists and has a different certificate body' in elb_cert_chain.msg"
+ - "'BotoServerError' in elb_cert_chain.msg"
+ when:
+ - openshift_aws_create_iam_cert | bool
+ - openshift_aws_iam_cert_path != ''
+ - openshift_aws_iam_cert_key_path != ''
+ - openshift_aws_elb_cert_arn == ''
+
+- name: set_fact openshift_aws_elb_cert_arn
+ set_fact:
+ openshift_aws_elb_cert_arn: "{{ elb_cert_chain.arn }}"
+
+- name: wait for cert to propagate
+ pause:
+ seconds: 5
+ when: elb_cert_chain.changed
diff --git a/roles/openshift_aws/tasks/launch_config.yml b/roles/openshift_aws/tasks/launch_config.yml
new file mode 100644
index 000000000..65c5a6cc0
--- /dev/null
+++ b/roles/openshift_aws/tasks/launch_config.yml
@@ -0,0 +1,45 @@
+---
+- fail:
+ msg: "Ensure that an AMI value is defined for openshift_aws_ami or openshift_aws_launch_config_custom_image."
+ when:
+ - openshift_aws_ami is undefined
+
+- name: fetch the security groups for launch config
+ ec2_group_facts:
+ filters:
+ group-name:
+ - "{{ openshift_aws_clusterid }}" # default sg
+ - "{{ openshift_aws_clusterid }}_{{ openshift_aws_node_group_type }}" # node type sg
+ - "{{ openshift_aws_clusterid }}_{{ openshift_aws_node_group_type }}_k8s" # node type sg k8s
+ region: "{{ openshift_aws_region }}"
+ register: ec2sgs
+
+# Create the scale group config
+- name: Create the node scale group launch config
+ ec2_lc:
+ name: "{{ openshift_aws_launch_config_name }}"
+ region: "{{ openshift_aws_region }}"
+ image_id: "{{ openshift_aws_ami }}"
+ instance_type: "{{ openshift_aws_node_group_config[openshift_aws_node_group_type].instance_type }}"
+ security_groups: "{{ ec2sgs.security_groups | map(attribute='group_id')| list }}"
+ user_data: |-
+ #cloud-config
+ {% if openshift_aws_node_group_type != 'master' %}
+ write_files:
+ - path: /root/csr_kubeconfig
+ owner: root:root
+ permissions: '0640'
+ content: {{ openshift_aws_launch_config_bootstrap_token | default('') | to_yaml }}
+ - path: /root/openshift_settings
+ owner: root:root
+ permissions: '0640'
+ content:
+ openshift_type: "{{ openshift_aws_node_group_type }}"
+ runcmd:
+ - [ systemctl, enable, atomic-openshift-node]
+ - [ systemctl, start, atomic-openshift-node]
+ {% endif %}
+ key_name: "{{ openshift_aws_ssh_key_name }}"
+ ebs_optimized: False
+ volumes: "{{ openshift_aws_node_group_config[openshift_aws_node_group_type].volumes }}"
+ assign_public_ip: True
diff --git a/roles/openshift_aws/tasks/provision.yml b/roles/openshift_aws/tasks/provision.yml
new file mode 100644
index 000000000..189caeaee
--- /dev/null
+++ b/roles/openshift_aws/tasks/provision.yml
@@ -0,0 +1,54 @@
+---
+- when: openshift_aws_create_vpc | bool
+ name: create default vpc
+ include: vpc.yml
+
+- when: openshift_aws_create_iam_cert | bool
+ name: create the iam_cert for elb certificate
+ include: iam_cert.yml
+
+- when: openshift_aws_users | length > 0
+ name: create aws ssh keypair
+ include: ssh_keys.yml
+
+- when: openshift_aws_create_s3 | bool
+ name: create s3 bucket for registry
+ include: s3.yml
+
+- name: include scale group creation for master
+ include: build_node_group.yml
+
+- name: fetch newly created instances
+ ec2_remote_facts:
+ region: "{{ openshift_aws_region }}"
+ filters:
+ "tag:clusterid": "{{ openshift_aws_clusterid }}"
+ "tag:host-type": "{{ openshift_aws_node_group_type }}"
+ instance-state-name: running
+ register: instancesout
+ retries: 20
+ delay: 3
+ until: instancesout.instances|length > 0
+
+- name: create our master internal load balancers
+ include: elb.yml
+ vars:
+ openshift_aws_elb_direction: internal
+ openshift_aws_elb_name: "{{ openshift_aws_clusterid }}-{{openshift_aws_node_group_type }}-internal"
+ openshift_aws_elb_scheme: internal
+
+- name: create our master external load balancers
+ include: elb.yml
+ vars:
+ openshift_aws_elb_direction: external
+ openshift_aws_elb_name: "{{ openshift_aws_clusterid }}-{{openshift_aws_node_group_type }}-external"
+ openshift_aws_elb_scheme: internet-facing
+
+- name: wait for ssh to become available
+ wait_for:
+ port: 22
+ host: "{{ item.public_ip_address }}"
+ timeout: 300
+ search_regex: OpenSSH
+ with_items: "{{ instancesout.instances }}"
+ when: openshift_aws_wait_for_ssh | bool
diff --git a/roles/openshift_aws/tasks/provision_nodes.yml b/roles/openshift_aws/tasks/provision_nodes.yml
new file mode 100644
index 000000000..fc4996c68
--- /dev/null
+++ b/roles/openshift_aws/tasks/provision_nodes.yml
@@ -0,0 +1,66 @@
+---
+# Get bootstrap config token
+# bootstrap should be created on first master
+# need to fetch it and shove it into cloud data
+- name: fetch master instances
+ ec2_remote_facts:
+ region: "{{ openshift_aws_region }}"
+ filters:
+ "tag:clusterid": "{{ openshift_aws_clusterid }}"
+ "tag:host-type": master
+ instance-state-name: running
+ register: instancesout
+ retries: 20
+ delay: 3
+ until: instancesout.instances|length > 0
+
+- name: slurp down the bootstrap.kubeconfig
+ slurp:
+ src: /etc/origin/master/bootstrap.kubeconfig
+ delegate_to: "{{ instancesout.instances[0].public_ip_address }}"
+ remote_user: root
+ register: bootstrap
+
+- name: set_fact for kubeconfig token
+ set_fact:
+ openshift_aws_launch_config_bootstrap_token: "{{ bootstrap['content'] | b64decode }}"
+
+- name: include build node group for infra
+ include: build_node_group.yml
+ vars:
+ openshift_aws_node_group_type: infra
+ openshift_aws_scale_group_name: "{{ openshift_aws_clusterid }} openshift infra"
+ openshift_aws_launch_config_name: "{{ openshift_aws_clusterid }}-infra-{{ ansible_date_time.epoch }}"
+
+- name: include build node group for compute
+ include: build_node_group.yml
+ vars:
+ openshift_aws_node_group_type: compute
+ openshift_aws_scale_group_name: "{{ openshift_aws_clusterid }} openshift compute"
+ openshift_aws_launch_config_name: "{{ openshift_aws_clusterid }}-compute-{{ ansible_date_time.epoch }}"
+
+- when: openshift_aws_wait_for_ssh | bool
+ block:
+ - name: pause and allow for instances to scale before we query them
+ pause:
+ seconds: 10
+
+ - name: fetch newly created instances
+ ec2_remote_facts:
+ region: "{{ openshift_aws_region }}"
+ filters:
+ "tag:clusterid": "{{ openshift_aws_clusterid }}"
+ "tag:host-type": node
+ instance-state-name: running
+ register: instancesout
+ retries: 20
+ delay: 3
+ until: instancesout.instances|length > 0
+
+ - name: wait for ssh to become available
+ wait_for:
+ port: 22
+ host: "{{ item.public_ip_address }}"
+ timeout: 300
+ search_regex: OpenSSH
+ with_items: "{{ instancesout.instances }}"
diff --git a/roles/openshift_aws/tasks/s3.yml b/roles/openshift_aws/tasks/s3.yml
new file mode 100644
index 000000000..9cf37c840
--- /dev/null
+++ b/roles/openshift_aws/tasks/s3.yml
@@ -0,0 +1,7 @@
+---
+- name: Create an s3 bucket
+ s3:
+ bucket: "{{ openshift_aws_s3_bucket_name }}"
+ mode: "{{ openshift_aws_s3_mode }}"
+ region: "{{ openshift_aws_region }}"
+ when: openshift_aws_create_s3 | bool
diff --git a/roles/openshift_aws/tasks/scale_group.yml b/roles/openshift_aws/tasks/scale_group.yml
new file mode 100644
index 000000000..3e969fc43
--- /dev/null
+++ b/roles/openshift_aws/tasks/scale_group.yml
@@ -0,0 +1,32 @@
+---
+- name: query vpc
+ ec2_vpc_net_facts:
+ region: "{{ openshift_aws_region }}"
+ filters:
+ 'tag:Name': "{{ openshift_aws_vpc_name }}"
+ register: vpcout
+
+- name: fetch the subnet to use in scale group
+ ec2_vpc_subnet_facts:
+ region: "{{ openshift_aws_region }}"
+ filters:
+ "tag:Name": "{{ openshift_aws_subnet_name }}"
+ vpc-id: "{{ vpcout.vpcs[0].id }}"
+ register: subnetout
+
+- name: Create the scale group
+ ec2_asg:
+ name: "{{ openshift_aws_scale_group_name }}"
+ launch_config_name: "{{ openshift_aws_launch_config_name }}"
+ health_check_period: "{{ openshift_aws_node_group_config[openshift_aws_node_group_type].health_check.period }}"
+ health_check_type: "{{ openshift_aws_node_group_config[openshift_aws_node_group_type].health_check.type }}"
+ min_size: "{{ openshift_aws_node_group_config[openshift_aws_node_group_type].min_size }}"
+ max_size: "{{ openshift_aws_node_group_config[openshift_aws_node_group_type].max_size }}"
+ desired_capacity: "{{ openshift_aws_node_group_config[openshift_aws_node_group_type].desired_size }}"
+ region: "{{ openshift_aws_region }}"
+ termination_policies: "{{ openshift_aws_node_group_config[openshift_aws_node_group_type].termination_policy if 'termination_policy' in openshift_aws_node_group_config[openshift_aws_node_group_type] else omit }}"
+ load_balancers: "{{ openshift_aws_node_group_config[openshift_aws_node_group_type].elbs if 'elbs' in openshift_aws_node_group_config[openshift_aws_node_group_type] else omit }}"
+ wait_for_instances: "{{ openshift_aws_node_group_config[openshift_aws_node_group_type].wait_for_instances | default(False)}}"
+ vpc_zone_identifier: "{{ subnetout.subnets[0].id }}"
+ tags:
+ - "{{ openshift_aws_node_group_config.tags | combine(openshift_aws_node_group_config[openshift_aws_node_group_type].tags) }}"
diff --git a/roles/openshift_aws/tasks/seal_ami.yml b/roles/openshift_aws/tasks/seal_ami.yml
new file mode 100644
index 000000000..0cb749dcc
--- /dev/null
+++ b/roles/openshift_aws/tasks/seal_ami.yml
@@ -0,0 +1,49 @@
+---
+- name: fetch newly created instances
+ ec2_remote_facts:
+ region: "{{ openshift_aws_region }}"
+ filters:
+ "tag:Name": "{{ openshift_aws_base_ami_name }}"
+ instance-state-name: running
+ register: instancesout
+ retries: 20
+ delay: 3
+ until: instancesout.instances|length > 0
+
+- name: bundle ami
+ ec2_ami:
+ instance_id: "{{ instancesout.instances.0.id }}"
+ region: "{{ openshift_aws_region }}"
+ state: present
+ description: "This was provisioned {{ ansible_date_time.iso8601 }}"
+ name: "{{ openshift_aws_ami_name }}"
+ tags: "{{ openshift_aws_ami_tags }}"
+ wait: yes
+ register: amioutput
+
+- debug: var=amioutput
+
+- when: openshift_aws_ami_encrypt | bool
+ block:
+ - name: augment the encrypted ami tags with source-ami
+ set_fact:
+ source_tag:
+ source-ami: "{{ amioutput.image_id }}"
+
+ - name: copy the ami for encrypted disks
+ include: ami_copy.yml
+ vars:
+ openshift_aws_ami_copy_name: "{{ openshift_aws_ami_name }}-encrypted"
+ openshift_aws_ami_copy_src_ami: "{{ amioutput.image_id }}"
+ # TODO: How does the kms alias get passed to ec2_ami_copy
+ openshift_aws_ami_copy_kms_alias: "alias/{{ openshift_aws_clusterid }}_kms"
+ openshift_aws_ami_copy_tags: "{{ source_tag | combine(openshift_aws_ami_tags) }}"
+ # this option currently fails due to boto waiters
+ # when supported this need to be reapplied
+ #openshift_aws_ami_copy_wait: True
+
+- name: terminate temporary instance
+ ec2:
+ state: absent
+ region: "{{ openshift_aws_region }}"
+ instance_ids: "{{ instancesout.instances.0.id }}"
diff --git a/roles/openshift_aws/tasks/security_group.yml b/roles/openshift_aws/tasks/security_group.yml
new file mode 100644
index 000000000..161e72fb4
--- /dev/null
+++ b/roles/openshift_aws/tasks/security_group.yml
@@ -0,0 +1,45 @@
+---
+- name: Fetch the VPC for the vpc.id
+ ec2_vpc_net_facts:
+ region: "{{ openshift_aws_region }}"
+ filters:
+ "tag:Name": "{{ openshift_aws_clusterid }}"
+ register: vpcout
+
+- name: Create default security group for cluster
+ ec2_group:
+ name: "{{ openshift_aws_node_security_groups.default.name }}"
+ description: "{{ openshift_aws_node_security_groups.default.desc }}"
+ region: "{{ openshift_aws_region }}"
+ vpc_id: "{{ vpcout.vpcs[0].id }}"
+ rules: "{{ openshift_aws_node_security_groups.default.rules | default(omit, True)}}"
+ register: sg_default_created
+
+- name: create the node group sgs
+ ec2_group:
+ name: "{{ item.name}}"
+ description: "{{ item.desc }}"
+ rules: "{{ item.rules if 'rules' in item else [] }}"
+ region: "{{ openshift_aws_region }}"
+ vpc_id: "{{ vpcout.vpcs[0].id }}"
+ register: sg_create
+ with_items:
+ - "{{ openshift_aws_node_security_groups[openshift_aws_node_group_type]}}"
+
+- name: create the k8s sgs for the node group
+ ec2_group:
+ name: "{{ item.name }}_k8s"
+ description: "{{ item.desc }} for k8s"
+ region: "{{ openshift_aws_region }}"
+ vpc_id: "{{ vpcout.vpcs[0].id }}"
+ register: k8s_sg_create
+ with_items:
+ - "{{ openshift_aws_node_security_groups[openshift_aws_node_group_type]}}"
+
+- name: tag sg groups with proper tags
+ ec2_tag:
+ tags:
+ KubernetesCluster: "{{ openshift_aws_clusterid }}"
+ resource: "{{ item.group_id }}"
+ region: "{{ openshift_aws_region }}"
+ with_items: "{{ k8s_sg_create.results }}"
diff --git a/roles/openshift_aws/tasks/ssh_keys.yml b/roles/openshift_aws/tasks/ssh_keys.yml
new file mode 100644
index 000000000..f439ce74e
--- /dev/null
+++ b/roles/openshift_aws/tasks/ssh_keys.yml
@@ -0,0 +1,8 @@
+---
+- name: Add the public keys for the users
+ ec2_key:
+ name: "{{ item.key_name }}"
+ key_material: "{{ item.pub_key }}"
+ region: "{{ openshift_aws_region }}"
+ with_items: "{{ openshift_aws_users }}"
+ no_log: True
diff --git a/roles/openshift_aws/tasks/vpc.yml b/roles/openshift_aws/tasks/vpc.yml
new file mode 100644
index 000000000..ce2c8eac5
--- /dev/null
+++ b/roles/openshift_aws/tasks/vpc.yml
@@ -0,0 +1,52 @@
+---
+- name: Create AWS VPC
+ ec2_vpc_net:
+ state: present
+ cidr_block: "{{ openshift_aws_vpc.cidr }}"
+ dns_support: True
+ dns_hostnames: True
+ region: "{{ openshift_aws_region }}"
+ name: "{{ openshift_aws_clusterid }}"
+ tags: "{{ openshift_aws_vpc_tags }}"
+ register: vpc
+
+- name: Sleep to avoid a race condition when creating the vpc
+ pause:
+ seconds: 5
+ when: vpc.changed
+
+- name: assign the vpc igw
+ ec2_vpc_igw:
+ region: "{{ openshift_aws_region }}"
+ vpc_id: "{{ vpc.vpc.id }}"
+ register: igw
+
+- name: assign the vpc subnets
+ ec2_vpc_subnet:
+ region: "{{ openshift_aws_region }}"
+ vpc_id: "{{ vpc.vpc.id }}"
+ cidr: "{{ item.cidr }}"
+ az: "{{ item.az }}"
+ resource_tags:
+ Name: "{{ item.az }}"
+ with_items: "{{ openshift_aws_vpc.subnets[openshift_aws_region] }}"
+
+- name: Grab the route tables from our VPC
+ ec2_vpc_route_table_facts:
+ region: "{{ openshift_aws_region }}"
+ filters:
+ vpc-id: "{{ vpc.vpc.id }}"
+ register: route_table
+
+- name: update the route table in the vpc
+ ec2_vpc_route_table:
+ lookup: id
+ route_table_id: "{{ route_table.route_tables[0].id }}"
+ vpc_id: "{{ vpc.vpc.id }}"
+ region: "{{ openshift_aws_region }}"
+ tags:
+ Name: "{{ openshift_aws_vpc_name }}"
+ routes:
+ - dest: 0.0.0.0/0
+ gateway_id: igw
+ register: route_table_out
diff --git a/roles/openshift_cfme/defaults/main.yml b/roles/openshift_cfme/defaults/main.yml
index 393bee1f3..b82c2e602 100644
--- a/roles/openshift_cfme/defaults/main.yml
+++ b/roles/openshift_cfme/defaults/main.yml
@@ -27,8 +27,6 @@ openshift_cfme_pv_data:
# Tuning parameter to use more than 5 images at once from an ImageStream
openshift_cfme_maxImagesBulkImportedPerRepository: 100
-# Hostname/IP of the NFS server. Currently defaults to first master
-openshift_cfme_nfs_server: "{{ groups.nfs.0 }}"
# TODO: Refactor '_install_app' variable. This is just for testing but
# maybe in the future it should control the entire yes/no for CFME.
#
diff --git a/roles/openshift_cfme/meta/main.yml b/roles/openshift_cfme/meta/main.yml
index 9200f2c3c..162d817f0 100644
--- a/roles/openshift_cfme/meta/main.yml
+++ b/roles/openshift_cfme/meta/main.yml
@@ -16,5 +16,4 @@ galaxy_info:
dependencies:
- role: lib_openshift
- role: lib_utils
-- role: openshift_common
- role: openshift_master_facts
diff --git a/roles/openshift_cfme/tasks/nfs.yml b/roles/openshift_cfme/tasks/nfs.yml
index 8db45492e..ca04628a8 100644
--- a/roles/openshift_cfme/tasks/nfs.yml
+++ b/roles/openshift_cfme/tasks/nfs.yml
@@ -1,6 +1,13 @@
---
# Tasks to statically provision NFS volumes
# Include if not using dynamic volume provisioning
+
+- name: Set openshift_cfme_nfs_server fact
+ when: openshift_cfme_nfs_server is not defined
+ set_fact:
+ # Hostname/IP of the NFS server. Currently defaults to first master
+ openshift_cfme_nfs_server: "{{ oo_nfs_to_config.0 }}"
+
- name: Ensure the /exports/ directory exists
file:
path: /exports/
diff --git a/roles/openshift_cfme/templates/miq-pv-db.yaml.j2 b/roles/openshift_cfme/templates/miq-pv-db.yaml.j2
index b8c3bb277..280f3e97a 100644
--- a/roles/openshift_cfme/templates/miq-pv-db.yaml.j2
+++ b/roles/openshift_cfme/templates/miq-pv-db.yaml.j2
@@ -8,6 +8,6 @@ spec:
accessModes:
- ReadWriteOnce
nfs:
- path: /exports/miq-pv01
+ path: {{ openshift_cfme_nfs_directory }}/miq-pv01
server: {{ openshift_cfme_nfs_server }}
persistentVolumeReclaimPolicy: Retain
diff --git a/roles/openshift_cfme/templates/miq-pv-region.yaml.j2 b/roles/openshift_cfme/templates/miq-pv-region.yaml.j2
index 7218773f0..fe80dffa5 100644
--- a/roles/openshift_cfme/templates/miq-pv-region.yaml.j2
+++ b/roles/openshift_cfme/templates/miq-pv-region.yaml.j2
@@ -8,6 +8,6 @@ spec:
accessModes:
- ReadWriteOnce
nfs:
- path: /exports/miq-pv02
+ path: {{ openshift_cfme_nfs_directory }}/miq-pv02
server: {{ openshift_cfme_nfs_server }}
persistentVolumeReclaimPolicy: Retain
diff --git a/roles/openshift_cfme/templates/miq-pv-server.yaml.j2 b/roles/openshift_cfme/templates/miq-pv-server.yaml.j2
index 7b40b6c69..f84b67ea9 100644
--- a/roles/openshift_cfme/templates/miq-pv-server.yaml.j2
+++ b/roles/openshift_cfme/templates/miq-pv-server.yaml.j2
@@ -8,6 +8,6 @@ spec:
accessModes:
- ReadWriteOnce
nfs:
- path: /exports/miq-pv03
+ path: {{ openshift_cfme_nfs_directory }}/miq-pv03
server: {{ openshift_cfme_nfs_server }}
persistentVolumeReclaimPolicy: Retain
diff --git a/roles/openshift_cli/meta/main.yml b/roles/openshift_cli/meta/main.yml
index c1de367d9..29ed82783 100644
--- a/roles/openshift_cli/meta/main.yml
+++ b/roles/openshift_cli/meta/main.yml
@@ -14,5 +14,4 @@ galaxy_info:
dependencies:
- role: openshift_docker
when: not skip_docker_role | default(False) | bool
-- role: openshift_common
-- role: openshift_cli_facts
+- role: openshift_facts
diff --git a/roles/openshift_cli/tasks/main.yml b/roles/openshift_cli/tasks/main.yml
index c716a0860..9e61805f9 100644
--- a/roles/openshift_cli/tasks/main.yml
+++ b/roles/openshift_cli/tasks/main.yml
@@ -1,6 +1,6 @@
---
- set_fact:
- l_use_crio: "{{ openshift_docker_use_crio | default(false) }}"
+ l_use_crio: "{{ openshift_use_crio | default(false) }}"
- name: Install clients
package: name={{ openshift.common.service_type }}-clients state=present
diff --git a/roles/openshift_cli_facts/meta/main.yml b/roles/openshift_cli_facts/meta/main.yml
deleted file mode 100644
index 59acde215..000000000
--- a/roles/openshift_cli_facts/meta/main.yml
+++ /dev/null
@@ -1,15 +0,0 @@
----
-galaxy_info:
- author: Jason DeTiberus
- description: OpenShift CLI Facts
- company: Red Hat, Inc.
- license: Apache License, Version 2.0
- min_ansible_version: 1.9
- platforms:
- - name: EL
- versions:
- - 7
- categories:
- - cloud
-dependencies:
-- role: openshift_facts
diff --git a/roles/openshift_cli_facts/tasks/main.yml b/roles/openshift_cli_facts/tasks/main.yml
deleted file mode 100644
index dd1ed8965..000000000
--- a/roles/openshift_cli_facts/tasks/main.yml
+++ /dev/null
@@ -1,6 +0,0 @@
----
-# TODO: move this to a new 'cli' role
-- openshift_facts:
- role: common
- local_facts:
- cli_image: "{{ osm_image | default(None) }}"
diff --git a/roles/openshift_clock/defaults/main.yml b/roles/openshift_clock/defaults/main.yml
new file mode 100644
index 000000000..a94f67199
--- /dev/null
+++ b/roles/openshift_clock/defaults/main.yml
@@ -0,0 +1,2 @@
+---
+openshift_clock_enabled: True
diff --git a/roles/openshift_clock/meta/main.yml b/roles/openshift_clock/meta/main.yml
index 3e175beb0..d1e86d826 100644
--- a/roles/openshift_clock/meta/main.yml
+++ b/roles/openshift_clock/meta/main.yml
@@ -11,5 +11,4 @@ galaxy_info:
- 7
categories:
- cloud
-dependencies:
-- { role: openshift_facts }
+dependencies: []
diff --git a/roles/openshift_clock/tasks/main.yaml b/roles/openshift_clock/tasks/main.yaml
index 3911201ea..f8b02524a 100644
--- a/roles/openshift_clock/tasks/main.yaml
+++ b/roles/openshift_clock/tasks/main.yaml
@@ -1,14 +1,15 @@
---
-- name: Set clock facts
- openshift_facts:
- role: clock
- local_facts:
- enabled: "{{ openshift_clock_enabled | default(None) }}"
+- name: Determine if chrony is installed
+ command: rpm -q chrony
+ failed_when: false
+ register: chrony_installed
- name: Install ntp package
package: name=ntp state=present
- when: openshift.clock.enabled | bool and not openshift.clock.chrony_installed | bool
+ when:
+ - openshift_clock_enabled | bool
+ - chrony_installed.rc != 0
- name: Start and enable ntpd/chronyd
- shell: timedatectl set-ntp true
- when: openshift.clock.enabled | bool
+ command: timedatectl set-ntp true
+ when: openshift_clock_enabled | bool
diff --git a/roles/openshift_common/README.md b/roles/openshift_common/README.md
deleted file mode 100644
index 2a271854b..000000000
--- a/roles/openshift_common/README.md
+++ /dev/null
@@ -1,45 +0,0 @@
-OpenShift/Atomic Enterprise Common
-===================================
-
-OpenShift/Atomic Enterprise common installation and configuration tasks.
-
-Requirements
-------------
-
-A RHEL 7.1 host pre-configured with access to the rhel-7-server-rpms,
-rhel-7-server-extra-rpms, and rhel-7-server-ose-3.0-rpms repos.
-
-Role Variables
---------------
-
-| Name | Default value | |
-|---------------------------|-------------------|---------------------------------------------|
-| openshift_cluster_id | default | Cluster name if multiple OpenShift clusters |
-| openshift_debug_level | 2 | Global openshift debug log verbosity |
-| openshift_hostname | UNDEF | Internal hostname to use for this host (this value will set the hostname on the system) |
-| openshift_ip | UNDEF | Internal IP address to use for this host |
-| openshift_public_hostname | UNDEF | Public hostname to use for this host |
-| openshift_public_ip | UNDEF | Public IP address to use for this host |
-| openshift_portal_net | UNDEF | Service IP CIDR |
-
-Dependencies
-------------
-
-os_firewall
-openshift_facts
-openshift_repos
-
-Example Playbook
-----------------
-
-TODO
-
-License
--------
-
-Apache License, Version 2.0
-
-Author Information
-------------------
-
-Jason DeTiberus (jdetiber@redhat.com)
diff --git a/roles/openshift_common/defaults/main.yml b/roles/openshift_common/defaults/main.yml
deleted file mode 100644
index 267c03605..000000000
--- a/roles/openshift_common/defaults/main.yml
+++ /dev/null
@@ -1,3 +0,0 @@
----
-openshift_cluster_id: 'default'
-openshift_debug_level: 2
diff --git a/roles/openshift_common/meta/main.yml b/roles/openshift_common/meta/main.yml
deleted file mode 100644
index 7cc95d8fa..000000000
--- a/roles/openshift_common/meta/main.yml
+++ /dev/null
@@ -1,15 +0,0 @@
----
-galaxy_info:
- author: Jason DeTiberus
- description: OpenShift Common
- company: Red Hat, Inc.
- license: Apache License, Version 2.0
- min_ansible_version: 1.7
- platforms:
- - name: EL
- versions:
- - 7
- categories:
- - cloud
-dependencies:
-- role: openshift_facts
diff --git a/roles/openshift_common/tasks/main.yml b/roles/openshift_common/tasks/main.yml
deleted file mode 100644
index 51313a258..000000000
--- a/roles/openshift_common/tasks/main.yml
+++ /dev/null
@@ -1,78 +0,0 @@
----
-- fail:
- msg: Flannel can not be used with openshift sdn, set openshift_use_openshift_sdn=false if you want to use flannel
- when: openshift_use_openshift_sdn | default(true) | bool and openshift_use_flannel | default(false) | bool
-
-- fail:
- msg: Nuage sdn can not be used with openshift sdn, set openshift_use_openshift_sdn=false if you want to use nuage
- when: openshift_use_openshift_sdn | default(true) | bool and openshift_use_nuage | default(false) | bool
-
-- fail:
- msg: Nuage sdn can not be used with flannel
- when: openshift_use_flannel | default(false) | bool and openshift_use_nuage | default(false) | bool
-
-- fail:
- msg: Contiv can not be used with openshift sdn, set openshift_use_openshift_sdn=false if you want to use contiv
- when: openshift_use_openshift_sdn | default(true) | bool and openshift_use_contiv | default(false) | bool
-
-- fail:
- msg: Contiv can not be used with flannel
- when: openshift_use_flannel | default(false) | bool and openshift_use_contiv | default(false) | bool
-
-- fail:
- msg: Contiv can not be used with nuage
- when: openshift_use_nuage | default(false) | bool and openshift_use_contiv | default(false) | bool
-
-- fail:
- msg: Calico can not be used with openshift sdn, set openshift_use_openshift_sdn=false if you want to use Calico
- when: openshift_use_openshift_sdn | default(true) | bool and openshift_use_calico | default(false) | bool
-
-- fail:
- msg: The Calico playbook does not yet integrate with the Flannel playbook in Openshift. Set either openshift_use_calico or openshift_use_flannel, but not both.
- when: openshift_use_calico | default(false) | bool and openshift_use_flannel | default(false) | bool
-
-- fail:
- msg: Calico can not be used with Nuage in Openshift. Set either openshift_use_calico or openshift_use_nuage, but not both
- when: openshift_use_calico | default(false) | bool and openshift_use_nuage | default(false) | bool
-
-- fail:
- msg: Calico can not be used with Contiv in Openshift. Set either openshift_use_calico or openshift_use_contiv, but not both
- when: openshift_use_calico | default(false) | bool and openshift_use_contiv | default(false) | bool
-
-- fail:
- msg: openshift_hostname must be 64 characters or less
- when: openshift_hostname is defined and openshift_hostname | length > 64
-
-- name: Set common Cluster facts
- openshift_facts:
- role: common
- local_facts:
- install_examples: "{{ openshift_install_examples | default(True) }}"
- use_openshift_sdn: "{{ openshift_use_openshift_sdn | default(None) }}"
- sdn_network_plugin_name: "{{ os_sdn_network_plugin_name | default(None) }}"
- use_flannel: "{{ openshift_use_flannel | default(None) }}"
- use_calico: "{{openshift_use_calico | default(None) }}"
- use_nuage: "{{ openshift_use_nuage | default(None) }}"
- use_contiv: "{{ openshift_use_contiv | default(None) }}"
- use_manageiq: "{{ openshift_use_manageiq | default(None) }}"
- data_dir: "{{ openshift_data_dir | default(None) }}"
- use_dnsmasq: "{{ openshift_use_dnsmasq | default(None) }}"
-
-- name: Install the base package for versioning
- package:
- name: "{{ openshift.common.service_type }}{{ openshift_pkg_version | default('') | oo_image_tag_to_rpm_version(include_dash=True) }}"
- state: present
- when: not openshift.common.is_containerized | bool
-
-- name: Set version facts
- openshift_facts:
-
-# For enterprise versions < 3.1 and origin versions < 1.1 we want to set the
-# hostname by default.
-- set_fact:
- set_hostname_default: "{{ not openshift.common.version_gte_3_1_or_1_1 }}"
-
-- name: Set hostname
- command: >
- hostnamectl set-hostname {{ openshift.common.hostname }}
- when: openshift_set_hostname | default(set_hostname_default) | bool
diff --git a/roles/openshift_docker_facts/tasks/main.yml b/roles/openshift_docker_facts/tasks/main.yml
index 516d7dc29..334150f63 100644
--- a/roles/openshift_docker_facts/tasks/main.yml
+++ b/roles/openshift_docker_facts/tasks/main.yml
@@ -17,7 +17,7 @@
hosted_registry_insecure: "{{ openshift_docker_hosted_registry_insecure | default(openshift.docker.hosted_registry_insecure | default(False)) }}"
hosted_registry_network: "{{ openshift_docker_hosted_registry_network | default(None) }}"
use_system_container: "{{ openshift_docker_use_system_container | default(False) }}"
- use_crio: "{{ openshift_docker_use_crio | default(False) }}"
+ use_crio: "{{ openshift_use_crio | default(False) }}"
- role: node
local_facts:
sdn_mtu: "{{ openshift_node_sdn_mtu | default(None) }}"
diff --git a/roles/openshift_examples/README.md b/roles/openshift_examples/README.md
index 8cc479c73..014cef111 100644
--- a/roles/openshift_examples/README.md
+++ b/roles/openshift_examples/README.md
@@ -21,13 +21,13 @@ Facts
Role Variables
--------------
-| Name | Default value | |
-|-------------------------------------|-----------------------------------------------------|------------------------------------------|
-| openshift_examples_load_centos | true when openshift_deployment_typenot 'enterprise' | Load centos image streams |
-| openshift_examples_load_rhel | true if openshift_deployment_type is 'enterprise' | Load rhel image streams |
-| openshift_examples_load_db_templates| true | Loads database templates |
-| openshift_examples_load_quickstarts | true | Loads quickstarts ie: nodejs, rails, etc |
-| openshift_examples_load_xpaas | false | Loads xpass streams and templates |
+| Name | Default value | |
+|-------------------------------------|----------------------------------------------------------------|------------------------------------------|
+| openshift_examples_load_centos | true when openshift_deployment_type not 'openshift-enterprise' | Load centos image streams |
+| openshift_examples_load_rhel | true if openshift_deployment_type is 'openshift-enterprise' | Load rhel image streams |
+| openshift_examples_load_db_templates| true | Loads database templates |
+| openshift_examples_load_quickstarts | true | Loads quickstarts ie: nodejs, rails, etc |
+| openshift_examples_load_xpaas | false | Loads xpass streams and templates |
Dependencies
diff --git a/roles/openshift_examples/examples-sync.sh b/roles/openshift_examples/examples-sync.sh
index 3a8ce55c4..ca3f219d8 100755
--- a/roles/openshift_examples/examples-sync.sh
+++ b/roles/openshift_examples/examples-sync.sh
@@ -40,5 +40,6 @@ popd
wget https://raw.githubusercontent.com/redhat-developer/s2i-dotnetcore/master/dotnet_imagestreams.json -O ${EXAMPLES_BASE}/image-streams/dotnet_imagestreams.json
wget https://raw.githubusercontent.com/redhat-developer/s2i-dotnetcore/master/templates/dotnet-example.json -O ${EXAMPLES_BASE}/quickstart-templates/dotnet-example.json
wget https://raw.githubusercontent.com/redhat-developer/s2i-dotnetcore/master/templates/dotnet-pgsql-persistent.json -O ${EXAMPLES_BASE}/quickstart-templates/dotnet-pgsql-persistent.json
+wget https://raw.githubusercontent.com/redhat-developer/s2i-dotnetcore/master/templates/dotnet-runtime-example.json -O ${EXAMPLES_BASE}/quickstart-templates/dotnet-runtime-example.json
git diff files/examples
diff --git a/roles/openshift_examples/files/examples/v1.5/cfme-templates/cfme-template.yaml b/roles/openshift_examples/files/examples/v1.5/cfme-templates/cfme-template.yaml
index 3bc6c5813..fd57a864c 100644
--- a/roles/openshift_examples/files/examples/v1.5/cfme-templates/cfme-template.yaml
+++ b/roles/openshift_examples/files/examples/v1.5/cfme-templates/cfme-template.yaml
@@ -10,6 +10,12 @@ metadata:
iconClass: "icon-rails"
objects:
- apiVersion: v1
+ kind: Secret
+ metadata:
+ name: "${NAME}-secrets"
+ stringData:
+ pg-password: "${DATABASE_PASSWORD}"
+- apiVersion: v1
kind: Service
metadata:
annotations:
@@ -148,7 +154,10 @@ objects:
value: "${DATABASE_USER}"
-
name: "POSTGRESQL_PASSWORD"
- value: "${DATABASE_PASSWORD}"
+ valueFrom:
+ secretKeyRef:
+ name: "${NAME}-secrets"
+ key: "pg-password"
-
name: "POSTGRESQL_DATABASE"
value: "${DATABASE_NAME}"
@@ -345,7 +354,10 @@ objects:
value: "${DATABASE_USER}"
-
name: "POSTGRESQL_PASSWORD"
- value: "${DATABASE_PASSWORD}"
+ valueFrom:
+ secretKeyRef:
+ name: "${NAME}-secrets"
+ key: "pg-password"
-
name: "POSTGRESQL_DATABASE"
value: "${DATABASE_NAME}"
@@ -386,7 +398,8 @@ parameters:
displayName: "PostgreSQL Password"
required: true
description: "Password for the PostgreSQL user."
- value: "smartvm"
+ from: "[a-zA-Z0-9]{8}"
+ generate: expression
-
name: "DATABASE_NAME"
required: true
diff --git a/roles/openshift_examples/files/examples/v3.6/cfme-templates/cfme-template.yaml b/roles/openshift_examples/files/examples/v3.6/cfme-templates/cfme-template.yaml
index 3bc6c5813..fd57a864c 100644
--- a/roles/openshift_examples/files/examples/v3.6/cfme-templates/cfme-template.yaml
+++ b/roles/openshift_examples/files/examples/v3.6/cfme-templates/cfme-template.yaml
@@ -10,6 +10,12 @@ metadata:
iconClass: "icon-rails"
objects:
- apiVersion: v1
+ kind: Secret
+ metadata:
+ name: "${NAME}-secrets"
+ stringData:
+ pg-password: "${DATABASE_PASSWORD}"
+- apiVersion: v1
kind: Service
metadata:
annotations:
@@ -148,7 +154,10 @@ objects:
value: "${DATABASE_USER}"
-
name: "POSTGRESQL_PASSWORD"
- value: "${DATABASE_PASSWORD}"
+ valueFrom:
+ secretKeyRef:
+ name: "${NAME}-secrets"
+ key: "pg-password"
-
name: "POSTGRESQL_DATABASE"
value: "${DATABASE_NAME}"
@@ -345,7 +354,10 @@ objects:
value: "${DATABASE_USER}"
-
name: "POSTGRESQL_PASSWORD"
- value: "${DATABASE_PASSWORD}"
+ valueFrom:
+ secretKeyRef:
+ name: "${NAME}-secrets"
+ key: "pg-password"
-
name: "POSTGRESQL_DATABASE"
value: "${DATABASE_NAME}"
@@ -386,7 +398,8 @@ parameters:
displayName: "PostgreSQL Password"
required: true
description: "Password for the PostgreSQL user."
- value: "smartvm"
+ from: "[a-zA-Z0-9]{8}"
+ generate: expression
-
name: "DATABASE_NAME"
required: true
diff --git a/roles/openshift_examples/files/examples/v3.6/db-templates/OWNERS b/roles/openshift_examples/files/examples/v3.6/db-templates/OWNERS
new file mode 100644
index 000000000..cbdc20f41
--- /dev/null
+++ b/roles/openshift_examples/files/examples/v3.6/db-templates/OWNERS
@@ -0,0 +1,12 @@
+reviewers:
+ - bparees
+ - gabemontero
+ - mfojtik
+ - dinhxuanvu
+ - jim-minter
+ - spadgett
+approvers:
+ - bparees
+ - mfojtik
+ - spadgett
+ - jupierce
diff --git a/roles/openshift_examples/files/examples/v3.6/db-templates/mariadb-ephemeral-template.json b/roles/openshift_examples/files/examples/v3.6/db-templates/mariadb-ephemeral-template.json
index 536f7275e..6500ed0d3 100644
--- a/roles/openshift_examples/files/examples/v3.6/db-templates/mariadb-ephemeral-template.json
+++ b/roles/openshift_examples/files/examples/v3.6/db-templates/mariadb-ephemeral-template.json
@@ -27,13 +27,15 @@
"annotations": {
"template.openshift.io/expose-username": "{.data['database-user']}",
"template.openshift.io/expose-password": "{.data['database-password']}",
- "template.openshift.io/expose-root_password": "{.data['database-root-password']}"
+ "template.openshift.io/expose-root_password": "{.data['database-root-password']}",
+ "template.openshift.io/expose-database_name": "{.data['database-name']}"
}
},
"stringData" : {
"database-user" : "${MYSQL_USER}",
"database-password" : "${MYSQL_PASSWORD}",
- "database-root-password" : "${MYSQL_ROOT_PASSWORD}"
+ "database-root-password" : "${MYSQL_ROOT_PASSWORD}",
+ "database-name" : "${MYSQL_DATABASE}"
}
},
{
@@ -61,7 +63,10 @@
"kind": "DeploymentConfig",
"apiVersion": "v1",
"metadata": {
- "name": "${DATABASE_SERVICE_NAME}"
+ "name": "${DATABASE_SERVICE_NAME}",
+ "annotations": {
+ "template.alpha.openshift.io/wait-for-ready": "true"
+ }
},
"spec": {
"strategy": {
@@ -151,7 +156,12 @@
},
{
"name": "MYSQL_DATABASE",
- "value": "${MYSQL_DATABASE}"
+ "valueFrom": {
+ "secretKeyRef" : {
+ "name" : "${DATABASE_SERVICE_NAME}",
+ "key" : "database-name"
+ }
+ }
}
],
"resources": {
diff --git a/roles/openshift_examples/files/examples/v3.6/db-templates/mariadb-persistent-template.json b/roles/openshift_examples/files/examples/v3.6/db-templates/mariadb-persistent-template.json
index 3b7fdccce..4378fa4a0 100644
--- a/roles/openshift_examples/files/examples/v3.6/db-templates/mariadb-persistent-template.json
+++ b/roles/openshift_examples/files/examples/v3.6/db-templates/mariadb-persistent-template.json
@@ -27,13 +27,15 @@
"annotations": {
"template.openshift.io/expose-username": "{.data['database-user']}",
"template.openshift.io/expose-password": "{.data['database-password']}",
- "template.openshift.io/expose-root_password": "{.data['database-root-password']}"
+ "template.openshift.io/expose-root_password": "{.data['database-root-password']}",
+ "template.openshift.io/expose-database_name": "{.data['database-name']}"
}
},
"stringData" : {
"database-user" : "${MYSQL_USER}",
"database-password" : "${MYSQL_PASSWORD}",
- "database-root-password" : "${MYSQL_ROOT_PASSWORD}"
+ "database-root-password" : "${MYSQL_ROOT_PASSWORD}",
+ "database-name" : "${MYSQL_DATABASE}"
}
},
{
@@ -78,7 +80,10 @@
"kind": "DeploymentConfig",
"apiVersion": "v1",
"metadata": {
- "name": "${DATABASE_SERVICE_NAME}"
+ "name": "${DATABASE_SERVICE_NAME}",
+ "annotations": {
+ "template.alpha.openshift.io/wait-for-ready": "true"
+ }
},
"spec": {
"strategy": {
@@ -168,7 +173,12 @@
},
{
"name": "MYSQL_DATABASE",
- "value": "${MYSQL_DATABASE}"
+ "valueFrom": {
+ "secretKeyRef" : {
+ "name" : "${DATABASE_SERVICE_NAME}",
+ "key" : "database-name"
+ }
+ }
}
],
"resources": {
diff --git a/roles/openshift_examples/files/examples/v3.6/db-templates/mongodb-ephemeral-template.json b/roles/openshift_examples/files/examples/v3.6/db-templates/mongodb-ephemeral-template.json
index ee274194f..7271a2c69 100644
--- a/roles/openshift_examples/files/examples/v3.6/db-templates/mongodb-ephemeral-template.json
+++ b/roles/openshift_examples/files/examples/v3.6/db-templates/mongodb-ephemeral-template.json
@@ -3,7 +3,6 @@
"apiVersion": "v1",
"metadata": {
"name": "mongodb-ephemeral",
- "creationTimestamp": null,
"annotations": {
"openshift.io/display-name": "MongoDB (Ephemeral)",
"description": "MongoDB database service, without persistent storage. For more information about using this template, including OpenShift considerations, see https://github.com/sclorg/mongodb-container/blob/master/3.2/README.md.\n\nWARNING: Any data stored will be lost upon pod destruction. Only use this template for testing",
@@ -28,13 +27,15 @@
"annotations": {
"template.openshift.io/expose-username": "{.data['database-user']}",
"template.openshift.io/expose-password": "{.data['database-password']}",
- "template.openshift.io/expose-admin_password": "{.data['database-admin-password']}"
+ "template.openshift.io/expose-admin_password": "{.data['database-admin-password']}",
+ "template.openshift.io/expose-database_name": "{.data['database-name']}"
}
},
"stringData" : {
"database-user" : "${MONGODB_USER}",
"database-password" : "${MONGODB_PASSWORD}",
- "database-admin-password" : "${MONGODB_ADMIN_PASSWORD}"
+ "database-admin-password" : "${MONGODB_ADMIN_PASSWORD}",
+ "database-name" : "${MONGODB_DATABASE}"
}
},
{
@@ -42,7 +43,6 @@
"apiVersion": "v1",
"metadata": {
"name": "${DATABASE_SERVICE_NAME}",
- "creationTimestamp": null,
"annotations": {
"template.openshift.io/expose-uri": "mongodb://{.spec.clusterIP}:{.spec.ports[?(.name==\"mongo\")].port}"
}
@@ -72,7 +72,9 @@
"apiVersion": "v1",
"metadata": {
"name": "${DATABASE_SERVICE_NAME}",
- "creationTimestamp": null
+ "annotations": {
+ "template.alpha.openshift.io/wait-for-ready": "true"
+ }
},
"spec": {
"strategy": {
@@ -104,7 +106,6 @@
},
"template": {
"metadata": {
- "creationTimestamp": null,
"labels": {
"name": "${DATABASE_SERVICE_NAME}"
}
@@ -164,7 +165,12 @@
},
{
"name": "MONGODB_DATABASE",
- "value": "${MONGODB_DATABASE}"
+ "valueFrom": {
+ "secretKeyRef" : {
+ "name" : "${DATABASE_SERVICE_NAME}",
+ "key" : "database-name"
+ }
+ }
}
],
"resources": {
diff --git a/roles/openshift_examples/files/examples/v3.6/db-templates/mongodb-persistent-template.json b/roles/openshift_examples/files/examples/v3.6/db-templates/mongodb-persistent-template.json
index e5ba43669..d70d2263f 100644
--- a/roles/openshift_examples/files/examples/v3.6/db-templates/mongodb-persistent-template.json
+++ b/roles/openshift_examples/files/examples/v3.6/db-templates/mongodb-persistent-template.json
@@ -3,7 +3,6 @@
"apiVersion": "v1",
"metadata": {
"name": "mongodb-persistent",
- "creationTimestamp": null,
"annotations": {
"openshift.io/display-name": "MongoDB (Persistent)",
"description": "MongoDB database service, with persistent storage. For more information about using this template, including OpenShift considerations, see https://github.com/sclorg/mongodb-container/blob/master/3.2/README.md.\n\nNOTE: Scaling to more than one replica is not supported. You must have persistent volumes available in your cluster to use this template.",
@@ -28,13 +27,15 @@
"annotations": {
"template.openshift.io/expose-username": "{.data['database-user']}",
"template.openshift.io/expose-password": "{.data['database-password']}",
- "template.openshift.io/expose-admin_password": "{.data['database-admin-password']}"
+ "template.openshift.io/expose-admin_password": "{.data['database-admin-password']}",
+ "template.openshift.io/expose-database_name": "{.data['database-name']}"
}
},
"stringData" : {
"database-user" : "${MONGODB_USER}",
"database-password" : "${MONGODB_PASSWORD}",
- "database-admin-password" : "${MONGODB_ADMIN_PASSWORD}"
+ "database-admin-password" : "${MONGODB_ADMIN_PASSWORD}",
+ "database-name" : "${MONGODB_DATABASE}"
}
},
{
@@ -42,7 +43,6 @@
"apiVersion": "v1",
"metadata": {
"name": "${DATABASE_SERVICE_NAME}",
- "creationTimestamp": null,
"annotations": {
"template.openshift.io/expose-uri": "mongodb://{.spec.clusterIP}:{.spec.ports[?(.name==\"mongo\")].port}"
}
@@ -89,7 +89,9 @@
"apiVersion": "v1",
"metadata": {
"name": "${DATABASE_SERVICE_NAME}",
- "creationTimestamp": null
+ "annotations": {
+ "template.alpha.openshift.io/wait-for-ready": "true"
+ }
},
"spec": {
"strategy": {
@@ -121,7 +123,6 @@
},
"template": {
"metadata": {
- "creationTimestamp": null,
"labels": {
"name": "${DATABASE_SERVICE_NAME}"
}
@@ -181,7 +182,12 @@
},
{
"name": "MONGODB_DATABASE",
- "value": "${MONGODB_DATABASE}"
+ "valueFrom": {
+ "secretKeyRef" : {
+ "name" : "${DATABASE_SERVICE_NAME}",
+ "key" : "database-name"
+ }
+ }
}
],
"resources": {
diff --git a/roles/openshift_examples/files/examples/v3.6/db-templates/mysql-ephemeral-template.json b/roles/openshift_examples/files/examples/v3.6/db-templates/mysql-ephemeral-template.json
index 969e62ac5..54785993c 100644
--- a/roles/openshift_examples/files/examples/v3.6/db-templates/mysql-ephemeral-template.json
+++ b/roles/openshift_examples/files/examples/v3.6/db-templates/mysql-ephemeral-template.json
@@ -19,7 +19,7 @@
"template": "mysql-ephemeral-template"
},
"objects": [
- {
+ {
"kind": "Secret",
"apiVersion": "v1",
"metadata": {
@@ -27,13 +27,15 @@
"annotations": {
"template.openshift.io/expose-username": "{.data['database-user']}",
"template.openshift.io/expose-password": "{.data['database-password']}",
- "template.openshift.io/expose-root_password": "{.data['database-root-password']}"
+ "template.openshift.io/expose-root_password": "{.data['database-root-password']}",
+ "template.openshift.io/expose-database_name": "{.data['database-name']}"
}
},
"stringData" : {
"database-user" : "${MYSQL_USER}",
"database-password" : "${MYSQL_PASSWORD}",
- "database-root-password" : "${MYSQL_ROOT_PASSWORD}"
+ "database-root-password" : "${MYSQL_ROOT_PASSWORD}",
+ "database-name" : "${MYSQL_DATABASE}"
}
},
{
@@ -41,7 +43,6 @@
"apiVersion": "v1",
"metadata": {
"name": "${DATABASE_SERVICE_NAME}",
- "creationTimestamp": null,
"annotations": {
"template.openshift.io/expose-uri": "mysql://{.spec.clusterIP}:{.spec.ports[?(.name==\"mysql\")].port}"
}
@@ -71,7 +72,9 @@
"apiVersion": "v1",
"metadata": {
"name": "${DATABASE_SERVICE_NAME}",
- "creationTimestamp": null
+ "annotations": {
+ "template.alpha.openshift.io/wait-for-ready": "true"
+ }
},
"spec": {
"strategy": {
@@ -103,7 +106,6 @@
},
"template": {
"metadata": {
- "creationTimestamp": null,
"labels": {
"name": "${DATABASE_SERVICE_NAME}"
}
@@ -164,7 +166,12 @@
},
{
"name": "MYSQL_DATABASE",
- "value": "${MYSQL_DATABASE}"
+ "valueFrom": {
+ "secretKeyRef" : {
+ "name" : "${DATABASE_SERVICE_NAME}",
+ "key" : "database-name"
+ }
+ }
}
],
"resources": {
diff --git a/roles/openshift_examples/files/examples/v3.6/db-templates/mysql-persistent-template.json b/roles/openshift_examples/files/examples/v3.6/db-templates/mysql-persistent-template.json
index 4f39d41a5..2bd84b106 100644
--- a/roles/openshift_examples/files/examples/v3.6/db-templates/mysql-persistent-template.json
+++ b/roles/openshift_examples/files/examples/v3.6/db-templates/mysql-persistent-template.json
@@ -27,13 +27,15 @@
"annotations": {
"template.openshift.io/expose-username": "{.data['database-user']}",
"template.openshift.io/expose-password": "{.data['database-password']}",
- "template.openshift.io/expose-root_password": "{.data['database-root-password']}"
+ "template.openshift.io/expose-root_password": "{.data['database-root-password']}",
+ "template.openshift.io/expose-database_name": "{.data['database-name']}"
}
},
"stringData" : {
"database-user" : "${MYSQL_USER}",
"database-password" : "${MYSQL_PASSWORD}",
- "database-root-password" : "${MYSQL_ROOT_PASSWORD}"
+ "database-root-password" : "${MYSQL_ROOT_PASSWORD}",
+ "database-name" : "${MYSQL_DATABASE}"
}
},
{
@@ -78,7 +80,10 @@
"kind": "DeploymentConfig",
"apiVersion": "v1",
"metadata": {
- "name": "${DATABASE_SERVICE_NAME}"
+ "name": "${DATABASE_SERVICE_NAME}",
+ "annotations": {
+ "template.alpha.openshift.io/wait-for-ready": "true"
+ }
},
"spec": {
"strategy": {
@@ -168,7 +173,12 @@
},
{
"name": "MYSQL_DATABASE",
- "value": "${MYSQL_DATABASE}"
+ "valueFrom": {
+ "secretKeyRef" : {
+ "name" : "${DATABASE_SERVICE_NAME}",
+ "key" : "database-name"
+ }
+ }
}
],
"resources": {
diff --git a/roles/openshift_examples/files/examples/v3.6/db-templates/postgresql-ephemeral-template.json b/roles/openshift_examples/files/examples/v3.6/db-templates/postgresql-ephemeral-template.json
index c37102cb0..849c9d83f 100644
--- a/roles/openshift_examples/files/examples/v3.6/db-templates/postgresql-ephemeral-template.json
+++ b/roles/openshift_examples/files/examples/v3.6/db-templates/postgresql-ephemeral-template.json
@@ -3,7 +3,6 @@
"apiVersion": "v1",
"metadata": {
"name": "postgresql-ephemeral",
- "creationTimestamp": null,
"annotations": {
"openshift.io/display-name": "PostgreSQL (Ephemeral)",
"description": "PostgreSQL database service, without persistent storage. For more information about using this template, including OpenShift considerations, see https://github.com/sclorg/postgresql-container/blob/master/9.5.\n\nWARNING: Any data stored will be lost upon pod destruction. Only use this template for testing",
@@ -27,12 +26,14 @@
"name": "${DATABASE_SERVICE_NAME}",
"annotations": {
"template.openshift.io/expose-username": "{.data['database-user']}",
- "template.openshift.io/expose-password": "{.data['database-password']}"
+ "template.openshift.io/expose-password": "{.data['database-password']}",
+ "template.openshift.io/expose-database_name": "{.data['database-name']}"
}
},
"stringData" : {
"database-user" : "${POSTGRESQL_USER}",
- "database-password" : "${POSTGRESQL_PASSWORD}"
+ "database-password" : "${POSTGRESQL_PASSWORD}",
+ "database-name" : "${POSTGRESQL_DATABASE}"
}
},
{
@@ -40,7 +41,6 @@
"apiVersion": "v1",
"metadata": {
"name": "${DATABASE_SERVICE_NAME}",
- "creationTimestamp": null,
"annotations": {
"template.openshift.io/expose-uri": "postgres://{.spec.clusterIP}:{.spec.ports[?(.name==\"postgresql\")].port}"
}
@@ -70,7 +70,9 @@
"apiVersion": "v1",
"metadata": {
"name": "${DATABASE_SERVICE_NAME}",
- "creationTimestamp": null
+ "annotations": {
+ "template.alpha.openshift.io/wait-for-ready": "true"
+ }
},
"spec": {
"strategy": {
@@ -102,7 +104,6 @@
},
"template": {
"metadata": {
- "creationTimestamp": null,
"labels": {
"name": "${DATABASE_SERVICE_NAME}"
}
@@ -153,7 +154,12 @@
},
{
"name": "POSTGRESQL_DATABASE",
- "value": "${POSTGRESQL_DATABASE}"
+ "valueFrom": {
+ "secretKeyRef" : {
+ "name" : "${DATABASE_SERVICE_NAME}",
+ "key" : "database-name"
+ }
+ }
}
],
"resources": {
diff --git a/roles/openshift_examples/files/examples/v3.6/db-templates/postgresql-persistent-template.json b/roles/openshift_examples/files/examples/v3.6/db-templates/postgresql-persistent-template.json
index 32dc93a95..b622baa01 100644
--- a/roles/openshift_examples/files/examples/v3.6/db-templates/postgresql-persistent-template.json
+++ b/roles/openshift_examples/files/examples/v3.6/db-templates/postgresql-persistent-template.json
@@ -3,7 +3,6 @@
"apiVersion": "v1",
"metadata": {
"name": "postgresql-persistent",
- "creationTimestamp": null,
"annotations": {
"openshift.io/display-name": "PostgreSQL (Persistent)",
"description": "PostgreSQL database service, with persistent storage. For more information about using this template, including OpenShift considerations, see https://github.com/sclorg/postgresql-container/blob/master/9.5.\n\nNOTE: Scaling to more than one replica is not supported. You must have persistent volumes available in your cluster to use this template.",
@@ -27,12 +26,14 @@
"name": "${DATABASE_SERVICE_NAME}",
"annotations": {
"template.openshift.io/expose-username": "{.data['database-user']}",
- "template.openshift.io/expose-password": "{.data['database-password']}"
+ "template.openshift.io/expose-password": "{.data['database-password']}",
+ "template.openshift.io/expose-database_name": "{.data['database-name']}"
}
},
"stringData" : {
"database-user" : "${POSTGRESQL_USER}",
- "database-password" : "${POSTGRESQL_PASSWORD}"
+ "database-password" : "${POSTGRESQL_PASSWORD}",
+ "database-name" : "${POSTGRESQL_DATABASE}"
}
},
{
@@ -40,7 +41,6 @@
"apiVersion": "v1",
"metadata": {
"name": "${DATABASE_SERVICE_NAME}",
- "creationTimestamp": null,
"annotations": {
"template.openshift.io/expose-uri": "postgres://{.spec.clusterIP}:{.spec.ports[?(.name==\"postgresql\")].port}"
}
@@ -87,7 +87,9 @@
"apiVersion": "v1",
"metadata": {
"name": "${DATABASE_SERVICE_NAME}",
- "creationTimestamp": null
+ "annotations": {
+ "template.alpha.openshift.io/wait-for-ready": "true"
+ }
},
"spec": {
"strategy": {
@@ -119,7 +121,6 @@
},
"template": {
"metadata": {
- "creationTimestamp": null,
"labels": {
"name": "${DATABASE_SERVICE_NAME}"
}
@@ -170,7 +171,12 @@
},
{
"name": "POSTGRESQL_DATABASE",
- "value": "${POSTGRESQL_DATABASE}"
+ "valueFrom": {
+ "secretKeyRef" : {
+ "name" : "${DATABASE_SERVICE_NAME}",
+ "key" : "database-name"
+ }
+ }
}
],
"resources": {
diff --git a/roles/openshift_examples/files/examples/v3.6/db-templates/redis-ephemeral-template.json b/roles/openshift_examples/files/examples/v3.6/db-templates/redis-ephemeral-template.json
index 6bb683e52..15bdd079b 100644
--- a/roles/openshift_examples/files/examples/v3.6/db-templates/redis-ephemeral-template.json
+++ b/roles/openshift_examples/files/examples/v3.6/db-templates/redis-ephemeral-template.json
@@ -3,7 +3,6 @@
"apiVersion": "v1",
"metadata": {
"name": "redis-ephemeral",
- "creationTimestamp": null,
"annotations": {
"openshift.io/display-name": "Redis (Ephemeral)",
"description": "Redis in-memory data structure store, without persistent storage. For more information about using this template, including OpenShift considerations, see https://github.com/sclorg/redis-container/blob/master/3.2.\n\nWARNING: Any data stored will be lost upon pod destruction. Only use this template for testing",
@@ -38,7 +37,6 @@
"apiVersion": "v1",
"metadata": {
"name": "${DATABASE_SERVICE_NAME}",
- "creationTimestamp": null,
"annotations": {
"template.openshift.io/expose-uri": "redis://{.spec.clusterIP}:{.spec.ports[?(.name==\"redis\")].port}"
}
@@ -68,7 +66,9 @@
"apiVersion": "v1",
"metadata": {
"name": "${DATABASE_SERVICE_NAME}",
- "creationTimestamp": null
+ "annotations": {
+ "template.alpha.openshift.io/wait-for-ready": "true"
+ }
},
"spec": {
"strategy": {
@@ -100,7 +100,6 @@
},
"template": {
"metadata": {
- "creationTimestamp": null,
"labels": {
"name": "${DATABASE_SERVICE_NAME}"
}
diff --git a/roles/openshift_examples/files/examples/v3.6/db-templates/redis-persistent-template.json b/roles/openshift_examples/files/examples/v3.6/db-templates/redis-persistent-template.json
index 9e8be2309..1e31b02e0 100644
--- a/roles/openshift_examples/files/examples/v3.6/db-templates/redis-persistent-template.json
+++ b/roles/openshift_examples/files/examples/v3.6/db-templates/redis-persistent-template.json
@@ -3,7 +3,6 @@
"apiVersion": "v1",
"metadata": {
"name": "redis-persistent",
- "creationTimestamp": null,
"annotations": {
"openshift.io/display-name": "Redis (Persistent)",
"description": "Redis in-memory data structure store, with persistent storage. For more information about using this template, including OpenShift considerations, see https://github.com/sclorg/redis-container/blob/master/3.2.\n\nNOTE: You must have persistent volumes available in your cluster to use this template.",
@@ -38,7 +37,6 @@
"apiVersion": "v1",
"metadata": {
"name": "${DATABASE_SERVICE_NAME}",
- "creationTimestamp": null,
"annotations": {
"template.openshift.io/expose-uri": "redis://{.spec.clusterIP}:{.spec.ports[?(.name==\"redis\")].port}"
}
@@ -85,7 +83,9 @@
"apiVersion": "v1",
"metadata": {
"name": "${DATABASE_SERVICE_NAME}",
- "creationTimestamp": null
+ "annotations": {
+ "template.alpha.openshift.io/wait-for-ready": "true"
+ }
},
"spec": {
"strategy": {
@@ -117,7 +117,6 @@
},
"template": {
"metadata": {
- "creationTimestamp": null,
"labels": {
"name": "${DATABASE_SERVICE_NAME}"
}
diff --git a/roles/openshift_examples/files/examples/v3.6/image-streams/OWNERS b/roles/openshift_examples/files/examples/v3.6/image-streams/OWNERS
new file mode 100644
index 000000000..6ddf77f12
--- /dev/null
+++ b/roles/openshift_examples/files/examples/v3.6/image-streams/OWNERS
@@ -0,0 +1,14 @@
+reviewers:
+ - bparees
+ - sspeiche
+ - mfojtik
+ - liggitt
+ - jcantrill
+ - hhorak
+ - csrwng
+approvers:
+ - bparees
+ - mfojtik
+ - liggitt
+ - jcantrill
+ - csrwng
diff --git a/roles/openshift_examples/files/examples/v3.6/image-streams/dotnet_imagestreams.json b/roles/openshift_examples/files/examples/v3.6/image-streams/dotnet_imagestreams.json
index 857ffa980..ee753966f 100644
--- a/roles/openshift_examples/files/examples/v3.6/image-streams/dotnet_imagestreams.json
+++ b/roles/openshift_examples/files/examples/v3.6/image-streams/dotnet_imagestreams.json
@@ -14,7 +14,7 @@
"metadata": {
"name": "dotnet",
"annotations": {
- "openshift.io/display-name": ".NET Core"
+ "openshift.io/display-name": ".NET Core Builder Images"
}
},
"spec": {
@@ -23,17 +23,35 @@
"name": "latest",
"annotations": {
"openshift.io/display-name": ".NET Core (Latest)",
- "description": "Build and run .NET Core applications on RHEL 7. For more information about using this builder image, including OpenShift considerations, see https://github.com/redhat-developer/s2i-dotnetcore/tree/master/1.1/README.md.\n\nWARNING: By selecting this tag, your application will automatically update to use the latest version of .NET Core available on OpenShift, including major versions updates.",
+ "description": "Build and run .NET Core applications on RHEL 7. For more information about using this builder image, including OpenShift considerations, see https://github.com/redhat-developer/s2i-dotnetcore/tree/master/2.0/build/README.md.\n\nWARNING: By selecting this tag, your application will automatically update to use the latest version of .NET Core available on OpenShift, including major versions updates.",
"iconClass": "icon-dotnet",
"tags": "builder,.net,dotnet,dotnetcore",
"supports":"dotnet",
"sampleRepo": "https://github.com/redhat-developer/s2i-dotnetcore-ex.git",
"sampleContextDir": "app",
- "sampleRef": "dotnetcore-1.1"
+ "sampleRef": "dotnetcore-2.0"
},
"from": {
"kind": "ImageStreamTag",
- "name": "1.1"
+ "name": "2.0"
+ }
+ },
+ {
+ "name": "2.0",
+ "annotations": {
+ "openshift.io/display-name": ".NET Core 2.0",
+ "description": "Build and run .NET Core 2.0 applications on RHEL 7. For more information about using this builder image, including OpenShift considerations, see https://github.com/redhat-developer/s2i-dotnetcore/tree/master/2.0/build/README.md.",
+ "iconClass": "icon-dotnet",
+ "tags": "builder,.net,dotnet,dotnetcore,rh-dotnet20",
+ "supports":"dotnet:2.0,dotnet",
+ "sampleRepo": "https://github.com/redhat-developer/s2i-dotnetcore-ex.git",
+ "sampleContextDir": "app",
+ "sampleRef": "dotnetcore-2.0",
+ "version": "2.0"
+ },
+ "from": {
+ "kind": "DockerImage",
+ "name": "registry.access.redhat.com/dotnet/dotnet-20-rhel7:2.0"
}
},
{
@@ -74,6 +92,49 @@
}
]
}
+ },
+ {
+ "kind": "ImageStream",
+ "apiVersion": "v1",
+ "metadata": {
+ "name": "dotnet-runtime",
+ "annotations": {
+ "openshift.io/display-name": ".NET Core Runtime Images"
+ }
+ },
+ "spec": {
+ "tags": [
+ {
+ "name": "latest",
+ "annotations": {
+ "openshift.io/display-name": ".NET Core Runtime (Latest)",
+ "description": "Run .NET Core applications on RHEL 7. For more information about using this image, including OpenShift considerations, see https://github.com/redhat-developer/s2i-dotnetcore/tree/master/2.0/runtime/README.md.\n\nWARNING: By selecting this tag, your application will automatically update to use the latest version of .NET Core Runtime available on OpenShift, including major versions updates.",
+ "iconClass": "icon-dotnet",
+ "tags": "runtime,.net-runtime,dotnet-runtime,dotnetcore-runtime",
+ "supports":"dotnet-runtime"
+ },
+ "from": {
+ "kind": "ImageStreamTag",
+ "name": "2.0"
+ }
+ },
+ {
+ "name": "2.0",
+ "annotations": {
+ "openshift.io/display-name": ".NET Core 2.0 Runtime",
+ "description": "Run .NET Core applications on RHEL 7. For more information about using this image, including OpenShift considerations, see https://github.com/redhat-developer/s2i-dotnetcore/tree/master/2.0/runtime/README.md.",
+ "iconClass": "icon-dotnet",
+ "tags": "runtime,.net-runtime,dotnet-runtime,dotnetcore-runtime",
+ "supports":"dotnet-runtime",
+ "version": "2.0"
+ },
+ "from": {
+ "kind": "DockerImage",
+ "name": "registry.access.redhat.com/dotnet/dotnet-20-runtime-rhel7:2.0"
+ }
+ }
+ ]
+ }
}
]
}
diff --git a/roles/openshift_examples/files/examples/v3.6/quickstart-templates/OWNERS b/roles/openshift_examples/files/examples/v3.6/quickstart-templates/OWNERS
new file mode 100644
index 000000000..a26e484d6
--- /dev/null
+++ b/roles/openshift_examples/files/examples/v3.6/quickstart-templates/OWNERS
@@ -0,0 +1,12 @@
+reviewers:
+ - bparees
+ - gabemontero
+ - coreydaley
+ - dinhxuanvu
+ - sspeiche
+ - mfojtik
+ - jupierce
+approvers:
+ - bparees
+ - mfojtik
+ - jupierce
diff --git a/roles/openshift_examples/files/examples/v3.6/quickstart-templates/cakephp-mysql-persistent.json b/roles/openshift_examples/files/examples/v3.6/quickstart-templates/cakephp-mysql-persistent.json
index 6d987ee33..289f809fa 100644
--- a/roles/openshift_examples/files/examples/v3.6/quickstart-templates/cakephp-mysql-persistent.json
+++ b/roles/openshift_examples/files/examples/v3.6/quickstart-templates/cakephp-mysql-persistent.json
@@ -89,7 +89,8 @@
"metadata": {
"name": "${NAME}",
"annotations": {
- "description": "Defines how to build the application"
+ "description": "Defines how to build the application",
+ "template.alpha.openshift.io/wait-for-ready": "true"
}
},
"spec": {
@@ -148,7 +149,8 @@
"metadata": {
"name": "${NAME}",
"annotations": {
- "description": "Defines how to deploy the application server"
+ "description": "Defines how to deploy the application server",
+ "template.alpha.openshift.io/wait-for-ready": "true"
}
},
"spec": {
diff --git a/roles/openshift_examples/files/examples/v3.6/quickstart-templates/cakephp-mysql.json b/roles/openshift_examples/files/examples/v3.6/quickstart-templates/cakephp-mysql.json
index fb2ef206e..0562982b3 100644
--- a/roles/openshift_examples/files/examples/v3.6/quickstart-templates/cakephp-mysql.json
+++ b/roles/openshift_examples/files/examples/v3.6/quickstart-templates/cakephp-mysql.json
@@ -89,7 +89,8 @@
"metadata": {
"name": "${NAME}",
"annotations": {
- "description": "Defines how to build the application"
+ "description": "Defines how to build the application",
+ "template.alpha.openshift.io/wait-for-ready": "true"
}
},
"spec": {
@@ -148,7 +149,8 @@
"metadata": {
"name": "${NAME}",
"annotations": {
- "description": "Defines how to deploy the application server"
+ "description": "Defines how to deploy the application server",
+ "template.alpha.openshift.io/wait-for-ready": "true"
}
},
"spec": {
diff --git a/roles/openshift_examples/files/examples/v3.6/quickstart-templates/dancer-mysql-persistent.json b/roles/openshift_examples/files/examples/v3.6/quickstart-templates/dancer-mysql-persistent.json
index 7ffb25e14..7a3875d09 100644
--- a/roles/openshift_examples/files/examples/v3.6/quickstart-templates/dancer-mysql-persistent.json
+++ b/roles/openshift_examples/files/examples/v3.6/quickstart-templates/dancer-mysql-persistent.json
@@ -87,7 +87,8 @@
"metadata": {
"name": "${NAME}",
"annotations": {
- "description": "Defines how to build the application"
+ "description": "Defines how to build the application",
+ "template.alpha.openshift.io/wait-for-ready": "true"
}
},
"spec": {
@@ -146,7 +147,8 @@
"metadata": {
"name": "${NAME}",
"annotations": {
- "description": "Defines how to deploy the application server"
+ "description": "Defines how to deploy the application server",
+ "template.alpha.openshift.io/wait-for-ready": "true"
}
},
"spec": {
diff --git a/roles/openshift_examples/files/examples/v3.6/quickstart-templates/dancer-mysql.json b/roles/openshift_examples/files/examples/v3.6/quickstart-templates/dancer-mysql.json
index d787e376b..399ec72a8 100644
--- a/roles/openshift_examples/files/examples/v3.6/quickstart-templates/dancer-mysql.json
+++ b/roles/openshift_examples/files/examples/v3.6/quickstart-templates/dancer-mysql.json
@@ -87,7 +87,8 @@
"metadata": {
"name": "${NAME}",
"annotations": {
- "description": "Defines how to build the application"
+ "description": "Defines how to build the application",
+ "template.alpha.openshift.io/wait-for-ready": "true"
}
},
"spec": {
@@ -146,7 +147,8 @@
"metadata": {
"name": "${NAME}",
"annotations": {
- "description": "Defines how to deploy the application server"
+ "description": "Defines how to deploy the application server",
+ "template.alpha.openshift.io/wait-for-ready": "true"
}
},
"spec": {
diff --git a/roles/openshift_examples/files/examples/v3.6/quickstart-templates/django-postgresql-persistent.json b/roles/openshift_examples/files/examples/v3.6/quickstart-templates/django-postgresql-persistent.json
index a2070207b..e37f7a492 100644
--- a/roles/openshift_examples/files/examples/v3.6/quickstart-templates/django-postgresql-persistent.json
+++ b/roles/openshift_examples/files/examples/v3.6/quickstart-templates/django-postgresql-persistent.json
@@ -87,7 +87,8 @@
"metadata": {
"name": "${NAME}",
"annotations": {
- "description": "Defines how to build the application"
+ "description": "Defines how to build the application",
+ "template.alpha.openshift.io/wait-for-ready": "true"
}
},
"spec": {
@@ -146,7 +147,8 @@
"metadata": {
"name": "${NAME}",
"annotations": {
- "description": "Defines how to deploy the application server"
+ "description": "Defines how to deploy the application server",
+ "template.alpha.openshift.io/wait-for-ready": "true"
}
},
"spec": {
diff --git a/roles/openshift_examples/files/examples/v3.6/quickstart-templates/django-postgresql.json b/roles/openshift_examples/files/examples/v3.6/quickstart-templates/django-postgresql.json
index 0d33c6e0e..965c2ebfe 100644
--- a/roles/openshift_examples/files/examples/v3.6/quickstart-templates/django-postgresql.json
+++ b/roles/openshift_examples/files/examples/v3.6/quickstart-templates/django-postgresql.json
@@ -87,7 +87,8 @@
"metadata": {
"name": "${NAME}",
"annotations": {
- "description": "Defines how to build the application"
+ "description": "Defines how to build the application",
+ "template.alpha.openshift.io/wait-for-ready": "true"
}
},
"spec": {
@@ -146,7 +147,8 @@
"metadata": {
"name": "${NAME}",
"annotations": {
- "description": "Defines how to deploy the application server"
+ "description": "Defines how to deploy the application server",
+ "template.alpha.openshift.io/wait-for-ready": "true"
}
},
"spec": {
diff --git a/roles/openshift_examples/files/examples/v3.6/quickstart-templates/dotnet-example.json b/roles/openshift_examples/files/examples/v3.6/quickstart-templates/dotnet-example.json
index af46579c8..f1fef3093 100644
--- a/roles/openshift_examples/files/examples/v3.6/quickstart-templates/dotnet-example.json
+++ b/roles/openshift_examples/files/examples/v3.6/quickstart-templates/dotnet-example.json
@@ -249,7 +249,7 @@
"displayName": ".NET builder",
"required": true,
"description": "The image stream tag which is used to build the code.",
- "value": "dotnet:1.0"
+ "value": "dotnet:2.0"
},
{
"name": "NAMESPACE",
@@ -269,7 +269,7 @@
"name": "SOURCE_REPOSITORY_REF",
"displayName": "Git Reference",
"description": "Set this to a branch name, tag or other ref of your repository if you are not using the default branch.",
- "value": "dotnetcore-1.0"
+ "value": "dotnetcore-2.0"
},
{
"name": "CONTEXT_DIR",
@@ -299,7 +299,7 @@
{
"name": "DOTNET_STARTUP_PROJECT",
"displayName": "Startup Project",
- "description": "Set this to the folder containing your startup project.",
+ "description": "Set this to a project file (e.g. csproj) or a folder containing a single project file.",
"value": "app"
},
{
diff --git a/roles/openshift_examples/files/examples/v3.6/quickstart-templates/dotnet-pgsql-persistent.json b/roles/openshift_examples/files/examples/v3.6/quickstart-templates/dotnet-pgsql-persistent.json
index a2b59c2d3..c83132152 100644
--- a/roles/openshift_examples/files/examples/v3.6/quickstart-templates/dotnet-pgsql-persistent.json
+++ b/roles/openshift_examples/files/examples/v3.6/quickstart-templates/dotnet-pgsql-persistent.json
@@ -455,7 +455,7 @@
"displayName": ".NET builder",
"required": true,
"description": "The image stream tag which is used to build the code.",
- "value": "dotnet:1.1"
+ "value": "dotnet:2.0"
},
{
"name": "NAMESPACE",
@@ -475,7 +475,7 @@
"name": "SOURCE_REPOSITORY_REF",
"displayName": "Git Reference",
"description": "Set this to a branch name, tag or other ref of your repository if you are not using the default branch.",
- "value": "rel/1.1-example"
+ "value": "rel/2.0-example"
},
{
"name": "CONTEXT_DIR",
@@ -485,7 +485,7 @@
{
"name": "DOTNET_STARTUP_PROJECT",
"displayName": "Startup Project",
- "description": "Set this to the folder containing your startup project.",
+ "description": "Set this to a project file (e.g. csproj) or a folder containing a single project file.",
"value": "samples/MusicStore"
},
{
diff --git a/roles/openshift_examples/files/examples/v3.6/quickstart-templates/dotnet-runtime-example.json b/roles/openshift_examples/files/examples/v3.6/quickstart-templates/dotnet-runtime-example.json
new file mode 100644
index 000000000..e1dccf290
--- /dev/null
+++ b/roles/openshift_examples/files/examples/v3.6/quickstart-templates/dotnet-runtime-example.json
@@ -0,0 +1,412 @@
+{
+ "kind": "Template",
+ "apiVersion": "v1",
+ "metadata": {
+ "name": "dotnet-runtime-example",
+ "annotations": {
+ "openshift.io/display-name": ".NET Core Runtime Example",
+ "description": "An example .NET Core Runtime example application.",
+ "tags": "quickstart,dotnet,.net",
+ "iconClass": "icon-dotnet",
+ "template.openshift.io/provider-display-name": "Red Hat, Inc.",
+ "template.openshift.io/documentation-url": "https://github.com/redhat-developer/s2i-dotnetcore",
+ "template.openshift.io/support-url": "https://access.redhat.com"
+ }
+ },
+ "objects": [
+ {
+ "kind": "Route",
+ "apiVersion": "v1",
+ "metadata": {
+ "name": "${NAME}"
+ },
+ "spec": {
+ "host": "${APPLICATION_DOMAIN}",
+ "to": {
+ "kind": "Service",
+ "name": "${NAME}"
+ }
+ }
+ },
+ {
+ "kind": "Service",
+ "apiVersion": "v1",
+ "metadata": {
+ "name": "${NAME}",
+ "annotations": {
+ "description": "Exposes and load balances the application pods"
+ }
+ },
+ "spec": {
+ "ports": [
+ {
+ "name": "web",
+ "port": 8080,
+ "targetPort": 8080
+ }
+ ],
+ "selector": {
+ "name": "${NAME}"
+ }
+ }
+ },
+ {
+ "kind": "ImageStream",
+ "apiVersion": "v1",
+ "metadata": {
+ "name": "${NAME}",
+ "annotations": {
+ "description": "Keeps track of changes in the application runtime image"
+ }
+ }
+ },
+ {
+ "kind": "ImageStream",
+ "apiVersion": "v1",
+ "metadata": {
+ "name": "${NAME}-build",
+ "annotations": {
+ "description": "Keeps track of changes in the application builder image"
+ }
+ }
+ },
+ {
+ "kind": "BuildConfig",
+ "apiVersion": "v1",
+ "metadata": {
+ "name": "${NAME}-build",
+ "annotations": {
+ "description": "Defines how to build the application"
+ }
+ },
+ "spec": {
+ "source": {
+ "type": "Git",
+ "git": {
+ "uri": "${SOURCE_REPOSITORY_URL}",
+ "ref": "${SOURCE_REPOSITORY_REF}"
+ },
+ "contextDir": "${CONTEXT_DIR}"
+ },
+ "strategy": {
+ "type": "Source",
+ "sourceStrategy": {
+ "from": {
+ "kind": "ImageStreamTag",
+ "namespace": "${NAMESPACE}",
+ "name": "${DOTNET_BUILD_IMAGE_STREAM_TAG}"
+ },
+ "env": [
+ {
+ "name": "DOTNET_STARTUP_PROJECT",
+ "value": "${DOTNET_STARTUP_PROJECT}"
+ },
+ {
+ "name": "DOTNET_ASSEMBLY_NAME",
+ "value": "${DOTNET_ASSEMBLY_NAME}"
+ },
+ {
+ "name": "DOTNET_NPM_TOOLS",
+ "value": "${DOTNET_NPM_TOOLS}"
+ },
+ {
+ "name": "DOTNET_TEST_PROJECTS",
+ "value": "${DOTNET_TEST_PROJECTS}"
+ },
+ {
+ "name": "DOTNET_CONFIGURATION",
+ "value": "${DOTNET_CONFIGURATION}"
+ },
+ {
+ "name": "DOTNET_RESTORE_SOURCES",
+ "value": "${DOTNET_RESTORE_SOURCES}"
+ },
+ {
+ "name": "DOTNET_PACK",
+ "value": "true"
+ }
+ ]
+ }
+ },
+ "output": {
+ "to": {
+ "kind": "ImageStreamTag",
+ "name": "${NAME}-build:latest"
+ }
+ },
+ "triggers": [
+ {
+ "type": "ImageChange"
+ },
+ {
+ "type": "ConfigChange"
+ },
+ {
+ "type": "GitHub",
+ "github": {
+ "secret": "${GITHUB_WEBHOOK_SECRET}"
+ }
+ },
+ {
+ "type": "Generic",
+ "generic": {
+ "secret": "${GENERIC_WEBHOOK_SECRET}"
+ }
+ }
+ ]
+ }
+ },
+ {
+ "kind": "BuildConfig",
+ "apiVersion": "v1",
+ "metadata": {
+ "name": "${NAME}-runtime",
+ "annotations": {
+ "description": "Defines how to chain the runtime image from the source build image"
+ }
+ },
+ "spec": {
+ "source": {
+ "dockerfile": "FROM ${DOTNET_RUNTIME_IMAGE_STREAM_TAG}\nADD app.tar.gz .",
+ "images": [
+ {
+ "from": {
+ "kind": "ImageStreamTag",
+ "name": "${NAME}-build:latest"
+ },
+ "paths": [
+ {
+ "sourcePath": "/opt/app-root/app.tar.gz",
+ "destinationDir": "."
+ }
+ ]
+ }
+ ]
+ },
+ "strategy": {
+ "type": "Docker",
+ "dockerStrategy": {
+ "from": {
+ "kind": "ImageStreamTag",
+ "namespace": "${NAMESPACE}",
+ "name": "${DOTNET_RUNTIME_IMAGE_STREAM_TAG}"
+ }
+ }
+ },
+ "output": {
+ "to": {
+ "kind": "ImageStreamTag",
+ "name": "${NAME}:latest"
+ }
+ },
+ "triggers": [
+ {
+ "type": "ImageChange"
+ },
+ {
+ "type": "ConfigChange"
+ },
+ {
+ "type": "ImageChange",
+ "imageChange": {
+ "from": {
+ "kind": "ImageStreamTag",
+ "name": "${NAME}-build:latest"
+ }
+ }
+ }
+ ]
+ }
+ },
+ {
+ "kind": "DeploymentConfig",
+ "apiVersion": "v1",
+ "metadata": {
+ "name": "${NAME}-runtime",
+ "annotations": {
+ "description": "Defines how to deploy the application server"
+ }
+ },
+ "spec": {
+ "strategy": {
+ "type": "Rolling"
+ },
+ "triggers": [
+ {
+ "type": "ImageChange",
+ "imageChangeParams": {
+ "automatic": true,
+ "containerNames": [
+ "dotnet-runtime-app"
+ ],
+ "from": {
+ "kind": "ImageStreamTag",
+ "name": "${NAME}:latest"
+ }
+ }
+ },
+ {
+ "type": "ConfigChange"
+ }
+ ],
+ "replicas": 1,
+ "selector": {
+ "name": "${NAME}"
+ },
+ "template": {
+ "metadata": {
+ "name": "${NAME}",
+ "labels": {
+ "name": "${NAME}"
+ }
+ },
+ "spec": {
+ "containers": [
+ {
+ "name": "dotnet-runtime-app",
+ "image": " ",
+ "ports": [
+ {
+ "containerPort": 8080
+ }
+ ],
+ "livenessProbe": {
+ "httpGet": {
+ "path": "/",
+ "port": 8080,
+ "scheme": "HTTP"
+ },
+ "initialDelaySeconds": 40,
+ "timeoutSeconds": 15
+ },
+ "readinessProbe": {
+ "httpGet": {
+ "path": "/",
+ "port": 8080,
+ "scheme": "HTTP"
+ },
+ "initialDelaySeconds": 10,
+ "timeoutSeconds": 30
+ },
+ "resources": {
+ "limits": {
+ "memory": "${MEMORY_LIMIT}"
+ }
+ },
+ "env": []
+ }
+ ]
+ }
+ }
+ }
+ }
+ ],
+ "parameters": [
+ {
+ "name": "NAME",
+ "displayName": "Name",
+ "description": "The name assigned to all of the frontend objects defined in this template.",
+ "required": true,
+ "value": "dotnet-runtime-example"
+ },
+ {
+ "name": "MEMORY_LIMIT",
+ "displayName": "Memory Limit",
+ "description": "Maximum amount of memory the container can use.",
+ "required": true,
+ "value": "512Mi"
+ },
+ {
+ "name": "DOTNET_RUNTIME_IMAGE_STREAM_TAG",
+ "displayName": ".NET Runtime Imagestream Tag",
+ "description": "The image stream tag which is used to run the application.",
+ "required": true,
+ "value": "dotnet-runtime:2.0"
+ },
+ {
+ "name": "DOTNET_BUILD_IMAGE_STREAM_TAG",
+ "displayName": ".NET builder",
+ "required": true,
+ "description": "The image stream tag which is used to build the application.",
+ "value": "dotnet:2.0"
+ },
+ {
+ "name": "NAMESPACE",
+ "displayName": "Namespace",
+ "description": "The OpenShift Namespace where the ImageStream resides.",
+ "required": true,
+ "value": "openshift"
+ },
+ {
+ "name": "APPLICATION_DOMAIN",
+ "displayName": "Application Hostname",
+ "description": "The exposed hostname that will route to the .NET Core service, if left blank a value will be defaulted.",
+ "value": ""
+ },
+ {
+ "name": "SOURCE_REPOSITORY_URL",
+ "displayName": "Git Repository URL",
+ "description": "The URL of the repository with your application source code.",
+ "required": true,
+ "value": "https://github.com/redhat-developer/s2i-dotnetcore-ex.git"
+ },
+ {
+ "name": "SOURCE_REPOSITORY_REF",
+ "displayName": "Git Reference",
+ "description": "Set this to a branch name, tag or other ref of your repository if you are not using the default branch.",
+ "value": "dotnetcore-2.0"
+ },
+ {
+ "name": "CONTEXT_DIR",
+ "displayName": "Context Directory",
+ "description": "Set this to use a subdirectory of the source code repository"
+ },
+ {
+ "name": "GITHUB_WEBHOOK_SECRET",
+ "displayName": "GitHub Webhook Secret",
+ "description": "A secret string used to configure the GitHub webhook.",
+ "generate": "expression",
+ "from": "[a-zA-Z0-9]{40}"
+ },
+ {
+ "name": "GENERIC_WEBHOOK_SECRET",
+ "displayName": "Generic Webhook Secret",
+ "description": "A secret string used to configure the Generic webhook.",
+ "generate": "expression",
+ "from": "[a-zA-Z0-9]{40}"
+ },
+ {
+ "name": "DOTNET_STARTUP_PROJECT",
+ "displayName": "Startup Project",
+ "description": "Set this to the folder containing your startup project.",
+ "value": "app"
+ },
+ {
+ "name": "DOTNET_ASSEMBLY_NAME",
+ "displayName": "Startup Assembly",
+ "description": "Set this when the assembly name is overridden in the project file."
+ },
+ {
+ "name": "DOTNET_NPM_TOOLS",
+ "displayName": "Npm Tools",
+ "description": "Set this to a space separated list of npm tools needed to publish.",
+ "value": "bower gulp"
+ },
+ {
+ "name": "DOTNET_TEST_PROJECTS",
+ "displayName": "Test projects",
+ "description": "Set this to a space separated list of test projects to run before publishing."
+ },
+ {
+ "name": "DOTNET_CONFIGURATION",
+ "displayName": "Configuration",
+ "description": "Set this to configuration (Release/Debug).",
+ "value": "Release"
+ },
+ {
+ "name": "DOTNET_RESTORE_SOURCES",
+ "displayName": "NuGet package sources",
+ "description": "Set this to override the NuGet.config sources."
+ }
+ ]
+}
diff --git a/roles/openshift_examples/files/examples/v3.6/quickstart-templates/httpd.json b/roles/openshift_examples/files/examples/v3.6/quickstart-templates/httpd.json
index ac671cc06..6cf9d76eb 100644
--- a/roles/openshift_examples/files/examples/v3.6/quickstart-templates/httpd.json
+++ b/roles/openshift_examples/files/examples/v3.6/quickstart-templates/httpd.json
@@ -74,7 +74,8 @@
"metadata": {
"name": "${NAME}",
"annotations": {
- "description": "Defines how to build the application"
+ "description": "Defines how to build the application",
+ "template.alpha.openshift.io/wait-for-ready": "true"
}
},
"spec": {
@@ -130,7 +131,8 @@
"metadata": {
"name": "${NAME}",
"annotations": {
- "description": "Defines how to deploy the application server"
+ "description": "Defines how to deploy the application server",
+ "template.alpha.openshift.io/wait-for-ready": "true"
}
},
"spec": {
diff --git a/roles/openshift_examples/files/examples/v3.6/quickstart-templates/jenkins-ephemeral-template.json b/roles/openshift_examples/files/examples/v3.6/quickstart-templates/jenkins-ephemeral-template.json
index ce96684a9..62f43bc0b 100644
--- a/roles/openshift_examples/files/examples/v3.6/quickstart-templates/jenkins-ephemeral-template.json
+++ b/roles/openshift_examples/files/examples/v3.6/quickstart-templates/jenkins-ephemeral-template.json
@@ -3,7 +3,6 @@
"apiVersion": "v1",
"metadata": {
"name": "jenkins-ephemeral",
- "creationTimestamp": null,
"annotations": {
"openshift.io/display-name": "Jenkins (Ephemeral)",
"description": "Jenkins service, without persistent storage.\n\nWARNING: Any data stored will be lost upon pod destruction. Only use this template for testing.",
@@ -22,7 +21,6 @@
"apiVersion": "v1",
"metadata": {
"name": "${JENKINS_SERVICE_NAME}",
- "creationTimestamp": null,
"annotations": {
"template.openshift.io/expose-uri": "http://{.spec.host}{.spec.path}"
}
@@ -43,7 +41,9 @@
"apiVersion": "v1",
"metadata": {
"name": "${JENKINS_SERVICE_NAME}",
- "creationTimestamp": null
+ "annotations": {
+ "template.alpha.openshift.io/wait-for-ready": "true"
+ }
},
"spec": {
"strategy": {
@@ -75,7 +75,6 @@
},
"template": {
"metadata": {
- "creationTimestamp": null,
"labels": {
"name": "${JENKINS_SERVICE_NAME}"
}
@@ -221,8 +220,7 @@
"annotations": {
"service.alpha.openshift.io/dependencies": "[{\"name\": \"${JNLP_SERVICE_NAME}\", \"namespace\": \"\", \"kind\": \"Service\"}]",
"service.openshift.io/infrastructure": "true"
- },
- "creationTimestamp": null
+ }
},
"spec": {
"ports": [
diff --git a/roles/openshift_examples/files/examples/v3.6/quickstart-templates/jenkins-persistent-template.json b/roles/openshift_examples/files/examples/v3.6/quickstart-templates/jenkins-persistent-template.json
index 34b2b920b..e9068e455 100644
--- a/roles/openshift_examples/files/examples/v3.6/quickstart-templates/jenkins-persistent-template.json
+++ b/roles/openshift_examples/files/examples/v3.6/quickstart-templates/jenkins-persistent-template.json
@@ -3,7 +3,6 @@
"apiVersion": "v1",
"metadata": {
"name": "jenkins-persistent",
- "creationTimestamp": null,
"annotations": {
"openshift.io/display-name": "Jenkins (Persistent)",
"description": "Jenkins service, with persistent storage.\n\nNOTE: You must have persistent volumes available in your cluster to use this template.",
@@ -22,7 +21,6 @@
"apiVersion": "v1",
"metadata": {
"name": "${JENKINS_SERVICE_NAME}",
- "creationTimestamp": null,
"annotations": {
"template.openshift.io/expose-uri": "http://{.spec.host}{.spec.path}"
}
@@ -60,7 +58,9 @@
"apiVersion": "v1",
"metadata": {
"name": "${JENKINS_SERVICE_NAME}",
- "creationTimestamp": null
+ "annotations": {
+ "template.alpha.openshift.io/wait-for-ready": "true"
+ }
},
"spec": {
"strategy": {
@@ -92,7 +92,6 @@
},
"template": {
"metadata": {
- "creationTimestamp": null,
"labels": {
"name": "${JENKINS_SERVICE_NAME}"
}
@@ -238,8 +237,7 @@
"annotations": {
"service.alpha.openshift.io/dependencies": "[{\"name\": \"${JNLP_SERVICE_NAME}\", \"namespace\": \"\", \"kind\": \"Service\"}]",
"service.openshift.io/infrastructure": "true"
- },
- "creationTimestamp": null
+ }
},
"spec": {
"ports": [
diff --git a/roles/openshift_examples/files/examples/v3.6/quickstart-templates/nodejs-mongodb-persistent.json b/roles/openshift_examples/files/examples/v3.6/quickstart-templates/nodejs-mongodb-persistent.json
index a9c365361..df3704b9f 100644
--- a/roles/openshift_examples/files/examples/v3.6/quickstart-templates/nodejs-mongodb-persistent.json
+++ b/roles/openshift_examples/files/examples/v3.6/quickstart-templates/nodejs-mongodb-persistent.json
@@ -87,7 +87,8 @@
"metadata": {
"name": "${NAME}",
"annotations": {
- "description": "Defines how to build the application"
+ "description": "Defines how to build the application",
+ "template.alpha.openshift.io/wait-for-ready": "true"
}
},
"spec": {
@@ -152,7 +153,8 @@
"metadata": {
"name": "${NAME}",
"annotations": {
- "description": "Defines how to deploy the application server"
+ "description": "Defines how to deploy the application server",
+ "template.alpha.openshift.io/wait-for-ready": "true"
}
},
"spec": {
diff --git a/roles/openshift_examples/files/examples/v3.6/quickstart-templates/nodejs-mongodb.json b/roles/openshift_examples/files/examples/v3.6/quickstart-templates/nodejs-mongodb.json
index 53a6147d5..eb6ab33d9 100644
--- a/roles/openshift_examples/files/examples/v3.6/quickstart-templates/nodejs-mongodb.json
+++ b/roles/openshift_examples/files/examples/v3.6/quickstart-templates/nodejs-mongodb.json
@@ -87,7 +87,8 @@
"metadata": {
"name": "${NAME}",
"annotations": {
- "description": "Defines how to build the application"
+ "description": "Defines how to build the application",
+ "template.alpha.openshift.io/wait-for-ready": "true"
}
},
"spec": {
@@ -152,7 +153,8 @@
"metadata": {
"name": "${NAME}",
"annotations": {
- "description": "Defines how to deploy the application server"
+ "description": "Defines how to deploy the application server",
+ "template.alpha.openshift.io/wait-for-ready": "true"
}
},
"spec": {
diff --git a/roles/openshift_examples/files/examples/v3.6/quickstart-templates/rails-postgresql-persistent.json b/roles/openshift_examples/files/examples/v3.6/quickstart-templates/rails-postgresql-persistent.json
index f07a43071..59e2e41ea 100644
--- a/roles/openshift_examples/files/examples/v3.6/quickstart-templates/rails-postgresql-persistent.json
+++ b/roles/openshift_examples/files/examples/v3.6/quickstart-templates/rails-postgresql-persistent.json
@@ -93,7 +93,8 @@
"metadata": {
"name": "${NAME}",
"annotations": {
- "description": "Defines how to build the application"
+ "description": "Defines how to build the application",
+ "template.alpha.openshift.io/wait-for-ready": "true"
}
},
"spec": {
@@ -152,7 +153,8 @@
"metadata": {
"name": "${NAME}",
"annotations": {
- "description": "Defines how to deploy the application server"
+ "description": "Defines how to deploy the application server",
+ "template.alpha.openshift.io/wait-for-ready": "true"
}
},
"spec": {
diff --git a/roles/openshift_examples/files/examples/v3.6/quickstart-templates/rails-postgresql.json b/roles/openshift_examples/files/examples/v3.6/quickstart-templates/rails-postgresql.json
index a7992c988..b3d080a91 100644
--- a/roles/openshift_examples/files/examples/v3.6/quickstart-templates/rails-postgresql.json
+++ b/roles/openshift_examples/files/examples/v3.6/quickstart-templates/rails-postgresql.json
@@ -93,7 +93,8 @@
"metadata": {
"name": "${NAME}",
"annotations": {
- "description": "Defines how to build the application"
+ "description": "Defines how to build the application",
+ "template.alpha.openshift.io/wait-for-ready": "true"
}
},
"spec": {
@@ -152,7 +153,8 @@
"metadata": {
"name": "${NAME}",
"annotations": {
- "description": "Defines how to deploy the application server"
+ "description": "Defines how to deploy the application server",
+ "template.alpha.openshift.io/wait-for-ready": "true"
}
},
"spec": {
diff --git a/roles/openshift_examples/files/examples/v3.7/db-templates/mariadb-ephemeral-template.json b/roles/openshift_examples/files/examples/v3.7/db-templates/mariadb-ephemeral-template.json
index 536f7275e..6500ed0d3 100644
--- a/roles/openshift_examples/files/examples/v3.7/db-templates/mariadb-ephemeral-template.json
+++ b/roles/openshift_examples/files/examples/v3.7/db-templates/mariadb-ephemeral-template.json
@@ -27,13 +27,15 @@
"annotations": {
"template.openshift.io/expose-username": "{.data['database-user']}",
"template.openshift.io/expose-password": "{.data['database-password']}",
- "template.openshift.io/expose-root_password": "{.data['database-root-password']}"
+ "template.openshift.io/expose-root_password": "{.data['database-root-password']}",
+ "template.openshift.io/expose-database_name": "{.data['database-name']}"
}
},
"stringData" : {
"database-user" : "${MYSQL_USER}",
"database-password" : "${MYSQL_PASSWORD}",
- "database-root-password" : "${MYSQL_ROOT_PASSWORD}"
+ "database-root-password" : "${MYSQL_ROOT_PASSWORD}",
+ "database-name" : "${MYSQL_DATABASE}"
}
},
{
@@ -61,7 +63,10 @@
"kind": "DeploymentConfig",
"apiVersion": "v1",
"metadata": {
- "name": "${DATABASE_SERVICE_NAME}"
+ "name": "${DATABASE_SERVICE_NAME}",
+ "annotations": {
+ "template.alpha.openshift.io/wait-for-ready": "true"
+ }
},
"spec": {
"strategy": {
@@ -151,7 +156,12 @@
},
{
"name": "MYSQL_DATABASE",
- "value": "${MYSQL_DATABASE}"
+ "valueFrom": {
+ "secretKeyRef" : {
+ "name" : "${DATABASE_SERVICE_NAME}",
+ "key" : "database-name"
+ }
+ }
}
],
"resources": {
diff --git a/roles/openshift_examples/files/examples/v3.7/db-templates/mariadb-persistent-template.json b/roles/openshift_examples/files/examples/v3.7/db-templates/mariadb-persistent-template.json
index 3b7fdccce..4378fa4a0 100644
--- a/roles/openshift_examples/files/examples/v3.7/db-templates/mariadb-persistent-template.json
+++ b/roles/openshift_examples/files/examples/v3.7/db-templates/mariadb-persistent-template.json
@@ -27,13 +27,15 @@
"annotations": {
"template.openshift.io/expose-username": "{.data['database-user']}",
"template.openshift.io/expose-password": "{.data['database-password']}",
- "template.openshift.io/expose-root_password": "{.data['database-root-password']}"
+ "template.openshift.io/expose-root_password": "{.data['database-root-password']}",
+ "template.openshift.io/expose-database_name": "{.data['database-name']}"
}
},
"stringData" : {
"database-user" : "${MYSQL_USER}",
"database-password" : "${MYSQL_PASSWORD}",
- "database-root-password" : "${MYSQL_ROOT_PASSWORD}"
+ "database-root-password" : "${MYSQL_ROOT_PASSWORD}",
+ "database-name" : "${MYSQL_DATABASE}"
}
},
{
@@ -78,7 +80,10 @@
"kind": "DeploymentConfig",
"apiVersion": "v1",
"metadata": {
- "name": "${DATABASE_SERVICE_NAME}"
+ "name": "${DATABASE_SERVICE_NAME}",
+ "annotations": {
+ "template.alpha.openshift.io/wait-for-ready": "true"
+ }
},
"spec": {
"strategy": {
@@ -168,7 +173,12 @@
},
{
"name": "MYSQL_DATABASE",
- "value": "${MYSQL_DATABASE}"
+ "valueFrom": {
+ "secretKeyRef" : {
+ "name" : "${DATABASE_SERVICE_NAME}",
+ "key" : "database-name"
+ }
+ }
}
],
"resources": {
diff --git a/roles/openshift_examples/files/examples/v3.7/db-templates/mongodb-ephemeral-template.json b/roles/openshift_examples/files/examples/v3.7/db-templates/mongodb-ephemeral-template.json
index ee274194f..7271a2c69 100644
--- a/roles/openshift_examples/files/examples/v3.7/db-templates/mongodb-ephemeral-template.json
+++ b/roles/openshift_examples/files/examples/v3.7/db-templates/mongodb-ephemeral-template.json
@@ -3,7 +3,6 @@
"apiVersion": "v1",
"metadata": {
"name": "mongodb-ephemeral",
- "creationTimestamp": null,
"annotations": {
"openshift.io/display-name": "MongoDB (Ephemeral)",
"description": "MongoDB database service, without persistent storage. For more information about using this template, including OpenShift considerations, see https://github.com/sclorg/mongodb-container/blob/master/3.2/README.md.\n\nWARNING: Any data stored will be lost upon pod destruction. Only use this template for testing",
@@ -28,13 +27,15 @@
"annotations": {
"template.openshift.io/expose-username": "{.data['database-user']}",
"template.openshift.io/expose-password": "{.data['database-password']}",
- "template.openshift.io/expose-admin_password": "{.data['database-admin-password']}"
+ "template.openshift.io/expose-admin_password": "{.data['database-admin-password']}",
+ "template.openshift.io/expose-database_name": "{.data['database-name']}"
}
},
"stringData" : {
"database-user" : "${MONGODB_USER}",
"database-password" : "${MONGODB_PASSWORD}",
- "database-admin-password" : "${MONGODB_ADMIN_PASSWORD}"
+ "database-admin-password" : "${MONGODB_ADMIN_PASSWORD}",
+ "database-name" : "${MONGODB_DATABASE}"
}
},
{
@@ -42,7 +43,6 @@
"apiVersion": "v1",
"metadata": {
"name": "${DATABASE_SERVICE_NAME}",
- "creationTimestamp": null,
"annotations": {
"template.openshift.io/expose-uri": "mongodb://{.spec.clusterIP}:{.spec.ports[?(.name==\"mongo\")].port}"
}
@@ -72,7 +72,9 @@
"apiVersion": "v1",
"metadata": {
"name": "${DATABASE_SERVICE_NAME}",
- "creationTimestamp": null
+ "annotations": {
+ "template.alpha.openshift.io/wait-for-ready": "true"
+ }
},
"spec": {
"strategy": {
@@ -104,7 +106,6 @@
},
"template": {
"metadata": {
- "creationTimestamp": null,
"labels": {
"name": "${DATABASE_SERVICE_NAME}"
}
@@ -164,7 +165,12 @@
},
{
"name": "MONGODB_DATABASE",
- "value": "${MONGODB_DATABASE}"
+ "valueFrom": {
+ "secretKeyRef" : {
+ "name" : "${DATABASE_SERVICE_NAME}",
+ "key" : "database-name"
+ }
+ }
}
],
"resources": {
diff --git a/roles/openshift_examples/files/examples/v3.7/db-templates/mongodb-persistent-template.json b/roles/openshift_examples/files/examples/v3.7/db-templates/mongodb-persistent-template.json
index e5ba43669..d70d2263f 100644
--- a/roles/openshift_examples/files/examples/v3.7/db-templates/mongodb-persistent-template.json
+++ b/roles/openshift_examples/files/examples/v3.7/db-templates/mongodb-persistent-template.json
@@ -3,7 +3,6 @@
"apiVersion": "v1",
"metadata": {
"name": "mongodb-persistent",
- "creationTimestamp": null,
"annotations": {
"openshift.io/display-name": "MongoDB (Persistent)",
"description": "MongoDB database service, with persistent storage. For more information about using this template, including OpenShift considerations, see https://github.com/sclorg/mongodb-container/blob/master/3.2/README.md.\n\nNOTE: Scaling to more than one replica is not supported. You must have persistent volumes available in your cluster to use this template.",
@@ -28,13 +27,15 @@
"annotations": {
"template.openshift.io/expose-username": "{.data['database-user']}",
"template.openshift.io/expose-password": "{.data['database-password']}",
- "template.openshift.io/expose-admin_password": "{.data['database-admin-password']}"
+ "template.openshift.io/expose-admin_password": "{.data['database-admin-password']}",
+ "template.openshift.io/expose-database_name": "{.data['database-name']}"
}
},
"stringData" : {
"database-user" : "${MONGODB_USER}",
"database-password" : "${MONGODB_PASSWORD}",
- "database-admin-password" : "${MONGODB_ADMIN_PASSWORD}"
+ "database-admin-password" : "${MONGODB_ADMIN_PASSWORD}",
+ "database-name" : "${MONGODB_DATABASE}"
}
},
{
@@ -42,7 +43,6 @@
"apiVersion": "v1",
"metadata": {
"name": "${DATABASE_SERVICE_NAME}",
- "creationTimestamp": null,
"annotations": {
"template.openshift.io/expose-uri": "mongodb://{.spec.clusterIP}:{.spec.ports[?(.name==\"mongo\")].port}"
}
@@ -89,7 +89,9 @@
"apiVersion": "v1",
"metadata": {
"name": "${DATABASE_SERVICE_NAME}",
- "creationTimestamp": null
+ "annotations": {
+ "template.alpha.openshift.io/wait-for-ready": "true"
+ }
},
"spec": {
"strategy": {
@@ -121,7 +123,6 @@
},
"template": {
"metadata": {
- "creationTimestamp": null,
"labels": {
"name": "${DATABASE_SERVICE_NAME}"
}
@@ -181,7 +182,12 @@
},
{
"name": "MONGODB_DATABASE",
- "value": "${MONGODB_DATABASE}"
+ "valueFrom": {
+ "secretKeyRef" : {
+ "name" : "${DATABASE_SERVICE_NAME}",
+ "key" : "database-name"
+ }
+ }
}
],
"resources": {
diff --git a/roles/openshift_examples/files/examples/v3.7/db-templates/mysql-ephemeral-template.json b/roles/openshift_examples/files/examples/v3.7/db-templates/mysql-ephemeral-template.json
index 969e62ac5..54785993c 100644
--- a/roles/openshift_examples/files/examples/v3.7/db-templates/mysql-ephemeral-template.json
+++ b/roles/openshift_examples/files/examples/v3.7/db-templates/mysql-ephemeral-template.json
@@ -19,7 +19,7 @@
"template": "mysql-ephemeral-template"
},
"objects": [
- {
+ {
"kind": "Secret",
"apiVersion": "v1",
"metadata": {
@@ -27,13 +27,15 @@
"annotations": {
"template.openshift.io/expose-username": "{.data['database-user']}",
"template.openshift.io/expose-password": "{.data['database-password']}",
- "template.openshift.io/expose-root_password": "{.data['database-root-password']}"
+ "template.openshift.io/expose-root_password": "{.data['database-root-password']}",
+ "template.openshift.io/expose-database_name": "{.data['database-name']}"
}
},
"stringData" : {
"database-user" : "${MYSQL_USER}",
"database-password" : "${MYSQL_PASSWORD}",
- "database-root-password" : "${MYSQL_ROOT_PASSWORD}"
+ "database-root-password" : "${MYSQL_ROOT_PASSWORD}",
+ "database-name" : "${MYSQL_DATABASE}"
}
},
{
@@ -41,7 +43,6 @@
"apiVersion": "v1",
"metadata": {
"name": "${DATABASE_SERVICE_NAME}",
- "creationTimestamp": null,
"annotations": {
"template.openshift.io/expose-uri": "mysql://{.spec.clusterIP}:{.spec.ports[?(.name==\"mysql\")].port}"
}
@@ -71,7 +72,9 @@
"apiVersion": "v1",
"metadata": {
"name": "${DATABASE_SERVICE_NAME}",
- "creationTimestamp": null
+ "annotations": {
+ "template.alpha.openshift.io/wait-for-ready": "true"
+ }
},
"spec": {
"strategy": {
@@ -103,7 +106,6 @@
},
"template": {
"metadata": {
- "creationTimestamp": null,
"labels": {
"name": "${DATABASE_SERVICE_NAME}"
}
@@ -164,7 +166,12 @@
},
{
"name": "MYSQL_DATABASE",
- "value": "${MYSQL_DATABASE}"
+ "valueFrom": {
+ "secretKeyRef" : {
+ "name" : "${DATABASE_SERVICE_NAME}",
+ "key" : "database-name"
+ }
+ }
}
],
"resources": {
diff --git a/roles/openshift_examples/files/examples/v3.7/db-templates/mysql-persistent-template.json b/roles/openshift_examples/files/examples/v3.7/db-templates/mysql-persistent-template.json
index 4f39d41a5..2bd84b106 100644
--- a/roles/openshift_examples/files/examples/v3.7/db-templates/mysql-persistent-template.json
+++ b/roles/openshift_examples/files/examples/v3.7/db-templates/mysql-persistent-template.json
@@ -27,13 +27,15 @@
"annotations": {
"template.openshift.io/expose-username": "{.data['database-user']}",
"template.openshift.io/expose-password": "{.data['database-password']}",
- "template.openshift.io/expose-root_password": "{.data['database-root-password']}"
+ "template.openshift.io/expose-root_password": "{.data['database-root-password']}",
+ "template.openshift.io/expose-database_name": "{.data['database-name']}"
}
},
"stringData" : {
"database-user" : "${MYSQL_USER}",
"database-password" : "${MYSQL_PASSWORD}",
- "database-root-password" : "${MYSQL_ROOT_PASSWORD}"
+ "database-root-password" : "${MYSQL_ROOT_PASSWORD}",
+ "database-name" : "${MYSQL_DATABASE}"
}
},
{
@@ -78,7 +80,10 @@
"kind": "DeploymentConfig",
"apiVersion": "v1",
"metadata": {
- "name": "${DATABASE_SERVICE_NAME}"
+ "name": "${DATABASE_SERVICE_NAME}",
+ "annotations": {
+ "template.alpha.openshift.io/wait-for-ready": "true"
+ }
},
"spec": {
"strategy": {
@@ -168,7 +173,12 @@
},
{
"name": "MYSQL_DATABASE",
- "value": "${MYSQL_DATABASE}"
+ "valueFrom": {
+ "secretKeyRef" : {
+ "name" : "${DATABASE_SERVICE_NAME}",
+ "key" : "database-name"
+ }
+ }
}
],
"resources": {
diff --git a/roles/openshift_examples/files/examples/v3.7/db-templates/postgresql-ephemeral-template.json b/roles/openshift_examples/files/examples/v3.7/db-templates/postgresql-ephemeral-template.json
index c37102cb0..849c9d83f 100644
--- a/roles/openshift_examples/files/examples/v3.7/db-templates/postgresql-ephemeral-template.json
+++ b/roles/openshift_examples/files/examples/v3.7/db-templates/postgresql-ephemeral-template.json
@@ -3,7 +3,6 @@
"apiVersion": "v1",
"metadata": {
"name": "postgresql-ephemeral",
- "creationTimestamp": null,
"annotations": {
"openshift.io/display-name": "PostgreSQL (Ephemeral)",
"description": "PostgreSQL database service, without persistent storage. For more information about using this template, including OpenShift considerations, see https://github.com/sclorg/postgresql-container/blob/master/9.5.\n\nWARNING: Any data stored will be lost upon pod destruction. Only use this template for testing",
@@ -27,12 +26,14 @@
"name": "${DATABASE_SERVICE_NAME}",
"annotations": {
"template.openshift.io/expose-username": "{.data['database-user']}",
- "template.openshift.io/expose-password": "{.data['database-password']}"
+ "template.openshift.io/expose-password": "{.data['database-password']}",
+ "template.openshift.io/expose-database_name": "{.data['database-name']}"
}
},
"stringData" : {
"database-user" : "${POSTGRESQL_USER}",
- "database-password" : "${POSTGRESQL_PASSWORD}"
+ "database-password" : "${POSTGRESQL_PASSWORD}",
+ "database-name" : "${POSTGRESQL_DATABASE}"
}
},
{
@@ -40,7 +41,6 @@
"apiVersion": "v1",
"metadata": {
"name": "${DATABASE_SERVICE_NAME}",
- "creationTimestamp": null,
"annotations": {
"template.openshift.io/expose-uri": "postgres://{.spec.clusterIP}:{.spec.ports[?(.name==\"postgresql\")].port}"
}
@@ -70,7 +70,9 @@
"apiVersion": "v1",
"metadata": {
"name": "${DATABASE_SERVICE_NAME}",
- "creationTimestamp": null
+ "annotations": {
+ "template.alpha.openshift.io/wait-for-ready": "true"
+ }
},
"spec": {
"strategy": {
@@ -102,7 +104,6 @@
},
"template": {
"metadata": {
- "creationTimestamp": null,
"labels": {
"name": "${DATABASE_SERVICE_NAME}"
}
@@ -153,7 +154,12 @@
},
{
"name": "POSTGRESQL_DATABASE",
- "value": "${POSTGRESQL_DATABASE}"
+ "valueFrom": {
+ "secretKeyRef" : {
+ "name" : "${DATABASE_SERVICE_NAME}",
+ "key" : "database-name"
+ }
+ }
}
],
"resources": {
diff --git a/roles/openshift_examples/files/examples/v3.7/db-templates/postgresql-persistent-template.json b/roles/openshift_examples/files/examples/v3.7/db-templates/postgresql-persistent-template.json
index 32dc93a95..b622baa01 100644
--- a/roles/openshift_examples/files/examples/v3.7/db-templates/postgresql-persistent-template.json
+++ b/roles/openshift_examples/files/examples/v3.7/db-templates/postgresql-persistent-template.json
@@ -3,7 +3,6 @@
"apiVersion": "v1",
"metadata": {
"name": "postgresql-persistent",
- "creationTimestamp": null,
"annotations": {
"openshift.io/display-name": "PostgreSQL (Persistent)",
"description": "PostgreSQL database service, with persistent storage. For more information about using this template, including OpenShift considerations, see https://github.com/sclorg/postgresql-container/blob/master/9.5.\n\nNOTE: Scaling to more than one replica is not supported. You must have persistent volumes available in your cluster to use this template.",
@@ -27,12 +26,14 @@
"name": "${DATABASE_SERVICE_NAME}",
"annotations": {
"template.openshift.io/expose-username": "{.data['database-user']}",
- "template.openshift.io/expose-password": "{.data['database-password']}"
+ "template.openshift.io/expose-password": "{.data['database-password']}",
+ "template.openshift.io/expose-database_name": "{.data['database-name']}"
}
},
"stringData" : {
"database-user" : "${POSTGRESQL_USER}",
- "database-password" : "${POSTGRESQL_PASSWORD}"
+ "database-password" : "${POSTGRESQL_PASSWORD}",
+ "database-name" : "${POSTGRESQL_DATABASE}"
}
},
{
@@ -40,7 +41,6 @@
"apiVersion": "v1",
"metadata": {
"name": "${DATABASE_SERVICE_NAME}",
- "creationTimestamp": null,
"annotations": {
"template.openshift.io/expose-uri": "postgres://{.spec.clusterIP}:{.spec.ports[?(.name==\"postgresql\")].port}"
}
@@ -87,7 +87,9 @@
"apiVersion": "v1",
"metadata": {
"name": "${DATABASE_SERVICE_NAME}",
- "creationTimestamp": null
+ "annotations": {
+ "template.alpha.openshift.io/wait-for-ready": "true"
+ }
},
"spec": {
"strategy": {
@@ -119,7 +121,6 @@
},
"template": {
"metadata": {
- "creationTimestamp": null,
"labels": {
"name": "${DATABASE_SERVICE_NAME}"
}
@@ -170,7 +171,12 @@
},
{
"name": "POSTGRESQL_DATABASE",
- "value": "${POSTGRESQL_DATABASE}"
+ "valueFrom": {
+ "secretKeyRef" : {
+ "name" : "${DATABASE_SERVICE_NAME}",
+ "key" : "database-name"
+ }
+ }
}
],
"resources": {
diff --git a/roles/openshift_examples/files/examples/v3.7/db-templates/redis-ephemeral-template.json b/roles/openshift_examples/files/examples/v3.7/db-templates/redis-ephemeral-template.json
index 6bb683e52..15bdd079b 100644
--- a/roles/openshift_examples/files/examples/v3.7/db-templates/redis-ephemeral-template.json
+++ b/roles/openshift_examples/files/examples/v3.7/db-templates/redis-ephemeral-template.json
@@ -3,7 +3,6 @@
"apiVersion": "v1",
"metadata": {
"name": "redis-ephemeral",
- "creationTimestamp": null,
"annotations": {
"openshift.io/display-name": "Redis (Ephemeral)",
"description": "Redis in-memory data structure store, without persistent storage. For more information about using this template, including OpenShift considerations, see https://github.com/sclorg/redis-container/blob/master/3.2.\n\nWARNING: Any data stored will be lost upon pod destruction. Only use this template for testing",
@@ -38,7 +37,6 @@
"apiVersion": "v1",
"metadata": {
"name": "${DATABASE_SERVICE_NAME}",
- "creationTimestamp": null,
"annotations": {
"template.openshift.io/expose-uri": "redis://{.spec.clusterIP}:{.spec.ports[?(.name==\"redis\")].port}"
}
@@ -68,7 +66,9 @@
"apiVersion": "v1",
"metadata": {
"name": "${DATABASE_SERVICE_NAME}",
- "creationTimestamp": null
+ "annotations": {
+ "template.alpha.openshift.io/wait-for-ready": "true"
+ }
},
"spec": {
"strategy": {
@@ -100,7 +100,6 @@
},
"template": {
"metadata": {
- "creationTimestamp": null,
"labels": {
"name": "${DATABASE_SERVICE_NAME}"
}
diff --git a/roles/openshift_examples/files/examples/v3.7/db-templates/redis-persistent-template.json b/roles/openshift_examples/files/examples/v3.7/db-templates/redis-persistent-template.json
index 9e8be2309..1e31b02e0 100644
--- a/roles/openshift_examples/files/examples/v3.7/db-templates/redis-persistent-template.json
+++ b/roles/openshift_examples/files/examples/v3.7/db-templates/redis-persistent-template.json
@@ -3,7 +3,6 @@
"apiVersion": "v1",
"metadata": {
"name": "redis-persistent",
- "creationTimestamp": null,
"annotations": {
"openshift.io/display-name": "Redis (Persistent)",
"description": "Redis in-memory data structure store, with persistent storage. For more information about using this template, including OpenShift considerations, see https://github.com/sclorg/redis-container/blob/master/3.2.\n\nNOTE: You must have persistent volumes available in your cluster to use this template.",
@@ -38,7 +37,6 @@
"apiVersion": "v1",
"metadata": {
"name": "${DATABASE_SERVICE_NAME}",
- "creationTimestamp": null,
"annotations": {
"template.openshift.io/expose-uri": "redis://{.spec.clusterIP}:{.spec.ports[?(.name==\"redis\")].port}"
}
@@ -85,7 +83,9 @@
"apiVersion": "v1",
"metadata": {
"name": "${DATABASE_SERVICE_NAME}",
- "creationTimestamp": null
+ "annotations": {
+ "template.alpha.openshift.io/wait-for-ready": "true"
+ }
},
"spec": {
"strategy": {
@@ -117,7 +117,6 @@
},
"template": {
"metadata": {
- "creationTimestamp": null,
"labels": {
"name": "${DATABASE_SERVICE_NAME}"
}
diff --git a/roles/openshift_examples/files/examples/v3.7/image-streams/OWNERS b/roles/openshift_examples/files/examples/v3.7/image-streams/OWNERS
index 4ccb64c74..6ddf77f12 100644
--- a/roles/openshift_examples/files/examples/v3.7/image-streams/OWNERS
+++ b/roles/openshift_examples/files/examples/v3.7/image-streams/OWNERS
@@ -1,7 +1,6 @@
reviewers:
- bparees
- sspeiche
- - oatmealraisin
- mfojtik
- liggitt
- jcantrill
diff --git a/roles/openshift_examples/files/examples/v3.7/image-streams/dotnet_imagestreams.json b/roles/openshift_examples/files/examples/v3.7/image-streams/dotnet_imagestreams.json
index 857ffa980..ee753966f 100644
--- a/roles/openshift_examples/files/examples/v3.7/image-streams/dotnet_imagestreams.json
+++ b/roles/openshift_examples/files/examples/v3.7/image-streams/dotnet_imagestreams.json
@@ -14,7 +14,7 @@
"metadata": {
"name": "dotnet",
"annotations": {
- "openshift.io/display-name": ".NET Core"
+ "openshift.io/display-name": ".NET Core Builder Images"
}
},
"spec": {
@@ -23,17 +23,35 @@
"name": "latest",
"annotations": {
"openshift.io/display-name": ".NET Core (Latest)",
- "description": "Build and run .NET Core applications on RHEL 7. For more information about using this builder image, including OpenShift considerations, see https://github.com/redhat-developer/s2i-dotnetcore/tree/master/1.1/README.md.\n\nWARNING: By selecting this tag, your application will automatically update to use the latest version of .NET Core available on OpenShift, including major versions updates.",
+ "description": "Build and run .NET Core applications on RHEL 7. For more information about using this builder image, including OpenShift considerations, see https://github.com/redhat-developer/s2i-dotnetcore/tree/master/2.0/build/README.md.\n\nWARNING: By selecting this tag, your application will automatically update to use the latest version of .NET Core available on OpenShift, including major versions updates.",
"iconClass": "icon-dotnet",
"tags": "builder,.net,dotnet,dotnetcore",
"supports":"dotnet",
"sampleRepo": "https://github.com/redhat-developer/s2i-dotnetcore-ex.git",
"sampleContextDir": "app",
- "sampleRef": "dotnetcore-1.1"
+ "sampleRef": "dotnetcore-2.0"
},
"from": {
"kind": "ImageStreamTag",
- "name": "1.1"
+ "name": "2.0"
+ }
+ },
+ {
+ "name": "2.0",
+ "annotations": {
+ "openshift.io/display-name": ".NET Core 2.0",
+ "description": "Build and run .NET Core 2.0 applications on RHEL 7. For more information about using this builder image, including OpenShift considerations, see https://github.com/redhat-developer/s2i-dotnetcore/tree/master/2.0/build/README.md.",
+ "iconClass": "icon-dotnet",
+ "tags": "builder,.net,dotnet,dotnetcore,rh-dotnet20",
+ "supports":"dotnet:2.0,dotnet",
+ "sampleRepo": "https://github.com/redhat-developer/s2i-dotnetcore-ex.git",
+ "sampleContextDir": "app",
+ "sampleRef": "dotnetcore-2.0",
+ "version": "2.0"
+ },
+ "from": {
+ "kind": "DockerImage",
+ "name": "registry.access.redhat.com/dotnet/dotnet-20-rhel7:2.0"
}
},
{
@@ -74,6 +92,49 @@
}
]
}
+ },
+ {
+ "kind": "ImageStream",
+ "apiVersion": "v1",
+ "metadata": {
+ "name": "dotnet-runtime",
+ "annotations": {
+ "openshift.io/display-name": ".NET Core Runtime Images"
+ }
+ },
+ "spec": {
+ "tags": [
+ {
+ "name": "latest",
+ "annotations": {
+ "openshift.io/display-name": ".NET Core Runtime (Latest)",
+ "description": "Run .NET Core applications on RHEL 7. For more information about using this image, including OpenShift considerations, see https://github.com/redhat-developer/s2i-dotnetcore/tree/master/2.0/runtime/README.md.\n\nWARNING: By selecting this tag, your application will automatically update to use the latest version of .NET Core Runtime available on OpenShift, including major versions updates.",
+ "iconClass": "icon-dotnet",
+ "tags": "runtime,.net-runtime,dotnet-runtime,dotnetcore-runtime",
+ "supports":"dotnet-runtime"
+ },
+ "from": {
+ "kind": "ImageStreamTag",
+ "name": "2.0"
+ }
+ },
+ {
+ "name": "2.0",
+ "annotations": {
+ "openshift.io/display-name": ".NET Core 2.0 Runtime",
+ "description": "Run .NET Core applications on RHEL 7. For more information about using this image, including OpenShift considerations, see https://github.com/redhat-developer/s2i-dotnetcore/tree/master/2.0/runtime/README.md.",
+ "iconClass": "icon-dotnet",
+ "tags": "runtime,.net-runtime,dotnet-runtime,dotnetcore-runtime",
+ "supports":"dotnet-runtime",
+ "version": "2.0"
+ },
+ "from": {
+ "kind": "DockerImage",
+ "name": "registry.access.redhat.com/dotnet/dotnet-20-runtime-rhel7:2.0"
+ }
+ }
+ ]
+ }
}
]
}
diff --git a/roles/openshift_examples/files/examples/v3.7/quickstart-templates/cakephp-mysql-persistent.json b/roles/openshift_examples/files/examples/v3.7/quickstart-templates/cakephp-mysql-persistent.json
index 6d987ee33..289f809fa 100644
--- a/roles/openshift_examples/files/examples/v3.7/quickstart-templates/cakephp-mysql-persistent.json
+++ b/roles/openshift_examples/files/examples/v3.7/quickstart-templates/cakephp-mysql-persistent.json
@@ -89,7 +89,8 @@
"metadata": {
"name": "${NAME}",
"annotations": {
- "description": "Defines how to build the application"
+ "description": "Defines how to build the application",
+ "template.alpha.openshift.io/wait-for-ready": "true"
}
},
"spec": {
@@ -148,7 +149,8 @@
"metadata": {
"name": "${NAME}",
"annotations": {
- "description": "Defines how to deploy the application server"
+ "description": "Defines how to deploy the application server",
+ "template.alpha.openshift.io/wait-for-ready": "true"
}
},
"spec": {
diff --git a/roles/openshift_examples/files/examples/v3.7/quickstart-templates/cakephp-mysql.json b/roles/openshift_examples/files/examples/v3.7/quickstart-templates/cakephp-mysql.json
index fb2ef206e..0562982b3 100644
--- a/roles/openshift_examples/files/examples/v3.7/quickstart-templates/cakephp-mysql.json
+++ b/roles/openshift_examples/files/examples/v3.7/quickstart-templates/cakephp-mysql.json
@@ -89,7 +89,8 @@
"metadata": {
"name": "${NAME}",
"annotations": {
- "description": "Defines how to build the application"
+ "description": "Defines how to build the application",
+ "template.alpha.openshift.io/wait-for-ready": "true"
}
},
"spec": {
@@ -148,7 +149,8 @@
"metadata": {
"name": "${NAME}",
"annotations": {
- "description": "Defines how to deploy the application server"
+ "description": "Defines how to deploy the application server",
+ "template.alpha.openshift.io/wait-for-ready": "true"
}
},
"spec": {
diff --git a/roles/openshift_examples/files/examples/v3.7/quickstart-templates/dancer-mysql-persistent.json b/roles/openshift_examples/files/examples/v3.7/quickstart-templates/dancer-mysql-persistent.json
index 7ffb25e14..7a3875d09 100644
--- a/roles/openshift_examples/files/examples/v3.7/quickstart-templates/dancer-mysql-persistent.json
+++ b/roles/openshift_examples/files/examples/v3.7/quickstart-templates/dancer-mysql-persistent.json
@@ -87,7 +87,8 @@
"metadata": {
"name": "${NAME}",
"annotations": {
- "description": "Defines how to build the application"
+ "description": "Defines how to build the application",
+ "template.alpha.openshift.io/wait-for-ready": "true"
}
},
"spec": {
@@ -146,7 +147,8 @@
"metadata": {
"name": "${NAME}",
"annotations": {
- "description": "Defines how to deploy the application server"
+ "description": "Defines how to deploy the application server",
+ "template.alpha.openshift.io/wait-for-ready": "true"
}
},
"spec": {
diff --git a/roles/openshift_examples/files/examples/v3.7/quickstart-templates/dancer-mysql.json b/roles/openshift_examples/files/examples/v3.7/quickstart-templates/dancer-mysql.json
index d787e376b..399ec72a8 100644
--- a/roles/openshift_examples/files/examples/v3.7/quickstart-templates/dancer-mysql.json
+++ b/roles/openshift_examples/files/examples/v3.7/quickstart-templates/dancer-mysql.json
@@ -87,7 +87,8 @@
"metadata": {
"name": "${NAME}",
"annotations": {
- "description": "Defines how to build the application"
+ "description": "Defines how to build the application",
+ "template.alpha.openshift.io/wait-for-ready": "true"
}
},
"spec": {
@@ -146,7 +147,8 @@
"metadata": {
"name": "${NAME}",
"annotations": {
- "description": "Defines how to deploy the application server"
+ "description": "Defines how to deploy the application server",
+ "template.alpha.openshift.io/wait-for-ready": "true"
}
},
"spec": {
diff --git a/roles/openshift_examples/files/examples/v3.7/quickstart-templates/django-postgresql-persistent.json b/roles/openshift_examples/files/examples/v3.7/quickstart-templates/django-postgresql-persistent.json
index a2070207b..e37f7a492 100644
--- a/roles/openshift_examples/files/examples/v3.7/quickstart-templates/django-postgresql-persistent.json
+++ b/roles/openshift_examples/files/examples/v3.7/quickstart-templates/django-postgresql-persistent.json
@@ -87,7 +87,8 @@
"metadata": {
"name": "${NAME}",
"annotations": {
- "description": "Defines how to build the application"
+ "description": "Defines how to build the application",
+ "template.alpha.openshift.io/wait-for-ready": "true"
}
},
"spec": {
@@ -146,7 +147,8 @@
"metadata": {
"name": "${NAME}",
"annotations": {
- "description": "Defines how to deploy the application server"
+ "description": "Defines how to deploy the application server",
+ "template.alpha.openshift.io/wait-for-ready": "true"
}
},
"spec": {
diff --git a/roles/openshift_examples/files/examples/v3.7/quickstart-templates/django-postgresql.json b/roles/openshift_examples/files/examples/v3.7/quickstart-templates/django-postgresql.json
index 0d33c6e0e..965c2ebfe 100644
--- a/roles/openshift_examples/files/examples/v3.7/quickstart-templates/django-postgresql.json
+++ b/roles/openshift_examples/files/examples/v3.7/quickstart-templates/django-postgresql.json
@@ -87,7 +87,8 @@
"metadata": {
"name": "${NAME}",
"annotations": {
- "description": "Defines how to build the application"
+ "description": "Defines how to build the application",
+ "template.alpha.openshift.io/wait-for-ready": "true"
}
},
"spec": {
@@ -146,7 +147,8 @@
"metadata": {
"name": "${NAME}",
"annotations": {
- "description": "Defines how to deploy the application server"
+ "description": "Defines how to deploy the application server",
+ "template.alpha.openshift.io/wait-for-ready": "true"
}
},
"spec": {
diff --git a/roles/openshift_examples/files/examples/v3.7/quickstart-templates/dotnet-example.json b/roles/openshift_examples/files/examples/v3.7/quickstart-templates/dotnet-example.json
index af46579c8..f1fef3093 100644
--- a/roles/openshift_examples/files/examples/v3.7/quickstart-templates/dotnet-example.json
+++ b/roles/openshift_examples/files/examples/v3.7/quickstart-templates/dotnet-example.json
@@ -249,7 +249,7 @@
"displayName": ".NET builder",
"required": true,
"description": "The image stream tag which is used to build the code.",
- "value": "dotnet:1.0"
+ "value": "dotnet:2.0"
},
{
"name": "NAMESPACE",
@@ -269,7 +269,7 @@
"name": "SOURCE_REPOSITORY_REF",
"displayName": "Git Reference",
"description": "Set this to a branch name, tag or other ref of your repository if you are not using the default branch.",
- "value": "dotnetcore-1.0"
+ "value": "dotnetcore-2.0"
},
{
"name": "CONTEXT_DIR",
@@ -299,7 +299,7 @@
{
"name": "DOTNET_STARTUP_PROJECT",
"displayName": "Startup Project",
- "description": "Set this to the folder containing your startup project.",
+ "description": "Set this to a project file (e.g. csproj) or a folder containing a single project file.",
"value": "app"
},
{
diff --git a/roles/openshift_examples/files/examples/v3.7/quickstart-templates/dotnet-pgsql-persistent.json b/roles/openshift_examples/files/examples/v3.7/quickstart-templates/dotnet-pgsql-persistent.json
index a2b59c2d3..c83132152 100644
--- a/roles/openshift_examples/files/examples/v3.7/quickstart-templates/dotnet-pgsql-persistent.json
+++ b/roles/openshift_examples/files/examples/v3.7/quickstart-templates/dotnet-pgsql-persistent.json
@@ -455,7 +455,7 @@
"displayName": ".NET builder",
"required": true,
"description": "The image stream tag which is used to build the code.",
- "value": "dotnet:1.1"
+ "value": "dotnet:2.0"
},
{
"name": "NAMESPACE",
@@ -475,7 +475,7 @@
"name": "SOURCE_REPOSITORY_REF",
"displayName": "Git Reference",
"description": "Set this to a branch name, tag or other ref of your repository if you are not using the default branch.",
- "value": "rel/1.1-example"
+ "value": "rel/2.0-example"
},
{
"name": "CONTEXT_DIR",
@@ -485,7 +485,7 @@
{
"name": "DOTNET_STARTUP_PROJECT",
"displayName": "Startup Project",
- "description": "Set this to the folder containing your startup project.",
+ "description": "Set this to a project file (e.g. csproj) or a folder containing a single project file.",
"value": "samples/MusicStore"
},
{
diff --git a/roles/openshift_examples/files/examples/v3.7/quickstart-templates/dotnet-runtime-example.json b/roles/openshift_examples/files/examples/v3.7/quickstart-templates/dotnet-runtime-example.json
new file mode 100644
index 000000000..e1dccf290
--- /dev/null
+++ b/roles/openshift_examples/files/examples/v3.7/quickstart-templates/dotnet-runtime-example.json
@@ -0,0 +1,412 @@
+{
+ "kind": "Template",
+ "apiVersion": "v1",
+ "metadata": {
+ "name": "dotnet-runtime-example",
+ "annotations": {
+ "openshift.io/display-name": ".NET Core Runtime Example",
+ "description": "An example .NET Core Runtime example application.",
+ "tags": "quickstart,dotnet,.net",
+ "iconClass": "icon-dotnet",
+ "template.openshift.io/provider-display-name": "Red Hat, Inc.",
+ "template.openshift.io/documentation-url": "https://github.com/redhat-developer/s2i-dotnetcore",
+ "template.openshift.io/support-url": "https://access.redhat.com"
+ }
+ },
+ "objects": [
+ {
+ "kind": "Route",
+ "apiVersion": "v1",
+ "metadata": {
+ "name": "${NAME}"
+ },
+ "spec": {
+ "host": "${APPLICATION_DOMAIN}",
+ "to": {
+ "kind": "Service",
+ "name": "${NAME}"
+ }
+ }
+ },
+ {
+ "kind": "Service",
+ "apiVersion": "v1",
+ "metadata": {
+ "name": "${NAME}",
+ "annotations": {
+ "description": "Exposes and load balances the application pods"
+ }
+ },
+ "spec": {
+ "ports": [
+ {
+ "name": "web",
+ "port": 8080,
+ "targetPort": 8080
+ }
+ ],
+ "selector": {
+ "name": "${NAME}"
+ }
+ }
+ },
+ {
+ "kind": "ImageStream",
+ "apiVersion": "v1",
+ "metadata": {
+ "name": "${NAME}",
+ "annotations": {
+ "description": "Keeps track of changes in the application runtime image"
+ }
+ }
+ },
+ {
+ "kind": "ImageStream",
+ "apiVersion": "v1",
+ "metadata": {
+ "name": "${NAME}-build",
+ "annotations": {
+ "description": "Keeps track of changes in the application builder image"
+ }
+ }
+ },
+ {
+ "kind": "BuildConfig",
+ "apiVersion": "v1",
+ "metadata": {
+ "name": "${NAME}-build",
+ "annotations": {
+ "description": "Defines how to build the application"
+ }
+ },
+ "spec": {
+ "source": {
+ "type": "Git",
+ "git": {
+ "uri": "${SOURCE_REPOSITORY_URL}",
+ "ref": "${SOURCE_REPOSITORY_REF}"
+ },
+ "contextDir": "${CONTEXT_DIR}"
+ },
+ "strategy": {
+ "type": "Source",
+ "sourceStrategy": {
+ "from": {
+ "kind": "ImageStreamTag",
+ "namespace": "${NAMESPACE}",
+ "name": "${DOTNET_BUILD_IMAGE_STREAM_TAG}"
+ },
+ "env": [
+ {
+ "name": "DOTNET_STARTUP_PROJECT",
+ "value": "${DOTNET_STARTUP_PROJECT}"
+ },
+ {
+ "name": "DOTNET_ASSEMBLY_NAME",
+ "value": "${DOTNET_ASSEMBLY_NAME}"
+ },
+ {
+ "name": "DOTNET_NPM_TOOLS",
+ "value": "${DOTNET_NPM_TOOLS}"
+ },
+ {
+ "name": "DOTNET_TEST_PROJECTS",
+ "value": "${DOTNET_TEST_PROJECTS}"
+ },
+ {
+ "name": "DOTNET_CONFIGURATION",
+ "value": "${DOTNET_CONFIGURATION}"
+ },
+ {
+ "name": "DOTNET_RESTORE_SOURCES",
+ "value": "${DOTNET_RESTORE_SOURCES}"
+ },
+ {
+ "name": "DOTNET_PACK",
+ "value": "true"
+ }
+ ]
+ }
+ },
+ "output": {
+ "to": {
+ "kind": "ImageStreamTag",
+ "name": "${NAME}-build:latest"
+ }
+ },
+ "triggers": [
+ {
+ "type": "ImageChange"
+ },
+ {
+ "type": "ConfigChange"
+ },
+ {
+ "type": "GitHub",
+ "github": {
+ "secret": "${GITHUB_WEBHOOK_SECRET}"
+ }
+ },
+ {
+ "type": "Generic",
+ "generic": {
+ "secret": "${GENERIC_WEBHOOK_SECRET}"
+ }
+ }
+ ]
+ }
+ },
+ {
+ "kind": "BuildConfig",
+ "apiVersion": "v1",
+ "metadata": {
+ "name": "${NAME}-runtime",
+ "annotations": {
+ "description": "Defines how to chain the runtime image from the source build image"
+ }
+ },
+ "spec": {
+ "source": {
+ "dockerfile": "FROM ${DOTNET_RUNTIME_IMAGE_STREAM_TAG}\nADD app.tar.gz .",
+ "images": [
+ {
+ "from": {
+ "kind": "ImageStreamTag",
+ "name": "${NAME}-build:latest"
+ },
+ "paths": [
+ {
+ "sourcePath": "/opt/app-root/app.tar.gz",
+ "destinationDir": "."
+ }
+ ]
+ }
+ ]
+ },
+ "strategy": {
+ "type": "Docker",
+ "dockerStrategy": {
+ "from": {
+ "kind": "ImageStreamTag",
+ "namespace": "${NAMESPACE}",
+ "name": "${DOTNET_RUNTIME_IMAGE_STREAM_TAG}"
+ }
+ }
+ },
+ "output": {
+ "to": {
+ "kind": "ImageStreamTag",
+ "name": "${NAME}:latest"
+ }
+ },
+ "triggers": [
+ {
+ "type": "ImageChange"
+ },
+ {
+ "type": "ConfigChange"
+ },
+ {
+ "type": "ImageChange",
+ "imageChange": {
+ "from": {
+ "kind": "ImageStreamTag",
+ "name": "${NAME}-build:latest"
+ }
+ }
+ }
+ ]
+ }
+ },
+ {
+ "kind": "DeploymentConfig",
+ "apiVersion": "v1",
+ "metadata": {
+ "name": "${NAME}-runtime",
+ "annotations": {
+ "description": "Defines how to deploy the application server"
+ }
+ },
+ "spec": {
+ "strategy": {
+ "type": "Rolling"
+ },
+ "triggers": [
+ {
+ "type": "ImageChange",
+ "imageChangeParams": {
+ "automatic": true,
+ "containerNames": [
+ "dotnet-runtime-app"
+ ],
+ "from": {
+ "kind": "ImageStreamTag",
+ "name": "${NAME}:latest"
+ }
+ }
+ },
+ {
+ "type": "ConfigChange"
+ }
+ ],
+ "replicas": 1,
+ "selector": {
+ "name": "${NAME}"
+ },
+ "template": {
+ "metadata": {
+ "name": "${NAME}",
+ "labels": {
+ "name": "${NAME}"
+ }
+ },
+ "spec": {
+ "containers": [
+ {
+ "name": "dotnet-runtime-app",
+ "image": " ",
+ "ports": [
+ {
+ "containerPort": 8080
+ }
+ ],
+ "livenessProbe": {
+ "httpGet": {
+ "path": "/",
+ "port": 8080,
+ "scheme": "HTTP"
+ },
+ "initialDelaySeconds": 40,
+ "timeoutSeconds": 15
+ },
+ "readinessProbe": {
+ "httpGet": {
+ "path": "/",
+ "port": 8080,
+ "scheme": "HTTP"
+ },
+ "initialDelaySeconds": 10,
+ "timeoutSeconds": 30
+ },
+ "resources": {
+ "limits": {
+ "memory": "${MEMORY_LIMIT}"
+ }
+ },
+ "env": []
+ }
+ ]
+ }
+ }
+ }
+ }
+ ],
+ "parameters": [
+ {
+ "name": "NAME",
+ "displayName": "Name",
+ "description": "The name assigned to all of the frontend objects defined in this template.",
+ "required": true,
+ "value": "dotnet-runtime-example"
+ },
+ {
+ "name": "MEMORY_LIMIT",
+ "displayName": "Memory Limit",
+ "description": "Maximum amount of memory the container can use.",
+ "required": true,
+ "value": "512Mi"
+ },
+ {
+ "name": "DOTNET_RUNTIME_IMAGE_STREAM_TAG",
+ "displayName": ".NET Runtime Imagestream Tag",
+ "description": "The image stream tag which is used to run the application.",
+ "required": true,
+ "value": "dotnet-runtime:2.0"
+ },
+ {
+ "name": "DOTNET_BUILD_IMAGE_STREAM_TAG",
+ "displayName": ".NET builder",
+ "required": true,
+ "description": "The image stream tag which is used to build the application.",
+ "value": "dotnet:2.0"
+ },
+ {
+ "name": "NAMESPACE",
+ "displayName": "Namespace",
+ "description": "The OpenShift Namespace where the ImageStream resides.",
+ "required": true,
+ "value": "openshift"
+ },
+ {
+ "name": "APPLICATION_DOMAIN",
+ "displayName": "Application Hostname",
+ "description": "The exposed hostname that will route to the .NET Core service, if left blank a value will be defaulted.",
+ "value": ""
+ },
+ {
+ "name": "SOURCE_REPOSITORY_URL",
+ "displayName": "Git Repository URL",
+ "description": "The URL of the repository with your application source code.",
+ "required": true,
+ "value": "https://github.com/redhat-developer/s2i-dotnetcore-ex.git"
+ },
+ {
+ "name": "SOURCE_REPOSITORY_REF",
+ "displayName": "Git Reference",
+ "description": "Set this to a branch name, tag or other ref of your repository if you are not using the default branch.",
+ "value": "dotnetcore-2.0"
+ },
+ {
+ "name": "CONTEXT_DIR",
+ "displayName": "Context Directory",
+ "description": "Set this to use a subdirectory of the source code repository"
+ },
+ {
+ "name": "GITHUB_WEBHOOK_SECRET",
+ "displayName": "GitHub Webhook Secret",
+ "description": "A secret string used to configure the GitHub webhook.",
+ "generate": "expression",
+ "from": "[a-zA-Z0-9]{40}"
+ },
+ {
+ "name": "GENERIC_WEBHOOK_SECRET",
+ "displayName": "Generic Webhook Secret",
+ "description": "A secret string used to configure the Generic webhook.",
+ "generate": "expression",
+ "from": "[a-zA-Z0-9]{40}"
+ },
+ {
+ "name": "DOTNET_STARTUP_PROJECT",
+ "displayName": "Startup Project",
+ "description": "Set this to the folder containing your startup project.",
+ "value": "app"
+ },
+ {
+ "name": "DOTNET_ASSEMBLY_NAME",
+ "displayName": "Startup Assembly",
+ "description": "Set this when the assembly name is overridden in the project file."
+ },
+ {
+ "name": "DOTNET_NPM_TOOLS",
+ "displayName": "Npm Tools",
+ "description": "Set this to a space separated list of npm tools needed to publish.",
+ "value": "bower gulp"
+ },
+ {
+ "name": "DOTNET_TEST_PROJECTS",
+ "displayName": "Test projects",
+ "description": "Set this to a space separated list of test projects to run before publishing."
+ },
+ {
+ "name": "DOTNET_CONFIGURATION",
+ "displayName": "Configuration",
+ "description": "Set this to configuration (Release/Debug).",
+ "value": "Release"
+ },
+ {
+ "name": "DOTNET_RESTORE_SOURCES",
+ "displayName": "NuGet package sources",
+ "description": "Set this to override the NuGet.config sources."
+ }
+ ]
+}
diff --git a/roles/openshift_examples/files/examples/v3.7/quickstart-templates/httpd.json b/roles/openshift_examples/files/examples/v3.7/quickstart-templates/httpd.json
index ac671cc06..6cf9d76eb 100644
--- a/roles/openshift_examples/files/examples/v3.7/quickstart-templates/httpd.json
+++ b/roles/openshift_examples/files/examples/v3.7/quickstart-templates/httpd.json
@@ -74,7 +74,8 @@
"metadata": {
"name": "${NAME}",
"annotations": {
- "description": "Defines how to build the application"
+ "description": "Defines how to build the application",
+ "template.alpha.openshift.io/wait-for-ready": "true"
}
},
"spec": {
@@ -130,7 +131,8 @@
"metadata": {
"name": "${NAME}",
"annotations": {
- "description": "Defines how to deploy the application server"
+ "description": "Defines how to deploy the application server",
+ "template.alpha.openshift.io/wait-for-ready": "true"
}
},
"spec": {
diff --git a/roles/openshift_examples/files/examples/v3.7/quickstart-templates/jenkins-ephemeral-template.json b/roles/openshift_examples/files/examples/v3.7/quickstart-templates/jenkins-ephemeral-template.json
index ce96684a9..62f43bc0b 100644
--- a/roles/openshift_examples/files/examples/v3.7/quickstart-templates/jenkins-ephemeral-template.json
+++ b/roles/openshift_examples/files/examples/v3.7/quickstart-templates/jenkins-ephemeral-template.json
@@ -3,7 +3,6 @@
"apiVersion": "v1",
"metadata": {
"name": "jenkins-ephemeral",
- "creationTimestamp": null,
"annotations": {
"openshift.io/display-name": "Jenkins (Ephemeral)",
"description": "Jenkins service, without persistent storage.\n\nWARNING: Any data stored will be lost upon pod destruction. Only use this template for testing.",
@@ -22,7 +21,6 @@
"apiVersion": "v1",
"metadata": {
"name": "${JENKINS_SERVICE_NAME}",
- "creationTimestamp": null,
"annotations": {
"template.openshift.io/expose-uri": "http://{.spec.host}{.spec.path}"
}
@@ -43,7 +41,9 @@
"apiVersion": "v1",
"metadata": {
"name": "${JENKINS_SERVICE_NAME}",
- "creationTimestamp": null
+ "annotations": {
+ "template.alpha.openshift.io/wait-for-ready": "true"
+ }
},
"spec": {
"strategy": {
@@ -75,7 +75,6 @@
},
"template": {
"metadata": {
- "creationTimestamp": null,
"labels": {
"name": "${JENKINS_SERVICE_NAME}"
}
@@ -221,8 +220,7 @@
"annotations": {
"service.alpha.openshift.io/dependencies": "[{\"name\": \"${JNLP_SERVICE_NAME}\", \"namespace\": \"\", \"kind\": \"Service\"}]",
"service.openshift.io/infrastructure": "true"
- },
- "creationTimestamp": null
+ }
},
"spec": {
"ports": [
diff --git a/roles/openshift_examples/files/examples/v3.7/quickstart-templates/jenkins-persistent-template.json b/roles/openshift_examples/files/examples/v3.7/quickstart-templates/jenkins-persistent-template.json
index 34b2b920b..e9068e455 100644
--- a/roles/openshift_examples/files/examples/v3.7/quickstart-templates/jenkins-persistent-template.json
+++ b/roles/openshift_examples/files/examples/v3.7/quickstart-templates/jenkins-persistent-template.json
@@ -3,7 +3,6 @@
"apiVersion": "v1",
"metadata": {
"name": "jenkins-persistent",
- "creationTimestamp": null,
"annotations": {
"openshift.io/display-name": "Jenkins (Persistent)",
"description": "Jenkins service, with persistent storage.\n\nNOTE: You must have persistent volumes available in your cluster to use this template.",
@@ -22,7 +21,6 @@
"apiVersion": "v1",
"metadata": {
"name": "${JENKINS_SERVICE_NAME}",
- "creationTimestamp": null,
"annotations": {
"template.openshift.io/expose-uri": "http://{.spec.host}{.spec.path}"
}
@@ -60,7 +58,9 @@
"apiVersion": "v1",
"metadata": {
"name": "${JENKINS_SERVICE_NAME}",
- "creationTimestamp": null
+ "annotations": {
+ "template.alpha.openshift.io/wait-for-ready": "true"
+ }
},
"spec": {
"strategy": {
@@ -92,7 +92,6 @@
},
"template": {
"metadata": {
- "creationTimestamp": null,
"labels": {
"name": "${JENKINS_SERVICE_NAME}"
}
@@ -238,8 +237,7 @@
"annotations": {
"service.alpha.openshift.io/dependencies": "[{\"name\": \"${JNLP_SERVICE_NAME}\", \"namespace\": \"\", \"kind\": \"Service\"}]",
"service.openshift.io/infrastructure": "true"
- },
- "creationTimestamp": null
+ }
},
"spec": {
"ports": [
diff --git a/roles/openshift_examples/files/examples/v3.7/quickstart-templates/nodejs-mongodb-persistent.json b/roles/openshift_examples/files/examples/v3.7/quickstart-templates/nodejs-mongodb-persistent.json
index a9c365361..df3704b9f 100644
--- a/roles/openshift_examples/files/examples/v3.7/quickstart-templates/nodejs-mongodb-persistent.json
+++ b/roles/openshift_examples/files/examples/v3.7/quickstart-templates/nodejs-mongodb-persistent.json
@@ -87,7 +87,8 @@
"metadata": {
"name": "${NAME}",
"annotations": {
- "description": "Defines how to build the application"
+ "description": "Defines how to build the application",
+ "template.alpha.openshift.io/wait-for-ready": "true"
}
},
"spec": {
@@ -152,7 +153,8 @@
"metadata": {
"name": "${NAME}",
"annotations": {
- "description": "Defines how to deploy the application server"
+ "description": "Defines how to deploy the application server",
+ "template.alpha.openshift.io/wait-for-ready": "true"
}
},
"spec": {
diff --git a/roles/openshift_examples/files/examples/v3.7/quickstart-templates/nodejs-mongodb.json b/roles/openshift_examples/files/examples/v3.7/quickstart-templates/nodejs-mongodb.json
index 53a6147d5..eb6ab33d9 100644
--- a/roles/openshift_examples/files/examples/v3.7/quickstart-templates/nodejs-mongodb.json
+++ b/roles/openshift_examples/files/examples/v3.7/quickstart-templates/nodejs-mongodb.json
@@ -87,7 +87,8 @@
"metadata": {
"name": "${NAME}",
"annotations": {
- "description": "Defines how to build the application"
+ "description": "Defines how to build the application",
+ "template.alpha.openshift.io/wait-for-ready": "true"
}
},
"spec": {
@@ -152,7 +153,8 @@
"metadata": {
"name": "${NAME}",
"annotations": {
- "description": "Defines how to deploy the application server"
+ "description": "Defines how to deploy the application server",
+ "template.alpha.openshift.io/wait-for-ready": "true"
}
},
"spec": {
diff --git a/roles/openshift_examples/files/examples/v3.7/quickstart-templates/rails-postgresql-persistent.json b/roles/openshift_examples/files/examples/v3.7/quickstart-templates/rails-postgresql-persistent.json
index f07a43071..59e2e41ea 100644
--- a/roles/openshift_examples/files/examples/v3.7/quickstart-templates/rails-postgresql-persistent.json
+++ b/roles/openshift_examples/files/examples/v3.7/quickstart-templates/rails-postgresql-persistent.json
@@ -93,7 +93,8 @@
"metadata": {
"name": "${NAME}",
"annotations": {
- "description": "Defines how to build the application"
+ "description": "Defines how to build the application",
+ "template.alpha.openshift.io/wait-for-ready": "true"
}
},
"spec": {
@@ -152,7 +153,8 @@
"metadata": {
"name": "${NAME}",
"annotations": {
- "description": "Defines how to deploy the application server"
+ "description": "Defines how to deploy the application server",
+ "template.alpha.openshift.io/wait-for-ready": "true"
}
},
"spec": {
diff --git a/roles/openshift_examples/files/examples/v3.7/quickstart-templates/rails-postgresql.json b/roles/openshift_examples/files/examples/v3.7/quickstart-templates/rails-postgresql.json
index a7992c988..b3d080a91 100644
--- a/roles/openshift_examples/files/examples/v3.7/quickstart-templates/rails-postgresql.json
+++ b/roles/openshift_examples/files/examples/v3.7/quickstart-templates/rails-postgresql.json
@@ -93,7 +93,8 @@
"metadata": {
"name": "${NAME}",
"annotations": {
- "description": "Defines how to build the application"
+ "description": "Defines how to build the application",
+ "template.alpha.openshift.io/wait-for-ready": "true"
}
},
"spec": {
@@ -152,7 +153,8 @@
"metadata": {
"name": "${NAME}",
"annotations": {
- "description": "Defines how to deploy the application server"
+ "description": "Defines how to deploy the application server",
+ "template.alpha.openshift.io/wait-for-ready": "true"
}
},
"spec": {
diff --git a/roles/openshift_examples/meta/main.yml b/roles/openshift_examples/meta/main.yml
index 5cfda1c89..f3fe2dcbe 100644
--- a/roles/openshift_examples/meta/main.yml
+++ b/roles/openshift_examples/meta/main.yml
@@ -11,5 +11,4 @@ galaxy_info:
- 7
categories:
- cloud
-dependencies:
-- role: openshift_common
+dependencies: []
diff --git a/roles/openshift_facts/library/openshift_facts.py b/roles/openshift_facts/library/openshift_facts.py
index 844d77255..a76751e81 100755
--- a/roles/openshift_facts/library/openshift_facts.py
+++ b/roles/openshift_facts/library/openshift_facts.py
@@ -193,7 +193,9 @@ def hostname_valid(hostname):
"""
if (not hostname or
hostname.startswith('localhost') or
- hostname.endswith('localdomain')):
+ hostname.endswith('localdomain') or
+ # OpenShift will not allow a node with more than 63 chars in name.
+ len(hostname) > 63):
return False
return True
@@ -447,78 +449,6 @@ def normalize_provider_facts(provider, metadata):
return facts
-def set_flannel_facts_if_unset(facts):
- """ Set flannel facts if not already present in facts dict
- dict: the facts dict updated with the flannel facts if
- missing
- Args:
- facts (dict): existing facts
- Returns:
- dict: the facts dict updated with the flannel
- facts if they were not already present
-
- """
- if 'common' in facts:
- if 'use_flannel' not in facts['common']:
- use_flannel = False
- facts['common']['use_flannel'] = use_flannel
- return facts
-
-
-def set_calico_facts_if_unset(facts):
- """ Set calico facts if not already present in facts dict
- dict: the facts dict updated with the calico facts if
- missing
- Args:
- facts (dict): existing facts
- Returns:
- dict: the facts dict updated with the calico
- facts if they were not already present
-
- """
- if 'common' in facts:
- if 'use_calico' not in facts['common']:
- use_calico = False
- facts['common']['use_calico'] = use_calico
- return facts
-
-
-def set_nuage_facts_if_unset(facts):
- """ Set nuage facts if not already present in facts dict
- dict: the facts dict updated with the nuage facts if
- missing
- Args:
- facts (dict): existing facts
- Returns:
- dict: the facts dict updated with the nuage
- facts if they were not already present
-
- """
- if 'common' in facts:
- if 'use_nuage' not in facts['common']:
- use_nuage = False
- facts['common']['use_nuage'] = use_nuage
- return facts
-
-
-def set_contiv_facts_if_unset(facts):
- """ Set contiv facts if not already present in facts dict
- dict: the facts dict updated with the contiv facts if
- missing
- Args:
- facts (dict): existing facts
- Returns:
- dict: the facts dict updated with the contiv
- facts if they were not already present
-
- """
- if 'common' in facts:
- if 'use_contiv' not in facts['common']:
- use_contiv = False
- facts['common']['use_contiv'] = use_contiv
- return facts
-
-
def set_node_schedulability(facts):
""" Set schedulable facts if not already present in facts dict
Args:
@@ -547,11 +477,7 @@ def set_selectors(facts):
facts if they were not already present
"""
- deployment_type = facts['common']['deployment_type']
- if deployment_type == 'online':
- selector = "type=infra"
- else:
- selector = "region=infra"
+ selector = "region=infra"
if 'hosted' not in facts:
facts['hosted'] = {}
@@ -588,13 +514,8 @@ def set_dnsmasq_facts_if_unset(facts):
"""
if 'common' in facts:
- if 'use_dnsmasq' not in facts['common']:
- facts['common']['use_dnsmasq'] = bool(safe_get_bool(facts['common']['version_gte_3_2_or_1_2']))
if 'master' in facts and 'dns_port' not in facts['master']:
- if safe_get_bool(facts['common']['use_dnsmasq']):
- facts['master']['dns_port'] = 8053
- else:
- facts['master']['dns_port'] = 53
+ facts['master']['dns_port'] = 8053
return facts
@@ -643,7 +564,7 @@ def set_identity_providers_if_unset(facts):
name='allow_all', challenge=True, login=True,
kind='AllowAllPasswordIdentityProvider'
)
- if deployment_type in ['enterprise', 'atomic-enterprise', 'openshift-enterprise']:
+ if deployment_type == 'openshift-enterprise':
identity_provider = dict(
name='deny_all', challenge=True, login=True,
kind='DenyAllPasswordIdentityProvider'
@@ -845,13 +766,11 @@ def set_deployment_facts_if_unset(facts):
service_type = 'atomic-openshift'
if deployment_type == 'origin':
service_type = 'origin'
- elif deployment_type in ['enterprise']:
- service_type = 'openshift'
facts['common']['service_type'] = service_type
if 'docker' in facts:
deployment_type = facts['common']['deployment_type']
- if deployment_type in ['enterprise', 'atomic-enterprise', 'openshift-enterprise']:
+ if deployment_type == 'openshift-enterprise':
addtl_regs = facts['docker'].get('additional_registries', [])
ent_reg = 'registry.access.redhat.com'
if ent_reg not in addtl_regs:
@@ -862,30 +781,21 @@ def set_deployment_facts_if_unset(facts):
deployment_type = facts['common']['deployment_type']
if 'registry_url' not in facts[role]:
registry_url = 'openshift/origin-${component}:${version}'
- if deployment_type in ['enterprise', 'online', 'openshift-enterprise']:
+ if deployment_type == 'openshift-enterprise':
registry_url = 'openshift3/ose-${component}:${version}'
- elif deployment_type == 'atomic-enterprise':
- registry_url = 'aep3_beta/aep-${component}:${version}'
facts[role]['registry_url'] = registry_url
if 'master' in facts:
deployment_type = facts['common']['deployment_type']
openshift_features = ['Builder', 'S2IBuilder', 'WebConsole']
- if 'disabled_features' in facts['master']:
- if deployment_type == 'atomic-enterprise':
- curr_disabled_features = set(facts['master']['disabled_features'])
- facts['master']['disabled_features'] = list(curr_disabled_features.union(openshift_features))
- else:
+ if 'disabled_features' not in facts['master']:
if facts['common']['deployment_subtype'] == 'registry':
facts['master']['disabled_features'] = openshift_features
if 'node' in facts:
deployment_type = facts['common']['deployment_type']
if 'storage_plugin_deps' not in facts['node']:
- if deployment_type in ['openshift-enterprise', 'atomic-enterprise', 'origin']:
- facts['node']['storage_plugin_deps'] = ['ceph', 'glusterfs', 'iscsi']
- else:
- facts['node']['storage_plugin_deps'] = []
+ facts['node']['storage_plugin_deps'] = ['ceph', 'glusterfs', 'iscsi']
return facts
@@ -966,27 +876,6 @@ def set_version_facts_if_unset(facts):
return facts
-def set_manageiq_facts_if_unset(facts):
- """ Set manageiq facts. This currently includes common.use_manageiq.
-
- Args:
- facts (dict): existing facts
- Returns:
- dict: the facts dict updated with version facts.
- Raises:
- OpenShiftFactsInternalError:
- """
- if 'common' not in facts:
- if 'version_gte_3_1_or_1_1' not in facts['common']:
- raise OpenShiftFactsInternalError(
- "Invalid invocation: The required facts are not set"
- )
- if 'use_manageiq' not in facts['common']:
- facts['common']['use_manageiq'] = facts['common']['version_gte_3_1_or_1_1']
-
- return facts
-
-
def set_sdn_facts_if_unset(facts, system_facts):
""" Set sdn facts if not already present in facts dict
@@ -997,15 +886,6 @@ def set_sdn_facts_if_unset(facts, system_facts):
dict: the facts dict updated with the generated sdn facts if they
were not already present
"""
- # pylint: disable=too-many-branches
- if 'common' in facts:
- use_sdn = facts['common']['use_openshift_sdn']
- if not (use_sdn == '' or isinstance(use_sdn, bool)):
- use_sdn = safe_get_bool(use_sdn)
- facts['common']['use_openshift_sdn'] = use_sdn
- if 'sdn_network_plugin_name' not in facts['common']:
- plugin = 'redhat/openshift-ovs-subnet' if use_sdn else ''
- facts['common']['sdn_network_plugin_name'] = plugin
if 'master' in facts:
# set defaults for sdn_cluster_network_cidr and sdn_host_subnet_length
@@ -1707,11 +1587,13 @@ def set_builddefaults_facts(facts):
builddefaults['git_no_proxy'] = builddefaults['no_proxy']
# If we're actually defining a builddefaults config then create admission_plugin_config
# then merge builddefaults[config] structure into admission_plugin_config
+
+ # 'config' is the 'openshift_builddefaults_json' inventory variable
if 'config' in builddefaults:
if 'admission_plugin_config' not in facts['master']:
- facts['master']['admission_plugin_config'] = dict()
+ # Scaffold out the full expected datastructure
+ facts['master']['admission_plugin_config'] = {'BuildDefaults': {'configuration': {'env': {}}}}
facts['master']['admission_plugin_config'].update(builddefaults['config'])
- # if the user didn't actually provide proxy values, delete the proxy env variable defaults.
delete_empty_keys(facts['master']['admission_plugin_config']['BuildDefaults']['configuration']['env'])
return facts
@@ -1774,7 +1656,7 @@ def set_container_facts_if_unset(facts):
facts
"""
deployment_type = facts['common']['deployment_type']
- if deployment_type in ['enterprise', 'openshift-enterprise']:
+ if deployment_type == 'openshift-enterprise':
master_image = 'openshift3/ose'
cli_image = master_image
node_image = 'openshift3/node'
@@ -1784,16 +1666,6 @@ def set_container_facts_if_unset(facts):
router_image = 'openshift3/ose-haproxy-router'
registry_image = 'openshift3/ose-docker-registry'
deployer_image = 'openshift3/ose-deployer'
- elif deployment_type == 'atomic-enterprise':
- master_image = 'aep3_beta/aep'
- cli_image = master_image
- node_image = 'aep3_beta/node'
- ovs_image = 'aep3_beta/openvswitch'
- etcd_image = 'registry.access.redhat.com/rhel7/etcd'
- pod_image = 'aep3_beta/aep-pod'
- router_image = 'aep3_beta/aep-haproxy-router'
- registry_image = 'aep3_beta/aep-docker-registry'
- deployer_image = 'aep3_beta/aep-deployer'
else:
master_image = 'openshift/origin'
cli_image = master_image
@@ -1907,7 +1779,6 @@ class OpenShiftFacts(object):
"""
known_roles = ['builddefaults',
'buildoverrides',
- 'clock',
'cloudprovider',
'common',
'docker',
@@ -1995,10 +1866,6 @@ class OpenShiftFacts(object):
facts['current_config'] = get_current_config(facts)
facts = set_url_facts_if_unset(facts)
facts = set_project_cfg_facts_if_unset(facts)
- facts = set_flannel_facts_if_unset(facts)
- facts = set_calico_facts_if_unset(facts)
- facts = set_nuage_facts_if_unset(facts)
- facts = set_contiv_facts_if_unset(facts)
facts = set_node_schedulability(facts)
facts = set_selectors(facts)
facts = set_identity_providers_if_unset(facts)
@@ -2010,7 +1877,6 @@ class OpenShiftFacts(object):
facts = build_api_server_args(facts)
facts = set_version_facts_if_unset(facts)
facts = set_dnsmasq_facts_if_unset(facts)
- facts = set_manageiq_facts_if_unset(facts)
facts = set_aggregate_facts(facts)
facts = set_etcd_facts_if_unset(facts)
facts = set_proxy_facts(facts)
@@ -2038,7 +1904,7 @@ class OpenShiftFacts(object):
self.system_facts['ansible_fqdn']]
hostname = choose_hostname(hostname_values, ip_addr)
- defaults['common'] = dict(use_openshift_sdn=True, ip=ip_addr,
+ defaults['common'] = dict(ip=ip_addr,
public_ip=ip_addr,
deployment_type=deployment_type,
deployment_subtype=deployment_subtype,
@@ -2047,10 +1913,8 @@ class OpenShiftFacts(object):
portal_net='172.30.0.0/16',
client_binary='oc', admin_binary='oadm',
dns_domain='cluster.local',
- install_examples=True,
debug_level=2,
- config_base='/etc/origin',
- data_dir='/var/lib/origin')
+ config_base='/etc/origin')
if 'master' in roles:
defaults['master'] = dict(api_use_ssl=True, api_port='8443',
@@ -2097,13 +1961,6 @@ class OpenShiftFacts(object):
docker['service_name'] = 'docker'
defaults['docker'] = docker
- if 'clock' in roles:
- exit_code, _, _ = module.run_command(['rpm', '-q', 'chrony']) # noqa: F405
- chrony_installed = bool(exit_code == 0)
- defaults['clock'] = dict(
- enabled=True,
- chrony_installed=chrony_installed)
-
if 'cloudprovider' in roles:
defaults['cloudprovider'] = dict(kind=None)
diff --git a/roles/openshift_gcp/tasks/main.yaml b/roles/openshift_gcp/tasks/main.yaml
new file mode 100644
index 000000000..ad205ba33
--- /dev/null
+++ b/roles/openshift_gcp/tasks/main.yaml
@@ -0,0 +1,43 @@
+#
+# This role relies on gcloud invoked via templated bash in order to
+# provide a high performance deployment option. The next logical step
+# is to transition to a deployment manager template which is then instantiated.
+# TODO: use a formal set of role parameters consistent with openshift_aws
+#
+---
+- name: Templatize DNS script
+ template: src=dns.j2.sh dest=/tmp/openshift_gcp_provision_dns.sh mode=u+rx
+- name: Templatize provision script
+ template: src=provision.j2.sh dest=/tmp/openshift_gcp_provision.sh mode=u+rx
+- name: Templatize de-provision script
+ template: src=remove.j2.sh dest=/tmp/openshift_gcp_provision_remove.sh mode=u+rx
+ when:
+ - state | default('present') == 'absent'
+
+- name: Provision GCP DNS domain
+ command: /tmp/openshift_gcp_provision_dns.sh
+ args:
+ chdir: "{{ playbook_dir }}/files"
+ register: dns_provision
+ when:
+ - state | default('present') == 'present'
+
+- name: Ensure that DNS resolves to the hosted zone
+ assert:
+ that:
+ - "lookup('dig', public_hosted_zone, 'qtype=NS', wantlist=True) | sort | join(',') == dns_provision.stdout"
+ msg: "The DNS domain {{ public_hosted_zone }} defined in 'public_hosted_zone' must have NS records pointing to the Google nameservers: '{{ dns_provision.stdout }}' instead of '{{ lookup('dig', public_hosted_zone, 'qtype=NS') }}'."
+ when:
+ - state | default('present') == 'present'
+
+- name: Provision GCP resources
+ command: /tmp/openshift_gcp_provision.sh
+ args:
+ chdir: "{{ playbook_dir }}/files"
+ when:
+ - state | default('present') == 'present'
+
+- name: De-provision GCP resources
+ command: /tmp/openshift_gcp_provision_remove.sh
+ when:
+ - state | default('present') == 'absent'
diff --git a/roles/openshift_gcp/templates/dns.j2.sh b/roles/openshift_gcp/templates/dns.j2.sh
new file mode 100644
index 000000000..eacf84b4d
--- /dev/null
+++ b/roles/openshift_gcp/templates/dns.j2.sh
@@ -0,0 +1,13 @@
+#!/bin/bash
+
+set -euo pipefail
+
+dns_zone="{{ dns_managed_zone | default(provision_prefix + 'managed-zone') }}"
+
+# Check the DNS managed zone in Google Cloud DNS, create it if it doesn't exist
+if ! gcloud --project "{{ gce_project_id }}" dns managed-zones describe "${dns_zone}" &>/dev/null; then
+ gcloud --project "{{ gce_project_id }}" dns managed-zones create "${dns_zone}" --dns-name "{{ public_hosted_zone }}" --description "{{ public_hosted_zone }} domain" >/dev/null
+fi
+
+# Always output the expected nameservers as a comma delimited list
+gcloud --project "{{ gce_project_id }}" dns managed-zones describe "${dns_zone}" --format='value(nameServers)' | tr ';' ','
diff --git a/roles/openshift_gcp/templates/provision.j2.sh b/roles/openshift_gcp/templates/provision.j2.sh
new file mode 100644
index 000000000..e68e9683f
--- /dev/null
+++ b/roles/openshift_gcp/templates/provision.j2.sh
@@ -0,0 +1,318 @@
+#!/bin/bash
+
+set -euo pipefail
+
+# Create SSH key for GCE
+if [ ! -f "{{ gce_ssh_private_key }}" ]; then
+ ssh-keygen -t rsa -f "{{ gce_ssh_private_key }}" -C gce-provision-cloud-user -N ''
+ ssh-add "{{ gce_ssh_private_key }}" || true
+fi
+
+# Check if the ~/.ssh/google_compute_engine.pub key is in the project metadata, and if not, add it there
+pub_key=$(cut -d ' ' -f 2 < "{{ gce_ssh_private_key }}.pub")
+key_tmp_file='/tmp/ocp-gce-keys'
+if ! gcloud --project "{{ gce_project_id }}" compute project-info describe | grep -q "$pub_key"; then
+ if gcloud --project "{{ gce_project_id }}" compute project-info describe | grep -q ssh-rsa; then
+ gcloud --project "{{ gce_project_id }}" compute project-info describe | grep ssh-rsa | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' -e 's/value: //' > "$key_tmp_file"
+ fi
+ echo -n 'cloud-user:' >> "$key_tmp_file"
+ cat "{{ gce_ssh_private_key }}.pub" >> "$key_tmp_file"
+ gcloud --project "{{ gce_project_id }}" compute project-info add-metadata --metadata-from-file "sshKeys=${key_tmp_file}"
+ rm -f "$key_tmp_file"
+fi
+
+metadata=""
+if [[ -n "{{ provision_gce_startup_script_file }}" ]]; then
+ if [[ ! -f "{{ provision_gce_startup_script_file }}" ]]; then
+ echo "Startup script file missing at {{ provision_gce_startup_script_file }} from=$(pwd)"
+ exit 1
+ fi
+ metadata+="--metadata-from-file=startup-script={{ provision_gce_startup_script_file }}"
+fi
+if [[ -n "{{ provision_gce_user_data_file }}" ]]; then
+ if [[ ! -f "{{ provision_gce_user_data_file }}" ]]; then
+ echo "User data file missing at {{ provision_gce_user_data_file }}"
+ exit 1
+ fi
+ if [[ -n "${metadata}" ]]; then
+ metadata+=","
+ else
+ metadata="--metadata-from-file="
+ fi
+ metadata+="user-data={{ provision_gce_user_data_file }}"
+fi
+
+# Select image or image family
+image="{{ provision_gce_registered_image }}"
+if ! gcloud --project "{{ gce_project_id }}" compute images describe "${image}" &>/dev/null; then
+ if ! gcloud --project "{{ gce_project_id }}" compute images describe-from-family "${image}" &>/dev/null; then
+ echo "No compute image or image-family found, create an image named '{{ provision_gce_registered_image }}' to continue'"
+ exit 1
+ fi
+ image="family/${image}"
+fi
+
+### PROVISION THE INFRASTRUCTURE ###
+
+dns_zone="{{ dns_managed_zone | default(provision_prefix + 'managed-zone') }}"
+
+# Check the DNS managed zone in Google Cloud DNS, create it if it doesn't exist and exit after printing NS servers
+if ! gcloud --project "{{ gce_project_id }}" dns managed-zones describe "${dns_zone}" &>/dev/null; then
+ echo "DNS zone '${dns_zone}' doesn't exist. Must be configured prior to running this script"
+ exit 1
+fi
+
+# Create network
+if ! gcloud --project "{{ gce_project_id }}" compute networks describe "{{ gce_network_name }}" &>/dev/null; then
+ gcloud --project "{{ gce_project_id }}" compute networks create "{{ gce_network_name }}" --mode "auto"
+else
+ echo "Network '{{ gce_network_name }}' already exists"
+fi
+
+# Firewall rules in a form:
+# ['name']='parameters for "gcloud compute firewall-rules create"'
+# For all possible parameters see: gcloud compute firewall-rules create --help
+range=""
+if [[ -n "{{ openshift_node_port_range }}" ]]; then
+ range=",tcp:{{ openshift_node_port_range }},udp:{{ openshift_node_port_range }}"
+fi
+declare -A FW_RULES=(
+ ['icmp']='--allow icmp'
+ ['ssh-external']='--allow tcp:22'
+ ['ssh-internal']='--allow tcp:22 --source-tags bastion'
+ ['master-internal']="--allow tcp:2224,tcp:2379,tcp:2380,tcp:4001,udp:4789,udp:5404,udp:5405,tcp:8053,udp:8053,tcp:8444,tcp:10250,tcp:10255,udp:10255,tcp:24224,udp:24224 --source-tags ocp --target-tags ocp-master"
+ ['master-external']="--allow tcp:80,tcp:443,tcp:1936,tcp:8080,tcp:8443${range} --target-tags ocp-master"
+ ['node-internal']="--allow udp:4789,tcp:10250,tcp:10255,udp:10255 --source-tags ocp --target-tags ocp-node,ocp-infra-node"
+ ['infra-node-internal']="--allow tcp:5000 --source-tags ocp --target-tags ocp-infra-node"
+ ['infra-node-external']="--allow tcp:80,tcp:443,tcp:1936${range} --target-tags ocp-infra-node"
+)
+for rule in "${!FW_RULES[@]}"; do
+ ( if ! gcloud --project "{{ gce_project_id }}" compute firewall-rules describe "{{ provision_prefix }}$rule" &>/dev/null; then
+ gcloud --project "{{ gce_project_id }}" compute firewall-rules create "{{ provision_prefix }}$rule" --network "{{ gce_network_name }}" ${FW_RULES[$rule]}
+ else
+ echo "Firewall rule '{{ provision_prefix }}${rule}' already exists"
+ fi ) &
+done
+
+
+# Master IP
+( if ! gcloud --project "{{ gce_project_id }}" compute addresses describe "{{ provision_prefix }}master-ssl-lb-ip" --global &>/dev/null; then
+ gcloud --project "{{ gce_project_id }}" compute addresses create "{{ provision_prefix }}master-ssl-lb-ip" --global
+else
+ echo "IP '{{ provision_prefix }}master-ssl-lb-ip' already exists"
+fi ) &
+
+# Internal master IP
+( if ! gcloud --project "{{ gce_project_id }}" compute addresses describe "{{ provision_prefix }}master-network-lb-ip" --region "{{ gce_region_name }}" &>/dev/null; then
+ gcloud --project "{{ gce_project_id }}" compute addresses create "{{ provision_prefix }}master-network-lb-ip" --region "{{ gce_region_name }}"
+else
+ echo "IP '{{ provision_prefix }}master-network-lb-ip' already exists"
+fi ) &
+
+# Router IP
+( if ! gcloud --project "{{ gce_project_id }}" compute addresses describe "{{ provision_prefix }}router-network-lb-ip" --region "{{ gce_region_name }}" &>/dev/null; then
+ gcloud --project "{{ gce_project_id }}" compute addresses create "{{ provision_prefix }}router-network-lb-ip" --region "{{ gce_region_name }}"
+else
+ echo "IP '{{ provision_prefix }}router-network-lb-ip' already exists"
+fi ) &
+
+
+{% for node_group in provision_gce_node_groups %}
+# configure {{ node_group.name }}
+(
+ if ! gcloud --project "{{ gce_project_id }}" compute instance-templates describe "{{ provision_prefix }}instance-template-{{ node_group.name }}" &>/dev/null; then
+ gcloud --project "{{ gce_project_id }}" compute instance-templates create "{{ provision_prefix }}instance-template-{{ node_group.name }}" \
+ --machine-type "{{ node_group.machine_type }}" --network "{{ gce_network_name }}" \
+ --tags "{{ provision_prefix }}ocp,ocp,{{ node_group.tags }}" \
+ --boot-disk-size "{{ node_group.boot_disk_size }}" --boot-disk-type "pd-ssd" \
+ --scopes "logging-write,monitoring-write,useraccounts-ro,service-control,service-management,storage-ro,compute-rw" \
+ --image "${image}" ${metadata}
+ else
+ echo "Instance template '{{ provision_prefix }}instance-template-{{ node_group.name }}' already exists"
+ fi
+
+ # Create instance group
+ if ! gcloud --project "{{ gce_project_id }}" compute instance-groups managed describe "{{ provision_prefix }}ig-{{ node_group.suffix }}" --zone "{{ gce_zone_name }}" &>/dev/null; then
+ gcloud --project "{{ gce_project_id }}" compute instance-groups managed create "{{ provision_prefix }}ig-{{ node_group.suffix }}" \
+ --zone "{{ gce_zone_name }}" --template "{{ provision_prefix }}instance-template-{{ node_group.name }}" --size "{{ node_group.scale }}"
+ else
+ echo "Instance group '{{ provision_prefix }}ig-{{ node_group.suffix }}' already exists"
+ fi
+) &
+{% endfor %}
+
+for i in `jobs -p`; do wait $i; done
+
+
+# Configure the master external LB rules
+(
+# Master health check
+if ! gcloud --project "{{ gce_project_id }}" compute health-checks describe "{{ provision_prefix }}master-ssl-lb-health-check" &>/dev/null; then
+ gcloud --project "{{ gce_project_id }}" compute health-checks create https "{{ provision_prefix }}master-ssl-lb-health-check" --port "{{ internal_console_port }}" --request-path "/healthz"
+else
+ echo "Health check '{{ provision_prefix }}master-ssl-lb-health-check' already exists"
+fi
+
+gcloud --project "{{ gce_project_id }}" compute instance-groups managed set-named-ports "{{ provision_prefix }}ig-m" \
+ --zone "{{ gce_zone_name }}" --named-ports "{{ provision_prefix }}port-name-master:{{ internal_console_port }}"
+
+# Master backend service
+if ! gcloud --project "{{ gce_project_id }}" compute backend-services describe "{{ provision_prefix }}master-ssl-lb-backend" --global &>/dev/null; then
+ gcloud --project "{{ gce_project_id }}" compute backend-services create "{{ provision_prefix }}master-ssl-lb-backend" --health-checks "{{ provision_prefix }}master-ssl-lb-health-check" --port-name "{{ provision_prefix }}port-name-master" --protocol "TCP" --global --timeout="{{ provision_gce_master_https_timeout | default('2m') }}"
+ gcloud --project "{{ gce_project_id }}" compute backend-services add-backend "{{ provision_prefix }}master-ssl-lb-backend" --instance-group "{{ provision_prefix }}ig-m" --global --instance-group-zone "{{ gce_zone_name }}"
+else
+ echo "Backend service '{{ provision_prefix }}master-ssl-lb-backend' already exists"
+fi
+
+# Master tcp proxy target
+if ! gcloud --project "{{ gce_project_id }}" compute target-tcp-proxies describe "{{ provision_prefix }}master-ssl-lb-target" &>/dev/null; then
+ gcloud --project "{{ gce_project_id }}" compute target-tcp-proxies create "{{ provision_prefix }}master-ssl-lb-target" --backend-service "{{ provision_prefix }}master-ssl-lb-backend"
+else
+ echo "Proxy target '{{ provision_prefix }}master-ssl-lb-target' already exists"
+fi
+
+# Master forwarding rule
+if ! gcloud --project "{{ gce_project_id }}" compute forwarding-rules describe "{{ provision_prefix }}master-ssl-lb-rule" --global &>/dev/null; then
+ IP=$(gcloud --project "{{ gce_project_id }}" compute addresses describe "{{ provision_prefix }}master-ssl-lb-ip" --global --format='value(address)')
+ gcloud --project "{{ gce_project_id }}" compute forwarding-rules create "{{ provision_prefix }}master-ssl-lb-rule" --address "$IP" --global --ports "{{ console_port }}" --target-tcp-proxy "{{ provision_prefix }}master-ssl-lb-target"
+else
+ echo "Forwarding rule '{{ provision_prefix }}master-ssl-lb-rule' already exists"
+fi
+) &
+
+
+# Configure the master internal LB rules
+(
+# Internal master health check
+if ! gcloud --project "{{ gce_project_id }}" compute http-health-checks describe "{{ provision_prefix }}master-network-lb-health-check" &>/dev/null; then
+ gcloud --project "{{ gce_project_id }}" compute http-health-checks create "{{ provision_prefix }}master-network-lb-health-check" --port "8080" --request-path "/healthz"
+else
+ echo "Health check '{{ provision_prefix }}master-network-lb-health-check' already exists"
+fi
+
+# Internal master target pool
+if ! gcloud --project "{{ gce_project_id }}" compute target-pools describe "{{ provision_prefix }}master-network-lb-pool" --region "{{ gce_region_name }}" &>/dev/null; then
+ gcloud --project "{{ gce_project_id }}" compute target-pools create "{{ provision_prefix }}master-network-lb-pool" --http-health-check "{{ provision_prefix }}master-network-lb-health-check" --region "{{ gce_region_name }}"
+else
+ echo "Target pool '{{ provision_prefix }}master-network-lb-pool' already exists"
+fi
+
+# Internal master forwarding rule
+if ! gcloud --project "{{ gce_project_id }}" compute forwarding-rules describe "{{ provision_prefix }}master-network-lb-rule" --region "{{ gce_region_name }}" &>/dev/null; then
+ IP=$(gcloud --project "{{ gce_project_id }}" compute addresses describe "{{ provision_prefix }}master-network-lb-ip" --region "{{ gce_region_name }}" --format='value(address)')
+ gcloud --project "{{ gce_project_id }}" compute forwarding-rules create "{{ provision_prefix }}master-network-lb-rule" --address "$IP" --region "{{ gce_region_name }}" --target-pool "{{ provision_prefix }}master-network-lb-pool"
+else
+ echo "Forwarding rule '{{ provision_prefix }}master-network-lb-rule' already exists"
+fi
+) &
+
+
+# Configure the infra node rules
+(
+# Router health check
+if ! gcloud --project "{{ gce_project_id }}" compute http-health-checks describe "{{ provision_prefix }}router-network-lb-health-check" &>/dev/null; then
+ gcloud --project "{{ gce_project_id }}" compute http-health-checks create "{{ provision_prefix }}router-network-lb-health-check" --port "1936" --request-path "/healthz"
+else
+ echo "Health check '{{ provision_prefix }}router-network-lb-health-check' already exists"
+fi
+
+# Router target pool
+if ! gcloud --project "{{ gce_project_id }}" compute target-pools describe "{{ provision_prefix }}router-network-lb-pool" --region "{{ gce_region_name }}" &>/dev/null; then
+ gcloud --project "{{ gce_project_id }}" compute target-pools create "{{ provision_prefix }}router-network-lb-pool" --http-health-check "{{ provision_prefix }}router-network-lb-health-check" --region "{{ gce_region_name }}"
+else
+ echo "Target pool '{{ provision_prefix }}router-network-lb-pool' already exists"
+fi
+
+# Router forwarding rule
+if ! gcloud --project "{{ gce_project_id }}" compute forwarding-rules describe "{{ provision_prefix }}router-network-lb-rule" --region "{{ gce_region_name }}" &>/dev/null; then
+ IP=$(gcloud --project "{{ gce_project_id }}" compute addresses describe "{{ provision_prefix }}router-network-lb-ip" --region "{{ gce_region_name }}" --format='value(address)')
+ gcloud --project "{{ gce_project_id }}" compute forwarding-rules create "{{ provision_prefix }}router-network-lb-rule" --address "$IP" --region "{{ gce_region_name }}" --target-pool "{{ provision_prefix }}router-network-lb-pool"
+else
+ echo "Forwarding rule '{{ provision_prefix }}router-network-lb-rule' already exists"
+fi
+) &
+
+for i in `jobs -p`; do wait $i; done
+
+# set the target pools
+(
+if [[ "ig-m" == "{{ provision_gce_router_network_instance_group }}" ]]; then
+ gcloud --project "{{ gce_project_id }}" compute instance-groups managed set-target-pools "{{ provision_prefix }}ig-m" --target-pools "{{ provision_prefix }}master-network-lb-pool,{{ provision_prefix }}router-network-lb-pool" --zone "{{ gce_zone_name }}"
+else
+ gcloud --project "{{ gce_project_id }}" compute instance-groups managed set-target-pools "{{ provision_prefix }}ig-m" --target-pools "{{ provision_prefix }}master-network-lb-pool" --zone "{{ gce_zone_name }}"
+ gcloud --project "{{ gce_project_id }}" compute instance-groups managed set-target-pools "{{ provision_prefix }}{{ provision_gce_router_network_instance_group }}" --target-pools "{{ provision_prefix }}router-network-lb-pool" --zone "{{ gce_zone_name }}"
+fi
+) &
+
+# configure DNS
+(
+# Retry DNS changes until they succeed since this may be a shared resource
+while true; do
+ dns="${TMPDIR:-/tmp}/dns.yaml"
+ rm -f $dns
+
+ # DNS record for master lb
+ if ! gcloud --project "{{ gce_project_id }}" dns record-sets list -z "${dns_zone}" --name "{{ openshift_master_cluster_public_hostname }}" 2>/dev/null | grep -q "{{ openshift_master_cluster_public_hostname }}"; then
+ IP=$(gcloud --project "{{ gce_project_id }}" compute addresses describe "{{ provision_prefix }}master-ssl-lb-ip" --global --format='value(address)')
+ if [[ ! -f $dns ]]; then
+ gcloud --project "{{ gce_project_id }}" dns record-sets transaction --transaction-file=$dns start -z "${dns_zone}"
+ fi
+ gcloud --project "{{ gce_project_id }}" dns record-sets transaction --transaction-file=$dns add -z "${dns_zone}" --ttl 3600 --name "{{ openshift_master_cluster_public_hostname }}." --type A "$IP"
+ else
+ echo "DNS record for '{{ openshift_master_cluster_public_hostname }}' already exists"
+ fi
+
+ # DNS record for internal master lb
+ if ! gcloud --project "{{ gce_project_id }}" dns record-sets list -z "${dns_zone}" --name "{{ openshift_master_cluster_hostname }}" 2>/dev/null | grep -q "{{ openshift_master_cluster_hostname }}"; then
+ IP=$(gcloud --project "{{ gce_project_id }}" compute addresses describe "{{ provision_prefix }}master-network-lb-ip" --region "{{ gce_region_name }}" --format='value(address)')
+ if [[ ! -f $dns ]]; then
+ gcloud --project "{{ gce_project_id }}" dns record-sets transaction --transaction-file=$dns start -z "${dns_zone}"
+ fi
+ gcloud --project "{{ gce_project_id }}" dns record-sets transaction --transaction-file=$dns add -z "${dns_zone}" --ttl 3600 --name "{{ openshift_master_cluster_hostname }}." --type A "$IP"
+ else
+ echo "DNS record for '{{ openshift_master_cluster_hostname }}' already exists"
+ fi
+
+ # DNS record for router lb
+ if ! gcloud --project "{{ gce_project_id }}" dns record-sets list -z "${dns_zone}" --name "{{ wildcard_zone }}" 2>/dev/null | grep -q "{{ wildcard_zone }}"; then
+ IP=$(gcloud --project "{{ gce_project_id }}" compute addresses describe "{{ provision_prefix }}router-network-lb-ip" --region "{{ gce_region_name }}" --format='value(address)')
+ if [[ ! -f $dns ]]; then
+ gcloud --project "{{ gce_project_id }}" dns record-sets transaction --transaction-file=$dns start -z "${dns_zone}"
+ fi
+ gcloud --project "{{ gce_project_id }}" dns record-sets transaction --transaction-file=$dns add -z "${dns_zone}" --ttl 3600 --name "{{ wildcard_zone }}." --type A "$IP"
+ gcloud --project "{{ gce_project_id }}" dns record-sets transaction --transaction-file=$dns add -z "${dns_zone}" --ttl 3600 --name "*.{{ wildcard_zone }}." --type CNAME "{{ wildcard_zone }}."
+ else
+ echo "DNS record for '{{ wildcard_zone }}' already exists"
+ fi
+
+ # Commit all DNS changes, retrying if preconditions are not met
+ if [[ -f $dns ]]; then
+ if ! out="$( gcloud --project "{{ gce_project_id }}" dns record-sets transaction --transaction-file=$dns execute -z "${dns_zone}" 2>&1 )"; then
+ rc=$?
+ if [[ "${out}" == *"HTTPError 412: Precondition not met"* ]]; then
+ continue
+ fi
+ exit $rc
+ fi
+ fi
+ break
+done
+) &
+
+# Create bucket for registry
+(
+if ! gsutil ls -p "{{ gce_project_id }}" "gs://{{ openshift_hosted_registry_storage_gcs_bucket }}" &>/dev/null; then
+ gsutil mb -p "{{ gce_project_id }}" -l "{{ gce_region_name }}" "gs://{{ openshift_hosted_registry_storage_gcs_bucket }}"
+else
+ echo "Bucket '{{ openshift_hosted_registry_storage_gcs_bucket }}' already exists"
+fi
+) &
+
+# wait until all node groups are stable
+{% for node_group in provision_gce_node_groups %}
+# wait for stable {{ node_group.name }}
+( gcloud --project "{{ gce_project_id }}" compute instance-groups managed wait-until-stable "{{ provision_prefix }}ig-{{ node_group.suffix }}" --zone "{{ gce_zone_name }}" --timeout=300) &
+{% endfor %}
+
+
+for i in `jobs -p`; do wait $i; done
diff --git a/roles/openshift_gcp/templates/remove.j2.sh b/roles/openshift_gcp/templates/remove.j2.sh
new file mode 100644
index 000000000..41ceab2b5
--- /dev/null
+++ b/roles/openshift_gcp/templates/remove.j2.sh
@@ -0,0 +1,156 @@
+#!/bin/bash
+
+set -euo pipefail
+
+function teardown_cmd() {
+ a=( $@ )
+ local name=$1
+ a=( "${a[@]:1}" )
+ local flag=0
+ local found=
+ for i in ${a[@]}; do
+ if [[ "$i" == "--"* ]]; then
+ found=true
+ break
+ fi
+ flag=$((flag+1))
+ done
+ if [[ -z "${found}" ]]; then
+ flag=$((flag+1))
+ fi
+ if gcloud --project "{{ gce_project_id }}" ${a[@]::$flag} describe "${name}" ${a[@]:$flag} &>/dev/null; then
+ gcloud --project "{{ gce_project_id }}" ${a[@]::$flag} delete -q "${name}" ${a[@]:$flag}
+ fi
+}
+
+function teardown() {
+ for i in `seq 1 20`; do
+ if teardown_cmd $@; then
+ break
+ fi
+ sleep 0.5
+ done
+}
+
+# Preemptively spin down the instances
+{% for node_group in provision_gce_node_groups %}
+# scale down {{ node_group.name }}
+(
+ # performs a delete and scale down as one operation to ensure maximum parallelism
+ if ! instances=$( gcloud --project "{{ gce_project_id }}" compute instance-groups managed list-instances "{{ provision_prefix }}ig-{{ node_group.suffix }}" --zone "{{ gce_zone_name }}" --format='value[terminator=","](instance)' ); then
+ exit 0
+ fi
+ instances="${instances%?}"
+ if [[ -z "${instances}" ]]; then
+ echo "warning: No instances in {{ node_group.name }}" 1>&2
+ exit 0
+ fi
+ if ! gcloud --project "{{ gce_project_id }}" compute instance-groups managed delete-instances "{{ provision_prefix }}ig-{{ node_group.suffix }}" --zone "{{ gce_zone_name }}" --instances "${instances}"; then
+ echo "warning: Unable to scale down the node group {{ node_group.name }}" 1>&2
+ exit 0
+ fi
+) &
+{% endfor %}
+
+# Bucket for registry
+(
+if gsutil ls -p "{{ gce_project_id }}" "gs://{{ openshift_hosted_registry_storage_gcs_bucket }}" &>/dev/null; then
+ gsutil -m rm -r "gs://{{ openshift_hosted_registry_storage_gcs_bucket }}"
+fi
+) &
+
+# DNS
+(
+dns_zone="{{ dns_managed_zone | default(provision_prefix + 'managed-zone') }}"
+if gcloud --project "{{ gce_project_id }}" dns managed-zones describe "${dns_zone}" &>/dev/null; then
+ # Retry DNS changes until they succeed since this may be a shared resource
+ while true; do
+ dns="${TMPDIR:-/tmp}/dns.yaml"
+ rm -f "${dns}"
+
+ # export all dns records that match into a zone format, and turn each line into a set of args for
+ # record-sets transaction.
+ gcloud dns record-sets export --project "{{ gce_project_id }}" -z "${dns_zone}" --zone-file-format "${dns}"
+ if grep -F -e '{{ openshift_master_cluster_hostname }}' -e '{{ openshift_master_cluster_public_hostname }}' -e '{{ wildcard_zone }}' "${dns}" | \
+ awk '{ print "--name", $1, "--ttl", $2, "--type", $4, $5; }' > "${dns}.input"
+ then
+ rm -f "${dns}"
+ gcloud --project "{{ gce_project_id }}" dns record-sets transaction --transaction-file=$dns start -z "${dns_zone}"
+ cat "${dns}.input" | xargs -L1 gcloud --project "{{ gce_project_id }}" dns record-sets transaction --transaction-file="${dns}" remove -z "${dns_zone}"
+
+ # Commit all DNS changes, retrying if preconditions are not met
+ if ! out="$( gcloud --project "{{ gce_project_id }}" dns record-sets transaction --transaction-file=$dns execute -z "${dns_zone}" 2>&1 )"; then
+ rc=$?
+ if [[ "${out}" == *"HTTPError 412: Precondition not met"* ]]; then
+ continue
+ fi
+ exit $rc
+ fi
+ fi
+ rm "${dns}.input"
+ break
+ done
+fi
+) &
+
+(
+# Router network rules
+teardown "{{ provision_prefix }}router-network-lb-rule" compute forwarding-rules --region "{{ gce_region_name }}"
+teardown "{{ provision_prefix }}router-network-lb-pool" compute target-pools --region "{{ gce_region_name }}"
+teardown "{{ provision_prefix }}router-network-lb-health-check" compute http-health-checks
+teardown "{{ provision_prefix }}router-network-lb-ip" compute addresses --region "{{ gce_region_name }}"
+
+# Internal master network rules
+teardown "{{ provision_prefix }}master-network-lb-rule" compute forwarding-rules --region "{{ gce_region_name }}"
+teardown "{{ provision_prefix }}master-network-lb-pool" compute target-pools --region "{{ gce_region_name }}"
+teardown "{{ provision_prefix }}master-network-lb-health-check" compute http-health-checks
+teardown "{{ provision_prefix }}master-network-lb-ip" compute addresses --region "{{ gce_region_name }}"
+) &
+
+(
+# Master SSL network rules
+teardown "{{ provision_prefix }}master-ssl-lb-rule" compute forwarding-rules --global
+teardown "{{ provision_prefix }}master-ssl-lb-target" compute target-tcp-proxies
+teardown "{{ provision_prefix }}master-ssl-lb-ip" compute addresses --global
+teardown "{{ provision_prefix }}master-ssl-lb-backend" compute backend-services --global
+teardown "{{ provision_prefix }}master-ssl-lb-health-check" compute health-checks
+) &
+
+#Firewall rules
+#['name']='parameters for "gcloud compute firewall-rules create"'
+#For all possible parameters see: gcloud compute firewall-rules create --help
+declare -A FW_RULES=(
+ ['icmp']=""
+ ['ssh-external']=""
+ ['ssh-internal']=""
+ ['master-internal']=""
+ ['master-external']=""
+ ['node-internal']=""
+ ['infra-node-internal']=""
+ ['infra-node-external']=""
+)
+for rule in "${!FW_RULES[@]}"; do
+ ( if gcloud --project "{{ gce_project_id }}" compute firewall-rules describe "{{ provision_prefix }}$rule" &>/dev/null; then
+ # retry a few times because this call can be flaky
+ for i in `seq 1 3`; do
+ if gcloud -q --project "{{ gce_project_id }}" compute firewall-rules delete "{{ provision_prefix }}$rule"; then
+ break
+ fi
+ done
+ fi ) &
+done
+
+for i in `jobs -p`; do wait $i; done
+
+{% for node_group in provision_gce_node_groups %}
+# teardown {{ node_group.name }} - any load balancers referencing these groups must be removed
+(
+ teardown "{{ provision_prefix }}ig-{{ node_group.suffix }}" compute instance-groups managed --zone "{{ gce_zone_name }}"
+ teardown "{{ provision_prefix }}instance-template-{{ node_group.name }}" compute instance-templates
+) &
+{% endfor %}
+
+for i in `jobs -p`; do wait $i; done
+
+# Network
+teardown "{{ gce_network_name }}" compute networks
diff --git a/roles/openshift_gcp_image_prep/files/partition.conf b/roles/openshift_gcp_image_prep/files/partition.conf
new file mode 100644
index 000000000..b87e5e0b6
--- /dev/null
+++ b/roles/openshift_gcp_image_prep/files/partition.conf
@@ -0,0 +1,3 @@
+[Service]
+ExecStartPost=-/usr/bin/growpart /dev/sda 1
+ExecStartPost=-/sbin/xfs_growfs /
diff --git a/roles/openshift_gcp_image_prep/tasks/main.yaml b/roles/openshift_gcp_image_prep/tasks/main.yaml
new file mode 100644
index 000000000..fee5ab618
--- /dev/null
+++ b/roles/openshift_gcp_image_prep/tasks/main.yaml
@@ -0,0 +1,18 @@
+---
+# GCE instances are starting with xfs AND barrier=1, which is only for extfs.
+- name: Remove barrier=1 from XFS fstab entries
+ lineinfile:
+ path: /etc/fstab
+ regexp: '^(.+)xfs(.+?),?barrier=1,?(.*?)$'
+ line: '\1xfs\2 \4'
+ backrefs: yes
+
+- name: Ensure the root filesystem has XFS group quota turned on
+ lineinfile:
+ path: /boot/grub2/grub.cfg
+ regexp: '^(.*)linux16 (.*)$'
+ line: '\1linux16 \2 rootflags=gquota'
+ backrefs: yes
+
+- name: Ensure the root partition grows on startup
+ copy: src=partition.conf dest=/etc/systemd/system/google-instance-setup.service.d/
diff --git a/roles/openshift_health_checker/action_plugins/openshift_health_check.py b/roles/openshift_health_checker/action_plugins/openshift_health_check.py
index 05e53333d..326176273 100644
--- a/roles/openshift_health_checker/action_plugins/openshift_health_check.py
+++ b/roles/openshift_health_checker/action_plugins/openshift_health_check.py
@@ -1,101 +1,144 @@
"""
Ansible action plugin to execute health checks in OpenShift clusters.
"""
-# pylint: disable=wrong-import-position,missing-docstring,invalid-name
import sys
import os
+import base64
+import traceback
+import errno
+import json
from collections import defaultdict
+from ansible.plugins.action import ActionBase
+from ansible.module_utils.six import string_types
+
try:
from __main__ import display
except ImportError:
+ # pylint: disable=ungrouped-imports; this is the standard way how to import
+ # the default display object in Ansible action plugins.
from ansible.utils.display import Display
display = Display()
-from ansible.plugins.action import ActionBase
-from ansible.module_utils.six import string_types
-
# Augment sys.path so that we can import checks from a directory relative to
# this callback plugin.
sys.path.insert(1, os.path.dirname(os.path.dirname(__file__)))
+# pylint: disable=wrong-import-position; the import statement must come after
+# the manipulation of sys.path.
from openshift_checks import OpenShiftCheck, OpenShiftCheckException, load_checks # noqa: E402
class ActionModule(ActionBase):
+ """Action plugin to execute health checks."""
def run(self, tmp=None, task_vars=None):
result = super(ActionModule, self).run(tmp, task_vars)
task_vars = task_vars or {}
- # vars are not supportably available in the callback plugin,
- # so record any it will need in the result.
+ # callback plugins cannot read Ansible vars, but we would like
+ # zz_failure_summary to have access to certain values. We do so by
+ # storing the information we need in the result.
result['playbook_context'] = task_vars.get('r_openshift_health_checker_playbook_context')
- if "openshift" not in task_vars:
- result["failed"] = True
- result["msg"] = "'openshift' is undefined, did 'openshift_facts' run?"
- return result
+ # if the user wants to write check results to files, they provide this directory:
+ output_dir = task_vars.get("openshift_checks_output_dir")
+ if output_dir:
+ output_dir = os.path.join(output_dir, task_vars["ansible_host"])
try:
- known_checks = self.load_known_checks(tmp, task_vars)
+ known_checks = self.load_known_checks(tmp, task_vars, output_dir)
args = self._task.args
requested_checks = normalize(args.get('checks', []))
+
+ if not requested_checks:
+ result['failed'] = True
+ result['msg'] = list_known_checks(known_checks)
+ return result
+
resolved_checks = resolve_checks(requested_checks, known_checks.values())
- except OpenShiftCheckException as e:
+ except OpenShiftCheckException as exc:
+ result["failed"] = True
+ result["msg"] = str(exc)
+ return result
+
+ if "openshift" not in task_vars:
result["failed"] = True
- result["msg"] = str(e)
+ result["msg"] = "'openshift' is undefined, did 'openshift_facts' run?"
return result
result["checks"] = check_results = {}
user_disabled_checks = normalize(task_vars.get('openshift_disable_check', []))
- for check_name in resolved_checks:
- display.banner("CHECK [{} : {}]".format(check_name, task_vars["ansible_host"]))
- check = known_checks[check_name]
-
- if not check.is_active():
- r = dict(skipped=True, skipped_reason="Not active for this host")
- elif check_name in user_disabled_checks:
- r = dict(skipped=True, skipped_reason="Disabled by user request")
- else:
- try:
- r = check.run()
- except OpenShiftCheckException as e:
- r = dict(
- failed=True,
- msg=str(e),
- )
-
- if check.changed:
- r["changed"] = True
- check_results[check_name] = r
+ for name in resolved_checks:
+ display.banner("CHECK [{} : {}]".format(name, task_vars["ansible_host"]))
+ check_results[name] = run_check(name, known_checks[name], user_disabled_checks, output_dir)
result["changed"] = any(r.get("changed") for r in check_results.values())
if any(r.get("failed") for r in check_results.values()):
result["failed"] = True
result["msg"] = "One or more checks failed"
+ write_result_to_output_dir(output_dir, result)
return result
- def load_known_checks(self, tmp, task_vars):
+ def load_known_checks(self, tmp, task_vars, output_dir=None):
+ """Find all existing checks and return a mapping of names to instances."""
load_checks()
+ want_full_results = bool(output_dir)
known_checks = {}
for cls in OpenShiftCheck.subclasses():
- check_name = cls.name
- if check_name in known_checks:
- other_cls = known_checks[check_name].__class__
+ name = cls.name
+ if name in known_checks:
+ other_cls = known_checks[name].__class__
raise OpenShiftCheckException(
- "non-unique check name '{}' in: '{}.{}' and '{}.{}'".format(
- check_name,
- cls.__module__, cls.__name__,
- other_cls.__module__, other_cls.__name__))
- known_checks[check_name] = cls(execute_module=self._execute_module, tmp=tmp, task_vars=task_vars)
+ "duplicate check name '{}' in: '{}' and '{}'"
+ "".format(name, full_class_name(cls), full_class_name(other_cls))
+ )
+ known_checks[name] = cls(
+ execute_module=self._execute_module,
+ tmp=tmp,
+ task_vars=task_vars,
+ want_full_results=want_full_results
+ )
return known_checks
+def list_known_checks(known_checks):
+ """Return text listing the existing checks and tags."""
+ # TODO: we could include a description of each check by taking it from a
+ # check class attribute (e.g., __doc__) when building the message below.
+ msg = (
+ 'This playbook is meant to run health checks, but no checks were '
+ 'requested. Set the `openshift_checks` variable to a comma-separated '
+ 'list of check names or a YAML list. Available checks:\n {}'
+ ).format('\n '.join(sorted(known_checks)))
+
+ tags = describe_tags(known_checks.values())
+
+ msg += (
+ '\n\nTags can be used as a shortcut to select multiple '
+ 'checks. Available tags and the checks they select:\n {}'
+ ).format('\n '.join(tags))
+
+ return msg
+
+
+def describe_tags(check_classes):
+ """Return a sorted list of strings describing tags and the checks they include."""
+ tag_checks = defaultdict(list)
+ for cls in check_classes:
+ for tag in cls.tags:
+ tag_checks[tag].append(cls.name)
+ tags = [
+ '@{} = {}'.format(tag, ','.join(sorted(checks)))
+ for tag, checks in tag_checks.items()
+ ]
+ return sorted(tags)
+
+
def resolve_checks(names, all_checks):
"""Returns a set of resolved check names.
@@ -123,6 +166,12 @@ def resolve_checks(names, all_checks):
if unknown_tag_names:
msg.append('Unknown tag names: {}.'.format(', '.join(sorted(unknown_tag_names))))
msg.append('Make sure there is no typo in the playbook and no files are missing.')
+ # TODO: implement a "Did you mean ...?" when the input is similar to a
+ # valid check or tag.
+ msg.append('Known checks:')
+ msg.append(' {}'.format('\n '.join(sorted(known_check_names))))
+ msg.append('Known tags:')
+ msg.append(' {}'.format('\n '.join(describe_tags(all_checks))))
raise OpenShiftCheckException('\n'.join(msg))
tag_to_checks = defaultdict(set)
@@ -146,3 +195,156 @@ def normalize(checks):
if isinstance(checks, string_types):
checks = checks.split(',')
return [name.strip() for name in checks if name.strip()]
+
+
+def run_check(name, check, user_disabled_checks, output_dir=None):
+ """Run a single check if enabled and return a result dict."""
+
+ # determine if we're going to run the check (not inactive or disabled)
+ if name in user_disabled_checks or '*' in user_disabled_checks:
+ return dict(skipped=True, skipped_reason="Disabled by user request")
+
+ # pylint: disable=broad-except; capturing exceptions broadly is intentional,
+ # to isolate arbitrary failures in one check from others.
+ try:
+ is_active = check.is_active()
+ except Exception as exc:
+ reason = "Could not determine if check should be run, exception: {}".format(exc)
+ return dict(skipped=True, skipped_reason=reason, exception=traceback.format_exc())
+
+ if not is_active:
+ return dict(skipped=True, skipped_reason="Not active for this host")
+
+ # run the check
+ result = {}
+ try:
+ result = check.run()
+ except OpenShiftCheckException as exc:
+ check.register_failure(exc)
+ except Exception as exc:
+ check.register_failure("\n".join([str(exc), traceback.format_exc()]))
+
+ # process the check state; compose the result hash, write files as needed
+ if check.changed:
+ result["changed"] = True
+ if check.failures or result.get("failed"):
+ if "msg" in result: # failure result has msg; combine with any registered failures
+ check.register_failure(result.get("msg"))
+ result["failures"] = [(fail.name, str(fail)) for fail in check.failures]
+ result["failed"] = True
+ result["msg"] = "\n".join(str(fail) for fail in check.failures)
+ write_to_output_file(output_dir, name + ".failures.json", result["failures"])
+ if check.logs:
+ write_to_output_file(output_dir, name + ".log.json", check.logs)
+ if check.files_to_save:
+ write_files_to_save(output_dir, check)
+
+ return result
+
+
+def prepare_output_dir(dirname):
+ """Create the directory, including parents. Return bool for success/failure."""
+ try:
+ os.makedirs(dirname)
+ return True
+ except OSError as exc:
+ # trying to create existing dir leads to error;
+ # that error is fine, but for any other, assume the dir is not there
+ return exc.errno == errno.EEXIST
+
+
+def copy_remote_file_to_dir(check, file_to_save, output_dir, fname):
+ """Copy file from remote host to local file in output_dir, if given."""
+ if not output_dir or not prepare_output_dir(output_dir):
+ return
+ local_file = os.path.join(output_dir, fname)
+
+ # pylint: disable=broad-except; do not need to do anything about failure to write dir/file
+ # and do not want exceptions to break anything.
+ try:
+ # NOTE: it would have been nice to copy the file directly without loading it into
+ # memory, but there does not seem to be a good way to do this via ansible.
+ result = check.execute_module("slurp", dict(src=file_to_save), register=False)
+ if result.get("failed"):
+ display.warning("Could not retrieve file {}: {}".format(file_to_save, result.get("msg")))
+ return
+
+ content = result["content"]
+ if result.get("encoding") == "base64":
+ content = base64.b64decode(content)
+ with open(local_file, "wb") as outfile:
+ outfile.write(content)
+ except Exception as exc:
+ display.warning("Failed writing remote {} to local {}: {}".format(file_to_save, local_file, exc))
+ return
+
+
+def _no_fail(obj):
+ # pylint: disable=broad-except; do not want serialization to fail for any reason
+ try:
+ return str(obj)
+ except Exception:
+ return "[not serializable]"
+
+
+def write_to_output_file(output_dir, filename, data):
+ """If output_dir provided, write data to file. Serialize as JSON if data is not a string."""
+
+ if not output_dir or not prepare_output_dir(output_dir):
+ return
+ filename = os.path.join(output_dir, filename)
+ try:
+ with open(filename, 'w') as outfile:
+ if isinstance(data, string_types):
+ outfile.write(data)
+ else:
+ json.dump(data, outfile, sort_keys=True, indent=4, default=_no_fail)
+ # pylint: disable=broad-except; do not want serialization/write to break for any reason
+ except Exception as exc:
+ display.warning("Could not write output file {}: {}".format(filename, exc))
+
+
+def write_result_to_output_dir(output_dir, result):
+ """If output_dir provided, write the result as json to result.json.
+
+ Success/failure of the write is recorded as "output_files" in the result hash afterward.
+ Otherwise this is much like write_to_output_file.
+ """
+
+ if not output_dir:
+ return
+ if not prepare_output_dir(output_dir):
+ result["output_files"] = "Error creating output directory " + output_dir
+ return
+
+ filename = os.path.join(output_dir, "result.json")
+ try:
+ with open(filename, 'w') as outfile:
+ json.dump(result, outfile, sort_keys=True, indent=4, default=_no_fail)
+ result["output_files"] = "Check results for this host written to " + filename
+ # pylint: disable=broad-except; do not want serialization/write to break for any reason
+ except Exception as exc:
+ result["output_files"] = "Error writing check results to {}:\n{}".format(filename, exc)
+
+
+def write_files_to_save(output_dir, check):
+ """Write files to check subdir in output dir."""
+ if not output_dir:
+ return
+ output_dir = os.path.join(output_dir, check.name)
+ seen_file = defaultdict(lambda: 0)
+ for file_to_save in check.files_to_save:
+ fname = file_to_save.filename
+ while seen_file[fname]: # just to be sure we never re-write a file, append numbers as needed
+ seen_file[fname] += 1
+ fname = "{}.{}".format(fname, seen_file[fname])
+ seen_file[fname] += 1
+ if file_to_save.remote_filename:
+ copy_remote_file_to_dir(check, file_to_save.remote_filename, output_dir, fname)
+ else:
+ write_to_output_file(output_dir, fname, file_to_save.contents)
+
+
+def full_class_name(cls):
+ """Return the name of a class prefixed with its module name."""
+ return '{}.{}'.format(cls.__module__, cls.__name__)
diff --git a/roles/openshift_health_checker/callback_plugins/zz_failure_summary.py b/roles/openshift_health_checker/callback_plugins/zz_failure_summary.py
index d10200719..dcaf87eca 100644
--- a/roles/openshift_health_checker/callback_plugins/zz_failure_summary.py
+++ b/roles/openshift_health_checker/callback_plugins/zz_failure_summary.py
@@ -1,161 +1,235 @@
-"""
-Ansible callback plugin to give a nicely formatted summary of failures.
-"""
+"""Ansible callback plugin to print a nicely formatted summary of failures.
-# Reason: In several locations below we disable pylint protected-access
-# for Ansible objects that do not give us any public way
-# to access the full details we need to report check failures.
-# Status: disabled permanently or until Ansible object has a public API.
-# This does leave the code more likely to be broken by future Ansible changes.
+The file / module name is prefixed with `zz_` to make this plugin be loaded last
+by Ansible, thus making its output the last thing that users see.
+"""
-from pprint import pformat
+from collections import defaultdict
+import traceback
from ansible.plugins.callback import CallbackBase
from ansible import constants as C
from ansible.utils.color import stringc
+from ansible.module_utils.six import string_types
+
+
+FAILED_NO_MSG = u'Failed without returning a message.'
class CallbackModule(CallbackBase):
- """
- This callback plugin stores task results and summarizes failures.
- The file name is prefixed with `zz_` to make this plugin be loaded last by
- Ansible, thus making its output the last thing that users see.
- """
+ """This callback plugin stores task results and summarizes failures."""
CALLBACK_VERSION = 2.0
CALLBACK_TYPE = 'aggregate'
CALLBACK_NAME = 'failure_summary'
CALLBACK_NEEDS_WHITELIST = False
- _playbook_file = None
def __init__(self):
super(CallbackModule, self).__init__()
self.__failures = []
+ self.__playbook_file = ''
def v2_playbook_on_start(self, playbook):
super(CallbackModule, self).v2_playbook_on_start(playbook)
- # re: playbook attrs see top comment # pylint: disable=protected-access
- self._playbook_file = playbook._file_name
+ # pylint: disable=protected-access; Ansible gives us no public API to
+ # get the file name of the current playbook from a callback plugin.
+ self.__playbook_file = playbook._file_name
def v2_runner_on_failed(self, result, ignore_errors=False):
super(CallbackModule, self).v2_runner_on_failed(result, ignore_errors)
if not ignore_errors:
- self.__failures.append(dict(result=result, ignore_errors=ignore_errors))
+ self.__failures.append(result)
def v2_playbook_on_stats(self, stats):
super(CallbackModule, self).v2_playbook_on_stats(stats)
- if self.__failures:
- self._print_failure_details(self.__failures)
-
- def _print_failure_details(self, failures):
- """Print a summary of failed tasks or checks."""
- self._display.display(u'\nFailure summary:\n')
-
- width = len(str(len(failures)))
- initial_indent_format = u' {{:>{width}}}. '.format(width=width)
- initial_indent_len = len(initial_indent_format.format(0))
- subsequent_indent = u' ' * initial_indent_len
- subsequent_extra_indent = u' ' * (initial_indent_len + 10)
-
- for i, failure in enumerate(failures, 1):
- entries = _format_failure(failure)
- self._display.display(u'\n{}{}'.format(initial_indent_format.format(i), entries[0]))
- for entry in entries[1:]:
- entry = entry.replace(u'\n', u'\n' + subsequent_extra_indent)
- indented = u'{}{}'.format(subsequent_indent, entry)
- self._display.display(indented)
-
- failed_checks = set()
- playbook_context = None
- # re: result attrs see top comment # pylint: disable=protected-access
- for failure in failures:
- # Get context from check task result since callback plugins cannot access task vars.
- # NOTE: thus context is not known unless checks run. Failures prior to checks running
- # don't have playbook_context in the results. But we only use it now when checks fail.
- playbook_context = playbook_context or failure['result']._result.get('playbook_context')
- failed_checks.update(
- name
- for name, result in failure['result']._result.get('checks', {}).items()
- if result.get('failed')
- )
- if failed_checks:
- self._print_check_failure_summary(failed_checks, playbook_context)
-
- def _print_check_failure_summary(self, failed_checks, context):
- checks = ','.join(sorted(failed_checks))
- # The purpose of specifying context is to vary the output depending on what the user was
- # expecting to happen (based on which playbook they ran). The only use currently is to
- # vary the message depending on whether the user was deliberately running checks or was
- # trying to install/upgrade and checks are just included. Other use cases may arise.
- summary = ( # default to explaining what checks are in the first place
- '\n'
- 'The execution of "{playbook}"\n'
- 'includes checks designed to fail early if the requirements\n'
- 'of the playbook are not met. One or more of these checks\n'
- 'failed. To disregard these results, you may choose to\n'
- 'disable failing checks by setting an Ansible variable:\n\n'
- ' openshift_disable_check={checks}\n\n'
- 'Failing check names are shown in the failure details above.\n'
- 'Some checks may be configurable by variables if your requirements\n'
- 'are different from the defaults; consult check documentation.\n'
- 'Variables can be set in the inventory or passed on the\n'
- 'command line using the -e flag to ansible-playbook.\n\n'
- ).format(playbook=self._playbook_file, checks=checks)
- if context in ['pre-install', 'health']:
- summary = ( # user was expecting to run checks, less explanation needed
- '\n'
- 'You may choose to configure or disable failing checks by\n'
- 'setting Ansible variables. To disable those above:\n\n'
- ' openshift_disable_check={checks}\n\n'
- 'Consult check documentation for configurable variables.\n'
- 'Variables can be set in the inventory or passed on the\n'
- 'command line using the -e flag to ansible-playbook.\n\n'
- ).format(checks=checks)
- self._display.display(summary)
-
-
-# re: result attrs see top comment # pylint: disable=protected-access
-def _format_failure(failure):
+ # pylint: disable=broad-except; capturing exceptions broadly is
+ # intentional, to isolate arbitrary failures in this callback plugin.
+ try:
+ if self.__failures:
+ self._display.display(failure_summary(self.__failures, self.__playbook_file))
+ except Exception:
+ msg = stringc(
+ u'An error happened while generating a summary of failures:\n'
+ u'{}'.format(traceback.format_exc()), C.COLOR_WARN)
+ self._display.v(msg)
+
+
+def failure_summary(failures, playbook):
+ """Return a summary of failed tasks, including details on health checks."""
+ if not failures:
+ return u''
+
+ # NOTE: because we don't have access to task_vars from callback plugins, we
+ # store the playbook context in the task result when the
+ # openshift_health_check action plugin is used, and we use this context to
+ # customize the error message.
+ # pylint: disable=protected-access; Ansible gives us no sufficient public
+ # API on TaskResult objects.
+ context = next((
+ context for context in
+ (failure._result.get('playbook_context') for failure in failures)
+ if context
+ ), None)
+
+ failures = [failure_to_dict(failure) for failure in failures]
+ failures = deduplicate_failures(failures)
+
+ summary = [u'', u'', u'Failure summary:', u'']
+
+ width = len(str(len(failures)))
+ initial_indent_format = u' {{:>{width}}}. '.format(width=width)
+ initial_indent_len = len(initial_indent_format.format(0))
+ subsequent_indent = u' ' * initial_indent_len
+ subsequent_extra_indent = u' ' * (initial_indent_len + 10)
+
+ for i, failure in enumerate(failures, 1):
+ entries = format_failure(failure)
+ summary.append(u'\n{}{}'.format(initial_indent_format.format(i), entries[0]))
+ for entry in entries[1:]:
+ entry = entry.replace(u'\n', u'\n' + subsequent_extra_indent)
+ indented = u'{}{}'.format(subsequent_indent, entry)
+ summary.append(indented)
+
+ failed_checks = set()
+ for failure in failures:
+ failed_checks.update(name for name, message in failure['checks'])
+ if failed_checks:
+ summary.append(check_failure_footer(failed_checks, context, playbook))
+
+ return u'\n'.join(summary)
+
+
+def failure_to_dict(failed_task_result):
+ """Extract information out of a failed TaskResult into a dict.
+
+ The intent is to transform a TaskResult object into something easier to
+ manipulate. TaskResult is ansible.executor.task_result.TaskResult.
+ """
+ # pylint: disable=protected-access; Ansible gives us no sufficient public
+ # API on TaskResult objects.
+ _result = failed_task_result._result
+ return {
+ 'host': failed_task_result._host.get_name(),
+ 'play': play_name(failed_task_result._task),
+ 'task': failed_task_result.task_name,
+ 'msg': _result.get('msg', FAILED_NO_MSG),
+ 'checks': tuple(
+ (name, result.get('msg', FAILED_NO_MSG))
+ for name, result in sorted(_result.get('checks', {}).items())
+ if result.get('failed')
+ ),
+ }
+
+
+def play_name(obj):
+ """Given a task or block, return the name of its parent play.
+
+ This is loosely inspired by ansible.playbook.base.Base.dump_me.
+ """
+ # pylint: disable=protected-access; Ansible gives us no sufficient public
+ # API to implement this.
+ if not obj:
+ return ''
+ if hasattr(obj, '_play'):
+ return obj._play.get_name()
+ return play_name(getattr(obj, '_parent'))
+
+
+def deduplicate_failures(failures):
+ """Group together similar failures from different hosts.
+
+ Returns a new list of failures such that identical failures from different
+ hosts are grouped together in a single entry. The relative order of failures
+ is preserved.
+
+ If failures is unhashable, the original list of failures is returned.
+ """
+ groups = defaultdict(list)
+ for failure in failures:
+ group_key = tuple(sorted((key, value) for key, value in failure.items() if key != 'host'))
+ try:
+ groups[group_key].append(failure)
+ except TypeError:
+ # abort and return original list of failures when failures has an
+ # unhashable type.
+ return failures
+
+ result = []
+ for failure in failures:
+ group_key = tuple(sorted((key, value) for key, value in failure.items() if key != 'host'))
+ if group_key not in groups:
+ continue
+ failure['host'] = tuple(sorted(g_failure['host'] for g_failure in groups.pop(group_key)))
+ result.append(failure)
+ return result
+
+
+def format_failure(failure):
"""Return a list of pretty-formatted text entries describing a failure, including
relevant information about it. Expect that the list of text entries will be joined
by a newline separator when output to the user."""
- result = failure['result']
- host = result._host.get_name()
- play = _get_play(result._task)
- if play:
- play = play.get_name()
- task = result._task.get_name()
- msg = result._result.get('msg', u'???')
+ if isinstance(failure['host'], string_types):
+ host = failure['host']
+ else:
+ host = u', '.join(failure['host'])
+ play = failure['play']
+ task = failure['task']
+ msg = failure['msg']
+ checks = failure['checks']
fields = (
- (u'Host', host),
+ (u'Hosts', host),
(u'Play', play),
(u'Task', task),
(u'Message', stringc(msg, C.COLOR_ERROR)),
)
- if 'checks' in result._result:
- fields += ((u'Details', _format_failed_checks(result._result['checks'])),)
+ if checks:
+ fields += ((u'Details', format_failed_checks(checks)),)
row_format = '{:10}{}'
return [row_format.format(header + u':', body) for header, body in fields]
-def _format_failed_checks(checks):
+def format_failed_checks(checks):
"""Return pretty-formatted text describing checks that failed."""
- failed_check_msgs = []
- for check, body in checks.items():
- if body.get('failed', False): # only show the failed checks
- msg = body.get('msg', u"Failed without returning a message")
- failed_check_msgs.append('check "%s":\n%s' % (check, msg))
- if failed_check_msgs:
- return stringc("\n\n".join(failed_check_msgs), C.COLOR_ERROR)
- else: # something failed but no checks will admit to it, so dump everything
- return stringc(pformat(checks), C.COLOR_ERROR)
-
-
-# This is inspired by ansible.playbook.base.Base.dump_me.
-# re: play/task/block attrs see top comment # pylint: disable=protected-access
-def _get_play(obj):
- """Given a task or block, recursively try to find its parent play."""
- if hasattr(obj, '_play'):
- return obj._play
- if getattr(obj, '_parent'):
- return _get_play(obj._parent)
+ messages = []
+ for name, message in checks:
+ messages.append(u'check "{}":\n{}'.format(name, message))
+ return stringc(u'\n\n'.join(messages), C.COLOR_ERROR)
+
+
+def check_failure_footer(failed_checks, context, playbook):
+ """Return a textual explanation about checks depending on context.
+
+ The purpose of specifying context is to vary the output depending on what
+ the user was expecting to happen (based on which playbook they ran). The
+ only use currently is to vary the message depending on whether the user was
+ deliberately running checks or was trying to install/upgrade and checks are
+ just included. Other use cases may arise.
+ """
+ checks = ','.join(sorted(failed_checks))
+ summary = [u'']
+ if context in ['pre-install', 'health', 'adhoc']:
+ # User was expecting to run checks, less explanation needed.
+ summary.extend([
+ u'You may configure or disable checks by setting Ansible '
+ u'variables. To disable those above, set:',
+ u' openshift_disable_check={checks}'.format(checks=checks),
+ u'Consult check documentation for configurable variables.',
+ ])
+ else:
+ # User may not be familiar with the checks, explain what checks are in
+ # the first place.
+ summary.extend([
+ u'The execution of "{playbook}" includes checks designed to fail '
+ u'early if the requirements of the playbook are not met. One or '
+ u'more of these checks failed. To disregard these results,'
+ u'explicitly disable checks by setting an Ansible variable:'.format(playbook=playbook),
+ u' openshift_disable_check={checks}'.format(checks=checks),
+ u'Failing check names are shown in the failure details above. '
+ u'Some checks may be configurable by variables if your requirements '
+ u'are different from the defaults; consult check documentation.',
+ ])
+ summary.append(
+ u'Variables can be set in the inventory or passed on the command line '
+ u'using the -e flag to ansible-playbook.'
+ )
+ return u'\n'.join(summary)
diff --git a/roles/openshift_health_checker/library/aos_version.py b/roles/openshift_health_checker/library/aos_version.py
index f9babebb9..db3c0b654 100644
--- a/roles/openshift_health_checker/library/aos_version.py
+++ b/roles/openshift_health_checker/library/aos_version.py
@@ -24,11 +24,17 @@ from ansible.module_utils.basic import AnsibleModule
# Python 3, we use six for cross compatibility in this module alone:
from ansible.module_utils.six import string_types
-IMPORT_EXCEPTION = None
+YUM_IMPORT_EXCEPTION = None
+DNF_IMPORT_EXCEPTION = None
try:
import yum # pylint: disable=import-error
except ImportError as err:
- IMPORT_EXCEPTION = err
+ YUM_IMPORT_EXCEPTION = err
+
+try:
+ import dnf # pylint: disable=import-error
+except ImportError as err:
+ DNF_IMPORT_EXCEPTION = err
class AosVersionException(Exception):
@@ -43,12 +49,20 @@ def main():
module = AnsibleModule(
argument_spec=dict(
package_list=dict(type="list", required=True),
+ package_mgr=dict(type="str", required=True),
),
supports_check_mode=True
)
- if IMPORT_EXCEPTION:
- module.fail_json(msg="aos_version module could not import yum: %s" % IMPORT_EXCEPTION)
+ # determine the package manager to use
+ package_mgr = module.params['package_mgr']
+ if package_mgr not in ('yum', 'dnf'):
+ module.fail_json(msg="package_mgr must be one of: yum, dnf")
+ pkg_mgr_exception = dict(yum=YUM_IMPORT_EXCEPTION, dnf=DNF_IMPORT_EXCEPTION)[package_mgr]
+ if pkg_mgr_exception:
+ module.fail_json(
+ msg="aos_version module could not import {}: {}".format(package_mgr, pkg_mgr_exception)
+ )
# determine the packages we will look for
package_list = module.params['package_list']
@@ -67,7 +81,7 @@ def main():
# get the list of packages available and complain if anything is wrong
try:
- pkgs = _retrieve_available_packages(expected_pkg_names)
+ pkgs = _retrieve_available_packages(package_mgr, expected_pkg_names)
if versioned_pkgs:
_check_precise_version_found(pkgs, _to_dict(versioned_pkgs))
_check_higher_version_found(pkgs, _to_dict(versioned_pkgs))
@@ -82,10 +96,7 @@ def _to_dict(pkg_list):
return {pkg["name"]: pkg for pkg in pkg_list}
-def _retrieve_available_packages(expected_pkgs):
- # search for package versions available for openshift pkgs
- yb = yum.YumBase() # pylint: disable=invalid-name
-
+def _retrieve_available_packages(pkg_mgr, expected_pkgs):
# The openshift excluder prevents unintended updates to openshift
# packages by setting yum excludes on those packages. See:
# https://wiki.centos.org/SpecialInterestGroup/PaaS/OpenShift-Origin-Control-Updates
@@ -94,17 +105,45 @@ def _retrieve_available_packages(expected_pkgs):
# attempt to determine what packages are available via yum they may
# be excluded. So, for our purposes here, disable excludes to see
# what will really be available during an install or upgrade.
- yb.conf.disable_excludes = ['all']
- try:
- pkgs = yb.pkgSack.returnPackages(patterns=expected_pkgs)
- except yum.Errors.PackageSackError as excinfo:
- # you only hit this if *none* of the packages are available
- raise AosVersionException('\n'.join([
- 'Unable to find any OpenShift packages.',
- 'Check your subscription and repo settings.',
- str(excinfo),
- ]))
+ if pkg_mgr == "yum":
+ # search for package versions available for openshift pkgs
+ yb = yum.YumBase() # pylint: disable=invalid-name
+
+ yb.conf.disable_excludes = ['all']
+
+ try:
+ pkgs = yb.rpmdb.returnPackages(patterns=expected_pkgs)
+ pkgs += yb.pkgSack.returnPackages(patterns=expected_pkgs)
+ except yum.Errors.PackageSackError as excinfo:
+ # you only hit this if *none* of the packages are available
+ raise AosVersionException('\n'.join([
+ 'Unable to find any OpenShift packages.',
+ 'Check your subscription and repo settings.',
+ str(excinfo),
+ ]))
+ elif pkg_mgr == "dnf":
+ dbase = dnf.Base() # pyling: disable=invalid-name
+
+ dbase.conf.disable_excludes = ['all']
+ dbase.read_all_repos()
+ dbase.fill_sack(load_system_repo=False, load_available_repos=True)
+
+ dquery = dbase.sack.query()
+ aquery = dquery.available()
+ iquery = dquery.installed()
+
+ available_pkgs = list(aquery.filter(name=expected_pkgs))
+ installed_pkgs = list(iquery.filter(name=expected_pkgs))
+ pkgs = available_pkgs + installed_pkgs
+
+ if not pkgs:
+ # pkgs list is empty, raise because no expected packages found
+ raise AosVersionException('\n'.join([
+ 'Unable to find any OpenShift packages.',
+ 'Check your subscription and repo settings.',
+ ]))
+
return pkgs
diff --git a/roles/openshift_health_checker/openshift_checks/__init__.py b/roles/openshift_health_checker/openshift_checks/__init__.py
index 07ec6f7ef..28cb53cc5 100644
--- a/roles/openshift_health_checker/openshift_checks/__init__.py
+++ b/roles/openshift_health_checker/openshift_checks/__init__.py
@@ -2,8 +2,11 @@
Health checks for OpenShift clusters.
"""
+import json
import operator
import os
+import time
+import collections
from abc import ABCMeta, abstractmethod, abstractproperty
from importlib import import_module
@@ -27,7 +30,7 @@ class OpenShiftCheckException(Exception):
class OpenShiftCheckExceptionList(OpenShiftCheckException):
- """A container for multiple logging errors that may be detected in one check."""
+ """A container for multiple errors that may be detected in one check."""
def __init__(self, errors):
self.errors = errors
super(OpenShiftCheckExceptionList, self).__init__(
@@ -40,26 +43,53 @@ class OpenShiftCheckExceptionList(OpenShiftCheckException):
return self.errors[index]
+FileToSave = collections.namedtuple("FileToSave", "filename contents remote_filename")
+
+
+# pylint: disable=too-many-instance-attributes; all represent significantly different state.
+# Arguably they could be separated into two hashes, one for storing parameters, and one for
+# storing result state; but that smells more like clutter than clarity.
@six.add_metaclass(ABCMeta)
class OpenShiftCheck(object):
- """
- A base class for defining checks for an OpenShift cluster environment.
+ """A base class for defining checks for an OpenShift cluster environment.
- Expect optional params: method execute_module, dict task_vars, and string tmp.
+ Optional init params: method execute_module, dict task_vars, and string tmp
execute_module is expected to have a signature compatible with _execute_module
from ansible plugins/action/__init__.py, e.g.:
def execute_module(module_name=None, module_args=None, tmp=None, task_vars=None, *args):
This is stored so that it can be invoked in subclasses via check.execute_module("name", args)
which provides the check's stored task_vars and tmp.
+
+ Optional init param: want_full_results
+ If the check can gather logs, tarballs, etc., do so when True; but no need to spend
+ the time if they're not wanted (won't be written to output directory).
"""
- def __init__(self, execute_module=None, task_vars=None, tmp=None):
+ def __init__(self, execute_module=None, task_vars=None, tmp=None, want_full_results=False):
+ # store a method for executing ansible modules from the check
self._execute_module = execute_module
+ # the task variables and tmpdir passed into the health checker task
self.task_vars = task_vars or {}
self.tmp = tmp
+ # a boolean for disabling the gathering of results (files, computations) that won't
+ # actually be recorded/used
+ self.want_full_results = want_full_results
+
+ # mainly for testing purposes; see execute_module_with_retries
+ self._module_retries = 3
+ self._module_retry_interval = 5 # seconds
+ # state to be recorded for inspection after the check runs:
+ #
# set to True when the check changes the host, for accurate total "changed" count
self.changed = False
+ # list of OpenShiftCheckException for check to report (alternative to returning a failed result)
+ self.failures = []
+ # list of FileToSave - files the check specifies to be written locally if so configured
+ self.files_to_save = []
+ # log messages for the check - tuples of (description, msg) where msg is serializable.
+ # These are intended to be a sequential record of what the check observed and determined.
+ self.logs = []
@abstractproperty
def name(self):
@@ -82,7 +112,13 @@ class OpenShiftCheck(object):
@abstractmethod
def run(self):
- """Executes a check, normally implemented as a module."""
+ """Executes a check against a host and returns a result hash similar to Ansible modules.
+
+ Actually the direction ahead is to record state in the attributes and
+ not bother building a result hash. Instead, return an empty hash and let
+ the action plugin fill it in. Or raise an OpenShiftCheckException.
+ Returning a hash may become deprecated if it does not prove necessary.
+ """
return {}
@classmethod
@@ -94,7 +130,43 @@ class OpenShiftCheck(object):
for subclass in subclass.subclasses():
yield subclass
- def execute_module(self, module_name=None, module_args=None):
+ def register_failure(self, error):
+ """Record in the check that a failure occurred.
+
+ Recorded failures are merged into the result hash for now. They are also saved to output directory
+ (if provided) <check>.failures.json and registered as a log entry for context <check>.log.json.
+ """
+ # It should be an exception; make it one if not
+ if not isinstance(error, OpenShiftCheckException):
+ error = OpenShiftCheckException(str(error))
+ self.failures.append(error)
+ # duplicate it in the logs so it can be seen in the context of any
+ # information that led to the failure
+ self.register_log("failure: " + error.name, str(error))
+
+ def register_log(self, context, msg):
+ """Record an entry for the check log.
+
+ Notes are intended to serve as context of the whole sequence of what the check observed.
+ They are be saved as an ordered list in a local check log file.
+ They are not to included in the result or in the ansible log; it's just for the record.
+ """
+ self.logs.append([context, msg])
+
+ def register_file(self, filename, contents=None, remote_filename=""):
+ """Record a file that a check makes available to be saved individually to output directory.
+
+ Either file contents should be passed in, or a file to be copied from the remote host
+ should be specified. Contents that are not a string are to be serialized as JSON.
+
+ NOTE: When copying a file from remote host, it is slurped into memory as base64, meaning
+ you should avoid using this on huge files (more than say 10M).
+ """
+ if contents is None and not remote_filename:
+ raise OpenShiftCheckException("File data/source not specified; this is a bug in the check.")
+ self.files_to_save.append(FileToSave(filename, contents, remote_filename))
+
+ def execute_module(self, module_name=None, module_args=None, save_as_name=None, register=True):
"""Invoke an Ansible module from a check.
Invoke stored _execute_module, normally copied from the action
@@ -106,6 +178,12 @@ class OpenShiftCheck(object):
Ansible version).
So e.g. check.execute_module("foo", dict(arg1=...))
+
+ save_as_name specifies a file name for saving the result to an output directory,
+ if needed, and is intended to uniquely identify the result of invoking execute_module.
+ If not provided, the module name will be used.
+ If register is set False, then the result won't be registered in logs or files to save.
+
Return: result hash from module execution.
"""
if self._execute_module is None:
@@ -113,7 +191,33 @@ class OpenShiftCheck(object):
self.__class__.__name__ +
" invoked execute_module without providing the method at initialization."
)
- return self._execute_module(module_name, module_args, self.tmp, self.task_vars)
+ result = self._execute_module(module_name, module_args, self.tmp, self.task_vars)
+ if result.get("changed"):
+ self.changed = True
+ for output in ["result", "stdout"]:
+ # output is often JSON; attempt to decode
+ try:
+ result[output + "_json"] = json.loads(result[output])
+ except (KeyError, ValueError):
+ pass
+
+ if register:
+ self.register_log("execute_module: " + module_name, result)
+ self.register_file(save_as_name or module_name + ".json", result)
+ return result
+
+ def execute_module_with_retries(self, module_name, module_args):
+ """Run execute_module and retry on failure."""
+ result = {}
+ tries = 0
+ while True:
+ res = self.execute_module(module_name, module_args)
+ if tries > self._module_retries or not res.get("failed"):
+ result.update(res)
+ return result
+ result["last_failed"] = res
+ tries += 1
+ time.sleep(self._module_retry_interval)
def get_var(self, *keys, **kwargs):
"""Get deeply nested values from task_vars.
@@ -171,8 +275,12 @@ class OpenShiftCheck(object):
'There is a bug in this check. While trying to convert variable \n'
' "{var}={value}"\n'
'the given converter cannot be used or failed unexpectedly:\n'
- '{error}'.format(var=".".join(keys), value=value, error=error)
- )
+ '{type}: {error}'.format(
+ var=".".join(keys),
+ value=value,
+ type=error.__class__.__name__,
+ error=error
+ ))
@staticmethod
def get_major_minor_version(openshift_image_tag):
@@ -214,7 +322,9 @@ class OpenShiftCheck(object):
mount_point = os.path.dirname(mount_point)
try:
- return mount_for_path[mount_point]
+ mount = mount_for_path[mount_point]
+ self.register_log("mount point for " + path, mount)
+ return mount
except KeyError:
known_mounts = ', '.join('"{}"'.format(mount) for mount in sorted(mount_for_path))
raise OpenShiftCheckException(
diff --git a/roles/openshift_health_checker/openshift_checks/disk_availability.py b/roles/openshift_health_checker/openshift_checks/disk_availability.py
index 6d1dea9ce..cdf56e959 100644
--- a/roles/openshift_health_checker/openshift_checks/disk_availability.py
+++ b/roles/openshift_health_checker/openshift_checks/disk_availability.py
@@ -70,6 +70,10 @@ class DiskAvailability(OpenShiftCheck):
# If it is not a number, then it should be a nested dict.
pass
+ self.register_log("recommended thresholds", self.recommended_disk_space_bytes)
+ if user_config:
+ self.register_log("user-configured thresholds", user_config)
+
# TODO: as suggested in
# https://github.com/openshift/openshift-ansible/pull/4436#discussion_r122180021,
# maybe we could support checking disk availability in paths that are
@@ -113,13 +117,7 @@ class DiskAvailability(OpenShiftCheck):
'in your Ansible inventory, and lower the recommended disk space availability\n'
'if necessary for this upgrade.').format(config_bytes)
- return {
- 'failed': True,
- 'msg': (
- 'Available disk space in "{}" ({:.1f} GB) '
- 'is below minimum recommended ({:.1f} GB)'
- ).format(path, free_gb, recommended_gb)
- }
+ self.register_failure(msg)
return {}
diff --git a/roles/openshift_health_checker/openshift_checks/docker_image_availability.py b/roles/openshift_health_checker/openshift_checks/docker_image_availability.py
index 85a922f86..98372d979 100644
--- a/roles/openshift_health_checker/openshift_checks/docker_image_availability.py
+++ b/roles/openshift_health_checker/openshift_checks/docker_image_availability.py
@@ -32,6 +32,12 @@ class DockerImageAvailability(DockerHostMixin, OpenShiftCheck):
# we use python-docker-py to check local docker for images, and skopeo
# to look for images available remotely without waiting to pull them.
dependencies = ["python-docker-py", "skopeo"]
+ skopeo_img_check_command = "timeout 10 skopeo inspect --tls-verify=false docker://{registry}/{image}"
+
+ def __init__(self, *args, **kwargs):
+ super(DockerImageAvailability, self).__init__(*args, **kwargs)
+ # record whether we could reach a registry or not (and remember results)
+ self.reachable_registries = {}
def is_active(self):
"""Skip hosts with unsupported deployment types."""
@@ -63,13 +69,21 @@ class DockerImageAvailability(DockerHostMixin, OpenShiftCheck):
unavailable_images = set(missing_images) - set(available_images)
if unavailable_images:
- return {
- "failed": True,
- "msg": (
- "One or more required Docker images are not available:\n {}\n"
- "Configured registries: {}"
- ).format(",\n ".join(sorted(unavailable_images)), ", ".join(registries)),
- }
+ registries = [
+ reg if self.reachable_registries.get(reg, True) else reg + " (unreachable)"
+ for reg in registries
+ ]
+ msg = (
+ "One or more required Docker images are not available:\n {}\n"
+ "Configured registries: {}\n"
+ "Checked by: {}"
+ ).format(
+ ",\n ".join(sorted(unavailable_images)),
+ ", ".join(registries),
+ self.skopeo_img_check_command
+ )
+
+ return dict(failed=True, msg=msg)
return {}
@@ -95,8 +109,6 @@ class DockerImageAvailability(DockerHostMixin, OpenShiftCheck):
# containerized etcd may not have openshift_image_tag, see bz 1466622
image_tag = self.get_var("openshift_image_tag", default="latest")
image_info = DEPLOYMENT_IMAGE_INFO[deployment_type]
- if not image_info:
- return required
# template for images that run on top of OpenShift
image_url = "{}/{}-{}:{}".format(image_info["namespace"], image_info["name"], "${component}", "${version}")
@@ -125,31 +137,31 @@ class DockerImageAvailability(DockerHostMixin, OpenShiftCheck):
def local_images(self, images):
"""Filter a list of images and return those available locally."""
- return [
- image for image in images
- if self.is_image_local(image)
- ]
+ registries = self.known_docker_registries()
+ found_images = []
+ for image in images:
+ # docker could have the image name as-is or prefixed with any registry
+ imglist = [image] + [reg + "/" + image for reg in registries]
+ if self.is_image_local(imglist):
+ found_images.append(image)
+ return found_images
def is_image_local(self, image):
"""Check if image is already in local docker index."""
result = self.execute_module("docker_image_facts", {"name": image})
- if result.get("failed", False):
- return False
-
- return bool(result.get("images", []))
+ return bool(result.get("images")) and not result.get("failed")
def known_docker_registries(self):
"""Build a list of docker registries available according to inventory vars."""
- docker_facts = self.get_var("openshift", "docker")
- regs = set(docker_facts["additional_registries"])
+ regs = list(self.get_var("openshift.docker.additional_registries", default=[]))
deployment_type = self.get_var("openshift_deployment_type")
- if deployment_type == "origin":
- regs.update(["docker.io"])
- elif "enterprise" in deployment_type:
- regs.update(["registry.access.redhat.com"])
+ if deployment_type == "origin" and "docker.io" not in regs:
+ regs.append("docker.io")
+ elif deployment_type == 'openshift-enterprise' and "registry.access.redhat.com" not in regs:
+ regs.append("registry.access.redhat.com")
- return list(regs)
+ return regs
def available_images(self, images, default_registries):
"""Search remotely for images. Returns: list of images found."""
@@ -162,15 +174,35 @@ class DockerImageAvailability(DockerHostMixin, OpenShiftCheck):
"""Use Skopeo to determine if required image exists in known registry(s)."""
registries = default_registries
- # if image already includes a registry, only use that
+ # If image already includes a registry, only use that.
+ # NOTE: This logic would incorrectly identify images that do not use a namespace, e.g.
+ # registry.access.redhat.com/rhel7 as if the registry were a namespace.
+ # It's not clear that there's any way to distinguish them, but fortunately
+ # the current set of images all look like [registry/]namespace/name[:version].
if image.count("/") > 1:
registry, image = image.split("/", 1)
registries = [registry]
for registry in registries:
- args = {"_raw_params": "skopeo inspect --tls-verify=false docker://{}/{}".format(registry, image)}
- result = self.execute_module("command", args)
+ if registry not in self.reachable_registries:
+ self.reachable_registries[registry] = self.connect_to_registry(registry)
+ if not self.reachable_registries[registry]:
+ continue
+
+ args = {"_raw_params": self.skopeo_img_check_command.format(registry=registry, image=image)}
+ result = self.execute_module_with_retries("command", args)
if result.get("rc", 0) == 0 and not result.get("failed"):
return True
+ if result.get("rc") == 124: # RC 124 == timed out; mark unreachable
+ self.reachable_registries[registry] = False
return False
+
+ def connect_to_registry(self, registry):
+ """Use ansible wait_for module to test connectivity from host to registry. Returns bool."""
+ # test a simple TCP connection
+ host, _, port = registry.partition(":")
+ port = port or 443
+ args = dict(host=host, port=port, state="started", timeout=30)
+ result = self.execute_module("wait_for", args)
+ return result.get("rc", 0) == 0 and not result.get("failed")
diff --git a/roles/openshift_health_checker/openshift_checks/logging/elasticsearch.py b/roles/openshift_health_checker/openshift_checks/logging/elasticsearch.py
index 7fc843fd7..986a01f38 100644
--- a/roles/openshift_health_checker/openshift_checks/logging/elasticsearch.py
+++ b/roles/openshift_health_checker/openshift_checks/logging/elasticsearch.py
@@ -72,7 +72,7 @@ class Elasticsearch(LoggingCheck):
for pod_name in pods_by_name.keys():
# Compare what each ES node reports as master and compare for split brain
get_master_cmd = self._build_es_curl_cmd(pod_name, "https://localhost:9200/_cat/master")
- master_name_str = self.exec_oc(get_master_cmd, [])
+ master_name_str = self.exec_oc(get_master_cmd, [], save_as_name="get_master_names.json")
master_names = (master_name_str or '').split(' ')
if len(master_names) > 1:
es_master_names.add(master_names[1])
@@ -113,7 +113,7 @@ class Elasticsearch(LoggingCheck):
# get ES cluster nodes
node_cmd = self._build_es_curl_cmd(list(pods_by_name.keys())[0], 'https://localhost:9200/_nodes')
- cluster_node_data = self.exec_oc(node_cmd, [])
+ cluster_node_data = self.exec_oc(node_cmd, [], save_as_name="get_es_nodes.json")
try:
cluster_nodes = json.loads(cluster_node_data)['nodes']
except (ValueError, KeyError):
@@ -142,7 +142,7 @@ class Elasticsearch(LoggingCheck):
errors = []
for pod_name in pods_by_name.keys():
cluster_health_cmd = self._build_es_curl_cmd(pod_name, 'https://localhost:9200/_cluster/health?pretty=true')
- cluster_health_data = self.exec_oc(cluster_health_cmd, [])
+ cluster_health_data = self.exec_oc(cluster_health_cmd, [], save_as_name='get_es_health.json')
try:
health_res = json.loads(cluster_health_data)
if not health_res or not health_res.get('status'):
@@ -171,7 +171,7 @@ class Elasticsearch(LoggingCheck):
errors = []
for pod_name in pods_by_name.keys():
df_cmd = 'exec {} -- df --output=ipcent,pcent /elasticsearch/persistent'.format(pod_name)
- disk_output = self.exec_oc(df_cmd, [])
+ disk_output = self.exec_oc(df_cmd, [], save_as_name='get_pv_diskspace.json')
lines = disk_output.splitlines()
# expecting one header looking like 'IUse% Use%' and one body line
body_re = r'\s*(\d+)%?\s+(\d+)%?\s*$'
diff --git a/roles/openshift_health_checker/openshift_checks/logging/logging.py b/roles/openshift_health_checker/openshift_checks/logging/logging.py
index ecd8adb64..06bdfebf6 100644
--- a/roles/openshift_health_checker/openshift_checks/logging/logging.py
+++ b/roles/openshift_health_checker/openshift_checks/logging/logging.py
@@ -78,7 +78,7 @@ class LoggingCheck(OpenShiftCheck):
"""Returns the namespace in which logging is configured to deploy."""
return self.get_var("openshift_logging_namespace", default="logging")
- def exec_oc(self, cmd_str="", extra_args=None):
+ def exec_oc(self, cmd_str="", extra_args=None, save_as_name=None):
"""
Execute an 'oc' command in the remote host.
Returns: output of command and namespace,
@@ -92,7 +92,7 @@ class LoggingCheck(OpenShiftCheck):
"extra_args": list(extra_args) if extra_args else [],
}
- result = self.execute_module("ocutil", args)
+ result = self.execute_module("ocutil", args, save_as_name=save_as_name)
if result.get("failed"):
if result['result'] == '[Errno 2] No such file or directory':
raise CouldNotUseOc(
diff --git a/roles/openshift_health_checker/openshift_checks/logging/logging_index_time.py b/roles/openshift_health_checker/openshift_checks/logging/logging_index_time.py
index d781db649..cacdf4213 100644
--- a/roles/openshift_health_checker/openshift_checks/logging/logging_index_time.py
+++ b/roles/openshift_health_checker/openshift_checks/logging/logging_index_time.py
@@ -104,7 +104,7 @@ class LoggingIndexTime(LoggingCheck):
"https://logging-es:9200/project.{namespace}*/_count?q=message:{uuid}"
)
exec_cmd = exec_cmd.format(pod_name=pod_name, namespace=self.logging_namespace(), uuid=uuid)
- result = self.exec_oc(exec_cmd, [])
+ result = self.exec_oc(exec_cmd, [], save_as_name="query_for_uuid.json")
try:
count = json.loads(result)["count"]
diff --git a/roles/openshift_health_checker/openshift_checks/mixins.py b/roles/openshift_health_checker/openshift_checks/mixins.py
index e9bae60a3..b90ebf6dd 100644
--- a/roles/openshift_health_checker/openshift_checks/mixins.py
+++ b/roles/openshift_health_checker/openshift_checks/mixins.py
@@ -36,7 +36,7 @@ class DockerHostMixin(object):
# NOTE: we would use the "package" module but it's actually an action plugin
# and it's not clear how to invoke one of those. This is about the same anyway:
- result = self.execute_module(
+ result = self.execute_module_with_retries(
self.get_var("ansible_pkg_mgr", default="yum"),
{"name": self.dependencies, "state": "present"},
)
@@ -49,5 +49,4 @@ class DockerHostMixin(object):
" {deps}\n{msg}"
).format(deps=',\n '.join(self.dependencies), msg=msg)
failed = result.get("failed", False) or result.get("rc", 0) != 0
- self.changed = result.get("changed", False)
return msg, failed
diff --git a/roles/openshift_health_checker/openshift_checks/package_availability.py b/roles/openshift_health_checker/openshift_checks/package_availability.py
index a86180b00..21355c2f0 100644
--- a/roles/openshift_health_checker/openshift_checks/package_availability.py
+++ b/roles/openshift_health_checker/openshift_checks/package_availability.py
@@ -26,7 +26,7 @@ class PackageAvailability(NotContainerizedMixin, OpenShiftCheck):
packages.update(self.node_packages(rpm_prefix))
args = {"packages": sorted(set(packages))}
- return self.execute_module("check_yum_update", args)
+ return self.execute_module_with_retries("check_yum_update", args)
@staticmethod
def master_packages(rpm_prefix):
diff --git a/roles/openshift_health_checker/openshift_checks/package_update.py b/roles/openshift_health_checker/openshift_checks/package_update.py
index 1e9aecbe0..8464e8a5e 100644
--- a/roles/openshift_health_checker/openshift_checks/package_update.py
+++ b/roles/openshift_health_checker/openshift_checks/package_update.py
@@ -11,4 +11,4 @@ class PackageUpdate(NotContainerizedMixin, OpenShiftCheck):
def run(self):
args = {"packages": []}
- return self.execute_module("check_yum_update", args)
+ return self.execute_module_with_retries("check_yum_update", args)
diff --git a/roles/openshift_health_checker/openshift_checks/package_version.py b/roles/openshift_health_checker/openshift_checks/package_version.py
index 8b780114f..d4aec3ed8 100644
--- a/roles/openshift_health_checker/openshift_checks/package_version.py
+++ b/roles/openshift_health_checker/openshift_checks/package_version.py
@@ -46,6 +46,7 @@ class PackageVersion(NotContainerizedMixin, OpenShiftCheck):
check_multi_minor_release = deployment_type in ['openshift-enterprise']
args = {
+ "package_mgr": self.get_var("ansible_pkg_mgr"),
"package_list": [
{
"name": "openvswitch",
@@ -75,7 +76,7 @@ class PackageVersion(NotContainerizedMixin, OpenShiftCheck):
],
}
- return self.execute_module("aos_version", args)
+ return self.execute_module_with_retries("aos_version", args)
def get_required_ovs_version(self):
"""Return the correct Open vSwitch version(s) for the current OpenShift version."""
diff --git a/roles/openshift_health_checker/test/action_plugin_test.py b/roles/openshift_health_checker/test/action_plugin_test.py
index f5161d6f5..f14887303 100644
--- a/roles/openshift_health_checker/test/action_plugin_test.py
+++ b/roles/openshift_health_checker/test/action_plugin_test.py
@@ -3,10 +3,12 @@ import pytest
from ansible.playbook.play_context import PlayContext
from openshift_health_check import ActionModule, resolve_checks
-from openshift_checks import OpenShiftCheckException
+from openshift_health_check import copy_remote_file_to_dir, write_result_to_output_dir, write_to_output_file
+from openshift_checks import OpenShiftCheckException, FileToSave
-def fake_check(name='fake_check', tags=None, is_active=True, run_return=None, run_exception=None, changed=False):
+def fake_check(name='fake_check', tags=None, is_active=True, run_return=None, run_exception=None,
+ run_logs=None, run_files=None, changed=False, get_var_return=None):
"""Returns a new class that is compatible with OpenShiftCheck for testing."""
_name, _tags = name, tags
@@ -14,12 +16,16 @@ def fake_check(name='fake_check', tags=None, is_active=True, run_return=None, ru
class FakeCheck(object):
name = _name
tags = _tags or []
- changed = False
- def __init__(self, execute_module=None, task_vars=None, tmp=None):
- pass
+ def __init__(self, **_):
+ self.changed = False
+ self.failures = []
+ self.logs = run_logs or []
+ self.files_to_save = run_files or []
def is_active(self):
+ if isinstance(is_active, Exception):
+ raise is_active
return is_active
def run(self):
@@ -28,6 +34,13 @@ def fake_check(name='fake_check', tags=None, is_active=True, run_return=None, ru
raise run_exception
return run_return
+ def get_var(*args, **_):
+ return get_var_return
+
+ def register_failure(self, exc):
+ self.failures.append(OpenShiftCheckException(str(exc)))
+ return
+
return FakeCheck
@@ -80,7 +93,8 @@ def skipped(result):
None,
{},
])
-def test_action_plugin_missing_openshift_facts(plugin, task_vars):
+def test_action_plugin_missing_openshift_facts(plugin, task_vars, monkeypatch):
+ monkeypatch.setattr('openshift_health_check.resolve_checks', lambda *args: ['fake_check'])
result = plugin.run(tmp=None, task_vars=task_vars)
assert failed(result, msg_has=['openshift_facts'])
@@ -94,26 +108,36 @@ def test_action_plugin_cannot_load_checks_with_the_same_name(plugin, task_vars,
result = plugin.run(tmp=None, task_vars=task_vars)
- assert failed(result, msg_has=['unique', 'duplicate_name', 'FakeCheck'])
+ assert failed(result, msg_has=['duplicate', 'duplicate_name', 'FakeCheck'])
-def test_action_plugin_skip_non_active_checks(plugin, task_vars, monkeypatch):
- checks = [fake_check(is_active=False)]
+@pytest.mark.parametrize('is_active, skipped_reason', [
+ (False, "Not active for this host"),
+ (Exception("borked"), "exception"),
+])
+def test_action_plugin_skip_non_active_checks(is_active, skipped_reason, plugin, task_vars, monkeypatch):
+ checks = [fake_check(is_active=is_active)]
monkeypatch.setattr('openshift_checks.OpenShiftCheck.subclasses', classmethod(lambda cls: checks))
result = plugin.run(tmp=None, task_vars=task_vars)
- assert result['checks']['fake_check'] == dict(skipped=True, skipped_reason="Not active for this host")
+ assert result['checks']['fake_check'].get('skipped')
+ assert skipped_reason in result['checks']['fake_check'].get('skipped_reason')
assert not failed(result)
assert not changed(result)
assert not skipped(result)
-def test_action_plugin_skip_disabled_checks(plugin, task_vars, monkeypatch):
+@pytest.mark.parametrize('to_disable', [
+ 'fake_check',
+ ['fake_check', 'spam'],
+ '*,spam,eggs',
+])
+def test_action_plugin_skip_disabled_checks(to_disable, plugin, task_vars, monkeypatch):
checks = [fake_check('fake_check', is_active=True)]
monkeypatch.setattr('openshift_checks.OpenShiftCheck.subclasses', classmethod(lambda cls: checks))
- task_vars['openshift_disable_check'] = 'fake_check'
+ task_vars['openshift_disable_check'] = to_disable
result = plugin.run(tmp=None, task_vars=task_vars)
assert result['checks']['fake_check'] == dict(skipped=True, skipped_reason="Disabled by user request")
@@ -122,10 +146,21 @@ def test_action_plugin_skip_disabled_checks(plugin, task_vars, monkeypatch):
assert not skipped(result)
+def test_action_plugin_run_list_checks(monkeypatch):
+ task = FakeTask('openshift_health_check', {'checks': []})
+ plugin = ActionModule(task, None, PlayContext(), None, None, None)
+ monkeypatch.setattr(plugin, 'load_known_checks', lambda *_: {})
+ result = plugin.run()
+
+ assert failed(result, msg_has="Available checks")
+ assert not changed(result)
+ assert not skipped(result)
+
+
def test_action_plugin_run_check_ok(plugin, task_vars, monkeypatch):
check_return_value = {'ok': 'test'}
- check_class = fake_check(run_return=check_return_value)
- monkeypatch.setattr(plugin, 'load_known_checks', lambda tmp, task_vars: {'fake_check': check_class()})
+ check_class = fake_check(run_return=check_return_value, run_files=[None])
+ monkeypatch.setattr(plugin, 'load_known_checks', lambda *_: {'fake_check': check_class()})
monkeypatch.setattr('openshift_health_check.resolve_checks', lambda *args: ['fake_check'])
result = plugin.run(tmp=None, task_vars=task_vars)
@@ -139,7 +174,7 @@ def test_action_plugin_run_check_ok(plugin, task_vars, monkeypatch):
def test_action_plugin_run_check_changed(plugin, task_vars, monkeypatch):
check_return_value = {'ok': 'test'}
check_class = fake_check(run_return=check_return_value, changed=True)
- monkeypatch.setattr(plugin, 'load_known_checks', lambda tmp, task_vars: {'fake_check': check_class()})
+ monkeypatch.setattr(plugin, 'load_known_checks', lambda *_: {'fake_check': check_class()})
monkeypatch.setattr('openshift_health_check.resolve_checks', lambda *args: ['fake_check'])
result = plugin.run(tmp=None, task_vars=task_vars)
@@ -152,9 +187,9 @@ def test_action_plugin_run_check_changed(plugin, task_vars, monkeypatch):
def test_action_plugin_run_check_fail(plugin, task_vars, monkeypatch):
- check_return_value = {'failed': True}
+ check_return_value = {'failed': True, 'msg': 'this is a failure'}
check_class = fake_check(run_return=check_return_value)
- monkeypatch.setattr(plugin, 'load_known_checks', lambda tmp, task_vars: {'fake_check': check_class()})
+ monkeypatch.setattr(plugin, 'load_known_checks', lambda *_: {'fake_check': check_class()})
monkeypatch.setattr('openshift_health_check.resolve_checks', lambda *args: ['fake_check'])
result = plugin.run(tmp=None, task_vars=task_vars)
@@ -165,24 +200,51 @@ def test_action_plugin_run_check_fail(plugin, task_vars, monkeypatch):
assert not skipped(result)
-def test_action_plugin_run_check_exception(plugin, task_vars, monkeypatch):
+@pytest.mark.parametrize('exc_class, expect_traceback', [
+ (OpenShiftCheckException, False),
+ (Exception, True),
+])
+def test_action_plugin_run_check_exception(plugin, task_vars, exc_class, expect_traceback, monkeypatch):
exception_msg = 'fake check has an exception'
- run_exception = OpenShiftCheckException(exception_msg)
+ run_exception = exc_class(exception_msg)
check_class = fake_check(run_exception=run_exception, changed=True)
- monkeypatch.setattr(plugin, 'load_known_checks', lambda tmp, task_vars: {'fake_check': check_class()})
+ monkeypatch.setattr(plugin, 'load_known_checks', lambda *_: {'fake_check': check_class()})
monkeypatch.setattr('openshift_health_check.resolve_checks', lambda *args: ['fake_check'])
result = plugin.run(tmp=None, task_vars=task_vars)
assert failed(result['checks']['fake_check'], msg_has=exception_msg)
+ assert expect_traceback == ("Traceback" in result['checks']['fake_check']['msg'])
assert failed(result, msg_has=['failed'])
assert changed(result['checks']['fake_check'])
assert changed(result)
assert not skipped(result)
+def test_action_plugin_run_check_output_dir(plugin, task_vars, tmpdir, monkeypatch):
+ check_class = fake_check(
+ run_return={},
+ run_logs=[('thing', 'note')],
+ run_files=[
+ FileToSave('save.file', 'contents', None),
+ FileToSave('save.file', 'duplicate', None),
+ FileToSave('copy.file', None, 'foo'), # note: copy runs execute_module => exception
+ ],
+ )
+ task_vars['openshift_checks_output_dir'] = str(tmpdir)
+ check_class.get_var = lambda self, name, **_: task_vars.get(name)
+ monkeypatch.setattr(plugin, 'load_known_checks', lambda *_: {'fake_check': check_class()})
+ monkeypatch.setattr('openshift_health_check.resolve_checks', lambda *args: ['fake_check'])
+
+ plugin.run(tmp=None, task_vars=task_vars)
+ assert any(path.basename == task_vars['ansible_host'] for path in tmpdir.listdir())
+ assert any(path.basename == 'fake_check.log.json' for path in tmpdir.visit())
+ assert any(path.basename == 'save.file' for path in tmpdir.visit())
+ assert any(path.basename == 'save.file.2' for path in tmpdir.visit())
+
+
def test_action_plugin_resolve_checks_exception(plugin, task_vars, monkeypatch):
- monkeypatch.setattr(plugin, 'load_known_checks', lambda tmp, task_vars: {})
+ monkeypatch.setattr(plugin, 'load_known_checks', lambda *_: {})
result = plugin.run(tmp=None, task_vars=task_vars)
@@ -217,24 +279,21 @@ def test_resolve_checks_ok(names, all_checks, expected):
assert resolve_checks(names, all_checks) == expected
-@pytest.mark.parametrize('names,all_checks,words_in_exception,words_not_in_exception', [
+@pytest.mark.parametrize('names,all_checks,words_in_exception', [
(
['testA', 'testB'],
[],
['check', 'name', 'testA', 'testB'],
- ['tag', 'group', '@'],
),
(
['@group'],
[],
['tag', 'name', 'group'],
- ['check', '@'],
),
(
['testA', 'testB', '@group'],
[],
['check', 'name', 'testA', 'testB', 'tag', 'group'],
- ['@'],
),
(
['testA', 'testB', '@group'],
@@ -244,13 +303,45 @@ def test_resolve_checks_ok(names, all_checks, expected):
fake_check('from_group_2', ['preflight', 'group']),
],
['check', 'name', 'testA', 'testB'],
- ['tag', 'group', '@'],
),
])
-def test_resolve_checks_failure(names, all_checks, words_in_exception, words_not_in_exception):
+def test_resolve_checks_failure(names, all_checks, words_in_exception):
with pytest.raises(Exception) as excinfo:
resolve_checks(names, all_checks)
for word in words_in_exception:
assert word in str(excinfo.value)
- for word in words_not_in_exception:
- assert word not in str(excinfo.value)
+
+
+@pytest.mark.parametrize('give_output_dir, result, expect_file', [
+ (False, None, False),
+ (True, dict(content="c3BhbQo=", encoding="base64"), True),
+ (True, dict(content="encoding error", encoding="base64"), False),
+ (True, dict(content="spam", no_encoding=None), True),
+ (True, dict(failed=True, msg="could not slurp"), False),
+])
+def test_copy_remote_file_to_dir(give_output_dir, result, expect_file, tmpdir):
+ check = fake_check()()
+ check.execute_module = lambda *args, **_: result
+ copy_remote_file_to_dir(check, "remote_file", str(tmpdir) if give_output_dir else "", "local_file")
+ assert expect_file == any(path.basename == "local_file" for path in tmpdir.listdir())
+
+
+def test_write_to_output_exceptions(tmpdir, monkeypatch, capsys):
+
+ class Spam(object):
+ def __str__(self):
+ raise Exception("break str")
+
+ test = {1: object(), 2: Spam()}
+ test[3] = test
+ write_result_to_output_dir(str(tmpdir), test)
+ assert "Error writing" in test["output_files"]
+
+ output_dir = tmpdir.join("eggs")
+ output_dir.write("spam") # so now it's not a dir
+ write_to_output_file(str(output_dir), "somefile", "somedata")
+ assert "Could not write" in capsys.readouterr()[1]
+
+ monkeypatch.setattr("openshift_health_check.prepare_output_dir", lambda *_: False)
+ write_result_to_output_dir(str(tmpdir), test)
+ assert "Error creating" in test["output_files"]
diff --git a/roles/openshift_health_checker/test/conftest.py b/roles/openshift_health_checker/test/conftest.py
index 3cbd65507..244a1f0fa 100644
--- a/roles/openshift_health_checker/test/conftest.py
+++ b/roles/openshift_health_checker/test/conftest.py
@@ -7,5 +7,6 @@ openshift_health_checker_path = os.path.dirname(os.path.dirname(__file__))
sys.path[1:1] = [
openshift_health_checker_path,
os.path.join(openshift_health_checker_path, 'action_plugins'),
+ os.path.join(openshift_health_checker_path, 'callback_plugins'),
os.path.join(openshift_health_checker_path, 'library'),
]
diff --git a/roles/openshift_health_checker/test/disk_availability_test.py b/roles/openshift_health_checker/test/disk_availability_test.py
index f4fd2dfed..9ae679b79 100644
--- a/roles/openshift_health_checker/test/disk_availability_test.py
+++ b/roles/openshift_health_checker/test/disk_availability_test.py
@@ -183,11 +183,12 @@ def test_fails_with_insufficient_disk_space(name, group_names, configured_min, a
ansible_mounts=ansible_mounts,
)
- result = DiskAvailability(fake_execute_module, task_vars).run()
+ check = DiskAvailability(fake_execute_module, task_vars)
+ check.run()
- assert result['failed']
+ assert check.failures
for chunk in 'below recommended'.split() + expect_chunks:
- assert chunk in result.get('msg', '')
+ assert chunk in str(check.failures[0])
@pytest.mark.parametrize('name,group_names,context,ansible_mounts,failed,extra_words', [
@@ -237,11 +238,11 @@ def test_min_required_space_changes_with_upgrade_context(name, group_names, cont
)
check = DiskAvailability(fake_execute_module, task_vars)
- result = check.run()
+ check.run()
- assert result.get("failed", False) == failed
+ assert bool(check.failures) == failed
for word in extra_words:
- assert word in result.get('msg', '')
+ assert word in str(check.failures[0])
def fake_execute_module(*args):
diff --git a/roles/openshift_health_checker/test/docker_image_availability_test.py b/roles/openshift_health_checker/test/docker_image_availability_test.py
index 8d0a53df9..952fa9aa6 100644
--- a/roles/openshift_health_checker/test/docker_image_availability_test.py
+++ b/roles/openshift_health_checker/test/docker_image_availability_test.py
@@ -3,11 +3,26 @@ import pytest
from openshift_checks.docker_image_availability import DockerImageAvailability
+@pytest.fixture()
+def task_vars():
+ return dict(
+ openshift=dict(
+ common=dict(
+ service_type='origin',
+ is_containerized=False,
+ is_atomic=False,
+ ),
+ docker=dict(),
+ ),
+ openshift_deployment_type='origin',
+ openshift_image_tag='',
+ group_names=['nodes', 'masters'],
+ )
+
+
@pytest.mark.parametrize('deployment_type, is_containerized, group_names, expect_active', [
("origin", True, [], True),
("openshift-enterprise", True, [], True),
- ("enterprise", True, [], False),
- ("online", True, [], False),
("invalid", True, [], False),
("", True, [], False),
("origin", False, [], False),
@@ -15,12 +30,10 @@ from openshift_checks.docker_image_availability import DockerImageAvailability
("origin", False, ["nodes", "masters"], True),
("openshift-enterprise", False, ["etcd"], False),
])
-def test_is_active(deployment_type, is_containerized, group_names, expect_active):
- task_vars = dict(
- openshift=dict(common=dict(is_containerized=is_containerized)),
- openshift_deployment_type=deployment_type,
- group_names=group_names,
- )
+def test_is_active(task_vars, deployment_type, is_containerized, group_names, expect_active):
+ task_vars['openshift_deployment_type'] = deployment_type
+ task_vars['openshift']['common']['is_containerized'] = is_containerized
+ task_vars['group_names'] = group_names
assert DockerImageAvailability(None, task_vars).is_active() == expect_active
@@ -30,10 +43,10 @@ def test_is_active(deployment_type, is_containerized, group_names, expect_active
(True, False),
(False, True),
])
-def test_all_images_available_locally(is_containerized, is_atomic):
+def test_all_images_available_locally(task_vars, is_containerized, is_atomic):
def execute_module(module_name, module_args, *_):
if module_name == "yum":
- return {"changed": True}
+ return {}
assert module_name == "docker_image_facts"
assert 'name' in module_args
@@ -42,19 +55,9 @@ def test_all_images_available_locally(is_containerized, is_atomic):
'images': [module_args['name']],
}
- result = DockerImageAvailability(execute_module, task_vars=dict(
- openshift=dict(
- common=dict(
- service_type='origin',
- is_containerized=is_containerized,
- is_atomic=is_atomic,
- ),
- docker=dict(additional_registries=["docker.io"]),
- ),
- openshift_deployment_type='origin',
- openshift_image_tag='3.4',
- group_names=['nodes', 'masters'],
- )).run()
+ task_vars['openshift']['common']['is_containerized'] = is_containerized
+ task_vars['openshift']['common']['is_atomic'] = is_atomic
+ result = DockerImageAvailability(execute_module, task_vars).run()
assert not result.get('failed', False)
@@ -63,30 +66,42 @@ def test_all_images_available_locally(is_containerized, is_atomic):
False,
True,
])
-def test_all_images_available_remotely(available_locally):
+def test_all_images_available_remotely(task_vars, available_locally):
def execute_module(module_name, *_):
if module_name == 'docker_image_facts':
return {'images': [], 'failed': available_locally}
- return {'changed': False}
+ return {}
- result = DockerImageAvailability(execute_module, task_vars=dict(
- openshift=dict(
- common=dict(
- service_type='origin',
- is_containerized=False,
- is_atomic=False,
- ),
- docker=dict(additional_registries=["docker.io", "registry.access.redhat.com"]),
- ),
- openshift_deployment_type='origin',
- openshift_image_tag='v3.4',
- group_names=['nodes', 'masters'],
- )).run()
+ task_vars['openshift']['docker']['additional_registries'] = ["docker.io", "registry.access.redhat.com"]
+ task_vars['openshift_image_tag'] = 'v3.4'
+ check = DockerImageAvailability(execute_module, task_vars)
+ check._module_retry_interval = 0
+ result = check.run()
assert not result.get('failed', False)
-def test_all_images_unavailable():
+def test_all_images_unavailable(task_vars):
+ def execute_module(module_name=None, *args):
+ if module_name == "wait_for":
+ return {}
+ elif module_name == "command":
+ return {'failed': True}
+
+ return {} # docker_image_facts failure
+
+ task_vars['openshift']['docker']['additional_registries'] = ["docker.io"]
+ task_vars['openshift_deployment_type'] = "openshift-enterprise"
+ task_vars['openshift_image_tag'] = 'latest'
+ check = DockerImageAvailability(execute_module, task_vars)
+ check._module_retry_interval = 0
+ actual = check.run()
+
+ assert actual['failed']
+ assert "required Docker images are not available" in actual['msg']
+
+
+def test_no_known_registries():
def execute_module(module_name=None, *_):
if module_name == "command":
return {
@@ -97,7 +112,10 @@ def test_all_images_unavailable():
'changed': False,
}
- actual = DockerImageAvailability(execute_module, task_vars=dict(
+ def mock_known_docker_registries():
+ return []
+
+ dia = DockerImageAvailability(execute_module, task_vars=dict(
openshift=dict(
common=dict(
service_type='origin',
@@ -109,10 +127,11 @@ def test_all_images_unavailable():
openshift_deployment_type="openshift-enterprise",
openshift_image_tag='latest',
group_names=['nodes', 'masters'],
- )).run()
-
+ ))
+ dia.known_docker_registries = mock_known_docker_registries
+ actual = dia.run()
assert actual['failed']
- assert "required Docker images are not available" in actual['msg']
+ assert "Unable to retrieve any docker registries." in actual['msg']
@pytest.mark.parametrize("message,extra_words", [
@@ -125,62 +144,63 @@ def test_all_images_unavailable():
["dependencies can be installed via `yum`"]
),
])
-def test_skopeo_update_failure(message, extra_words):
+def test_skopeo_update_failure(task_vars, message, extra_words):
def execute_module(module_name=None, *_):
if module_name == "yum":
return {
"failed": True,
"msg": message,
- "changed": False,
}
- return {'changed': False}
+ return {}
- actual = DockerImageAvailability(execute_module, task_vars=dict(
- openshift=dict(
- common=dict(
- service_type='origin',
- is_containerized=False,
- is_atomic=False,
- ),
- docker=dict(additional_registries=["unknown.io"]),
- ),
- openshift_deployment_type="openshift-enterprise",
- openshift_image_tag='',
- group_names=['nodes', 'masters'],
- )).run()
+ task_vars['openshift']['docker']['additional_registries'] = ["unknown.io"]
+ task_vars['openshift_deployment_type'] = "openshift-enterprise"
+ check = DockerImageAvailability(execute_module, task_vars)
+ check._module_retry_interval = 0
+ actual = check.run()
assert actual["failed"]
for word in extra_words:
assert word in actual["msg"]
-@pytest.mark.parametrize("deployment_type,registries", [
- ("origin", ["unknown.io"]),
- ("openshift-enterprise", ["registry.access.redhat.com"]),
- ("openshift-enterprise", []),
-])
-def test_registry_availability(deployment_type, registries):
+@pytest.mark.parametrize(
+ "image, registries, connection_test_failed, skopeo_failed, "
+ "expect_success, expect_registries_reached", [
+ (
+ "spam/eggs:v1", ["test.reg"],
+ True, True,
+ False,
+ {"test.reg": False},
+ ),
+ (
+ "spam/eggs:v1", ["test.reg"],
+ False, True,
+ False,
+ {"test.reg": True},
+ ),
+ (
+ "eggs.reg/spam/eggs:v1", ["test.reg"],
+ False, False,
+ True,
+ {"eggs.reg": True},
+ ),
+ ])
+def test_registry_availability(image, registries, connection_test_failed, skopeo_failed,
+ expect_success, expect_registries_reached):
def execute_module(module_name=None, *_):
- return {
- 'changed': False,
- }
+ if module_name == "wait_for":
+ return dict(msg="msg", failed=connection_test_failed)
+ elif module_name == "command":
+ return dict(msg="msg", failed=skopeo_failed)
- actual = DockerImageAvailability(execute_module, task_vars=dict(
- openshift=dict(
- common=dict(
- service_type='origin',
- is_containerized=False,
- is_atomic=False,
- ),
- docker=dict(additional_registries=registries),
- ),
- openshift_deployment_type=deployment_type,
- openshift_image_tag='',
- group_names=['nodes', 'masters'],
- )).run()
+ check = DockerImageAvailability(execute_module, task_vars())
+ check._module_retry_interval = 0
- assert not actual.get("failed", False)
+ available = check.is_available_skopeo_image(image, registries)
+ assert available == expect_success
+ assert expect_registries_reached == check.reachable_registries
@pytest.mark.parametrize("deployment_type, is_containerized, groups, oreg_url, expected", [
@@ -257,7 +277,7 @@ def test_required_images(deployment_type, is_containerized, groups, oreg_url, ex
openshift_image_tag='vtest',
)
- assert expected == DockerImageAvailability("DUMMY", task_vars).required_images()
+ assert expected == DockerImageAvailability(task_vars=task_vars).required_images()
def test_containerized_etcd():
@@ -271,4 +291,4 @@ def test_containerized_etcd():
group_names=['etcd'],
)
expected = set(['registry.access.redhat.com/rhel7/etcd'])
- assert expected == DockerImageAvailability("DUMMY", task_vars).required_images()
+ assert expected == DockerImageAvailability(task_vars=task_vars).required_images()
diff --git a/roles/openshift_health_checker/test/elasticsearch_test.py b/roles/openshift_health_checker/test/elasticsearch_test.py
index 09bacd9ac..3fa5e8929 100644
--- a/roles/openshift_health_checker/test/elasticsearch_test.py
+++ b/roles/openshift_health_checker/test/elasticsearch_test.py
@@ -72,7 +72,7 @@ def test_check_elasticsearch():
assert_error_in_list('NoRunningPods', excinfo.value)
# canned oc responses to match so all the checks pass
- def exec_oc(cmd, args):
+ def exec_oc(cmd, args, **_):
if '_cat/master' in cmd:
return 'name logging-es'
elif '/_nodes' in cmd:
@@ -97,7 +97,7 @@ def test_check_running_es_pods():
def test_check_elasticsearch_masters():
pods = [plain_es_pod]
- check = canned_elasticsearch(task_vars_config_base, lambda *_: plain_es_pod['_test_master_name_str'])
+ check = canned_elasticsearch(task_vars_config_base, lambda *args, **_: plain_es_pod['_test_master_name_str'])
assert not check.check_elasticsearch_masters(pods_by_name(pods))
@@ -117,7 +117,7 @@ def test_check_elasticsearch_masters():
])
def test_check_elasticsearch_masters_error(pods, expect_error):
test_pods = list(pods)
- check = canned_elasticsearch(task_vars_config_base, lambda *_: test_pods.pop(0)['_test_master_name_str'])
+ check = canned_elasticsearch(task_vars_config_base, lambda *args, **_: test_pods.pop(0)['_test_master_name_str'])
assert_error_in_list(expect_error, check.check_elasticsearch_masters(pods_by_name(pods)))
@@ -129,7 +129,7 @@ es_node_list = {
def test_check_elasticsearch_node_list():
- check = canned_elasticsearch(task_vars_config_base, lambda *_: json.dumps(es_node_list))
+ check = canned_elasticsearch(task_vars_config_base, lambda *args, **_: json.dumps(es_node_list))
assert not check.check_elasticsearch_node_list(pods_by_name([plain_es_pod]))
@@ -151,13 +151,13 @@ def test_check_elasticsearch_node_list():
),
])
def test_check_elasticsearch_node_list_errors(pods, node_list, expect_error):
- check = canned_elasticsearch(task_vars_config_base, lambda cmd, args: json.dumps(node_list))
+ check = canned_elasticsearch(task_vars_config_base, lambda cmd, args, **_: json.dumps(node_list))
assert_error_in_list(expect_error, check.check_elasticsearch_node_list(pods_by_name(pods)))
def test_check_elasticsearch_cluster_health():
test_health_data = [{"status": "green"}]
- check = canned_elasticsearch(exec_oc=lambda *_: json.dumps(test_health_data.pop(0)))
+ check = canned_elasticsearch(exec_oc=lambda *args, **_: json.dumps(test_health_data.pop(0)))
assert not check.check_es_cluster_health(pods_by_name([plain_es_pod]))
@@ -175,12 +175,12 @@ def test_check_elasticsearch_cluster_health():
])
def test_check_elasticsearch_cluster_health_errors(pods, health_data, expect_error):
test_health_data = list(health_data)
- check = canned_elasticsearch(exec_oc=lambda *_: json.dumps(test_health_data.pop(0)))
+ check = canned_elasticsearch(exec_oc=lambda *args, **_: json.dumps(test_health_data.pop(0)))
assert_error_in_list(expect_error, check.check_es_cluster_health(pods_by_name(pods)))
def test_check_elasticsearch_diskspace():
- check = canned_elasticsearch(exec_oc=lambda *_: 'IUse% Use%\n 3% 4%\n')
+ check = canned_elasticsearch(exec_oc=lambda *args, **_: 'IUse% Use%\n 3% 4%\n')
assert not check.check_elasticsearch_diskspace(pods_by_name([plain_es_pod]))
@@ -199,5 +199,5 @@ def test_check_elasticsearch_diskspace():
),
])
def test_check_elasticsearch_diskspace_errors(disk_data, expect_error):
- check = canned_elasticsearch(exec_oc=lambda *_: disk_data)
+ check = canned_elasticsearch(exec_oc=lambda *args, **_: disk_data)
assert_error_in_list(expect_error, check.check_elasticsearch_diskspace(pods_by_name([plain_es_pod])))
diff --git a/roles/openshift_health_checker/test/logging_index_time_test.py b/roles/openshift_health_checker/test/logging_index_time_test.py
index 22566b295..c48ade9b8 100644
--- a/roles/openshift_health_checker/test/logging_index_time_test.py
+++ b/roles/openshift_health_checker/test/logging_index_time_test.py
@@ -102,7 +102,7 @@ def test_with_running_pods():
),
], ids=lambda argval: argval[0])
def test_wait_until_cmd_or_err_succeeds(name, json_response, uuid, timeout):
- check = canned_loggingindextime(lambda *_: json.dumps(json_response))
+ check = canned_loggingindextime(lambda *args, **_: json.dumps(json_response))
check.wait_until_cmd_or_err(plain_running_elasticsearch_pod, uuid, timeout)
@@ -131,7 +131,7 @@ def test_wait_until_cmd_or_err_succeeds(name, json_response, uuid, timeout):
)
], ids=lambda argval: argval[0])
def test_wait_until_cmd_or_err(name, json_response, timeout, expect_error):
- check = canned_loggingindextime(lambda *_: json.dumps(json_response))
+ check = canned_loggingindextime(lambda *args, **_: json.dumps(json_response))
with pytest.raises(OpenShiftCheckException) as error:
check.wait_until_cmd_or_err(plain_running_elasticsearch_pod, SAMPLE_UUID, timeout)
@@ -139,7 +139,7 @@ def test_wait_until_cmd_or_err(name, json_response, timeout, expect_error):
def test_curl_kibana_with_uuid():
- check = canned_loggingindextime(lambda *_: json.dumps({"statusCode": 404}))
+ check = canned_loggingindextime(lambda *args, **_: json.dumps({"statusCode": 404}))
check.generate_uuid = lambda: SAMPLE_UUID
assert SAMPLE_UUID == check.curl_kibana_with_uuid(plain_running_kibana_pod)
@@ -161,7 +161,7 @@ def test_curl_kibana_with_uuid():
),
], ids=lambda argval: argval[0])
def test_failed_curl_kibana_with_uuid(name, json_response, expect_error):
- check = canned_loggingindextime(lambda *_: json.dumps(json_response))
+ check = canned_loggingindextime(lambda *args, **_: json.dumps(json_response))
check.generate_uuid = lambda: SAMPLE_UUID
with pytest.raises(OpenShiftCheckException) as error:
diff --git a/roles/openshift_health_checker/test/openshift_check_test.py b/roles/openshift_health_checker/test/openshift_check_test.py
index 789784c77..bc0c3b26c 100644
--- a/roles/openshift_health_checker/test/openshift_check_test.py
+++ b/roles/openshift_health_checker/test/openshift_check_test.py
@@ -106,13 +106,40 @@ def test_get_var_convert(task_vars, keys, convert, expected):
assert dummy_check(task_vars).get_var(*keys, convert=convert) == expected
-@pytest.mark.parametrize("keys, convert", [
- (("bar", "baz"), int),
- (("bar.baz"), float),
- (("foo"), "bogus"),
- (("foo"), lambda a, b: 1),
- (("foo"), lambda a: 1 / 0),
+def convert_oscexc(_):
+ raise OpenShiftCheckException("known failure")
+
+
+def convert_exc(_):
+ raise Exception("failure unknown")
+
+
+@pytest.mark.parametrize("keys, convert, expect_text", [
+ (("bar", "baz"), int, "Cannot convert"),
+ (("bar.baz",), float, "Cannot convert"),
+ (("foo",), "bogus", "TypeError"),
+ (("foo",), lambda a, b: 1, "TypeError"),
+ (("foo",), lambda a: 1 / 0, "ZeroDivisionError"),
+ (("foo",), convert_oscexc, "known failure"),
+ (("foo",), convert_exc, "failure unknown"),
])
-def test_get_var_convert_error(task_vars, keys, convert):
- with pytest.raises(OpenShiftCheckException):
+def test_get_var_convert_error(task_vars, keys, convert, expect_text):
+ with pytest.raises(OpenShiftCheckException) as excinfo:
dummy_check(task_vars).get_var(*keys, convert=convert)
+ assert expect_text in str(excinfo.value)
+
+
+def test_register(task_vars):
+ check = dummy_check(task_vars)
+
+ check.register_failure(OpenShiftCheckException("spam"))
+ assert "spam" in str(check.failures[0])
+
+ with pytest.raises(OpenShiftCheckException) as excinfo:
+ check.register_file("spam") # no file contents specified
+ assert "not specified" in str(excinfo.value)
+
+ # normally execute_module registers the result file; test disabling that
+ check._execute_module = lambda *args, **_: dict()
+ check.execute_module("eggs", module_args={}, register=False)
+ assert not check.files_to_save
diff --git a/roles/openshift_health_checker/test/ovs_version_test.py b/roles/openshift_health_checker/test/ovs_version_test.py
index e1bf29d2a..602f32989 100644
--- a/roles/openshift_health_checker/test/ovs_version_test.py
+++ b/roles/openshift_health_checker/test/ovs_version_test.py
@@ -50,7 +50,7 @@ def test_ovs_package_version(openshift_release, expected_ovs_version):
openshift_release=openshift_release,
openshift_image_tag='v' + openshift_release,
)
- return_value = object()
+ return_value = {} # note: check.execute_module modifies return hash contents
def execute_module(module_name=None, module_args=None, *_):
assert module_name == 'rpm_version'
diff --git a/roles/openshift_health_checker/test/package_availability_test.py b/roles/openshift_health_checker/test/package_availability_test.py
index 1fe648b75..b34e8fbfc 100644
--- a/roles/openshift_health_checker/test/package_availability_test.py
+++ b/roles/openshift_health_checker/test/package_availability_test.py
@@ -49,14 +49,14 @@ def test_is_active(pkg_mgr, is_containerized, is_active):
),
])
def test_package_availability(task_vars, must_have_packages, must_not_have_packages):
- return_value = object()
+ return_value = {}
def execute_module(module_name=None, module_args=None, *_):
assert module_name == 'check_yum_update'
assert 'packages' in module_args
assert set(module_args['packages']).issuperset(must_have_packages)
assert not set(module_args['packages']).intersection(must_not_have_packages)
- return return_value
+ return {'foo': return_value}
result = PackageAvailability(execute_module, task_vars).run()
- assert result is return_value
+ assert result['foo'] is return_value
diff --git a/roles/openshift_health_checker/test/package_update_test.py b/roles/openshift_health_checker/test/package_update_test.py
index 06489b0d7..85d3c9cab 100644
--- a/roles/openshift_health_checker/test/package_update_test.py
+++ b/roles/openshift_health_checker/test/package_update_test.py
@@ -2,14 +2,14 @@ from openshift_checks.package_update import PackageUpdate
def test_package_update():
- return_value = object()
+ return_value = {}
def execute_module(module_name=None, module_args=None, *_):
assert module_name == 'check_yum_update'
assert 'packages' in module_args
# empty list of packages means "generic check if 'yum update' will work"
assert module_args['packages'] == []
- return return_value
+ return {'foo': return_value}
result = PackageUpdate(execute_module).run()
- assert result is return_value
+ assert result['foo'] is return_value
diff --git a/roles/openshift_health_checker/test/package_version_test.py b/roles/openshift_health_checker/test/package_version_test.py
index 6054d3f3e..8564cd4db 100644
--- a/roles/openshift_health_checker/test/package_version_test.py
+++ b/roles/openshift_health_checker/test/package_version_test.py
@@ -5,6 +5,7 @@ from openshift_checks.package_version import PackageVersion, OpenShiftCheckExcep
def task_vars_for(openshift_release, deployment_type):
return dict(
+ ansible_pkg_mgr='yum',
openshift=dict(common=dict(service_type=deployment_type)),
openshift_release=openshift_release,
openshift_image_tag='v' + openshift_release,
@@ -27,6 +28,7 @@ def test_openshift_version_not_supported():
def test_invalid_openshift_release_format():
task_vars = dict(
+ ansible_pkg_mgr='yum',
openshift=dict(common=dict(service_type='origin')),
openshift_image_tag='v0',
openshift_deployment_type='origin',
@@ -50,7 +52,7 @@ def test_invalid_openshift_release_format():
])
def test_package_version(openshift_release):
- return_value = object()
+ return_value = {"foo": object()}
def execute_module(module_name=None, module_args=None, tmp=None, task_vars=None, *_):
assert module_name == 'aos_version'
@@ -64,7 +66,7 @@ def test_package_version(openshift_release):
check = PackageVersion(execute_module, task_vars_for(openshift_release, 'origin'))
result = check.run()
- assert result is return_value
+ assert result == return_value
@pytest.mark.parametrize('deployment_type,openshift_release,expected_docker_version', [
@@ -77,7 +79,7 @@ def test_package_version(openshift_release):
])
def test_docker_package_version(deployment_type, openshift_release, expected_docker_version):
- return_value = object()
+ return_value = {"foo": object()}
def execute_module(module_name=None, module_args=None, *_):
assert module_name == 'aos_version'
@@ -91,7 +93,7 @@ def test_docker_package_version(deployment_type, openshift_release, expected_doc
check = PackageVersion(execute_module, task_vars_for(openshift_release, deployment_type))
result = check.run()
- assert result is return_value
+ assert result == return_value
@pytest.mark.parametrize('group_names,is_containerized,is_active', [
diff --git a/roles/openshift_health_checker/test/zz_failure_summary_test.py b/roles/openshift_health_checker/test/zz_failure_summary_test.py
new file mode 100644
index 000000000..69f27653c
--- /dev/null
+++ b/roles/openshift_health_checker/test/zz_failure_summary_test.py
@@ -0,0 +1,85 @@
+from zz_failure_summary import deduplicate_failures
+
+import pytest
+
+
+@pytest.mark.parametrize('failures,deduplicated', [
+ (
+ [
+ {
+ 'host': 'master1',
+ 'msg': 'One or more checks failed',
+ },
+ ],
+ [
+ {
+ 'host': ('master1',),
+ 'msg': 'One or more checks failed',
+ },
+ ],
+ ),
+ (
+ [
+ {
+ 'host': 'master1',
+ 'msg': 'One or more checks failed',
+ },
+ {
+ 'host': 'node1',
+ 'msg': 'One or more checks failed',
+ },
+ ],
+ [
+ {
+ 'host': ('master1', 'node1'),
+ 'msg': 'One or more checks failed',
+ },
+ ],
+ ),
+ (
+ [
+ {
+ 'host': 'node1',
+ 'msg': 'One or more checks failed',
+ 'checks': (('test_check', 'error message'),),
+ },
+ {
+ 'host': 'master2',
+ 'msg': 'Some error happened',
+ },
+ {
+ 'host': 'master1',
+ 'msg': 'One or more checks failed',
+ 'checks': (('test_check', 'error message'),),
+ },
+ ],
+ [
+ {
+ 'host': ('master1', 'node1'),
+ 'msg': 'One or more checks failed',
+ 'checks': (('test_check', 'error message'),),
+ },
+ {
+ 'host': ('master2',),
+ 'msg': 'Some error happened',
+ },
+ ],
+ ),
+ # if a failure contain an unhashable value, it will not be deduplicated
+ (
+ [
+ {
+ 'host': 'master1',
+ 'msg': {'unhashable': 'value'},
+ },
+ ],
+ [
+ {
+ 'host': 'master1',
+ 'msg': {'unhashable': 'value'},
+ },
+ ],
+ ),
+])
+def test_deduplicate_failures(failures, deduplicated):
+ assert deduplicate_failures(failures) == deduplicated
diff --git a/roles/openshift_hosted/README.md b/roles/openshift_hosted/README.md
index 3e5d7f860..29ae58556 100644
--- a/roles/openshift_hosted/README.md
+++ b/roles/openshift_hosted/README.md
@@ -39,7 +39,6 @@ variables also control configuration behavior:
Dependencies
------------
-* openshift_common
* openshift_hosted_facts
Example Playbook
diff --git a/roles/openshift_hosted/defaults/main.yml b/roles/openshift_hosted/defaults/main.yml
index 13cbfb14e..712a2a591 100644
--- a/roles/openshift_hosted/defaults/main.yml
+++ b/roles/openshift_hosted/defaults/main.yml
@@ -1,9 +1,12 @@
---
-r_openshift_hosted_router_firewall_enabled: True
-r_openshift_hosted_router_use_firewalld: False
+r_openshift_hosted_router_firewall_enabled: "{{ os_firewall_enabled | default(True) }}"
+r_openshift_hosted_router_use_firewalld: "{{ os_firewall_use_firewalld | default(False) }}"
-r_openshift_hosted_registry_firewall_enabled: True
-r_openshift_hosted_registry_use_firewalld: False
+r_openshift_hosted_registry_firewall_enabled: "{{ os_firewall_enabled | default(True) }}"
+r_openshift_hosted_registry_use_firewalld: "{{ os_firewall_use_firewalld | default(False) }}"
+
+openshift_hosted_router_wait: "{{ not (openshift_master_bootstrap_enabled | default(False)) }}"
+openshift_hosted_registry_wait: "{{ not (openshift_master_bootstrap_enabled | default(False)) }}"
registry_volume_claim: 'registry-claim'
@@ -44,3 +47,9 @@ r_openshift_hosted_registry_os_firewall_allow:
- service: Docker Registry Port
port: 5000/tcp
cond: "{{ r_openshift_hosted_use_calico }}"
+
+# NOTE
+# r_openshift_hosted_use_calico_default may be defined external to this role.
+# openshift_use_calico, if defined, may affect other roles or play behavior.
+r_openshift_hosted_use_calico_default: "{{ openshift_use_calico | default(False) }}"
+r_openshift_hosted_use_calico: "{{ r_openshift_hosted_use_calico_default }}"
diff --git a/roles/openshift_hosted/tasks/registry/registry.yml b/roles/openshift_hosted/tasks/registry/registry.yml
index dcd9c87fc..48f53aef8 100644
--- a/roles/openshift_hosted/tasks/registry/registry.yml
+++ b/roles/openshift_hosted/tasks/registry/registry.yml
@@ -43,9 +43,6 @@
openshift_hosted_registry_images: "{{ openshift.hosted.registry.registryurl | default('openshift3/ose-${component}:${version}')}}"
openshift_hosted_registry_volumes: []
openshift_hosted_registry_env_vars: {}
- openshift_hosted_registry_routecertificates: "{{ ('routecertificates' in openshift.hosted.registry.keys()) | ternary(openshift.hosted.registry.routecertificates, {}) }}"
- openshift_hosted_registry_routehost: "{{ ('routehost' in openshift.hosted.registry.keys()) | ternary(openshift.hosted.registry.routehost, False) }}"
- openshift_hosted_registry_routetermination: "{{ ('routetermination' in openshift.hosted.registry.keys()) | ternary(openshift.hosted.registry.routetermination, 'passthrough') }}"
openshift_hosted_registry_edits:
# These edits are being specified only to prevent 'changed' on rerun
- key: spec.strategy.rollingParams
@@ -64,6 +61,14 @@
openshift_hosted_registry_env_vars: "{{ openshift_hosted_registry_env_vars | combine({'OPENSHIFT_DEFAULT_REGISTRY':'docker-registry.default.svc:5000'}) }}"
when: openshift_push_via_dns | default(false) | bool
+- name: Update registry proxy settings for dc/docker-registry
+ set_fact:
+ openshift_hosted_registry_env_vars: "{{ {'HTTPS_PROXY': (openshift.common.https_proxy | default('')),
+ 'HTTP_PROXY': (openshift.common.http_proxy | default('')),
+ 'NO_PROXY': (openshift.common.no_proxy | default(''))}
+ | combine(openshift_hosted_registry_env_vars) }}"
+ when: (openshift.common.https_proxy | default(False)) or (openshift.common.http_proxy | default('')) != ''
+
- name: Create the registry service account
oc_serviceaccount:
name: "{{ openshift_hosted_registry_serviceaccount }}"
@@ -132,34 +137,36 @@
edits: "{{ openshift_hosted_registry_edits }}"
force: "{{ True|bool in openshift_hosted_registry_force }}"
-- name: Ensure OpenShift registry correctly rolls out (best-effort today)
- command: |
- oc rollout status deploymentconfig {{ openshift_hosted_registry_name }} \
- --namespace {{ openshift_hosted_registry_namespace }} \
- --config {{ openshift.common.config_base }}/master/admin.kubeconfig
- async: 600
- poll: 15
- failed_when: false
-
-- name: Determine the latest version of the OpenShift registry deployment
- command: |
- {{ openshift.common.client_binary }} get deploymentconfig {{ openshift_hosted_registry_name }} \
- --namespace {{ openshift_hosted_registry_namespace }} \
- --config {{ openshift.common.config_base }}/master/admin.kubeconfig \
- -o jsonpath='{ .status.latestVersion }'
- register: openshift_hosted_registry_latest_version
-
-- name: Sanity-check that the OpenShift registry rolled out correctly
- command: |
- {{ openshift.common.client_binary }} get replicationcontroller {{ openshift_hosted_registry_name }}-{{ openshift_hosted_registry_latest_version.stdout }} \
- --namespace {{ openshift_hosted_registry_namespace }} \
- --config {{ openshift.common.config_base }}/master/admin.kubeconfig \
- -o jsonpath='{ .metadata.annotations.openshift\.io/deployment\.phase }'
- register: openshift_hosted_registry_rc_phase
- until: "'Running' not in openshift_hosted_registry_rc_phase.stdout"
- delay: 15
- retries: 40
- failed_when: "'Failed' in openshift_hosted_registry_rc_phase.stdout"
+- when: openshift_hosted_registry_wait | bool
+ block:
+ - name: Ensure OpenShift registry correctly rolls out (best-effort today)
+ command: |
+ oc rollout status deploymentconfig {{ openshift_hosted_registry_name }} \
+ --namespace {{ openshift_hosted_registry_namespace }} \
+ --config {{ openshift.common.config_base }}/master/admin.kubeconfig
+ async: 600
+ poll: 15
+ failed_when: false
+
+ - name: Determine the latest version of the OpenShift registry deployment
+ command: |
+ {{ openshift.common.client_binary }} get deploymentconfig {{ openshift_hosted_registry_name }} \
+ --namespace {{ openshift_hosted_registry_namespace }} \
+ --config {{ openshift.common.config_base }}/master/admin.kubeconfig \
+ -o jsonpath='{ .status.latestVersion }'
+ register: openshift_hosted_registry_latest_version
+
+ - name: Sanity-check that the OpenShift registry rolled out correctly
+ command: |
+ {{ openshift.common.client_binary }} get replicationcontroller {{ openshift_hosted_registry_name }}-{{ openshift_hosted_registry_latest_version.stdout }} \
+ --namespace {{ openshift_hosted_registry_namespace }} \
+ --config {{ openshift.common.config_base }}/master/admin.kubeconfig \
+ -o jsonpath='{ .metadata.annotations.openshift\.io/deployment\.phase }'
+ register: openshift_hosted_registry_rc_phase
+ until: "'Running' not in openshift_hosted_registry_rc_phase.stdout"
+ delay: 15
+ retries: 40
+ failed_when: "'Failed' in openshift_hosted_registry_rc_phase.stdout"
- include: storage/glusterfs.yml
when:
diff --git a/roles/openshift_hosted/tasks/registry/secure.yml b/roles/openshift_hosted/tasks/registry/secure.yml
index 29c164f52..434b679df 100644
--- a/roles/openshift_hosted/tasks/registry/secure.yml
+++ b/roles/openshift_hosted/tasks/registry/secure.yml
@@ -1,65 +1,71 @@
---
-- name: Set fact docker_registry_route_hostname
+- name: Configure facts for docker-registry
set_fact:
- docker_registry_route_hostname: "{{ 'docker-registry-default.' ~ (openshift_master_default_subdomain | default('router.default.svc.cluster.local', true)) }}"
+ openshift_hosted_registry_routecertificates: "{{ ('routecertificates' in openshift.hosted.registry.keys()) | ternary(openshift_hosted_registry_routecertificates, {}) }}"
+ openshift_hosted_registry_routehost: "{{ ('routehost' in openshift.hosted.registry.keys()) | ternary(openshift.hosted.registry.routehost, False) }}"
+ openshift_hosted_registry_routetermination: "{{ ('routetermination' in openshift.hosted.registry.keys()) | ternary(openshift.hosted.registry.routetermination, 'passthrough') }}"
-- name: Get the certificate contents for registry
- copy:
- backup: True
- dest: "/etc/origin/master/named_certificates/{{ item.value | basename }}"
- src: "{{ item.value }}"
- when: item.key in ['certfile', 'keyfile', 'cafile'] and item.value
- with_dict: "{{ openshift_hosted_registry_routecertificates }}"
+- name: Include reencrypt route configuration
+ include: secure/reencrypt.yml
+ static: no
+ when: openshift_hosted_registry_routetermination == 'reencrypt'
-# When certificates are defined we will create the reencrypt
-# docker-registry route
-- name: Create a reencrypt route for docker-registry
- oc_route:
- name: docker-registry
- namespace: "{{ openshift_hosted_registry_namespace }}"
- service_name: docker-registry
- tls_termination: "{{ openshift_hosted_registry_routetermination }}"
- host: "{{ openshift_hosted_registry_routehost | default(docker_registry_route_hostname) }}"
- cert_path: "/etc/origin/master/named_certificates/{{ openshift_hosted_registry_routecertificates['certfile'] | basename }}"
- key_path: "/etc/origin/master/named_certificates/{{ openshift_hosted_registry_routecertificates['keyfile'] | basename }}"
- cacert_path: "/etc/origin/master/named_certificates/{{ openshift_hosted_registry_routecertificates['cafile'] | basename }}"
- dest_cacert_path: /etc/origin/master/ca.crt
- when:
- - "'cafile' in openshift_hosted_registry_routecertificates"
- - "'certfile' in openshift_hosted_registry_routecertificates"
- - "'keyfile' in openshift_hosted_registry_routecertificates"
+- name: Include passthrough route configuration
+ include: secure/passthrough.yml
+ static: no
+ when: openshift_hosted_registry_routetermination == 'passthrough'
-# When routetermination is passthrough we will create the route
-- name: Create passthrough route for docker-registry
+- name: Fetch the docker-registry route
oc_route:
name: docker-registry
- namespace: "{{ openshift_hosted_registry_namespace }}"
- service_name: docker-registry
- tls_termination: "{{ openshift_hosted_registry_routetermination }}"
- host: "{{ openshift_hosted_registry_routehost | ternary(openshift_hosted_registry_routehost, docker_registry_route_hostname) }}"
- when: openshift_hosted_registry_routetermination == 'passthrough'
+ namespace: default
+ state: list
+ register: docker_registry_route
-- name: Retrieve registry service IP
+- name: Retrieve registry service for the clusterip
oc_service:
namespace: "{{ openshift_hosted_registry_namespace }}"
name: docker-registry
state: list
- register: docker_registry_service_ip
+ register: docker_registry_service
-- name: Create registry certificates
+- name: Generate self-signed docker-registry certificates
oc_adm_ca_server_cert:
signer_cert: "{{ openshift_master_config_dir }}/ca.crt"
signer_key: "{{ openshift_master_config_dir }}/ca.key"
signer_serial: "{{ openshift_master_config_dir }}/ca.serial.txt"
hostnames:
- - "{{ docker_registry_service_ip.results.clusterip }}"
+ - "{{ docker_registry_service.results.clusterip }}"
+ - "{{ docker_registry_route.results[0].spec.host }}"
- "{{ openshift_hosted_registry_name }}.default.svc"
- "{{ openshift_hosted_registry_name }}.default.svc.{{ openshift.common.dns_domain }}"
- - "{{ docker_registry_route_hostname }}"
- cert: "{{ openshift_master_config_dir }}/registry.crt"
- key: "{{ openshift_master_config_dir }}/registry.key"
+ - "{{ openshift_hosted_registry_routehost }}"
+ cert: "{{ docker_registry_cert_path }}"
+ key: "{{ docker_registry_key_path }}"
expire_days: "{{ openshift_hosted_registry_cert_expire_days if openshift_version | oo_version_gte_3_5_or_1_5(openshift.common.deployment_type) | bool else omit }}"
- register: server_cert_out
+ register: registry_self_cert
+ when: docker_registry_self_signed
+
+# Setting up REGISTRY_HTTP_TLS_CLIENTCAS as the cacert doesn't seem to work.
+# If we need to set up a cacert, bundle it with the cert.
+- when: docker_registry_cacert_path is defined
+ block:
+ - name: Retrieve certificate files to generate certificate bundle
+ slurp:
+ src: "{{ item }}"
+ with_items:
+ - "{{ docker_registry_cert_path }}"
+ - "{{ docker_registry_cacert_path }}"
+ register: certificate_files
+
+ - name: Generate certificate bundle
+ copy:
+ content: "{{ certificate_files.results | map(attribute='content') | map('b64decode') | join('') }}"
+ dest: "{{ openshift_master_config_dir }}/named_certificates/docker-registry.pem"
+
+ - name: Reset the certificate path to use the bundle
+ set_fact:
+ docker_registry_cert_path: "{{ openshift_master_config_dir }}/named_certificates/docker-registry.pem"
- name: Create the secret for the registry certificates
oc_secret:
@@ -67,9 +73,9 @@
namespace: "{{ openshift_hosted_registry_namespace }}"
files:
- name: registry.crt
- path: "{{ openshift_master_config_dir }}/registry.crt"
+ path: "{{ docker_registry_cert_path }}"
- name: registry.key
- path: "{{ openshift_master_config_dir }}/registry.key"
+ path: "{{ docker_registry_key_path }}"
register: create_registry_certificates_secret_out
- name: Add the secret to the registry's pod service accounts
@@ -99,9 +105,15 @@
value: HTTPS
action: put
+- name: Detect if there has been certificate changes
+ set_fact:
+ registry_cert_changed: true
+ when: ( registry_self_cert is defined and registry_self_cert.changed ) or
+ create_registry_certificates_secret_out.changed
+
- name: Update openshift_hosted facts with secure registry variables
set_fact:
openshift_hosted_registry_volumes: "{{ openshift_hosted_registry_volumes | union(registry_secure_volume_mounts) }}"
openshift_hosted_registry_env_vars: "{{ openshift_hosted_registry_env_vars | combine(registry_secure_env_vars) }}"
openshift_hosted_registry_edits: "{{ openshift_hosted_registry_edits | union(registry_secure_edits) }}"
- openshift_hosted_registry_force: "{{ openshift_hosted_registry_force | union([server_cert_out.changed]) | union([create_registry_certificates_secret_out.changed]) }}"
+ openshift_hosted_registry_force: "{{ openshift_hosted_registry_force | union([registry_cert_changed | default(false)]) }}"
diff --git a/roles/openshift_hosted/tasks/registry/secure/passthrough.yml b/roles/openshift_hosted/tasks/registry/secure/passthrough.yml
new file mode 100644
index 000000000..5b44fda10
--- /dev/null
+++ b/roles/openshift_hosted/tasks/registry/secure/passthrough.yml
@@ -0,0 +1,45 @@
+---
+# Generate a self-signed certificate when there is no user-supplied certificate
+- name: Configure self-signed certificate file paths
+ set_fact:
+ docker_registry_cert_path: "{{ openshift_master_config_dir }}/registry.crt"
+ docker_registry_key_path: "{{ openshift_master_config_dir }}/registry.key"
+ docker_registry_cacert_path: "{{ openshift_master_config_dir }}/ca.crt"
+ docker_registry_self_signed: true
+ when:
+ - "'certfile' not in openshift_hosted_registry_routecertificates"
+ - "'keyfile' not in openshift_hosted_registry_routecertificates"
+
+# Retrieve user supplied certificate files if they are provided
+- when:
+ - "'certfile' in openshift_hosted_registry_routecertificates"
+ - "'keyfile' in openshift_hosted_registry_routecertificates"
+ block:
+ - name: Configure provided certificate file paths
+ set_fact:
+ docker_registry_cert_path: "{{ openshift_master_config_dir }}/named_certificates/{{ openshift_hosted_registry_routecertificates['certfile'] | basename }}"
+ docker_registry_key_path: "{{ openshift_master_config_dir }}/named_certificates/{{ openshift_hosted_registry_routecertificates['keyfile'] | basename }}"
+ docker_registry_self_signed: false
+
+ # Since we end up bundling the cert, cacert and key in a .pem file, the 'cafile'
+ # is optional
+ - name: Configure provided ca certificate file path
+ set_fact:
+ docker_registry_cacert_path: "{{ openshift_master_config_dir }}/named_certificates/{{ openshift_hosted_registry_routecertificates['cafile'] | basename }}"
+ when: "'cafile' in openshift_hosted_registry_routecertificates"
+
+ - name: Retrieve provided certificate files
+ copy:
+ backup: True
+ dest: "{{ openshift_master_config_dir }}/named_certificates/{{ item.value | basename }}"
+ src: "{{ item.value }}"
+ when: item.key in ['certfile', 'keyfile', 'cafile'] and item.value
+ with_dict: "{{ openshift_hosted_registry_routecertificates }}"
+
+- name: Configure a passthrough route for docker-registry
+ oc_route:
+ name: docker-registry
+ namespace: "{{ openshift_hosted_registry_namespace }}"
+ service_name: docker-registry
+ tls_termination: "{{ openshift_hosted_registry_routetermination }}"
+ host: "{{ openshift_hosted_registry_routehost | default(omit, true) }}"
diff --git a/roles/openshift_hosted/tasks/registry/secure/reencrypt.yml b/roles/openshift_hosted/tasks/registry/secure/reencrypt.yml
new file mode 100644
index 000000000..48e5b0fba
--- /dev/null
+++ b/roles/openshift_hosted/tasks/registry/secure/reencrypt.yml
@@ -0,0 +1,38 @@
+---
+- name: Validate route termination configuration
+ fail:
+ msg: >
+ When 'openshift_hosted_registry_routetermination' is 'reencrypt', you must
+ provide certificate files with 'openshift_hosted_registry_routecertificates'
+ when: ('certfile' not in openshift_hosted_registry_routecertificates) or
+ ('keyfile' not in openshift_hosted_registry_routecertificates) or
+ ('cafile' not in openshift_hosted_registry_routecertificates)
+
+- name: Configure self-signed certificate file paths
+ set_fact:
+ docker_registry_cert_path: "{{ openshift_master_config_dir }}/registry.crt"
+ docker_registry_key_path: "{{ openshift_master_config_dir }}/registry.key"
+ docker_registry_cacert_path: "{{ openshift_master_config_dir }}/ca.crt"
+ docker_registry_self_signed: true
+
+- name: Retrieve provided certificate files
+ copy:
+ backup: True
+ dest: "{{ openshift_master_config_dir }}/named_certificates/{{ item.value | basename }}"
+ src: "{{ item.value }}"
+ when: item.key in ['certfile', 'keyfile', 'cafile'] and item.value
+ with_dict: "{{ openshift_hosted_registry_routecertificates }}"
+
+# Encrypt with the provided certificate and provide the dest_cacert for the
+# self-signed certificate at the endpoint
+- name: Configure a reencrypt route for docker-registry
+ oc_route:
+ name: docker-registry
+ namespace: "{{ openshift_hosted_registry_namespace }}"
+ service_name: docker-registry
+ tls_termination: "{{ openshift_hosted_registry_routetermination }}"
+ host: "{{ openshift_hosted_registry_routehost | default(omit, true) }}"
+ cert_path: "{{ openshift_master_config_dir }}/named_certificates/{{ openshift_hosted_registry_routecertificates['certfile'] | basename }}"
+ key_path: "{{ openshift_master_config_dir }}/named_certificates/{{ openshift_hosted_registry_routecertificates['keyfile'] | basename }}"
+ cacert_path: "{{ openshift_master_config_dir }}/named_certificates/{{ openshift_hosted_registry_routecertificates['cafile'] | basename }}"
+ dest_cacert_path: "{{ openshift_master_config_dir }}/ca.crt"
diff --git a/roles/openshift_hosted/tasks/registry/storage/object_storage.yml b/roles/openshift_hosted/tasks/registry/storage/object_storage.yml
index 8aaba0f3c..8553a8098 100644
--- a/roles/openshift_hosted/tasks/registry/storage/object_storage.yml
+++ b/roles/openshift_hosted/tasks/registry/storage/object_storage.yml
@@ -2,7 +2,7 @@
- include: s3.yml
when: openshift.hosted.registry.storage.provider == 's3'
-- name: Ensure the resgistry secret exists
+- name: Ensure the registry secret exists
oc_secret:
name: "{{ registry_config_secret_name }}"
state: present
@@ -10,6 +10,19 @@
- path: /tmp/config.yml
data: "{{ lookup('template', 'registry_config.j2') }}"
register: registry_config_out
+ when: openshift_hosted_registry_storage_gcs_keyfile is not defined
+
+- name: Ensure the registry secret exists for GCS
+ oc_secret:
+ name: "{{ registry_config_secret_name }}"
+ state: present
+ contents:
+ - path: /tmp/config.yml
+ data: "{{ lookup('template', 'registry_config.j2') }}"
+ - path: /tmp/gcs.json
+ data: "{{ lookup('file', openshift_hosted_registry_storage_gcs_keyfile) | string }}"
+ register: registry_config_out
+ when: openshift_hosted_registry_storage_gcs_keyfile is defined
- name: Add secrets to registry service account
oc_serviceaccount_secret:
diff --git a/roles/openshift_hosted/tasks/registry/storage/registry_config_secret.j2 b/roles/openshift_hosted/tasks/registry/storage/registry_config_secret.j2
deleted file mode 120000
index b9e82c1ea..000000000
--- a/roles/openshift_hosted/tasks/registry/storage/registry_config_secret.j2
+++ /dev/null
@@ -1 +0,0 @@
-../../../templates/registry_config_secret.j2 \ No newline at end of file
diff --git a/roles/openshift_hosted/tasks/router/router.yml b/roles/openshift_hosted/tasks/router/router.yml
index 72a1ead80..2a42b5a7c 100644
--- a/roles/openshift_hosted/tasks/router/router.yml
+++ b/roles/openshift_hosted/tasks/router/router.yml
@@ -18,6 +18,15 @@
openshift_hosted_router_selector: "{{ openshift.hosted.router.selector | default(None) }}"
openshift_hosted_router_image: "{{ openshift.hosted.router.registryurl }}"
+- name: Get the certificate contents for router
+ copy:
+ backup: True
+ dest: "/etc/origin/master/{{ item | basename }}"
+ src: "{{ item }}"
+ with_items: "{{ openshift_hosted_routers | oo_collect(attribute='certificate') |
+ oo_select_keys_from_list(['keyfile', 'certfile', 'cafile']) }}"
+ when: ( not openshift_hosted_router_create_certificate | bool ) or openshift_hosted_router_certificate != {}
+
# This is for when we desire a cluster signed cert
# The certificate is generated and placed in master_config_dir/
- block:
@@ -43,15 +52,6 @@
# End Block
when: ( openshift_hosted_router_create_certificate | bool ) and openshift_hosted_router_certificate == {}
-- name: Get the certificate contents for router
- copy:
- backup: True
- dest: "/etc/origin/master/{{ item | basename }}"
- src: "{{ item }}"
- with_items: "{{ openshift_hosted_routers | oo_collect(attribute='certificate') |
- oo_select_keys_from_list(['keyfile', 'certfile', 'cafile']) }}"
- when: not openshift_hosted_router_create_certificate | bool
-
- name: Create the router service account(s)
oc_serviceaccount:
name: "{{ item.serviceaccount }}"
@@ -94,36 +94,38 @@
stats_port: "{{ item.stats_port }}"
with_items: "{{ openshift_hosted_routers }}"
-- name: Ensure OpenShift router correctly rolls out (best-effort today)
- command: |
- {{ openshift.common.client_binary }} rollout status deploymentconfig {{ item.name }} \
- --namespace {{ item.namespace | default('default') }} \
- --config {{ openshift.common.config_base }}/master/admin.kubeconfig
- async: 600
- poll: 15
- with_items: "{{ openshift_hosted_routers }}"
- failed_when: false
+- when: openshift_hosted_router_wait | bool
+ block:
+ - name: Ensure OpenShift router correctly rolls out (best-effort today)
+ command: |
+ {{ openshift.common.client_binary }} rollout status deploymentconfig {{ item.name }} \
+ --namespace {{ item.namespace | default('default') }} \
+ --config {{ openshift.common.config_base }}/master/admin.kubeconfig
+ async: 600
+ poll: 15
+ with_items: "{{ openshift_hosted_routers }}"
+ failed_when: false
-- name: Determine the latest version of the OpenShift router deployment
- command: |
- {{ openshift.common.client_binary }} get deploymentconfig {{ item.name }} \
- --namespace {{ item.namespace }} \
- --config {{ openshift.common.config_base }}/master/admin.kubeconfig \
- -o jsonpath='{ .status.latestVersion }'
- register: openshift_hosted_routers_latest_version
- with_items: "{{ openshift_hosted_routers }}"
+ - name: Determine the latest version of the OpenShift router deployment
+ command: |
+ {{ openshift.common.client_binary }} get deploymentconfig {{ item.name }} \
+ --namespace {{ item.namespace }} \
+ --config {{ openshift.common.config_base }}/master/admin.kubeconfig \
+ -o jsonpath='{ .status.latestVersion }'
+ register: openshift_hosted_routers_latest_version
+ with_items: "{{ openshift_hosted_routers }}"
-- name: Poll for OpenShift router deployment success
- command: |
- {{ openshift.common.client_binary }} get replicationcontroller {{ item.0.name }}-{{ item.1.stdout }} \
- --namespace {{ item.0.namespace }} \
- --config {{ openshift.common.config_base }}/master/admin.kubeconfig \
- -o jsonpath='{ .metadata.annotations.openshift\.io/deployment\.phase }'
- register: openshift_hosted_router_rc_phase
- until: "'Running' not in openshift_hosted_router_rc_phase.stdout"
- delay: 15
- retries: 40
- failed_when: "'Failed' in openshift_hosted_router_rc_phase.stdout"
- with_together:
- - "{{ openshift_hosted_routers }}"
- - "{{ openshift_hosted_routers_latest_version.results }}"
+ - name: Poll for OpenShift router deployment success
+ command: |
+ {{ openshift.common.client_binary }} get replicationcontroller {{ item.0.name }}-{{ item.1.stdout }} \
+ --namespace {{ item.0.namespace }} \
+ --config {{ openshift.common.config_base }}/master/admin.kubeconfig \
+ -o jsonpath='{ .metadata.annotations.openshift\.io/deployment\.phase }'
+ register: openshift_hosted_router_rc_phase
+ until: "'Running' not in openshift_hosted_router_rc_phase.stdout"
+ delay: 15
+ retries: 40
+ failed_when: "'Failed' in openshift_hosted_router_rc_phase.stdout"
+ with_together:
+ - "{{ openshift_hosted_routers }}"
+ - "{{ openshift_hosted_routers_latest_version.results }}"
diff --git a/roles/openshift_hosted/templates/registry_config.j2 b/roles/openshift_hosted/templates/registry_config.j2
index fc9272679..61da452de 100644
--- a/roles/openshift_hosted/templates/registry_config.j2
+++ b/roles/openshift_hosted/templates/registry_config.j2
@@ -60,7 +60,7 @@ storage:
gcs:
bucket: {{ openshift_hosted_registry_storage_gcs_bucket }}
{% if openshift_hosted_registry_storage_gcs_keyfile is defined %}
- keyfile: {{ openshift_hosted_registry_storage_gcs_keyfile }}
+ keyfile: /etc/registry/gcs.json
{% endif -%}
{% if openshift_hosted_registry_storage_gcs_rootdirectory is defined %}
rootdirectory: {{ openshift_hosted_registry_storage_gcs_rootdirectory }}
diff --git a/roles/openshift_hosted/templates/registry_config_secret.j2 b/roles/openshift_hosted/templates/registry_config_secret.j2
deleted file mode 100644
index ca68544ec..000000000
--- a/roles/openshift_hosted/templates/registry_config_secret.j2
+++ /dev/null
@@ -1,9 +0,0 @@
----
-apiVersion: v1
-kind: Secret
-metadata:
- name: registry-config
- annotations:
- provider: {{ openshift.hosted.registry.storage.provider }}
-data:
- config.yml: {{ registry_config }}
diff --git a/roles/openshift_hosted_logging/meta/main.yaml b/roles/openshift_hosted_logging/meta/main.yaml
index 044c8043c..ab07a77c1 100644
--- a/roles/openshift_hosted_logging/meta/main.yaml
+++ b/roles/openshift_hosted_logging/meta/main.yaml
@@ -1,4 +1,3 @@
---
dependencies:
- - { role: openshift_common }
- { role: openshift_master_facts }
diff --git a/roles/openshift_hosted_templates/files/v1.3/enterprise/registry-console.yaml b/roles/openshift_hosted_templates/files/v1.3/enterprise/registry-console.yaml
index 11478263c..72754df2e 100644
--- a/roles/openshift_hosted_templates/files/v1.3/enterprise/registry-console.yaml
+++ b/roles/openshift_hosted_templates/files/v1.3/enterprise/registry-console.yaml
@@ -89,7 +89,7 @@ objects:
- annotations: null
from:
kind: DockerImage
- name: ${IMAGE_PREFIX}registry-console
+ name: ${IMAGE_PREFIX}registry-console:${IMAGE_VERSION}
name: ${IMAGE_VERSION}
- kind: OAuthClient
apiVersion: v1
diff --git a/roles/openshift_hosted_templates/files/v1.3/origin/registry-console.yaml b/roles/openshift_hosted_templates/files/v1.3/origin/registry-console.yaml
index 80cc4233b..6811ece28 100644
--- a/roles/openshift_hosted_templates/files/v1.3/origin/registry-console.yaml
+++ b/roles/openshift_hosted_templates/files/v1.3/origin/registry-console.yaml
@@ -89,7 +89,7 @@ objects:
- annotations: null
from:
kind: DockerImage
- name: ${IMAGE_NAME}
+ name: ${IMAGE_NAME}:${IMAGE_VERSION}
name: ${IMAGE_VERSION}
- kind: OAuthClient
apiVersion: v1
diff --git a/roles/openshift_hosted_templates/files/v1.4/enterprise/registry-console.yaml b/roles/openshift_hosted_templates/files/v1.4/enterprise/registry-console.yaml
index 0e3d006a7..298f8039e 100644
--- a/roles/openshift_hosted_templates/files/v1.4/enterprise/registry-console.yaml
+++ b/roles/openshift_hosted_templates/files/v1.4/enterprise/registry-console.yaml
@@ -89,7 +89,7 @@ objects:
- annotations: null
from:
kind: DockerImage
- name: ${IMAGE_PREFIX}registry-console
+ name: ${IMAGE_PREFIX}registry-console:${IMAGE_VERSION}
name: ${IMAGE_VERSION}
- kind: OAuthClient
apiVersion: v1
diff --git a/roles/openshift_hosted_templates/files/v1.4/origin/registry-console.yaml b/roles/openshift_hosted_templates/files/v1.4/origin/registry-console.yaml
index 80cc4233b..6811ece28 100644
--- a/roles/openshift_hosted_templates/files/v1.4/origin/registry-console.yaml
+++ b/roles/openshift_hosted_templates/files/v1.4/origin/registry-console.yaml
@@ -89,7 +89,7 @@ objects:
- annotations: null
from:
kind: DockerImage
- name: ${IMAGE_NAME}
+ name: ${IMAGE_NAME}:${IMAGE_VERSION}
name: ${IMAGE_VERSION}
- kind: OAuthClient
apiVersion: v1
diff --git a/roles/openshift_hosted_templates/files/v1.5/enterprise/registry-console.yaml b/roles/openshift_hosted_templates/files/v1.5/enterprise/registry-console.yaml
index 28feac4e6..dace26793 100644
--- a/roles/openshift_hosted_templates/files/v1.5/enterprise/registry-console.yaml
+++ b/roles/openshift_hosted_templates/files/v1.5/enterprise/registry-console.yaml
@@ -89,7 +89,7 @@ objects:
- annotations: null
from:
kind: DockerImage
- name: ${IMAGE_PREFIX}registry-console
+ name: ${IMAGE_PREFIX}registry-console:${IMAGE_VERSION}
name: ${IMAGE_VERSION}
- kind: OAuthClient
apiVersion: v1
diff --git a/roles/openshift_hosted_templates/files/v1.5/origin/registry-console.yaml b/roles/openshift_hosted_templates/files/v1.5/origin/registry-console.yaml
index 80cc4233b..6811ece28 100644
--- a/roles/openshift_hosted_templates/files/v1.5/origin/registry-console.yaml
+++ b/roles/openshift_hosted_templates/files/v1.5/origin/registry-console.yaml
@@ -89,7 +89,7 @@ objects:
- annotations: null
from:
kind: DockerImage
- name: ${IMAGE_NAME}
+ name: ${IMAGE_NAME}:${IMAGE_VERSION}
name: ${IMAGE_VERSION}
- kind: OAuthClient
apiVersion: v1
diff --git a/roles/openshift_hosted_templates/files/v3.6/enterprise/registry-console.yaml b/roles/openshift_hosted_templates/files/v3.6/enterprise/registry-console.yaml
index 8bf98ba41..f821efd6b 100644
--- a/roles/openshift_hosted_templates/files/v3.6/enterprise/registry-console.yaml
+++ b/roles/openshift_hosted_templates/files/v3.6/enterprise/registry-console.yaml
@@ -89,7 +89,7 @@ objects:
- annotations: null
from:
kind: DockerImage
- name: ${IMAGE_PREFIX}registry-console
+ name: ${IMAGE_PREFIX}registry-console:${IMAGE_VERSION}
name: ${IMAGE_VERSION}
- kind: OAuthClient
apiVersion: v1
diff --git a/roles/openshift_hosted_templates/files/v3.6/origin/registry-console.yaml b/roles/openshift_hosted_templates/files/v3.6/origin/registry-console.yaml
index 80cc4233b..6811ece28 100644
--- a/roles/openshift_hosted_templates/files/v3.6/origin/registry-console.yaml
+++ b/roles/openshift_hosted_templates/files/v3.6/origin/registry-console.yaml
@@ -89,7 +89,7 @@ objects:
- annotations: null
from:
kind: DockerImage
- name: ${IMAGE_NAME}
+ name: ${IMAGE_NAME}:${IMAGE_VERSION}
name: ${IMAGE_VERSION}
- kind: OAuthClient
apiVersion: v1
diff --git a/roles/openshift_hosted_templates/files/v3.7/enterprise/registry-console.yaml b/roles/openshift_hosted_templates/files/v3.7/enterprise/registry-console.yaml
index bbaf76c17..019d836fe 100644
--- a/roles/openshift_hosted_templates/files/v3.7/enterprise/registry-console.yaml
+++ b/roles/openshift_hosted_templates/files/v3.7/enterprise/registry-console.yaml
@@ -89,7 +89,7 @@ objects:
- annotations: null
from:
kind: DockerImage
- name: ${IMAGE_PREFIX}registry-console
+ name: ${IMAGE_PREFIX}registry-console:${IMAGE_VERSION}
name: ${IMAGE_VERSION}
- kind: OAuthClient
apiVersion: v1
diff --git a/roles/openshift_hosted_templates/files/v3.7/origin/registry-console.yaml b/roles/openshift_hosted_templates/files/v3.7/origin/registry-console.yaml
index 80cc4233b..6811ece28 100644
--- a/roles/openshift_hosted_templates/files/v3.7/origin/registry-console.yaml
+++ b/roles/openshift_hosted_templates/files/v3.7/origin/registry-console.yaml
@@ -89,7 +89,7 @@ objects:
- annotations: null
from:
kind: DockerImage
- name: ${IMAGE_NAME}
+ name: ${IMAGE_NAME}:${IMAGE_VERSION}
name: ${IMAGE_VERSION}
- kind: OAuthClient
apiVersion: v1
diff --git a/roles/openshift_hosted_templates/meta/main.yml b/roles/openshift_hosted_templates/meta/main.yml
index 9c12865bf..4027f524b 100644
--- a/roles/openshift_hosted_templates/meta/main.yml
+++ b/roles/openshift_hosted_templates/meta/main.yml
@@ -11,5 +11,4 @@ galaxy_info:
- 7
categories:
- cloud
-dependencies:
-- role: openshift_common
+dependencies: []
diff --git a/roles/openshift_loadbalancer/defaults/main.yml b/roles/openshift_loadbalancer/defaults/main.yml
index 3f6409233..239b16427 100644
--- a/roles/openshift_loadbalancer/defaults/main.yml
+++ b/roles/openshift_loadbalancer/defaults/main.yml
@@ -1,6 +1,6 @@
---
-r_openshift_loadbalancer_firewall_enabled: True
-r_openshift_loadbalancer_use_firewalld: False
+r_openshift_loadbalancer_firewall_enabled: "{{ os_firewall_enabled | default(True) }}"
+r_openshift_loadbalancer_use_firewalld: "{{ os_firewall_use_firewalld | default(False) }}"
haproxy_frontends:
- name: main
@@ -24,4 +24,10 @@ r_openshift_loadbalancer_os_firewall_allow:
port: "{{ openshift_master_api_port | default(8443) }}/tcp"
- service: nuage mon
port: "{{ nuage_mon_rest_server_port | default(9443) }}/tcp"
- cond: "{{ openshift_use_nuage | default(false) | bool }}"
+ cond: "{{ r_openshift_lb_use_nuage | bool }}"
+
+# NOTE
+# r_openshift_lb_use_nuage_default may be defined external to this role.
+# openshift_use_nuage, if defined, may affect other roles or play behavior.
+r_openshift_lb_use_nuage_default: "{{ openshift_use_nuage | default(False) }}"
+r_openshift_lb_use_nuage: "{{ r_openshift_lb_use_nuage_default }}"
diff --git a/roles/openshift_logging/README.md b/roles/openshift_logging/README.md
index 84ead3548..f283261c4 100644
--- a/roles/openshift_logging/README.md
+++ b/roles/openshift_logging/README.md
@@ -15,14 +15,25 @@ to the list of persisted [node labels](https://docs.openshift.org/latest/install
###Required vars:
- `openshift_logging_install_logging`: When `True` the `openshift_logging` role will install Aggregated Logging.
-- `openshift_logging_upgrade_logging`: When `True` the `openshift_logging` role will upgrade Aggregated Logging.
-When both `openshift_logging_install_logging` and `openshift_logging_upgrade_logging` are `False` the `openshift_logging` role will uninstall Aggregated Logging.
+When `openshift_logging_install_logging` is set to `False` the `openshift_logging` role will uninstall Aggregated Logging.
###Optional vars:
-
+- `openshift_logging_purge_logging`: When `openshift_logging_install_logging` is set to 'False' to trigger uninstalation and `openshift_logging_purge_logging` is set to 'True', it will completely and irreversibly remove all logging persistent data including PVC. Defaults to 'False'.
- `openshift_logging_image_prefix`: The prefix for the logging images to use. Defaults to 'docker.io/openshift/origin-'.
+- `openshift_logging_curator_image_prefix`: Setting the image prefix for Curator image. Defaults to `openshift_logging_image_prefix`.
+- `openshift_logging_elasticsearch_image_prefix`: Setting the image prefix for Elasticsearch image. Defaults to `openshift_logging_image_prefix`.
+- `openshift_logging_fluentd_image_prefix`: Setting the image prefix for Fluentd image. Defaults to `openshift_logging_image_prefix`.
+- `openshift_logging_kibana_image_prefix`: Setting the image prefix for Kibana image. Defaults to `openshift_logging_image_prefix`.
+- `openshift_logging_kibana_proxy_image_prefix`: Setting the image prefix for Kibana proxy image. Defaults to `openshift_logging_image_prefix`.
+- `openshift_logging_mux_image_prefix`: Setting the image prefix for Mux image. Defaults to `openshift_logging_image_prefix`.
- `openshift_logging_image_version`: The image version for the logging images to use. Defaults to 'latest'.
+- `openshift_logging_curator_image_version`: Setting the image version for Curator image. Defaults to `openshift_logging_image_version`.
+- `openshift_logging_elasticsearch_image_version`: Setting the image version for Elasticsearch image. Defaults to `openshift_logging_image_version`.
+- `openshift_logging_fluentd_image_version`: Setting the image version for Fluentd image. Defaults to `openshift_logging_image_version`.
+- `openshift_logging_kibana_image_version`: Setting the image version for Kibana image. Defaults to `openshift_logging_image_version`.
+- `openshift_logging_kibana_proxy_image_version`: Setting the image version for Kibana proxy image. Defaults to `openshift_logging_image_version`.
+- `openshift_logging_mux_image_version`: Setting the image version for Mux image. Defaults to `openshift_logging_image_version`.
- `openshift_logging_use_ops`: If 'True', set up a second ES and Kibana cluster for infrastructure logs. Defaults to 'False'.
- `openshift_logging_master_url`: The URL for the Kubernetes master, this does not need to be public facing but should be accessible from within the cluster. Defaults to 'https://kubernetes.default.svc.{{openshift.common.dns_domain}}'.
- `openshift_logging_master_public_url`: The public facing URL for the Kubernetes master, this is used for Authentication redirection. Defaults to 'https://{{openshift.common.public_hostname}}:{{openshift.master.api_port}}'.
diff --git a/roles/openshift_logging/defaults/main.yml b/roles/openshift_logging/defaults/main.yml
index 8b0f4cb62..716f0e002 100644
--- a/roles/openshift_logging/defaults/main.yml
+++ b/roles/openshift_logging/defaults/main.yml
@@ -8,6 +8,7 @@ openshift_logging_labels: {}
openshift_logging_label_key: ""
openshift_logging_label_value: ""
openshift_logging_install_logging: True
+openshift_logging_purge_logging: False
openshift_logging_image_pull_secret: "{{ openshift_hosted_logging_image_pull_secret | default('') }}"
openshift_logging_curator_default_days: 30
@@ -84,7 +85,7 @@ openshift_logging_es_ca: /etc/fluent/keys/ca
openshift_logging_es_client_cert: /etc/fluent/keys/cert
openshift_logging_es_client_key: /etc/fluent/keys/key
openshift_logging_es_cluster_size: "{{ openshift_hosted_logging_elasticsearch_cluster_size | default(1) }}"
-openshift_logging_es_cpu_limit: null
+openshift_logging_es_cpu_limit: 1000m
# the logging appenders for the root loggers to write ES logs. Valid values: 'file', 'console'
openshift_logging_es_log_appenders: ['file']
openshift_logging_es_memory_limit: "{{ openshift_hosted_logging_elasticsearch_instance_ram | default('8Gi') }}"
@@ -125,7 +126,7 @@ openshift_logging_es_ops_ca: /etc/fluent/keys/ca
openshift_logging_es_ops_client_cert: /etc/fluent/keys/cert
openshift_logging_es_ops_client_key: /etc/fluent/keys/key
openshift_logging_es_ops_cluster_size: "{{ openshift_hosted_logging_elasticsearch_ops_cluster_size | default(1) }}"
-openshift_logging_es_ops_cpu_limit: null
+openshift_logging_es_ops_cpu_limit: 1000m
openshift_logging_es_ops_memory_limit: "{{ openshift_hosted_logging_elasticsearch_ops_instance_ram | default('8Gi') }}"
openshift_logging_es_ops_pv_selector: "{{ openshift_hosted_loggingops_storage_labels | default('') }}"
openshift_logging_es_ops_pvc_dynamic: "{{ openshift_hosted_logging_elasticsearch_ops_pvc_dynamic | default(False) }}"
diff --git a/roles/openshift_logging/tasks/annotate_ops_projects.yaml b/roles/openshift_logging/tasks/annotate_ops_projects.yaml
new file mode 100644
index 000000000..fcb4c94d3
--- /dev/null
+++ b/roles/openshift_logging/tasks/annotate_ops_projects.yaml
@@ -0,0 +1,17 @@
+---
+- oc_obj:
+ state: list
+ kind: project
+ name: "{{ item }}"
+ with_items: "{{ __default_logging_ops_projects }}"
+ register: __logging_ops_projects
+
+- name: Annotate Operations Projects
+ oc_edit:
+ kind: ns
+ name: "{{ item.item }}"
+ separator: '#'
+ content:
+ metadata#annotations#openshift.io/logging.ui.hostname: "{{ openshift_logging_kibana_ops_hostname }}"
+ with_items: "{{ __logging_ops_projects.results }}"
+ when: item.results.stderr is not defined
diff --git a/roles/openshift_logging/tasks/delete_logging.yaml b/roles/openshift_logging/tasks/delete_logging.yaml
index 6d023a02d..45298e345 100644
--- a/roles/openshift_logging/tasks/delete_logging.yaml
+++ b/roles/openshift_logging/tasks/delete_logging.yaml
@@ -14,6 +14,16 @@
- templates
- ds
+# return all persistent volume claims as well if purge is set
+- name: delete logging pvc objects
+ oc_obj:
+ state: absent
+ kind: pvc
+ namespace: "{{ openshift_logging_namespace }}"
+ selector: "logging-infra"
+ when:
+ - openshift_logging_purge_logging | default(false) | bool
+
# delete the oauthclient
- name: delete oauthclient kibana-proxy
oc_obj:
diff --git a/roles/openshift_logging/tasks/install_logging.yaml b/roles/openshift_logging/tasks/install_logging.yaml
index 464e8594f..de5e25061 100644
--- a/roles/openshift_logging/tasks/install_logging.yaml
+++ b/roles/openshift_logging/tasks/install_logging.yaml
@@ -132,6 +132,9 @@
openshift_logging_elasticsearch_pvc_size: "{{ openshift_logging_es_ops_pvc_size }}"
openshift_logging_elasticsearch_pvc_dynamic: "{{ openshift_logging_es_ops_pvc_dynamic }}"
openshift_logging_elasticsearch_pvc_pv_selector: "{{ openshift_logging_es_ops_pv_selector }}"
+ openshift_logging_elasticsearch_memory_limit: "{{ openshift_logging_es_ops_memory_limit }}"
+ openshift_logging_elasticsearch_cpu_limit: "{{ openshift_logging_es_ops_cpu_limit }}"
+ openshift_logging_elasticsearch_nodeselector: "{{ openshift_logging_es_ops_nodeselector }}"
openshift_logging_es_key: "{{ openshift_logging_es_ops_key }}"
openshift_logging_es_cert: "{{ openshift_logging_es_ops_cert }}"
openshift_logging_es_ca_ext: "{{ openshift_logging_es_ops_ca_ext }}"
@@ -161,6 +164,9 @@
openshift_logging_elasticsearch_pvc_size: "{{ openshift_logging_es_ops_pvc_size }}"
openshift_logging_elasticsearch_pvc_dynamic: "{{ openshift_logging_es_ops_pvc_dynamic }}"
openshift_logging_elasticsearch_pvc_pv_selector: "{{ openshift_logging_es_ops_pv_selector }}"
+ openshift_logging_elasticsearch_memory_limit: "{{ openshift_logging_es_ops_memory_limit }}"
+ openshift_logging_elasticsearch_cpu_limit: "{{ openshift_logging_es_ops_cpu_limit }}"
+ openshift_logging_elasticsearch_nodeselector: "{{ openshift_logging_es_ops_nodeselector }}"
openshift_logging_es_key: "{{ openshift_logging_es_ops_key }}"
openshift_logging_es_cert: "{{ openshift_logging_es_ops_cert }}"
openshift_logging_es_ca_ext: "{{ openshift_logging_es_ops_ca_ext }}"
@@ -181,8 +187,6 @@
openshift_logging_kibana_namespace: "{{ openshift_logging_namespace }}"
openshift_logging_kibana_master_url: "{{ openshift_logging_master_url }}"
openshift_logging_kibana_master_public_url: "{{ openshift_logging_master_public_url }}"
- openshift_logging_kibana_image_prefix: "{{ openshift_logging_image_prefix }}"
- openshift_logging_kibana_image_version: "{{ openshift_logging_image_version }}"
openshift_logging_kibana_replicas: "{{ openshift_logging_kibana_replica_count }}"
openshift_logging_kibana_es_host: "{{ openshift_logging_es_host }}"
openshift_logging_kibana_es_port: "{{ openshift_logging_es_port }}"
@@ -197,8 +201,6 @@
openshift_logging_kibana_namespace: "{{ openshift_logging_namespace }}"
openshift_logging_kibana_master_url: "{{ openshift_logging_master_url }}"
openshift_logging_kibana_master_public_url: "{{ openshift_logging_master_public_url }}"
- openshift_logging_kibana_image_prefix: "{{ openshift_logging_image_prefix }}"
- openshift_logging_kibana_image_version: "{{ openshift_logging_image_version }}"
openshift_logging_kibana_image_pull_secret: "{{ openshift_logging_image_pull_secret }}"
openshift_logging_kibana_es_host: "{{ openshift_logging_es_ops_host }}"
openshift_logging_kibana_es_port: "{{ openshift_logging_es_ops_port }}"
@@ -216,6 +218,7 @@
when:
- openshift_logging_use_ops | bool
+- include: annotate_ops_projects.yaml
## Curator
- include_role:
@@ -226,8 +229,6 @@
openshift_logging_curator_es_host: "{{ openshift_logging_es_host }}"
openshift_logging_curator_es_port: "{{ openshift_logging_es_port }}"
openshift_logging_curator_master_url: "{{ openshift_logging_master_url }}"
- openshift_logging_curator_image_prefix: "{{ openshift_logging_image_prefix }}"
- openshift_logging_curator_image_version: "{{ openshift_logging_image_version }}"
openshift_logging_curator_image_pull_secret: "{{ openshift_logging_image_pull_secret }}"
- include_role:
@@ -239,8 +240,6 @@
openshift_logging_curator_es_port: "{{ openshift_logging_es_ops_port }}"
openshift_logging_curator_namespace: "{{ openshift_logging_namespace }}"
openshift_logging_curator_master_url: "{{ openshift_logging_master_url }}"
- openshift_logging_curator_image_prefix: "{{ openshift_logging_image_prefix }}"
- openshift_logging_curator_image_version: "{{ openshift_logging_image_version }}"
openshift_logging_curator_image_pull_secret: "{{ openshift_logging_image_pull_secret }}"
openshift_logging_curator_cpu_limit: "{{ openshift_logging_curator_ops_cpu_limit }}"
openshift_logging_curator_memory_limit: "{{ openshift_logging_curator_ops_memory_limit }}"
@@ -256,8 +255,6 @@
openshift_logging_mux_ops_host: "{{ ( openshift_logging_use_ops | bool ) | ternary('logging-es-ops', 'logging-es') }}"
openshift_logging_mux_namespace: "{{ openshift_logging_namespace }}"
openshift_logging_mux_master_url: "{{ openshift_logging_master_url }}"
- openshift_logging_mux_image_prefix: "{{ openshift_logging_image_prefix }}"
- openshift_logging_mux_image_version: "{{ openshift_logging_image_version }}"
openshift_logging_mux_image_pull_secret: "{{ openshift_logging_image_pull_secret }}"
when:
- openshift_logging_use_mux | bool
@@ -269,8 +266,6 @@
vars:
generated_certs_dir: "{{openshift.common.config_base}}/logging"
openshift_logging_fluentd_ops_host: "{{ ( openshift_logging_use_ops | bool ) | ternary('logging-es-ops', 'logging-es') }}"
- openshift_logging_fluentd_image_prefix: "{{ openshift_logging_image_prefix }}"
- openshift_logging_fluentd_image_version: "{{ openshift_logging_image_version }}"
openshift_logging_fluentd_image_pull_secret: "{{ openshift_logging_image_pull_secret }}"
openshift_logging_fluentd_master_url: "{{ openshift_logging_master_url }}"
openshift_logging_fluentd_namespace: "{{ openshift_logging_namespace }}"
diff --git a/roles/openshift_logging/vars/main.yaml b/roles/openshift_logging/vars/main.yaml
index e561b41e2..01809fddf 100644
--- a/roles/openshift_logging/vars/main.yaml
+++ b/roles/openshift_logging/vars/main.yaml
@@ -6,3 +6,5 @@ es_ops_node_quorum: "{{ (openshift_logging_es_ops_cluster_size | int/2 | round(0
es_ops_recover_expected_nodes: "{{openshift_logging_es_ops_cluster_size | int}}"
es_log_appenders: ['file', 'console']
+
+__default_logging_ops_projects: ['default', 'openshift', 'openshift-infra', 'kube-system']
diff --git a/roles/openshift_logging_curator/defaults/main.yml b/roles/openshift_logging_curator/defaults/main.yml
index 82ffb2f93..17807b644 100644
--- a/roles/openshift_logging_curator/defaults/main.yml
+++ b/roles/openshift_logging_curator/defaults/main.yml
@@ -1,7 +1,7 @@
---
### General logging settings
-openshift_logging_curator_image_prefix: "{{ openshift_hosted_logging_deployer_prefix | default('docker.io/openshift/origin-') }}"
-openshift_logging_curator_image_version: "{{ openshift_hosted_logging_deployer_version | default('latest') }}"
+openshift_logging_curator_image_prefix: "{{ openshift_logging_image_prefix | default(__openshift_logging_image_prefix) }}"
+openshift_logging_curator_image_version: "{{ openshift_logging_image_version | default('latest') }}"
openshift_logging_curator_image_pull_secret: "{{ openshift_hosted_logging_image_pull_secret | default('') }}"
openshift_logging_curator_master_url: "https://kubernetes.default.svc.cluster.local"
diff --git a/roles/openshift_logging_curator/tasks/main.yaml b/roles/openshift_logging_curator/tasks/main.yaml
index 3113fb3c9..6e8fab2b5 100644
--- a/roles/openshift_logging_curator/tasks/main.yaml
+++ b/roles/openshift_logging_curator/tasks/main.yaml
@@ -86,7 +86,7 @@
component: "{{ curator_component }}"
logging_component: curator
deploy_name: "{{ curator_name }}"
- image: "{{openshift_logging_image_prefix}}logging-curator:{{openshift_logging_image_version}}"
+ image: "{{openshift_logging_curator_image_prefix}}logging-curator:{{openshift_logging_curator_image_version}}"
es_host: "{{ openshift_logging_curator_es_host }}"
es_port: "{{ openshift_logging_curator_es_port }}"
curator_cpu_limit: "{{ openshift_logging_curator_cpu_limit }}"
diff --git a/roles/openshift_logging_curator/templates/curator.j2 b/roles/openshift_logging_curator/templates/curator.j2
index 6431f86d9..e74918a40 100644
--- a/roles/openshift_logging_curator/templates/curator.j2
+++ b/roles/openshift_logging_curator/templates/curator.j2
@@ -44,6 +44,8 @@ spec:
cpu: "{{curator_cpu_limit}}"
{% if curator_memory_limit is defined and curator_memory_limit is not none and curator_memory_limit != "" %}
memory: "{{curator_memory_limit}}"
+ requests:
+ memory: "{{curator_memory_limit}}"
{% endif %}
env:
-
diff --git a/roles/openshift_logging_curator/vars/main.yml b/roles/openshift_logging_curator/vars/main.yml
index 97525479e..95bf462d1 100644
--- a/roles/openshift_logging_curator/vars/main.yml
+++ b/roles/openshift_logging_curator/vars/main.yml
@@ -1,3 +1,3 @@
---
-__latest_curator_version: "3_5"
-__allowed_curator_versions: ["3_5", "3_6"]
+__latest_curator_version: "3_6"
+__allowed_curator_versions: ["3_5", "3_6", "3_7"]
diff --git a/roles/openshift_logging_elasticsearch/defaults/main.yml b/roles/openshift_logging_elasticsearch/defaults/main.yml
index 0690bf114..75bd479be 100644
--- a/roles/openshift_logging_elasticsearch/defaults/main.yml
+++ b/roles/openshift_logging_elasticsearch/defaults/main.yml
@@ -1,7 +1,7 @@
---
### Common settings
-openshift_logging_elasticsearch_image_prefix: "{{ openshift_hosted_logging_deployer_prefix | default('docker.io/openshift/origin-') }}"
-openshift_logging_elasticsearch_image_version: "{{ openshift_hosted_logging_deployer_version | default('latest') }}"
+openshift_logging_elasticsearch_image_prefix: "{{ openshift_logging_image_prefix | default(__openshift_logging_image_prefix) }}"
+openshift_logging_elasticsearch_image_version: "{{ openshift_logging_image_version | default('latest') }}"
openshift_logging_elasticsearch_image_pull_secret: "{{ openshift_hosted_logging_image_pull_secret | default('') }}"
openshift_logging_elasticsearch_namespace: logging
diff --git a/roles/openshift_logging_elasticsearch/tasks/main.yaml b/roles/openshift_logging_elasticsearch/tasks/main.yaml
index 28c3ffd96..1e800b1d6 100644
--- a/roles/openshift_logging_elasticsearch/tasks/main.yaml
+++ b/roles/openshift_logging_elasticsearch/tasks/main.yaml
@@ -229,7 +229,7 @@
dest: "{{ tempdir }}/templates/logging-es-pvc.yml"
vars:
obj_name: "{{ openshift_logging_elasticsearch_pvc_name }}"
- size: "{{ openshift_logging_elasticsearch_pvc_size }}"
+ size: "{{ (openshift_logging_elasticsearch_pvc_size | trim | length == 0) | ternary('10Gi', openshift_logging_elasticsearch_pvc_size) }}"
access_modes: "{{ openshift_logging_elasticsearch_pvc_access_modes | list }}"
pv_selector: "{{ openshift_logging_elasticsearch_pvc_pv_selector }}"
storage_class_name: "{{ openshift_logging_elasticsearch_pvc_storage_class_name | default('', true) }}"
@@ -243,7 +243,7 @@
dest: "{{ tempdir }}/templates/logging-es-pvc.yml"
vars:
obj_name: "{{ openshift_logging_elasticsearch_pvc_name }}"
- size: "{{ openshift_logging_elasticsearch_pvc_size }}"
+ size: "{{ (openshift_logging_elasticsearch_pvc_size | trim | length == 0) | ternary('10Gi', openshift_logging_elasticsearch_pvc_size) }}"
access_modes: "{{ openshift_logging_elasticsearch_pvc_access_modes | list }}"
pv_selector: "{{ openshift_logging_elasticsearch_pvc_pv_selector }}"
when:
@@ -277,7 +277,7 @@
component: "{{ es_component }}"
logging_component: elasticsearch
deploy_name: "{{ es_deploy_name }}"
- image: "{{ openshift_logging_image_prefix }}logging-elasticsearch:{{ openshift_logging_image_version }}"
+ image: "{{ openshift_logging_elasticsearch_image_prefix }}logging-elasticsearch:{{ openshift_logging_elasticsearch_image_version }}"
es_cpu_limit: "{{ openshift_logging_elasticsearch_cpu_limit }}"
es_memory_limit: "{{ openshift_logging_elasticsearch_memory_limit }}"
es_node_selector: "{{ openshift_logging_elasticsearch_nodeselector | default({}) }}"
diff --git a/roles/openshift_logging_elasticsearch/templates/elasticsearch.yml.j2 b/roles/openshift_logging_elasticsearch/templates/elasticsearch.yml.j2
index 0c06a7677..65b08d970 100644
--- a/roles/openshift_logging_elasticsearch/templates/elasticsearch.yml.j2
+++ b/roles/openshift_logging_elasticsearch/templates/elasticsearch.yml.j2
@@ -24,7 +24,8 @@ network:
cloud:
kubernetes:
- service: ${SERVICE_DNS}
+ pod_label: ${POD_LABEL}
+ pod_port: 9300
namespace: ${NAMESPACE}
discovery:
diff --git a/roles/openshift_logging_elasticsearch/templates/es.j2 b/roles/openshift_logging_elasticsearch/templates/es.j2
index cbe6b89f2..3c8f390c4 100644
--- a/roles/openshift_logging_elasticsearch/templates/es.j2
+++ b/roles/openshift_logging_elasticsearch/templates/es.j2
@@ -48,7 +48,7 @@ spec:
cpu: "{{es_cpu_limit}}"
{% endif %}
requests:
- memory: "512Mi"
+ memory: "{{es_memory_limit}}"
ports:
-
containerPort: 9200
@@ -90,6 +90,12 @@ spec:
name: "RECOVER_AFTER_TIME"
value: "{{openshift_logging_elasticsearch_recover_after_time}}"
-
+ name: "READINESS_PROBE_TIMEOUT"
+ value: "30"
+ -
+ name: "POD_LABEL"
+ value: "component={{component}}"
+ -
name: "IS_MASTER"
value: "{% if deploy_type in ['data-master', 'master'] %}true{% else %}false{% endif %}"
@@ -106,6 +112,13 @@ spec:
readOnly: true
- name: elasticsearch-storage
mountPath: /elasticsearch/persistent
+ readinessProbe:
+ exec:
+ command:
+ - "/usr/share/java/elasticsearch/probe/readiness.sh"
+ initialDelaySeconds: 10
+ timeoutSeconds: 30
+ periodSeconds: 5
volumes:
- name: elasticsearch
secret:
diff --git a/roles/openshift_logging_elasticsearch/vars/main.yml b/roles/openshift_logging_elasticsearch/vars/main.yml
index 20fa63543..09e2ee4d0 100644
--- a/roles/openshift_logging_elasticsearch/vars/main.yml
+++ b/roles/openshift_logging_elasticsearch/vars/main.yml
@@ -1,6 +1,6 @@
---
-__latest_es_version: "3_5"
-__allowed_es_versions: ["3_5", "3_6"]
+__latest_es_version: "3_6"
+__allowed_es_versions: ["3_5", "3_6", "3_7"]
__allowed_es_types: ["data-master", "data-client", "master", "client"]
__es_log_appenders: ['file', 'console']
__kibana_index_modes: ["unique", "shared_ops"]
diff --git a/roles/openshift_logging_fluentd/defaults/main.yml b/roles/openshift_logging_fluentd/defaults/main.yml
index a53bbd2df..30d3d854a 100644
--- a/roles/openshift_logging_fluentd/defaults/main.yml
+++ b/roles/openshift_logging_fluentd/defaults/main.yml
@@ -1,7 +1,7 @@
---
### General logging settings
-openshift_logging_fluentd_image_prefix: "{{ openshift_hosted_logging_deployer_prefix | default('docker.io/openshift/origin-') }}"
-openshift_logging_fluentd_image_version: "{{ openshift_hosted_logging_deployer_version | default('latest') }}"
+openshift_logging_fluentd_image_prefix: "{{ openshift_logging_image_prefix | default(__openshift_logging_image_prefix) }}"
+openshift_logging_fluentd_image_version: "{{ openshift_logging_image_version | default('latest') }}"
openshift_logging_fluentd_image_pull_secret: "{{ openshift_hosted_logging_image_pull_secret | default('') }}"
openshift_logging_fluentd_master_url: "https://kubernetes.default.svc.{{ openshift.common.dns_domain }}"
openshift_logging_fluentd_namespace: logging
diff --git a/roles/openshift_logging_fluentd/templates/fluentd.j2 b/roles/openshift_logging_fluentd/templates/fluentd.j2
index 39dffba19..a4afb6618 100644
--- a/roles/openshift_logging_fluentd/templates/fluentd.j2
+++ b/roles/openshift_logging_fluentd/templates/fluentd.j2
@@ -28,7 +28,7 @@ spec:
{{ fluentd_nodeselector_key }}: "{{ fluentd_nodeselector_value }}"
containers:
- name: "{{ daemonset_container_name }}"
- image: "{{ openshift_logging_image_prefix }}{{ daemonset_name }}:{{ openshift_logging_image_version }}"
+ image: "{{ openshift_logging_fluentd_image_prefix }}{{ daemonset_name }}:{{ openshift_logging_fluentd_image_version }}"
imagePullPolicy: Always
securityContext:
privileged: true
@@ -36,6 +36,8 @@ spec:
limits:
cpu: {{ openshift_logging_fluentd_cpu_limit }}
memory: {{ openshift_logging_fluentd_memory_limit }}
+ requests:
+ memory: {{ openshift_logging_fluentd_memory_limit }}
volumeMounts:
- name: runlogjournal
mountPath: /run/log/journal
diff --git a/roles/openshift_logging_fluentd/vars/main.yml b/roles/openshift_logging_fluentd/vars/main.yml
index ec8e565c3..92a426952 100644
--- a/roles/openshift_logging_fluentd/vars/main.yml
+++ b/roles/openshift_logging_fluentd/vars/main.yml
@@ -1,5 +1,5 @@
---
-__latest_fluentd_version: "3_5"
-__allowed_fluentd_versions: ["3_5", "3_6"]
+__latest_fluentd_version: "3_6"
+__allowed_fluentd_versions: ["3_5", "3_6", "3_7"]
__allowed_fluentd_types: ["hosted", "secure-aggregator", "secure-host"]
__allowed_mux_client_modes: ["minimal", "maximal"]
diff --git a/roles/openshift_logging_kibana/defaults/main.yml b/roles/openshift_logging_kibana/defaults/main.yml
index b2556fd71..ee265bb14 100644
--- a/roles/openshift_logging_kibana/defaults/main.yml
+++ b/roles/openshift_logging_kibana/defaults/main.yml
@@ -2,8 +2,8 @@
### Common settings
openshift_logging_kibana_master_url: "https://kubernetes.default.svc.cluster.local"
openshift_logging_kibana_master_public_url: "https://kubernetes.default.svc.cluster.local"
-openshift_logging_kibana_image_prefix: "{{ openshift_hosted_logging_deployer_prefix | default('docker.io/openshift/origin-') }}"
-openshift_logging_kibana_image_version: "{{ openshift_hosted_logging_deployer_version | default('latest') }}"
+openshift_logging_kibana_image_prefix: "{{ openshift_logging_image_prefix | default(__openshift_logging_image_prefix) }}"
+openshift_logging_kibana_image_version: "{{ openshift_logging_image_version | default('latest') }}"
openshift_logging_kibana_image_pull_secret: "{{ openshift_hosted_logging_image_pull_secret | default('') }}"
openshift_logging_kibana_namespace: logging
@@ -24,9 +24,11 @@ openshift_logging_kibana_edge_term_policy: Redirect
openshift_logging_kibana_ops_deployment: false
# Proxy settings
+openshift_logging_kibana_proxy_image_prefix: "{{ openshift_logging_image_prefix | default(__openshift_logging_image_prefix) }}"
+openshift_logging_kibana_proxy_image_version: "{{ openshift_logging_image_version | default('latest') }}"
openshift_logging_kibana_proxy_debug: false
openshift_logging_kibana_proxy_cpu_limit: null
-openshift_logging_kibana_proxy_memory_limit: 96Mi
+openshift_logging_kibana_proxy_memory_limit: 256Mi
#The absolute path on the control node to the cert file to use
#for the public facing kibana certs
diff --git a/roles/openshift_logging_kibana/tasks/main.yaml b/roles/openshift_logging_kibana/tasks/main.yaml
index 166f102f7..e17e8c1f2 100644
--- a/roles/openshift_logging_kibana/tasks/main.yaml
+++ b/roles/openshift_logging_kibana/tasks/main.yaml
@@ -225,8 +225,8 @@
component: "{{ kibana_component }}"
logging_component: kibana
deploy_name: "{{ kibana_name }}"
- image: "{{ openshift_logging_image_prefix }}logging-kibana:{{ openshift_logging_image_version }}"
- proxy_image: "{{ openshift_logging_image_prefix }}logging-auth-proxy:{{ openshift_logging_image_version }}"
+ image: "{{ openshift_logging_kibana_image_prefix }}logging-kibana:{{ openshift_logging_kibana_image_version }}"
+ proxy_image: "{{ openshift_logging_kibana_proxy_image_prefix }}logging-auth-proxy:{{ openshift_logging_kibana_proxy_image_version }}"
es_host: "{{ openshift_logging_kibana_es_host }}"
es_port: "{{ openshift_logging_kibana_es_port }}"
kibana_cpu_limit: "{{ openshift_logging_kibana_cpu_limit }}"
diff --git a/roles/openshift_logging_kibana/templates/kibana.j2 b/roles/openshift_logging_kibana/templates/kibana.j2
index 512d99d06..da1386d3e 100644
--- a/roles/openshift_logging_kibana/templates/kibana.j2
+++ b/roles/openshift_logging_kibana/templates/kibana.j2
@@ -46,6 +46,8 @@ spec:
{% endif %}
{% if kibana_memory_limit is not none and kibana_memory_limit != "" %}
memory: "{{ kibana_memory_limit }}"
+ requests:
+ memory: "{{ kibana_memory_limit }}"
{% endif %}
{% endif %}
env:
@@ -82,6 +84,8 @@ spec:
{% endif %}
{% if kibana_proxy_memory_limit is not none and kibana_proxy_memory_limit != "" %}
memory: "{{ kibana_proxy_memory_limit }}"
+ requests:
+ memory: "{{ kibana_proxy_memory_limit }}"
{% endif %}
{% endif %}
ports:
diff --git a/roles/openshift_logging_kibana/vars/main.yml b/roles/openshift_logging_kibana/vars/main.yml
index 87b281c4b..241877a02 100644
--- a/roles/openshift_logging_kibana/vars/main.yml
+++ b/roles/openshift_logging_kibana/vars/main.yml
@@ -1,3 +1,3 @@
---
-__latest_kibana_version: "3_5"
-__allowed_kibana_versions: ["3_5", "3_6"]
+__latest_kibana_version: "3_6"
+__allowed_kibana_versions: ["3_5", "3_6", "3_7"]
diff --git a/roles/openshift_logging_mux/defaults/main.yml b/roles/openshift_logging_mux/defaults/main.yml
index 7a3da9b4c..68412aec8 100644
--- a/roles/openshift_logging_mux/defaults/main.yml
+++ b/roles/openshift_logging_mux/defaults/main.yml
@@ -1,7 +1,7 @@
---
### General logging settings
-openshift_logging_mux_image_prefix: "{{ openshift_hosted_logging_deployer_prefix | default('docker.io/openshift/origin-') }}"
-openshift_logging_mux_image_version: "{{ openshift_hosted_logging_deployer_version | default('latest') }}"
+openshift_logging_mux_image_prefix: "{{ openshift_logging_image_prefix | default(__openshift_logging_image_prefix) }}"
+openshift_logging_mux_image_version: "{{ openshift_logging_image_version | default('latest') }}"
openshift_logging_mux_image_pull_secret: "{{ openshift_hosted_logging_image_pull_secret | default('') }}"
openshift_logging_mux_master_url: "https://kubernetes.default.svc.{{ openshift.common.dns_domain }}"
openshift_logging_mux_master_public_url: "{{ openshift_hosted_logging_master_public_url | default('https://' + openshift.common.public_hostname + ':' ~ (openshift_master_api_port | default('8443', true))) }}"
diff --git a/roles/openshift_logging_mux/tasks/main.yaml b/roles/openshift_logging_mux/tasks/main.yaml
index 8ec93de7d..2ec863afa 100644
--- a/roles/openshift_logging_mux/tasks/main.yaml
+++ b/roles/openshift_logging_mux/tasks/main.yaml
@@ -165,7 +165,7 @@
component: mux
logging_component: mux
deploy_name: "logging-{{ component }}"
- image: "{{ openshift_logging_image_prefix }}logging-fluentd:{{ openshift_logging_image_version }}"
+ image: "{{ openshift_logging_mux_image_prefix }}logging-fluentd:{{ openshift_logging_mux_image_version }}"
es_host: "{{ openshift_logging_mux_app_host }}"
es_port: "{{ openshift_logging_mux_app_port }}"
ops_host: "{{ openshift_logging_mux_ops_host }}"
diff --git a/roles/openshift_logging_mux/templates/mux.j2 b/roles/openshift_logging_mux/templates/mux.j2
index 70afe5cee..ff18d3270 100644
--- a/roles/openshift_logging_mux/templates/mux.j2
+++ b/roles/openshift_logging_mux/templates/mux.j2
@@ -45,6 +45,8 @@ spec:
{% endif %}
{% if mux_memory_limit is not none %}
memory: "{{mux_memory_limit}}"
+ requests:
+ memory: "{{mux_memory_limit}}"
{% endif %}
{% endif %}
ports:
diff --git a/roles/openshift_logging_mux/vars/main.yml b/roles/openshift_logging_mux/vars/main.yml
index 4234b74e2..e7b57f4b5 100644
--- a/roles/openshift_logging_mux/vars/main.yml
+++ b/roles/openshift_logging_mux/vars/main.yml
@@ -1,3 +1,3 @@
---
-__latest_mux_version: "3_5"
-__allowed_mux_versions: ["3_5", "3_6"]
+__latest_mux_version: "3_6"
+__allowed_mux_versions: ["3_5", "3_6", "3_7"]
diff --git a/roles/openshift_manageiq/vars/main.yml b/roles/openshift_manageiq/vars/main.yml
index 7ccc2fc3b..f142f89f0 100644
--- a/roles/openshift_manageiq/vars/main.yml
+++ b/roles/openshift_manageiq/vars/main.yml
@@ -3,6 +3,9 @@ manage_iq_tasks:
- resource_kind: role
resource_name: admin
user: management-admin
+- resource_kind: role
+ resource_name: admin
+ user: system:serviceaccount:management-infra:management-admin
- resource_kind: cluster-role
resource_name: management-infra-admin
user: system:serviceaccount:management-infra:management-admin
diff --git a/roles/openshift_master/README.md b/roles/openshift_master/README.md
index fbf69c270..86fa57b50 100644
--- a/roles/openshift_master/README.md
+++ b/roles/openshift_master/README.md
@@ -17,7 +17,6 @@ From this role:
| Name | Default value | |
|---------------------------------------------------|-----------------------|-------------------------------------------------------------------------------|
-| openshift_master_debug_level | openshift_debug_level | Verbosity of the debug logs for master |
| openshift_node_ips | [] | List of the openshift node ip addresses to pre-register when master starts up |
| oreg_url | UNDEF | Default docker registry to use |
| oreg_url_master | UNDEF | Default docker registry to use, specifically on the master |
@@ -29,18 +28,10 @@ From this role:
| openshift_master_public_console_url | UNDEF | |
| openshift_master_saconfig_limit_secret_references | false | |
-From openshift_common:
-
-| Name | Default Value | |
-|-------------------------------|----------------|----------------------------------------|
-| openshift_debug_level | 2 | Global openshift debug log verbosity |
-| openshift_public_ip | UNDEF | Public IP address to use for this host |
-| openshift_hostname | UNDEF | hostname to use for this instance |
Dependencies
------------
-openshift_common
Example Playbook
----------------
diff --git a/roles/openshift_master/defaults/main.yml b/roles/openshift_master/defaults/main.yml
index a4c178908..4c8d6fdad 100644
--- a/roles/openshift_master/defaults/main.yml
+++ b/roles/openshift_master/defaults/main.yml
@@ -1,6 +1,6 @@
---
-r_openshift_master_firewall_enabled: True
-r_openshift_master_use_firewalld: False
+r_openshift_master_firewall_enabled: "{{ os_firewall_enabled | default(True) }}"
+r_openshift_master_use_firewalld: "{{ os_firewall_use_firewalld | default(False) }}"
openshift_node_ips: []
r_openshift_master_clean_install: false
@@ -19,3 +19,27 @@ r_openshift_master_os_firewall_allow:
- service: etcd embedded
port: 4001/tcp
cond: "{{ groups.oo_etcd_to_config | default([]) | length == 0 }}"
+
+oreg_url: ''
+oreg_host: "{{ oreg_url.split('/')[0] if '.' in oreg_url.split('/')[0] else '' }}"
+oreg_auth_credentials_path: "{{ r_openshift_master_data_dir }}/.docker"
+oreg_auth_credentials_replace: False
+l_bind_docker_reg_auth: False
+
+# NOTE
+# r_openshift_master_*_default may be defined external to this role.
+# openshift_use_*, if defined, may affect other roles or play behavior.
+r_openshift_master_use_openshift_sdn_default: "{{ openshift_use_openshift_sdn | default(True) }}"
+r_openshift_master_use_openshift_sdn: "{{ r_openshift_master_use_openshift_sdn_default }}"
+
+r_openshift_master_use_nuage_default: "{{ openshift_use_nuage | default(False) }}"
+r_openshift_master_use_nuage: "{{ r_openshift_master_use_nuage_default }}"
+
+r_openshift_master_use_contiv_default: "{{ openshift_use_contiv | default(False) }}"
+r_openshift_master_use_contiv: "{{ r_openshift_master_use_contiv_default }}"
+
+r_openshift_master_data_dir_default: "{{ openshift_data_dir | default('/var/lib/origin') }}"
+r_openshift_master_data_dir: "{{ r_openshift_master_data_dir_default }}"
+
+r_openshift_master_sdn_network_plugin_name_default: "{{ os_sdn_network_plugin_name | default('redhat/openshift-ovs-subnet') }}"
+r_openshift_master_sdn_network_plugin_name: "{{ r_openshift_master_sdn_network_plugin_name_default }}"
diff --git a/roles/openshift_master/meta/main.yml b/roles/openshift_master/meta/main.yml
index bd2383f61..a657668a9 100644
--- a/roles/openshift_master/meta/main.yml
+++ b/roles/openshift_master/meta/main.yml
@@ -14,19 +14,3 @@ galaxy_info:
dependencies:
- role: lib_openshift
- role: lib_os_firewall
-- role: openshift_master_facts
-- role: openshift_hosted_facts
-- role: openshift_master_certificates
-- role: openshift_etcd_client_certificates
- etcd_cert_subdir: "openshift-master-{{ openshift.common.hostname }}"
- etcd_cert_config_dir: "{{ openshift.common.config_base }}/master"
- etcd_cert_prefix: "master.etcd-"
- when: groups.oo_etcd_to_config | default([]) | length != 0
-- role: openshift_clock
-- role: openshift_cloud_provider
-- role: openshift_builddefaults
-- role: openshift_buildoverrides
-- role: nickhammond.logrotate
-- role: contiv
- contiv_role: netmaster
- when: openshift.common.use_contiv | bool
diff --git a/roles/openshift_master/tasks/bootstrap.yml b/roles/openshift_master/tasks/bootstrap.yml
new file mode 100644
index 000000000..0013f5289
--- /dev/null
+++ b/roles/openshift_master/tasks/bootstrap.yml
@@ -0,0 +1,28 @@
+---
+
+- name: ensure the node-bootstrap service account exists
+ oc_serviceaccount:
+ name: node-bootstrapper
+ namespace: openshift-infra
+ state: present
+ run_once: true
+
+- name: grant node-bootstrapper the correct permissions to bootstrap
+ oc_adm_policy_user:
+ namespace: openshift-infra
+ user: system:serviceaccount:openshift-infra:node-bootstrapper
+ resource_kind: cluster-role
+ resource_name: system:node-bootstrapper
+ state: present
+ run_once: true
+
+# TODO: create a module for this command.
+# oc_serviceaccounts_kubeconfig
+- name: create service account kubeconfig with csr rights
+ command: "oc serviceaccounts create-kubeconfig node-bootstrapper -n openshift-infra"
+ register: kubeconfig_out
+
+- name: put service account kubeconfig into a file on disk for bootstrap
+ copy:
+ content: "{{ kubeconfig_out.stdout }}"
+ dest: "{{ openshift_master_config_dir }}/bootstrap.kubeconfig"
diff --git a/roles/openshift_master/tasks/main.yml b/roles/openshift_master/tasks/main.yml
index a11471891..94b7df1fc 100644
--- a/roles/openshift_master/tasks/main.yml
+++ b/roles/openshift_master/tasks/main.yml
@@ -47,9 +47,9 @@
when:
- not openshift.common.is_containerized | bool
-- name: Create openshift.common.data_dir
+- name: Create r_openshift_master_data_dir
file:
- path: "{{ openshift.common.data_dir }}"
+ path: "{{ r_openshift_master_data_dir }}"
state: directory
mode: 0755
owner: root
@@ -169,7 +169,7 @@
register: l_already_set
- set_fact:
- openshift_push_via_dns: "{{ (openshift_use_dnsmasq | default(true) and openshift.common.version_gte_3_6) or (l_already_set.stdout is defined and l_already_set.stdout | match('OPENSHIFT_DEFAULT_REGISTRY=docker-registry.default.svc:5000')) }}"
+ openshift_push_via_dns: "{{ openshift.common.version_gte_3_6 or (l_already_set.stdout is defined and l_already_set.stdout | match('OPENSHIFT_DEFAULT_REGISTRY=docker-registry.default.svc:5000')) }}"
- name: Set fact of all etcd host IPs
openshift_facts:
@@ -177,12 +177,33 @@
local_facts:
no_proxy_etcd_host_ips: "{{ openshift_no_proxy_etcd_host_ips }}"
-- name: Remove the legacy master service if it exists
- include: clean_systemd_units.yml
+- include: registry_auth.yml
- name: Install the systemd units
include: systemd_units.yml
+- name: Checking for journald.conf
+ stat: path=/etc/systemd/journald.conf
+ register: journald_conf_file
+
+- name: Update journald setup
+ replace:
+ dest: /etc/systemd/journald.conf
+ regexp: '^(\#| )?{{ item.var }}=\s*.*?$'
+ replace: ' {{ item.var }}={{ item.val }}'
+ backup: yes
+ with_items: "{{ journald_vars_to_replace | default([]) }}"
+ when: journald_conf_file.stat.exists
+ register: journald_update
+
+# I need to restart journald immediatelly, otherwise it gets into way during
+# further steps in ansible
+- name: Restart journald
+ systemd:
+ name: systemd-journald
+ state: restarted
+ when: journald_update | changed
+
- name: Install Master system container
include: system_container.yml
when:
@@ -203,7 +224,7 @@
- restart master api
- set_fact:
- translated_identity_providers: "{{ openshift.master.identity_providers | translate_idps('v1', openshift.common.version, openshift.common.deployment_type) }}"
+ translated_identity_providers: "{{ openshift.master.identity_providers | translate_idps('v1') }}"
# TODO: add the validate parameter when there is a validation command to run
- name: Create master config
@@ -218,6 +239,20 @@
- restart master api
- restart master controllers
+- name: modify controller args
+ yedit:
+ src: /etc/origin/master/master-config.yaml
+ edits:
+ - key: kubernetesMasterConfig.controllerArguments.cluster-signing-cert-file
+ value:
+ - /etc/origin/master/ca.crt
+ - key: kubernetesMasterConfig.controllerArguments.cluster-signing-key-file
+ value:
+ - /etc/origin/master/ca.key
+ notify:
+ - restart master controllers
+ when: openshift_master_bootstrap_enabled | default(False)
+
- include: set_loopback_context.yml
when:
- openshift.common.version_gte_3_2_or_1_2
@@ -366,3 +401,7 @@
shell: echo {{ openshift_master_cluster_password | quote }} | passwd --stdin hacluster
when:
- l_install_result | changed
+
+- name: node bootstrap settings
+ include: bootstrap.yml
+ when: openshift_master_bootstrap_enabled | default(False)
diff --git a/roles/openshift_master/tasks/registry_auth.yml b/roles/openshift_master/tasks/registry_auth.yml
new file mode 100644
index 000000000..96b6c614e
--- /dev/null
+++ b/roles/openshift_master/tasks/registry_auth.yml
@@ -0,0 +1,27 @@
+---
+- name: Check for credentials file for registry auth
+ stat:
+ path: "{{ oreg_auth_credentials_path }}"
+ when: oreg_auth_user is defined
+ register: master_oreg_auth_credentials_stat
+
+# Container images may need the registry credentials
+- name: Setup ro mount of /root/.docker for containerized hosts
+ set_fact:
+ l_bind_docker_reg_auth: True
+ when:
+ - openshift.common.is_containerized | bool
+ - oreg_auth_user is defined
+ - (not master_oreg_auth_credentials_stat.stat.exists or oreg_auth_credentials_replace) | bool
+ notify:
+ - restart master api
+ - restart master controllers
+
+- name: Create credentials for registry auth
+ command: "docker --config={{ oreg_auth_credentials_path }} login -u {{ oreg_auth_user }} -p {{ oreg_auth_password }} {{ oreg_host }}"
+ when:
+ - oreg_auth_user is defined
+ - (not master_oreg_auth_credentials_stat.stat.exists or oreg_auth_credentials_replace) | bool
+ notify:
+ - restart master api
+ - restart master controllers
diff --git a/roles/openshift_master/tasks/systemd_units.yml b/roles/openshift_master/tasks/systemd_units.yml
index 72c231e52..7a918c57e 100644
--- a/roles/openshift_master/tasks/systemd_units.yml
+++ b/roles/openshift_master/tasks/systemd_units.yml
@@ -3,6 +3,23 @@
# playbooks. For that reason the ha_svc variables are use set_fact instead of
# the vars directory on the role.
+# This play may be consumed outside the role, we need to ensure that
+# openshift_master_config_dir is set.
+- name: Set openshift_master_config_dir if unset
+ set_fact:
+ openshift_master_config_dir: '/etc/origin/master'
+ when: openshift_master_config_dir is not defined
+
+# This play may be consumed outside the role, we need to ensure that
+# r_openshift_master_data_dir is set.
+- name: Set r_openshift_master_data_dir if unset
+ set_fact:
+ r_openshift_master_data_dir: "{{ openshift_data_dir | default('/var/lib/origin') }}"
+ when: r_openshift_master_data_dir is not defined
+
+- name: Remove the legacy master service if it exists
+ include: clean_systemd_units.yml
+
- name: Init HA Service Info
set_fact:
containerized_svc_dir: "/usr/lib/systemd/system"
diff --git a/roles/openshift_master/tasks/update_etcd_client_urls.yml b/roles/openshift_master/tasks/update_etcd_client_urls.yml
new file mode 100644
index 000000000..1ab105808
--- /dev/null
+++ b/roles/openshift_master/tasks/update_etcd_client_urls.yml
@@ -0,0 +1,8 @@
+---
+- yedit:
+ src: "{{ openshift.common.config_base }}/master/master-config.yaml"
+ key: 'etcdClientInfo.urls'
+ value: "{{ openshift.master.etcd_urls }}"
+ notify:
+ - restart master api
+ - restart master controllers
diff --git a/roles/openshift_master/templates/docker-cluster/atomic-openshift-master-api.service.j2 b/roles/openshift_master/templates/docker-cluster/atomic-openshift-master-api.service.j2
index e8f7c47b0..a184a59f6 100644
--- a/roles/openshift_master/templates/docker-cluster/atomic-openshift-master-api.service.j2
+++ b/roles/openshift_master/templates/docker-cluster/atomic-openshift-master-api.service.j2
@@ -12,12 +12,22 @@ Requires={{ openshift.docker.service_name }}.service
EnvironmentFile=/etc/sysconfig/{{ openshift.common.service_type }}-master-api
Environment=GOTRACEBACK=crash
ExecStartPre=-/usr/bin/docker rm -f {{ openshift.common.service_type}}-master-api
-ExecStart=/usr/bin/docker run --rm --privileged --net=host --name {{ openshift.common.service_type }}-master-api --env-file=/etc/sysconfig/{{ openshift.common.service_type }}-master-api -v {{ openshift.common.data_dir }}:{{ openshift.common.data_dir }} -v /var/log:/var/log -v /var/run/docker.sock:/var/run/docker.sock -v {{ openshift.common.config_base }}:{{ openshift.common.config_base }} {% if openshift_cloudprovider_kind | default('') != '' -%} -v {{ openshift.common.config_base }}/cloudprovider:{{ openshift.common.config_base}}/cloudprovider {% endif -%} -v /etc/pki:/etc/pki:ro {{ openshift.master.master_image }}:${IMAGE_VERSION} start master api --config=${CONFIG_FILE} $OPTIONS
+ExecStart=/usr/bin/docker run --rm --privileged --net=host \
+ --name {{ openshift.common.service_type }}-master-api \
+ --env-file=/etc/sysconfig/{{ openshift.common.service_type }}-master-api \
+ -v {{ r_openshift_master_data_dir }}:{{ r_openshift_master_data_dir }} \
+ -v /var/log:/var/log -v /var/run/docker.sock:/var/run/docker.sock \
+ -v {{ openshift.common.config_base }}:{{ openshift.common.config_base }} \
+ {% if openshift_cloudprovider_kind | default('') != '' -%} -v {{ openshift.common.config_base }}/cloudprovider:{{ openshift.common.config_base}}/cloudprovider {% endif -%} \
+ -v /etc/pki:/etc/pki:ro \
+ {% if l_bind_docker_reg_auth %} -v {{ oreg_auth_credentials_path }}:/root/.docker:ro{% endif %}\
+ {{ openshift.master.master_image }}:${IMAGE_VERSION} start master api \
+ --config=${CONFIG_FILE} $OPTIONS
ExecStartPost=/usr/bin/sleep 10
ExecStop=/usr/bin/docker stop {{ openshift.common.service_type }}-master-api
LimitNOFILE=131072
LimitCORE=infinity
-WorkingDirectory={{ openshift.common.data_dir }}
+WorkingDirectory={{ r_openshift_master_data_dir }}
SyslogIdentifier={{ openshift.common.service_type }}-master-api
Restart=always
RestartSec=5s
diff --git a/roles/openshift_master/templates/docker-cluster/atomic-openshift-master-controllers.service.j2 b/roles/openshift_master/templates/docker-cluster/atomic-openshift-master-controllers.service.j2
index 69db62f16..2ded05f53 100644
--- a/roles/openshift_master/templates/docker-cluster/atomic-openshift-master-controllers.service.j2
+++ b/roles/openshift_master/templates/docker-cluster/atomic-openshift-master-controllers.service.j2
@@ -11,12 +11,22 @@ PartOf={{ openshift.docker.service_name }}.service
EnvironmentFile=/etc/sysconfig/{{ openshift.common.service_type }}-master-controllers
Environment=GOTRACEBACK=crash
ExecStartPre=-/usr/bin/docker rm -f {{ openshift.common.service_type}}-master-controllers
-ExecStart=/usr/bin/docker run --rm --privileged --net=host --name {{ openshift.common.service_type }}-master-controllers --env-file=/etc/sysconfig/{{ openshift.common.service_type }}-master-controllers -v {{ openshift.common.data_dir }}:{{ openshift.common.data_dir }} -v /var/run/docker.sock:/var/run/docker.sock -v {{ openshift.common.config_base }}:{{ openshift.common.config_base }} {% if openshift_cloudprovider_kind | default('') != '' -%} -v {{ openshift.common.config_base }}/cloudprovider:{{ openshift.common.config_base}}/cloudprovider {% endif -%} -v /etc/pki:/etc/pki:ro {{ openshift.master.master_image }}:${IMAGE_VERSION} start master controllers --config=${CONFIG_FILE} $OPTIONS
+ExecStart=/usr/bin/docker run --rm --privileged --net=host \
+ --name {{ openshift.common.service_type }}-master-controllers \
+ --env-file=/etc/sysconfig/{{ openshift.common.service_type }}-master-controllers \
+ -v {{ r_openshift_master_data_dir }}:{{ r_openshift_master_data_dir }} \
+ -v /var/run/docker.sock:/var/run/docker.sock \
+ -v {{ openshift.common.config_base }}:{{ openshift.common.config_base }} \
+ {% if openshift_cloudprovider_kind | default('') != '' -%} -v {{ openshift.common.config_base }}/cloudprovider:{{ openshift.common.config_base}}/cloudprovider {% endif -%} \
+ -v /etc/pki:/etc/pki:ro \
+ {% if l_bind_docker_reg_auth %} -v {{ oreg_auth_credentials_path }}:/root/.docker:ro{% endif %}\
+ {{ openshift.master.master_image }}:${IMAGE_VERSION} start master controllers \
+ --config=${CONFIG_FILE} $OPTIONS
ExecStartPost=/usr/bin/sleep 10
ExecStop=/usr/bin/docker stop {{ openshift.common.service_type }}-master-controllers
LimitNOFILE=131072
LimitCORE=infinity
-WorkingDirectory={{ openshift.common.data_dir }}
+WorkingDirectory={{ r_openshift_master_data_dir }}
SyslogIdentifier={{ openshift.common.service_type }}-master-controllers
Restart=always
RestartSec=5s
diff --git a/roles/openshift_master/templates/master.yaml.v1.j2 b/roles/openshift_master/templates/master.yaml.v1.j2
index c14579435..d045b402b 100644
--- a/roles/openshift_master/templates/master.yaml.v1.j2
+++ b/roles/openshift_master/templates/master.yaml.v1.j2
@@ -106,7 +106,7 @@ etcdConfig:
clientCA: ca.crt
{% endif %}
keyFile: etcd.server.key
- storageDirectory: {{ openshift.common.data_dir }}/openshift.local.etcd
+ storageDirectory: {{ r_openshift_master_data_dir }}/openshift.local.etcd
{% endif %}
etcdStorageConfig:
kubernetesStoragePrefix: kubernetes.io
@@ -179,8 +179,8 @@ masterPublicURL: {{ openshift.master.public_api_url }}
networkConfig:
clusterNetworkCIDR: {{ openshift.master.sdn_cluster_network_cidr }}
hostSubnetLength: {{ openshift.master.sdn_host_subnet_length }}
-{% if openshift.common.use_openshift_sdn or openshift.common.use_nuage or openshift.common.use_contiv or openshift.common.sdn_network_plugin_name == 'cni' %}
- networkPluginName: {{ openshift.common.sdn_network_plugin_name }}
+{% if r_openshift_master_use_openshift_sdn or r_openshift_master_use_nuage or r_openshift_master_use_contiv or r_openshift_master_sdn_network_plugin_name == 'cni' %}
+ networkPluginName: {{ r_openshift_master_sdn_network_plugin_name_default }}
{% endif %}
# serviceNetworkCIDR must match kubernetesMasterConfig.servicesSubnet
serviceNetworkCIDR: {{ openshift.common.portal_net }}
diff --git a/roles/openshift_master/templates/native-cluster/atomic-openshift-master-api.service.j2 b/roles/openshift_master/templates/native-cluster/atomic-openshift-master-api.service.j2
index 0e78d2d23..02bfd6f62 100644
--- a/roles/openshift_master/templates/native-cluster/atomic-openshift-master-api.service.j2
+++ b/roles/openshift_master/templates/native-cluster/atomic-openshift-master-api.service.j2
@@ -13,7 +13,7 @@ Environment=GOTRACEBACK=crash
ExecStart=/usr/bin/openshift start master api --config=${CONFIG_FILE} $OPTIONS
LimitNOFILE=131072
LimitCORE=infinity
-WorkingDirectory={{ openshift.common.data_dir }}
+WorkingDirectory={{ r_openshift_master_data_dir }}
SyslogIdentifier=atomic-openshift-master-api
Restart=always
RestartSec=5s
diff --git a/roles/openshift_master/templates/native-cluster/atomic-openshift-master-controllers.service.j2 b/roles/openshift_master/templates/native-cluster/atomic-openshift-master-controllers.service.j2
index 94928f88c..e284413f7 100644
--- a/roles/openshift_master/templates/native-cluster/atomic-openshift-master-controllers.service.j2
+++ b/roles/openshift_master/templates/native-cluster/atomic-openshift-master-controllers.service.j2
@@ -17,7 +17,7 @@ Environment=GOTRACEBACK=crash
ExecStart=/usr/bin/openshift start master controllers --config=${CONFIG_FILE} $OPTIONS
LimitNOFILE=131072
LimitCORE=infinity
-WorkingDirectory={{ openshift.common.data_dir }}
+WorkingDirectory={{ r_openshift_master_data_dir }}
SyslogIdentifier={{ openshift.common.service_type }}-master-controllers
Restart=always
RestartSec=5s
diff --git a/roles/openshift_master/vars/main.yml b/roles/openshift_master/vars/main.yml
index cf39b73f6..0c681c764 100644
--- a/roles/openshift_master/vars/main.yml
+++ b/roles/openshift_master/vars/main.yml
@@ -20,3 +20,22 @@ openshift_master_valid_grant_methods:
- deny
openshift_master_is_scaleup_host: False
+
+# These defaults assume forcing journald persistence, fsync to disk once
+# a second, rate-limiting to 10,000 logs a second, no forwarding to
+# syslog or wall, using 8GB of disk space maximum, using 10MB journal
+# files, keeping only a days worth of logs per journal file, and
+# retaining journal files no longer than a month.
+journald_vars_to_replace:
+- { var: Storage, val: persistent }
+- { var: Compress, val: yes }
+- { var: SyncIntervalSec, val: 1s }
+- { var: RateLimitInterval, val: 1s }
+- { var: RateLimitBurst, val: 10000 }
+- { var: SystemMaxUse, val: 8G }
+- { var: SystemKeepFree, val: 20% }
+- { var: SystemMaxFileSize, val: 10M }
+- { var: MaxRetentionSec, val: 1month }
+- { var: MaxFileSec, val: 1day }
+- { var: ForwardToSyslog, val: no }
+- { var: ForwardToWall, val: no }
diff --git a/roles/openshift_master_facts/filter_plugins/openshift_master.py b/roles/openshift_master_facts/filter_plugins/openshift_master.py
index e767772ce..f7f3ac2b1 100644
--- a/roles/openshift_master_facts/filter_plugins/openshift_master.py
+++ b/roles/openshift_master_facts/filter_plugins/openshift_master.py
@@ -6,10 +6,6 @@ Custom filters for use in openshift-master
import copy
import sys
-# pylint import-error disabled because pylint cannot find the package
-# when installed in a virtualenv
-from distutils.version import LooseVersion # pylint: disable=no-name-in-module,import-error
-
from ansible import errors
from ansible.parsing.yaml.dumper import AnsibleDumper
from ansible.plugins.filter.core import to_bool as ansible_bool
@@ -82,23 +78,8 @@ class IdentityProviderBase(object):
self._allow_additional = True
@staticmethod
- def validate_idp_list(idp_list, openshift_version, deployment_type):
+ def validate_idp_list(idp_list):
''' validates a list of idps '''
- login_providers = [x.name for x in idp_list if x.login]
-
- multiple_logins_unsupported = False
- if len(login_providers) > 1:
- if deployment_type in ['enterprise', 'online', 'atomic-enterprise', 'openshift-enterprise']:
- if LooseVersion(openshift_version) < LooseVersion('3.2'):
- multiple_logins_unsupported = True
- if deployment_type in ['origin']:
- if LooseVersion(openshift_version) < LooseVersion('1.2'):
- multiple_logins_unsupported = True
- if multiple_logins_unsupported:
- raise errors.AnsibleFilterError("|failed multiple providers are "
- "not allowed for login. login "
- "providers: {0}".format(', '.join(login_providers)))
-
names = [x.name for x in idp_list]
if len(set(names)) != len(names):
raise errors.AnsibleFilterError("|failed more than one provider configured with the same name")
@@ -380,11 +361,6 @@ class OpenIDIdentityProvider(IdentityProviderOauthBase):
if 'extra_authorize_parameters' in self._idp:
self._idp['extraAuthorizeParameters'] = self._idp.pop('extra_authorize_parameters')
- if 'extraAuthorizeParameters' in self._idp:
- if 'include_granted_scopes' in self._idp['extraAuthorizeParameters']:
- val = ansible_bool(self._idp['extraAuthorizeParameters'].pop('include_granted_scopes'))
- self._idp['extraAuthorizeParameters']['include_granted_scopes'] = val
-
def validate(self):
''' validate this idp instance '''
IdentityProviderOauthBase.validate(self)
@@ -476,7 +452,7 @@ class FilterModule(object):
''' Custom ansible filters for use by the openshift_master role'''
@staticmethod
- def translate_idps(idps, api_version, openshift_version, deployment_type):
+ def translate_idps(idps, api_version):
''' Translates a list of dictionaries into a valid identityProviders config '''
idp_list = []
@@ -492,7 +468,7 @@ class FilterModule(object):
idp_inst.set_provider_items()
idp_list.append(idp_inst)
- IdentityProviderBase.validate_idp_list(idp_list, openshift_version, deployment_type)
+ IdentityProviderBase.validate_idp_list(idp_list)
return u(yaml.dump([idp.to_dict() for idp in idp_list],
allow_unicode=True,
default_flow_style=False,
diff --git a/roles/openshift_metrics/tasks/pre_install.yaml b/roles/openshift_metrics/tasks/pre_install.yaml
index 2e2013d40..d6756f9b9 100644
--- a/roles/openshift_metrics/tasks/pre_install.yaml
+++ b/roles/openshift_metrics/tasks/pre_install.yaml
@@ -10,7 +10,7 @@
is invalid, must be one of: emptydir, pv, dynamic
when:
- openshift_metrics_cassandra_storage_type not in openshift_metrics_cassandra_storage_types
- - "not {{ openshift_metrics_heapster_standalone | bool }}"
+ - not (openshift_metrics_heapster_standalone | bool)
- name: list existing secrets
command: >
diff --git a/roles/openshift_node/README.md b/roles/openshift_node/README.md
index fb0b494da..32670b18e 100644
--- a/roles/openshift_node/README.md
+++ b/roles/openshift_node/README.md
@@ -17,22 +17,12 @@ From this role:
| Name | Default value | |
|----------------------------|-----------------------|----------------------------------------------------------|
-| openshift_node_debug_level | openshift_debug_level | Verbosity of the debug logs for node |
| oreg_url | UNDEF (Optional) | Default docker registry to use |
| oreg_url_node | UNDEF (Optional) | Default docker registry to use, specifically on the node |
-From openshift_common:
-
-| Name | Default Value | |
-|-------------------------------|---------------------|---------------------|
-| openshift_debug_level | 2 | Global openshift debug log verbosity |
-| openshift_public_ip | UNDEF (Required) | Public IP address to use for this host |
-| openshift_hostname | UNDEF (Required) | hostname to use for this instance |
-
Dependencies
------------
-openshift_common
Example Playbook
----------------
diff --git a/roles/openshift_node/defaults/main.yml b/roles/openshift_node/defaults/main.yml
index 973b3a619..433e92201 100644
--- a/roles/openshift_node/defaults/main.yml
+++ b/roles/openshift_node/defaults/main.yml
@@ -1,8 +1,66 @@
---
-r_openshift_node_firewall_enabled: True
-r_openshift_node_use_firewalld: False
+r_openshift_node_firewall_enabled: "{{ os_firewall_enabled | default(True) }}"
+r_openshift_node_use_firewalld: "{{ os_firewall_use_firewalld | default(False) }}"
+
+openshift_service_type: "{{ openshift.common.service_type }}"
+
+openshift_image_tag: ''
+
+openshift_node_ami_prep_packages:
+- "{{ openshift_service_type }}-master"
+- "{{ openshift_service_type }}-node"
+- "{{ openshift_service_type }}-docker-excluder"
+- "{{ openshift_service_type }}-sdn-ovs"
+- ansible
+- openvswitch
+- docker
+- etcd
+#- pcs
+- haproxy
+- dnsmasq
+- ntp
+- logrotate
+- httpd-tools
+- bind
+- firewalld
+- libselinux-python
+- conntrack-tools
+- openssl
+- cloud-init
+- iproute
+- python-dbus
+- PyYAML
+- yum-utils
+- python2-boto
+- python2-boto3
+- cloud-utils-growpart
+# gluster
+- glusterfs-fuse
+- heketi-client
+# nfs
+- nfs-utils
+- flannel
+- bash-completion
+# cockpit
+- cockpit-ws
+- cockpit-system
+- cockpit-bridge
+- cockpit-docker
+# iscsi
+- iscsi-initiator-utils
+# ceph
+- ceph-common
+# systemcontainer
+# - runc
+# - container-selinux
+# - atomic
+#
+openshift_deployment_type: origin
+
+openshift_node_bootstrap: False
+
r_openshift_node_os_firewall_deny: []
-r_openshift_node_os_firewall_allow:
+default_r_openshift_node_os_firewall_allow:
- service: Kubernetes kubelet
port: 10250/tcp
- service: http
@@ -11,13 +69,42 @@ r_openshift_node_os_firewall_allow:
port: 443/tcp
- service: OpenShift OVS sdn
port: 4789/udp
- cond: openshift.common.use_openshift_sdn | default(true) | bool
+ cond: openshift_use_openshift_sdn | bool
- service: Calico BGP Port
port: 179/tcp
- cond: "{{ openshift.common.use_calico | bool }}"
+ cond: "{{ openshift_node_use_calico }}"
- service: Kubernetes service NodePort TCP
port: "{{ openshift_node_port_range | default('') }}/tcp"
cond: "{{ openshift_node_port_range is defined }}"
- service: Kubernetes service NodePort UDP
port: "{{ openshift_node_port_range | default('') }}/udp"
cond: "{{ openshift_node_port_range is defined }}"
+# Allow multiple port ranges to be added to the role
+r_openshift_node_os_firewall_allow: "{{ default_r_openshift_node_os_firewall_allow | union(openshift_node_open_ports | default([])) }}"
+
+oreg_url: ''
+oreg_host: "{{ oreg_url.split('/')[0] if '.' in oreg_url.split('/')[0] else '' }}"
+oreg_auth_credentials_path: "{{ openshift_node_data_dir }}/.docker"
+oreg_auth_credentials_replace: False
+l_bind_docker_reg_auth: False
+
+# NOTE
+# r_openshift_node_*_default may be defined external to this role.
+# openshift_use_*, if defined, may affect other roles or play behavior.
+openshift_node_use_openshift_sdn_default: "{{ openshift_use_openshift_sdn | default(True) }}"
+openshift_node_use_openshift_sdn: "{{ openshift_node_use_openshift_sdn_default }}"
+
+openshift_node_sdn_network_plugin_name_default: "{{ os_sdn_network_plugin_name | default('redhat/openshift-ovs-subnet') }}"
+openshift_node_sdn_network_plugin_name: "{{ openshift_node_sdn_network_plugin_name_default }}"
+
+openshift_node_use_calico_default: "{{ openshift_use_calico | default(False) }}"
+openshift_node_use_calico: "{{ openshift_node_use_calico_default }}"
+
+openshift_node_use_nuage_default: "{{ openshift_use_nuage | default(False) }}"
+openshift_node_use_nuage: "{{ openshift_node_use_nuage_default }}"
+
+openshift_node_use_contiv_default: "{{ openshift_use_contiv | default(False) }}"
+openshift_node_use_contiv: "{{ openshift_node_use_contiv_default }}"
+
+openshift_node_data_dir_default: "{{ openshift_data_dir | default('/var/lib/origin') }}"
+openshift_node_data_dir: "{{ openshift_node_data_dir_default }}"
diff --git a/roles/openshift_node/handlers/main.yml b/roles/openshift_node/handlers/main.yml
index f2c45a4bd..25a6fc721 100644
--- a/roles/openshift_node/handlers/main.yml
+++ b/roles/openshift_node/handlers/main.yml
@@ -3,7 +3,7 @@
systemd:
name: openvswitch
state: restarted
- when: (not skip_node_svc_handlers | default(False) | bool) and not (ovs_service_status_changed | default(false) | bool) and openshift.common.use_openshift_sdn | default(true) | bool
+ when: (not skip_node_svc_handlers | default(False) | bool) and not (ovs_service_status_changed | default(false) | bool) and openshift_node_use_openshift_sdn | bool
register: l_openshift_node_stop_openvswitch_result
until: not l_openshift_node_stop_openvswitch_result | failed
retries: 3
@@ -27,9 +27,7 @@
when:
- (not skip_node_svc_handlers | default(False) | bool)
- not (node_service_status_changed | default(false) | bool)
-
-- name: reload sysctl.conf
- command: /sbin/sysctl -p
+ - not openshift_node_bootstrap
- name: reload systemd units
command: systemctl daemon-reload
diff --git a/roles/openshift_node/meta/main.yml b/roles/openshift_node/meta/main.yml
index 06373de04..ce5ecb9d0 100644
--- a/roles/openshift_node/meta/main.yml
+++ b/roles/openshift_node/meta/main.yml
@@ -15,10 +15,9 @@ dependencies:
- role: openshift_node_facts
- role: lib_openshift
- role: lib_os_firewall
-- role: openshift_common
- role: openshift_clock
- role: openshift_docker
- role: openshift_node_certificates
+ when: not openshift_node_bootstrap
- role: openshift_cloud_provider
- role: openshift_node_dnsmasq
- when: openshift.common.use_dnsmasq | bool
diff --git a/roles/openshift_node/tasks/bootstrap.yml b/roles/openshift_node/tasks/bootstrap.yml
new file mode 100644
index 000000000..b83b2c452
--- /dev/null
+++ b/roles/openshift_node/tasks/bootstrap.yml
@@ -0,0 +1,66 @@
+---
+- name: install needed rpm(s)
+ package:
+ name: "{{ item }}"
+ state: present
+ with_items: "{{ openshift_node_ami_prep_packages }}"
+
+- name: create the directory for node
+ file:
+ state: directory
+ path: "/etc/systemd/system/{{ openshift_service_type }}-node.service.d"
+
+- name: laydown systemd override
+ copy:
+ dest: "/etc/systemd/system/{{ openshift_service_type }}-node.service.d/override.conf"
+ content: |
+ [Unit]
+ After=cloud-init.service
+
+- name: update the sysconfig to have KUBECONFIG
+ lineinfile:
+ dest: "/etc/sysconfig/{{ openshift_service_type }}-node"
+ line: "KUBECONFIG=/root/csr_kubeconfig"
+ regexp: "^KUBECONFIG=.*"
+
+- name: update the ExecStart to have bootstrap
+ lineinfile:
+ dest: "/usr/lib/systemd/system/{{ openshift_service_type }}-node.service"
+ line: "{% raw %}ExecStart=/usr/bin/openshift start node --bootstrap --kubeconfig=${KUBECONFIG} $OPTIONS{% endraw %}"
+ regexp: "^ExecStart=.*"
+
+- name: "systemctl enable {{ openshift_service_type }}-node"
+ systemd:
+ name: "{{ item }}"
+ enabled: no
+ with_items:
+ - "{{ openshift_service_type }}-node.service"
+ - "{{ openshift_service_type }}-master.service"
+
+- name: Check for RPM generated config marker file .config_managed
+ stat:
+ path: /etc/origin/.config_managed
+ register: rpmgenerated_config
+
+- when: rpmgenerated_config.stat.exists
+ block:
+ - name: Remove RPM generated config files if present
+ file:
+ path: "/etc/origin/{{ item }}"
+ state: absent
+ with_items:
+ - master
+
+ # with_fileglob doesn't work correctly due to a few issues.
+ # Could change this to fileglob when it gets fixed.
+ - name: find all files in /etc/origin/node so we can remove them
+ find:
+ path: /etc/origin/node/
+ register: find_results
+
+ - name: Remove everything except the resolv.conf required for node
+ file:
+ path: "{{ item.path }}"
+ state: absent
+ when: "'resolv.conf' not in item.path or 'node-dnsmasq.conf' not in item.path"
+ with_items: "{{ find_results.files }}"
diff --git a/roles/openshift_node/tasks/config.yml b/roles/openshift_node/tasks/config.yml
new file mode 100644
index 000000000..2759188f3
--- /dev/null
+++ b/roles/openshift_node/tasks/config.yml
@@ -0,0 +1,103 @@
+---
+- name: Install the systemd units
+ include: systemd_units.yml
+
+- name: Start and enable openvswitch service
+ systemd:
+ name: openvswitch.service
+ enabled: yes
+ state: started
+ daemon_reload: yes
+ when:
+ - openshift.common.is_containerized | bool
+ - openshift_node_use_openshift_sdn | default(true) | bool
+ register: ovs_start_result
+ until: not ovs_start_result | failed
+ retries: 3
+ delay: 30
+
+- set_fact:
+ ovs_service_status_changed: "{{ ovs_start_result | changed }}"
+
+- file:
+ dest: "{{ (openshift_node_kubelet_args|default({'config':None})).config}}"
+ state: directory
+ when: openshift_node_kubelet_args is defined and 'config' in openshift_node_kubelet_args
+
+# TODO: add the validate parameter when there is a validation command to run
+- name: Create the Node config
+ template:
+ dest: "{{ openshift.common.config_base }}/node/node-config.yaml"
+ src: node.yaml.v1.j2
+ backup: true
+ owner: root
+ group: root
+ mode: 0600
+ notify:
+ - restart node
+
+- name: Configure Node Environment Variables
+ lineinfile:
+ dest: /etc/sysconfig/{{ openshift.common.service_type }}-node
+ regexp: "^{{ item.key }}="
+ line: "{{ item.key }}={{ item.value }}"
+ create: true
+ with_dict: "{{ openshift.node.env_vars | default({}) }}"
+ notify:
+ - restart node
+
+# Necessary because when you're on a node that's also a master the master will be
+# restarted after the node restarts docker and it will take up to 60 seconds for
+# systemd to start the master again
+- when: openshift.common.is_containerized | bool
+ block:
+ - name: Wait for master API to become available before proceeding
+ # Using curl here since the uri module requires python-httplib2 and
+ # wait_for port doesn't provide health information.
+ command: >
+ curl --silent --tlsv1.2 --cacert {{ openshift.common.config_base }}/node/ca.crt
+ {{ openshift_node_master_api_url }}/healthz/ready
+ args:
+ # Disables the following warning:
+ # Consider using get_url or uri module rather than running curl
+ warn: no
+ register: api_available_output
+ until: api_available_output.stdout == 'ok'
+ retries: 120
+ delay: 1
+ changed_when: false
+
+ - name: Start and enable node dep
+ systemd:
+ daemon_reload: yes
+ name: "{{ openshift.common.service_type }}-node-dep"
+ enabled: yes
+ state: started
+
+- name: Start and enable node
+ systemd:
+ name: "{{ openshift.common.service_type }}-node"
+ enabled: yes
+ state: started
+ daemon_reload: yes
+ register: node_start_result
+ until: not node_start_result | failed
+ retries: 1
+ delay: 30
+ ignore_errors: true
+
+- name: Dump logs from node service if it failed
+ command: journalctl --no-pager -n 100 -u {{ openshift.common.service_type }}-node
+ when: node_start_result | failed
+
+- name: Abort if node failed to start
+ fail:
+ msg: Node failed to start please inspect the logs and try again
+ when: node_start_result | failed
+
+- name: Setup tuned
+ include: tuned.yml
+ static: yes
+
+- set_fact:
+ node_service_status_changed: "{{ node_start_result | changed }}"
diff --git a/roles/openshift_node/tasks/install.yml b/roles/openshift_node/tasks/install.yml
new file mode 100644
index 000000000..265bf2c46
--- /dev/null
+++ b/roles/openshift_node/tasks/install.yml
@@ -0,0 +1,31 @@
+---
+- when: not openshift.common.is_containerized | bool
+ block:
+ - name: Install Node package
+ package:
+ name: "{{ openshift.common.service_type }}-node{{ openshift_pkg_version | default('') | oo_image_tag_to_rpm_version(include_dash=True) }}"
+ state: present
+
+ - name: Install sdn-ovs package
+ package:
+ name: "{{ openshift.common.service_type }}-sdn-ovs{{ openshift_pkg_version | oo_image_tag_to_rpm_version(include_dash=True) }}"
+ state: present
+ when:
+ - openshift_node_use_openshift_sdn | bool
+
+ - name: Install conntrack-tools package
+ package:
+ name: "conntrack-tools"
+ state: present
+
+- when:
+ - openshift.common.is_containerized | bool
+ - not openshift.common.is_node_system_container | bool
+ block:
+ - name: Pre-pull node image when containerized
+ command: >
+ docker pull {{ openshift.node.node_image }}:{{ openshift_image_tag }}
+ register: pull_result
+ changed_when: "'Downloaded newer image' in pull_result.stdout"
+
+ - include: config/install-node-docker-service-file.yml
diff --git a/roles/openshift_node/tasks/main.yml b/roles/openshift_node/tasks/main.yml
index 3353a22e3..e82fb42b8 100644
--- a/roles/openshift_node/tasks/main.yml
+++ b/roles/openshift_node/tasks/main.yml
@@ -1,43 +1,16 @@
---
-# TODO: allow for overriding default ports where possible
- fail:
msg: "SELinux is disabled, This deployment type requires that SELinux is enabled."
when:
- - (not ansible_selinux or ansible_selinux.status != 'enabled') and deployment_type in ['enterprise', 'online', 'atomic-enterprise', 'openshift-enterprise']
- - not openshift_docker_use_crio | default(false)
+ - (not ansible_selinux or ansible_selinux.status != 'enabled')
+ - deployment_type == 'openshift-enterprise'
+ - not openshift_use_crio | default(false)
- name: setup firewall
include: firewall.yml
static: yes
-- name: Set node facts
- openshift_facts:
- role: "{{ item.role }}"
- local_facts: "{{ item.local_facts }}"
- with_items:
- # Reset node labels to an empty dictionary.
- - role: node
- local_facts:
- labels: {}
- - role: node
- local_facts:
- annotations: "{{ openshift_node_annotations | default(none) }}"
- debug_level: "{{ openshift_node_debug_level | default(openshift.common.debug_level) }}"
- iptables_sync_period: "{{ openshift_node_iptables_sync_period | default(None) }}"
- kubelet_args: "{{ openshift_node_kubelet_args | default(None) }}"
- labels: "{{ lookup('oo_option', 'openshift_node_labels') | default( openshift_node_labels | default(none), true) }}"
- registry_url: "{{ oreg_url_node | default(oreg_url) | default(None) }}"
- schedulable: "{{ openshift_schedulable | default(openshift_scheduleable) | default(None) }}"
- sdn_mtu: "{{ openshift_node_sdn_mtu | default(None) }}"
- storage_plugin_deps: "{{ osn_storage_plugin_deps | default(None) }}"
- set_node_ip: "{{ openshift_set_node_ip | default(None) }}"
- node_image: "{{ osn_image | default(None) }}"
- ovs_image: "{{ osn_ovs_image | default(None) }}"
- proxy_mode: "{{ openshift_node_proxy_mode | default('iptables') }}"
- local_quota_per_fsgroup: "{{ openshift_node_local_quota_per_fsgroup | default(None) }}"
- dns_ip: "{{ openshift_dns_ip | default(none) | get_dns_ip(hostvars[inventory_hostname])}}"
- env_vars: "{{ openshift_node_env_vars | default(None) }}"
-
+#### Disable SWAP #####
# https://docs.openshift.com/container-platform/3.4/admin_guide/overcommit.html#disabling-swap-memory
- name: Check for swap usage
command: grep "^[^#].*swap" /etc/fstab
@@ -46,9 +19,10 @@
failed_when: false
register: swap_result
-# Disable Swap Block
-- block:
-
+- when:
+ - swap_result.stdout_lines | length > 0
+ - openshift_disable_swap | default(true) | bool
+ block:
- name: Disable swap
command: swapoff --all
@@ -64,101 +38,43 @@
dest: /etc/fstab
line: '# OpenShift-Ansible Installer disabled swap per overcommit guidelines'
state: present
+#### End Disable Swap Block ####
- when:
- - swap_result.stdout_lines | length > 0
- - openshift_disable_swap | default(true) | bool
-# End Disable Swap Block
-
-# We have to add tuned-profiles in the same transaction otherwise we run into depsolving
-# problems because the rpms don't pin the version properly. This was fixed in 3.1 packaging.
-- name: Install Node package
- package:
- name: "{{ openshift.common.service_type }}-node{{ openshift_pkg_version | default('') | oo_image_tag_to_rpm_version(include_dash=True) }},tuned-profiles-{{ openshift.common.service_type }}-node{{ openshift_pkg_version | default('') | oo_image_tag_to_rpm_version(include_dash=True) }}"
- state: present
- when: not openshift.common.is_containerized | bool
-
-- name: Check for tuned package
- command: rpm -q tuned
- args:
- warn: no
- register: tuned_installed
- changed_when: false
- failed_when: false
-
-- name: Set atomic-guest tuned profile
- command: "tuned-adm profile atomic-guest"
- when: tuned_installed.rc == 0 and openshift.common.is_atomic | bool
-
-- name: Install sdn-ovs package
- package:
- name: "{{ openshift.common.service_type }}-sdn-ovs{{ openshift_pkg_version | oo_image_tag_to_rpm_version(include_dash=True) }}"
- state: present
- when:
- - openshift.common.use_openshift_sdn | default(true) | bool
- - not openshift.common.is_containerized | bool
+- name: include node installer
+ include: install.yml
- name: Restart cri-o
systemd:
name: cri-o
enabled: yes
state: restarted
- when: openshift_docker_use_crio | default(false)
-
-- name: Install conntrack-tools package
- package:
- name: "conntrack-tools"
- state: present
- when: not openshift.common.is_containerized | bool
+ when: openshift_use_crio | default(false)
-- name: Install the systemd units
- include: systemd_units.yml
+- name: restart NetworkManager to ensure resolv.conf is present
+ systemd:
+ name: NetworkManager
+ enabled: yes
+ state: restarted
+ when: openshift_node_bootstrap | bool
# The atomic-openshift-node service will set this parameter on
# startup, but if the network service is restarted this setting is
# lost. Reference: https://bugzilla.redhat.com/show_bug.cgi?id=1372388
-#
-# Use lineinfile w/ a handler for this task until
-# https://github.com/ansible/ansible/pull/24277 is included in an
-# ansible release and we can use the sysctl module.
-- name: Persist net.ipv4.ip_forward sysctl entry
- lineinfile: dest=/etc/sysctl.conf regexp='^net.ipv4.ip_forward' line='net.ipv4.ip_forward=1'
- notify:
- - reload sysctl.conf
-
-- name: Start and enable openvswitch service
- systemd:
- name: openvswitch.service
- enabled: yes
- state: started
- daemon_reload: yes
- when:
- - openshift.common.is_containerized | bool
- - openshift.common.use_openshift_sdn | default(true) | bool
- register: ovs_start_result
- until: not ovs_start_result | failed
- retries: 3
- delay: 30
+- sysctl:
+ name: net.ipv4.ip_forward
+ value: 1
+ sysctl_file: "/etc/sysctl.d/99-openshift.conf"
+ reload: yes
-- set_fact:
- ovs_service_status_changed: "{{ ovs_start_result | changed }}"
+- name: include bootstrap node config
+ include: bootstrap.yml
+ when: openshift_node_bootstrap
-- file:
- dest: "{{ (openshift_node_kubelet_args|default({'config':None})).config}}"
- state: directory
- when: openshift_node_kubelet_args is defined and 'config' in openshift_node_kubelet_args
+- include: registry_auth.yml
-# TODO: add the validate parameter when there is a validation command to run
-- name: Create the Node config
- template:
- dest: "{{ openshift.common.config_base }}/node/node-config.yaml"
- src: node.yaml.v1.j2
- backup: true
- owner: root
- group: root
- mode: 0600
- notify:
- - restart node
+- name: include standard node config
+ include: config.yml
+ when: not openshift_node_bootstrap
- name: Configure AWS Cloud Provider Settings
lineinfile:
@@ -176,16 +92,7 @@
notify:
- restart node
-- name: Configure Node Environment Variables
- lineinfile:
- dest: /etc/sysconfig/{{ openshift.common.service_type }}-node
- regexp: "^{{ item.key }}="
- line: "{{ item.key }}={{ item.value }}"
- create: true
- with_dict: "{{ openshift.node.env_vars | default({}) }}"
- notify:
- - restart node
-
+#### Storage class plugins here ####
- name: NFS storage plugin configuration
include: storage_plugins/nfs.yml
tags:
@@ -203,55 +110,7 @@
include: storage_plugins/iscsi.yml
when: "'iscsi' in openshift.node.storage_plugin_deps"
-# Necessary because when you're on a node that's also a master the master will be
-# restarted after the node restarts docker and it will take up to 60 seconds for
-# systemd to start the master again
-- name: Wait for master API to become available before proceeding
- # Using curl here since the uri module requires python-httplib2 and
- # wait_for port doesn't provide health information.
- command: >
- curl --silent --tlsv1.2 --cacert {{ openshift.common.config_base }}/node/ca.crt
- {{ openshift_node_master_api_url }}/healthz/ready
- args:
- # Disables the following warning:
- # Consider using get_url or uri module rather than running curl
- warn: no
- register: api_available_output
- until: api_available_output.stdout == 'ok'
- retries: 120
- delay: 1
- changed_when: false
- when: openshift.common.is_containerized | bool
-
-- name: Start and enable node dep
- systemd:
- daemon_reload: yes
- name: "{{ openshift.common.service_type }}-node-dep"
- enabled: yes
- state: started
- when: openshift.common.is_containerized | bool
-
-
-- name: Start and enable node
- systemd:
- name: "{{ openshift.common.service_type }}-node"
- enabled: yes
- state: started
- daemon_reload: yes
- register: node_start_result
- until: not node_start_result | failed
- retries: 1
- delay: 30
- ignore_errors: true
-
-- name: Dump logs from node service if it failed
- command: journalctl --no-pager -n 100 -u {{ openshift.common.service_type }}-node
- when: node_start_result | failed
-
-- name: Abort if node failed to start
- fail:
- msg: Node failed to start please inspect the logs and try again
- when: node_start_result | failed
+##### END Storage #####
-- set_fact:
- node_service_status_changed: "{{ node_start_result | changed }}"
+- include: config/workaround-bz1331590-ovs-oom-fix.yml
+ when: openshift_node_use_openshift_sdn | default(true) | bool
diff --git a/roles/openshift_node/tasks/openvswitch_system_container.yml b/roles/openshift_node/tasks/openvswitch_system_container.yml
index dc1df9185..e09063aa5 100644
--- a/roles/openshift_node/tasks/openvswitch_system_container.yml
+++ b/roles/openshift_node/tasks/openvswitch_system_container.yml
@@ -1,6 +1,6 @@
---
- set_fact:
- l_use_crio: "{{ openshift_docker_use_crio | default(false) }}"
+ l_use_crio: "{{ openshift_use_crio | default(false) }}"
- set_fact:
l_service_name: "cri-o"
diff --git a/roles/openshift_node/tasks/registry_auth.yml b/roles/openshift_node/tasks/registry_auth.yml
new file mode 100644
index 000000000..f370bb260
--- /dev/null
+++ b/roles/openshift_node/tasks/registry_auth.yml
@@ -0,0 +1,25 @@
+---
+- name: Check for credentials file for registry auth
+ stat:
+ path: "{{ oreg_auth_credentials_path }}"
+ when: oreg_auth_user is defined
+ register: node_oreg_auth_credentials_stat
+
+# Container images may need the registry credentials
+- name: Setup ro mount of /root/.docker for containerized hosts
+ set_fact:
+ l_bind_docker_reg_auth: True
+ when:
+ - openshift.common.is_containerized | bool
+ - oreg_auth_user is defined
+ - (not node_oreg_auth_credentials_stat.stat.exists or oreg_auth_credentials_replace) | bool
+ notify:
+ - restart node
+
+- name: Create credentials for registry auth
+ command: "docker --config={{ oreg_auth_credentials_path }} login -u {{ oreg_auth_user }} -p {{ oreg_auth_password }} {{ oreg_host }}"
+ when:
+ - oreg_auth_user is defined
+ - (not node_oreg_auth_credentials_stat.stat.exists or oreg_auth_credentials_replace) | bool
+ notify:
+ - restart node
diff --git a/roles/openshift_node/tasks/systemd_units.yml b/roles/openshift_node/tasks/systemd_units.yml
index b86bb1549..6b4490f61 100644
--- a/roles/openshift_node/tasks/systemd_units.yml
+++ b/roles/openshift_node/tasks/systemd_units.yml
@@ -1,22 +1,6 @@
---
# This file is included both in the openshift_master role and in the upgrade
# playbooks.
-
-- include: config/install-node-deps-docker-service-file.yml
- when: openshift.common.is_containerized | bool
-
-- block:
- - name: Pre-pull node image
- command: >
- docker pull {{ openshift.node.node_image }}:{{ openshift_image_tag }}
- register: pull_result
- changed_when: "'Downloaded newer image' in pull_result.stdout"
-
- - include: config/install-node-docker-service-file.yml
- when:
- - openshift.common.is_containerized | bool
- - not openshift.common.is_node_system_container | bool
-
- name: Install Node service file
template:
dest: "/etc/systemd/system/{{ openshift.common.service_type }}-node.service"
@@ -26,24 +10,24 @@
- reload systemd units
- restart node
-- include: config/install-ovs-service-env-file.yml
- when: openshift.common.is_containerized | bool
+- when: openshift.common.is_containerized | bool
+ block:
+ - name: include node deps docker service file
+ include: config/install-node-deps-docker-service-file.yml
-- name: Install Node system container
- include: node_system_container.yml
- when:
- - openshift.common.is_containerized | bool
- - openshift.common.is_node_system_container | bool
+ - name: include ovs service environment file
+ include: config/install-ovs-service-env-file.yml
-- name: Install OpenvSwitch system containers
- include: openvswitch_system_container.yml
- when:
- - openshift.common.use_openshift_sdn | default(true) | bool
- - openshift.common.is_containerized | bool
- - openshift.common.is_openvswitch_system_container | bool
+ - name: Install Node system container
+ include: node_system_container.yml
+ when:
+ - openshift.common.is_node_system_container | bool
-- include: config/workaround-bz1331590-ovs-oom-fix.yml
- when: openshift.common.use_openshift_sdn | default(true) | bool
+ - name: Install OpenvSwitch system containers
+ include: openvswitch_system_container.yml
+ when:
+ - openshift_node_use_openshift_sdn | bool
+ - openshift.common.is_openvswitch_system_container | bool
- block:
- name: Pre-pull openvswitch image
@@ -55,7 +39,7 @@
- include: config/install-ovs-docker-service-file.yml
when:
- openshift.common.is_containerized | bool
- - openshift.common.use_openshift_sdn | default(true) | bool
+ - openshift_node_use_openshift_sdn | bool
- not openshift.common.is_openvswitch_system_container | bool
- include: config/configure-node-settings.yml
diff --git a/roles/openshift_node/tasks/tuned.yml b/roles/openshift_node/tasks/tuned.yml
new file mode 100644
index 000000000..425bf6a26
--- /dev/null
+++ b/roles/openshift_node/tasks/tuned.yml
@@ -0,0 +1,41 @@
+---
+- name: Check for tuned package
+ command: rpm -q tuned
+ args:
+ warn: no
+ register: tuned_installed
+ changed_when: false
+ failed_when: false
+
+- name: Tuned service setup
+ block:
+ - name: Set tuned OpenShift variables
+ set_fact:
+ openshift_tuned_guest_profile: "{{ 'atomic-guest' if openshift.common.is_atomic else 'virtual-guest' }}"
+ tuned_etc_directory: '/etc/tuned'
+ tuned_templates_source: '../templates/tuned'
+
+ - name: Ensure directory structure exists
+ file:
+ state: directory
+ dest: '{{ tuned_etc_directory }}/{{ item.path }}'
+ with_filetree: '{{ tuned_templates_source }}'
+ when: item.state == 'directory'
+
+ - name: Ensure files are populated from templates
+ template:
+ src: '{{ item.src }}'
+ dest: '{{ tuned_etc_directory }}/{{ item.path }}'
+ with_filetree: '{{ tuned_templates_source }}'
+ when: item.state == 'file'
+
+ - name: Make tuned use the recommended tuned profile on restart
+ file: path=/etc/tuned/active_profile state=absent
+
+ - name: Restart tuned service
+ systemd:
+ state: restarted
+ daemon_reload: yes
+ name: tuned
+
+ when: tuned_installed.rc == 0 | bool
diff --git a/roles/openshift_node/templates/node.service.j2 b/roles/openshift_node/templates/node.service.j2
index 3d0ae3bbd..0856737f6 100644
--- a/roles/openshift_node/templates/node.service.j2
+++ b/roles/openshift_node/templates/node.service.j2
@@ -8,7 +8,7 @@ Wants={{ openshift.docker.service_name }}.service
Documentation=https://github.com/openshift/origin
Requires=dnsmasq.service
After=dnsmasq.service
-{% if openshift.docker.use_crio %}Wants=cri-o.service{% endif %}
+{% if openshift_use_crio|default(false) %}Wants=cri-o.service{% endif %}
[Service]
Type=notify
diff --git a/roles/openshift_node/templates/node.yaml.v1.j2 b/roles/openshift_node/templates/node.yaml.v1.j2
index 93f8658b4..7049f7189 100644
--- a/roles/openshift_node/templates/node.yaml.v1.j2
+++ b/roles/openshift_node/templates/node.yaml.v1.j2
@@ -16,13 +16,11 @@ imageConfig:
latest: false
kind: NodeConfig
kubeletArguments: {{ openshift.node.kubelet_args | default(None) | to_padded_yaml(level=1) }}
-{% if openshift.docker.use_crio | default(False) %}
+{% if openshift_use_crio | default(False) %}
container-runtime:
- remote
container-runtime-endpoint:
- /var/run/crio.sock
- experimental-cri:
- - 'true'
image-service-endpoint:
- /var/run/crio.sock
node-labels:
@@ -39,15 +37,15 @@ masterClientConnectionOverrides:
qps: 100
{% endif %}
masterKubeConfig: system:node:{{ openshift.common.hostname }}.kubeconfig
-{% if openshift.common.use_openshift_sdn | bool %}
-networkPluginName: {{ openshift.common.sdn_network_plugin_name }}
+{% if openshift_node_use_openshift_sdn | bool %}
+networkPluginName: {{ openshift_node_sdn_network_plugin_name }}
{% endif %}
# networkConfig struct introduced in origin 1.0.6 and OSE 3.0.2 which
# deprecates networkPluginName above. The two should match.
networkConfig:
mtu: {{ openshift.node.sdn_mtu }}
-{% if openshift.common.use_openshift_sdn | bool or openshift.common.use_nuage | bool or openshift.common.use_contiv | bool or openshift.common.sdn_network_plugin_name == 'cni' %}
- networkPluginName: {{ openshift.common.sdn_network_plugin_name }}
+{% if openshift_node_use_openshift_sdn | bool or openshift_node_use_nuage | bool or openshift_node_use_contiv | bool or openshift_node_sdn_network_plugin_name == 'cni' %}
+ networkPluginName: {{ openshift_node_sdn_network_plugin_name }}
{% endif %}
{% if openshift.node.set_node_ip | bool %}
nodeIP: {{ openshift.common.ip }}
@@ -68,7 +66,7 @@ servingInfo:
- {{ cipher_suite }}
{% endfor %}
{% endif %}
-volumeDirectory: {{ openshift.common.data_dir }}/openshift.local.volumes
+volumeDirectory: {{ openshift_node_data_dir }}/openshift.local.volumes
proxyArguments:
proxy-mode:
- {{ openshift.node.proxy_mode }}
diff --git a/roles/openshift_node/templates/openshift.docker.node.dep.service b/roles/openshift_node/templates/openshift.docker.node.dep.service
index c4580be1f..8734e7443 100644
--- a/roles/openshift_node/templates/openshift.docker.node.dep.service
+++ b/roles/openshift_node/templates/openshift.docker.node.dep.service
@@ -3,7 +3,7 @@ Requires={{ openshift.docker.service_name }}.service
After={{ openshift.docker.service_name }}.service
PartOf={{ openshift.common.service_type }}-node.service
Before={{ openshift.common.service_type }}-node.service
-{% if openshift.docker.use_crio %}Wants=cri-o.service{% endif %}
+{% if openshift_use_crio|default(false) %}Wants=cri-o.service{% endif %}
[Service]
ExecStart=/bin/bash -c "if [[ -f /usr/bin/docker-current ]]; then echo \"DOCKER_ADDTL_BIND_MOUNTS=--volume=/usr/bin/docker-current:/usr/bin/docker-current:ro --volume=/etc/sysconfig/docker:/etc/sysconfig/docker:ro\" > /etc/sysconfig/{{ openshift.common.service_type }}-node-dep; else echo \"#DOCKER_ADDTL_BIND_MOUNTS=\" > /etc/sysconfig/{{ openshift.common.service_type }}-node-dep; fi"
diff --git a/roles/openshift_node/templates/openshift.docker.node.service b/roles/openshift_node/templates/openshift.docker.node.service
index 639b6f6c8..4ab10b95f 100644
--- a/roles/openshift_node/templates/openshift.docker.node.service
+++ b/roles/openshift_node/templates/openshift.docker.node.service
@@ -4,7 +4,7 @@ After={{ openshift.docker.service_name }}.service
After=openvswitch.service
PartOf={{ openshift.docker.service_name }}.service
Requires={{ openshift.docker.service_name }}.service
-{% if openshift.common.use_openshift_sdn %}
+{% if openshift_node_use_openshift_sdn %}
Wants=openvswitch.service
After=ovsdb-server.service
After=ovs-vswitchd.service
@@ -21,7 +21,22 @@ EnvironmentFile=/etc/sysconfig/{{ openshift.common.service_type }}-node-dep
ExecStartPre=-/usr/bin/docker rm -f {{ openshift.common.service_type }}-node
ExecStartPre=/usr/bin/cp /etc/origin/node/node-dnsmasq.conf /etc/dnsmasq.d/
ExecStartPre=/usr/bin/dbus-send --system --dest=uk.org.thekelleys.dnsmasq /uk/org/thekelleys/dnsmasq uk.org.thekelleys.SetDomainServers array:string:/in-addr.arpa/127.0.0.1,/{{ openshift.common.dns_domain }}/127.0.0.1
-ExecStart=/usr/bin/docker run --name {{ openshift.common.service_type }}-node --rm --privileged --net=host --pid=host --env-file=/etc/sysconfig/{{ openshift.common.service_type }}-node -v /:/rootfs:ro,rslave -e CONFIG_FILE=${CONFIG_FILE} -e OPTIONS=${OPTIONS} -e HOST=/rootfs -e HOST_ETC=/host-etc -v {{ openshift.common.data_dir }}:{{ openshift.common.data_dir }}{{ ':rslave' if openshift.docker.gte_1_10 | default(False) | bool else '' }} -v {{ openshift.common.config_base }}/node:{{ openshift.common.config_base }}/node {% if openshift_cloudprovider_kind | default('') != '' -%} -v {{ openshift.common.config_base }}/cloudprovider:{{ openshift.common.config_base}}/cloudprovider {% endif -%} -v /etc/localtime:/etc/localtime:ro -v /etc/machine-id:/etc/machine-id:ro -v /run:/run -v /sys:/sys:rw -v /sys/fs/cgroup:/sys/fs/cgroup:rw -v /usr/bin/docker:/usr/bin/docker:ro -v /var/lib/docker:/var/lib/docker -v /lib/modules:/lib/modules -v /etc/origin/openvswitch:/etc/openvswitch -v /etc/origin/sdn:/etc/openshift-sdn -v /var/lib/cni:/var/lib/cni -v /etc/systemd/system:/host-etc/systemd/system -v /var/log:/var/log -v /dev:/dev $DOCKER_ADDTL_BIND_MOUNTS -v /etc/pki:/etc/pki:ro {{ openshift.node.node_image }}:${IMAGE_VERSION}
+ExecStart=/usr/bin/docker run --name {{ openshift.common.service_type }}-node \
+ --rm --privileged --net=host --pid=host --env-file=/etc/sysconfig/{{ openshift.common.service_type }}-node \
+ -v /:/rootfs:ro,rslave -e CONFIG_FILE=${CONFIG_FILE} -e OPTIONS=${OPTIONS} \
+ -e HOST=/rootfs -e HOST_ETC=/host-etc \
+ -v {{ openshift_node_data_dir }}:{{ openshift_node_data_dir }}{{ ':rslave' if openshift.docker.gte_1_10 | default(False) | bool else '' }} \
+ -v {{ openshift.common.config_base }}/node:{{ openshift.common.config_base }}/node \
+ {% if openshift_cloudprovider_kind | default('') != '' -%} -v {{ openshift.common.config_base }}/cloudprovider:{{ openshift.common.config_base}}/cloudprovider {% endif -%} \
+ -v /etc/localtime:/etc/localtime:ro -v /etc/machine-id:/etc/machine-id:ro \
+ -v /run:/run -v /sys:/sys:rw -v /sys/fs/cgroup:/sys/fs/cgroup:rw \
+ -v /usr/bin/docker:/usr/bin/docker:ro -v /var/lib/docker:/var/lib/docker \
+ -v /lib/modules:/lib/modules -v /etc/origin/openvswitch:/etc/openvswitch \
+ -v /etc/origin/sdn:/etc/openshift-sdn -v /var/lib/cni:/var/lib/cni \
+ -v /etc/systemd/system:/host-etc/systemd/system -v /var/log:/var/log \
+ -v /dev:/dev $DOCKER_ADDTL_BIND_MOUNTS -v /etc/pki:/etc/pki:ro \
+ {% if l_bind_docker_reg_auth %} -v {{ oreg_auth_credentials_path }}:/root/.docker:ro{% endif %}\
+ {{ openshift.node.node_image }}:${IMAGE_VERSION}
ExecStartPost=/usr/bin/sleep 10
ExecStop=/usr/bin/docker stop {{ openshift.common.service_type }}-node
ExecStopPost=/usr/bin/rm /etc/dnsmasq.d/node-dnsmasq.conf
diff --git a/roles/openshift_node/templates/tuned/openshift-control-plane/tuned.conf b/roles/openshift_node/templates/tuned/openshift-control-plane/tuned.conf
new file mode 100644
index 000000000..f22f21065
--- /dev/null
+++ b/roles/openshift_node/templates/tuned/openshift-control-plane/tuned.conf
@@ -0,0 +1,25 @@
+#
+# tuned configuration
+#
+
+[main]
+summary=Optimize systems running OpenShift control plane
+include=openshift
+
+[sysctl]
+# ktune sysctl settings, maximizing i/o throughput
+#
+# Minimal preemption granularity for CPU-bound tasks:
+# (default: 1 msec# (1 + ilog(ncpus)), units: nanoseconds)
+kernel.sched_min_granularity_ns=10000000
+
+# The total time the scheduler will consider a migrated process
+# "cache hot" and thus less likely to be re-migrated
+# (system default is 500000, i.e. 0.5 ms)
+kernel.sched_migration_cost_ns=5000000
+
+# SCHED_OTHER wake-up granularity.
+#
+# Preemption granularity when tasks wake up. Lower the value to improve
+# wake-up latency and throughput for latency critical tasks.
+kernel.sched_wakeup_granularity_ns = 4000000
diff --git a/roles/openshift_node/templates/tuned/openshift-node/tuned.conf b/roles/openshift_node/templates/tuned/openshift-node/tuned.conf
new file mode 100644
index 000000000..78c7d19c9
--- /dev/null
+++ b/roles/openshift_node/templates/tuned/openshift-node/tuned.conf
@@ -0,0 +1,10 @@
+#
+# tuned configuration
+#
+
+[main]
+summary=Optimize systems running OpenShift nodes
+include=openshift
+
+[sysctl]
+net.ipv4.tcp_fastopen=3
diff --git a/roles/openshift_node/templates/tuned/openshift/tuned.conf b/roles/openshift_node/templates/tuned/openshift/tuned.conf
new file mode 100644
index 000000000..68ac5dadb
--- /dev/null
+++ b/roles/openshift_node/templates/tuned/openshift/tuned.conf
@@ -0,0 +1,24 @@
+#
+# tuned configuration
+#
+
+[main]
+summary=Optimize systems running OpenShift (parent profile)
+include=${f:virt_check:{{ openshift_tuned_guest_profile }}:throughput-performance}
+
+[selinux]
+avc_cache_threshold=65536
+
+[net]
+nf_conntrack_hashsize=131072
+
+[sysctl]
+kernel.pid_max=131072
+net.netfilter.nf_conntrack_max=1048576
+fs.inotify.max_user_watches=65536
+net.ipv4.neigh.default.gc_thresh1=8192
+net.ipv4.neigh.default.gc_thresh2=32768
+net.ipv4.neigh.default.gc_thresh3=65536
+net.ipv6.neigh.default.gc_thresh1=8192
+net.ipv6.neigh.default.gc_thresh2=32768
+net.ipv6.neigh.default.gc_thresh3=65536
diff --git a/roles/openshift_node/templates/tuned/recommend.conf b/roles/openshift_node/templates/tuned/recommend.conf
new file mode 100644
index 000000000..5fa765798
--- /dev/null
+++ b/roles/openshift_node/templates/tuned/recommend.conf
@@ -0,0 +1,8 @@
+[openshift-node]
+/etc/origin/node/node-config.yaml=.*region=primary
+
+[openshift-control-plane,master]
+/etc/origin/master/master-config.yaml=.*
+
+[openshift-control-plane,node]
+/etc/origin/node/node-config.yaml=.*region=infra
diff --git a/roles/openshift_node_certificates/defaults/main.yml b/roles/openshift_node_certificates/defaults/main.yml
index 70a38b844..455f26f30 100644
--- a/roles/openshift_node_certificates/defaults/main.yml
+++ b/roles/openshift_node_certificates/defaults/main.yml
@@ -1,2 +1,3 @@
---
openshift_node_cert_expire_days: 730
+openshift_ca_host: ''
diff --git a/roles/openshift_node_dnsmasq/files/networkmanager/99-origin-dns.sh b/roles/openshift_node_dnsmasq/files/networkmanager/99-origin-dns.sh
index 4aab8f2e9..61d2a5b51 100755
--- a/roles/openshift_node_dnsmasq/files/networkmanager/99-origin-dns.sh
+++ b/roles/openshift_node_dnsmasq/files/networkmanager/99-origin-dns.sh
@@ -46,9 +46,7 @@ if [[ $2 =~ ^(up|dhcp4-change|dhcp6-change)$ ]]; then
def_route=$(/sbin/ip route list match 0.0.0.0/0 | awk '{print $3 }')
def_route_int=$(/sbin/ip route get to ${def_route} | awk '{print $3}')
def_route_ip=$(/sbin/ip route get to ${def_route} | awk '{print $5}')
- if [[ ${DEVICE_IFACE} == ${def_route_int} && \
- -n "${IP4_NAMESERVERS}" && \
- "${IP4_NAMESERVERS}" != "${def_route_ip}" ]]; then
+ if [[ ${DEVICE_IFACE} == ${def_route_int} ]]; then
if [ ! -f /etc/dnsmasq.d/origin-dns.conf ]; then
cat << EOF > /etc/dnsmasq.d/origin-dns.conf
no-resolv
@@ -61,35 +59,40 @@ EOF
NEEDS_RESTART=1
fi
- ######################################################################
- # Write out default nameservers for /etc/dnsmasq.d/origin-upstream-dns.conf
- # and /etc/origin/node/resolv.conf in their respective formats
- for ns in ${IP4_NAMESERVERS}; do
- if [[ ! -z $ns ]]; then
- echo "server=${ns}" >> $UPSTREAM_DNS_TMP
- echo "nameserver ${ns}" >> $NEW_NODE_RESOLV_CONF
+ # If network manager doesn't know about the nameservers then the best
+ # we can do is grab them from /etc/resolv.conf but only if we've got no
+ # watermark
+ if ! grep -q '99-origin-dns.sh' /etc/resolv.conf; then
+ if [[ -z "${IP4_NAMESERVERS}" || "${IP4_NAMESERVERS}" == "${def_route_ip}" ]]; then
+ IP4_NAMESERVERS=`grep '^nameserver ' /etc/resolv.conf | awk '{ print $2 }'`
+ fi
+ ######################################################################
+ # Write out default nameservers for /etc/dnsmasq.d/origin-upstream-dns.conf
+ # and /etc/origin/node/resolv.conf in their respective formats
+ for ns in ${IP4_NAMESERVERS}; do
+ if [[ ! -z $ns ]]; then
+ echo "server=${ns}" >> $UPSTREAM_DNS_TMP
+ echo "nameserver ${ns}" >> $NEW_NODE_RESOLV_CONF
+ fi
+ done
+ # Sort it in case DNS servers arrived in a different order
+ sort $UPSTREAM_DNS_TMP > $UPSTREAM_DNS_TMP_SORTED
+ sort $UPSTREAM_DNS > $CURRENT_UPSTREAM_DNS_SORTED
+ # Compare to the current config file (sorted)
+ NEW_DNS_SUM=`md5sum ${UPSTREAM_DNS_TMP_SORTED} | awk '{print $1}'`
+ CURRENT_DNS_SUM=`md5sum ${CURRENT_UPSTREAM_DNS_SORTED} | awk '{print $1}'`
+ if [ "${NEW_DNS_SUM}" != "${CURRENT_DNS_SUM}" ]; then
+ # DNS has changed, copy the temp file to the proper location (-Z
+ # sets default selinux context) and set the restart flag
+ cp -Z $UPSTREAM_DNS_TMP $UPSTREAM_DNS
+ NEEDS_RESTART=1
+ fi
+ # compare /etc/origin/node/resolv.conf checksum and replace it if different
+ NEW_NODE_RESOLV_CONF_MD5=`md5sum ${NEW_NODE_RESOLV_CONF}`
+ OLD_NODE_RESOLV_CONF_MD5=`md5sum /etc/origin/node/resolv.conf`
+ if [ "${NEW_NODE_RESOLV_CONF_MD5}" != "${OLD_NODE_RESOLV_CONF_MD5}" ]; then
+ cp -Z $NEW_NODE_RESOLV_CONF /etc/origin/node/resolv.conf
fi
- done
-
- # Sort it in case DNS servers arrived in a different order
- sort $UPSTREAM_DNS_TMP > $UPSTREAM_DNS_TMP_SORTED
- sort $UPSTREAM_DNS > $CURRENT_UPSTREAM_DNS_SORTED
-
- # Compare to the current config file (sorted)
- NEW_DNS_SUM=`md5sum ${UPSTREAM_DNS_TMP_SORTED} | awk '{print $1}'`
- CURRENT_DNS_SUM=`md5sum ${CURRENT_UPSTREAM_DNS_SORTED} | awk '{print $1}'`
- if [ "${NEW_DNS_SUM}" != "${CURRENT_DNS_SUM}" ]; then
- # DNS has changed, copy the temp file to the proper location (-Z
- # sets default selinux context) and set the restart flag
- cp -Z $UPSTREAM_DNS_TMP $UPSTREAM_DNS
- NEEDS_RESTART=1
- fi
-
- # compare /etc/origin/node/resolv.conf checksum and replace it if different
- NEW_NODE_RESOLV_CONF_MD5=`md5sum ${NEW_NODE_RESOLV_CONF}`
- OLD_NODE_RESOLV_CONF_MD5=`md5sum /etc/origin/node/resolv.conf`
- if [ "${NEW_NODE_RESOLV_CONF_MD5}" != "${OLD_NODE_RESOLV_CONF_MD5}" ]; then
- cp -Z $NEW_NODE_RESOLV_CONF /etc/origin/node/resolv.conf
fi
if ! `systemctl -q is-active dnsmasq.service`; then
diff --git a/roles/openshift_node_dnsmasq/meta/main.yml b/roles/openshift_node_dnsmasq/meta/main.yml
index 84035b88c..d80ed1b72 100644
--- a/roles/openshift_node_dnsmasq/meta/main.yml
+++ b/roles/openshift_node_dnsmasq/meta/main.yml
@@ -12,5 +12,4 @@ galaxy_info:
categories:
- cloud
dependencies:
-- role: openshift_common
- role: openshift_node_facts
diff --git a/roles/openshift_node_dnsmasq/tasks/main.yml b/roles/openshift_node_dnsmasq/tasks/main.yml
index d0221a94b..9bbaafc29 100644
--- a/roles/openshift_node_dnsmasq/tasks/main.yml
+++ b/roles/openshift_node_dnsmasq/tasks/main.yml
@@ -14,6 +14,17 @@
package: name=dnsmasq state=installed
when: not openshift.common.is_atomic | bool
+- name: ensure origin/node directory exists
+ file:
+ state: directory
+ path: "{{ item }}"
+ owner: root
+ group: root
+ mode: '0700'
+ with_items:
+ - /etc/origin
+ - /etc/origin/node
+
# this file is copied to /etc/dnsmasq.d/ when the node starts and is removed
# when the node stops. A dbus-message is sent to dnsmasq to add the same entries
# so that dnsmasq doesn't need to be restarted. Once we can use dnsmasq 2.77 or
diff --git a/roles/openshift_node_upgrade/README.md b/roles/openshift_node_upgrade/README.md
index 4e6229bfb..5ad994df9 100644
--- a/roles/openshift_node_upgrade/README.md
+++ b/roles/openshift_node_upgrade/README.md
@@ -32,14 +32,12 @@ From openshift.common:
| Name | Default Value | |
|------------------------------------|---------------------|---------------------|
| openshift.common.config_base |---------------------|---------------------|
-| openshift.common.data_dir |---------------------|---------------------|
| openshift.common.hostname |---------------------|---------------------|
| openshift.common.http_proxy |---------------------|---------------------|
| openshift.common.is_atomic |---------------------|---------------------|
| openshift.common.is_containerized |---------------------|---------------------|
| openshift.common.portal_net |---------------------|---------------------|
| openshift.common.service_type |---------------------|---------------------|
-| openshift.common.use_openshift_sdn |---------------------|---------------------|
From openshift.master:
@@ -58,7 +56,7 @@ From openshift.node:
Dependencies
------------
-openshift_common
+
TODO
diff --git a/roles/openshift_node_upgrade/defaults/main.yml b/roles/openshift_node_upgrade/defaults/main.yml
index ed97d539c..3d8704308 100644
--- a/roles/openshift_node_upgrade/defaults/main.yml
+++ b/roles/openshift_node_upgrade/defaults/main.yml
@@ -1 +1,6 @@
---
+openshift_use_openshift_sdn: True
+os_sdn_network_plugin_name: "redhat/openshift-ovs-subnet"
+
+openshift_node_data_dir_default: "{{ openshift_data_dir | default('/var/lib/origin') }}"
+openshift_node_data_dir: "{{ openshift_node_data_dir_default }}"
diff --git a/roles/openshift_node_upgrade/handlers/main.yml b/roles/openshift_node_upgrade/handlers/main.yml
index d31b899cf..90d80855e 100644
--- a/roles/openshift_node_upgrade/handlers/main.yml
+++ b/roles/openshift_node_upgrade/handlers/main.yml
@@ -6,7 +6,7 @@
when:
- not skip_node_svc_handlers | default(False) | bool
- not (ovs_service_status_changed | default(false) | bool)
- - openshift.common.use_openshift_sdn | default(true) | bool
+ - openshift_use_openshift_sdn | bool
register: l_openshift_node_upgrade_stop_openvswitch_result
until: not l_openshift_node_upgrade_stop_openvswitch_result | failed
retries: 3
diff --git a/roles/openshift_node_upgrade/meta/main.yml b/roles/openshift_node_upgrade/meta/main.yml
index 2a36d8945..a810b01dc 100644
--- a/roles/openshift_node_upgrade/meta/main.yml
+++ b/roles/openshift_node_upgrade/meta/main.yml
@@ -11,4 +11,3 @@ galaxy_info:
- 7
dependencies:
- role: lib_utils
-- role: openshift_common
diff --git a/roles/openshift_node_upgrade/tasks/main.yml b/roles/openshift_node_upgrade/tasks/main.yml
index bc092c26c..e34319186 100644
--- a/roles/openshift_node_upgrade/tasks/main.yml
+++ b/roles/openshift_node_upgrade/tasks/main.yml
@@ -44,7 +44,7 @@
changed_when: "'Downloaded newer image' in pull_result.stdout"
when:
- openshift.common.is_containerized | bool
- - openshift.common.use_openshift_sdn | default(true) | bool
+ - openshift_use_openshift_sdn | bool
- include: docker/upgrade.yml
vars:
@@ -142,7 +142,7 @@
# End Disable Swap Block
- name: Reset selinux context
- command: restorecon -RF {{ openshift.common.data_dir }}/openshift.local.volumes
+ command: restorecon -RF {{ openshift_node_data_dir }}/openshift.local.volumes
when:
- ansible_selinux is defined
- ansible_selinux.status == 'enabled'
diff --git a/roles/openshift_node_upgrade/tasks/systemd_units.yml b/roles/openshift_node_upgrade/tasks/systemd_units.yml
index 4e9550150..afff2f8ba 100644
--- a/roles/openshift_node_upgrade/tasks/systemd_units.yml
+++ b/roles/openshift_node_upgrade/tasks/systemd_units.yml
@@ -4,7 +4,7 @@
# - openshift_image_tag
# - openshift.common.is_containerized
# - openshift.node.ovs_image
-# - openshift.common.use_openshift_sdn
+# - openshift_use_openshift_sdn
# - openshift.common.service_type
# - openshift.node.debug_level
# - openshift.common.config_base
@@ -28,10 +28,10 @@
when: openshift.common.is_containerized | bool
- include: config/workaround-bz1331590-ovs-oom-fix.yml
- when: openshift.common.use_openshift_sdn | default(true) | bool
+ when: openshift_use_openshift_sdn | bool
- include: config/install-ovs-docker-service-file.yml
- when: openshift.common.is_containerized | bool and openshift.common.use_openshift_sdn | default(true) | bool
+ when: openshift.common.is_containerized | bool and openshift_use_openshift_sdn | bool
- include: config/configure-node-settings.yml
- include: config/configure-proxy-settings.yml
diff --git a/roles/openshift_node_upgrade/templates/openshift.docker.node.service b/roles/openshift_node_upgrade/templates/openshift.docker.node.service
index 639b6f6c8..451412ab0 100644
--- a/roles/openshift_node_upgrade/templates/openshift.docker.node.service
+++ b/roles/openshift_node_upgrade/templates/openshift.docker.node.service
@@ -4,7 +4,7 @@ After={{ openshift.docker.service_name }}.service
After=openvswitch.service
PartOf={{ openshift.docker.service_name }}.service
Requires={{ openshift.docker.service_name }}.service
-{% if openshift.common.use_openshift_sdn %}
+{% if openshift_use_openshift_sdn %}
Wants=openvswitch.service
After=ovsdb-server.service
After=ovs-vswitchd.service
@@ -21,7 +21,7 @@ EnvironmentFile=/etc/sysconfig/{{ openshift.common.service_type }}-node-dep
ExecStartPre=-/usr/bin/docker rm -f {{ openshift.common.service_type }}-node
ExecStartPre=/usr/bin/cp /etc/origin/node/node-dnsmasq.conf /etc/dnsmasq.d/
ExecStartPre=/usr/bin/dbus-send --system --dest=uk.org.thekelleys.dnsmasq /uk/org/thekelleys/dnsmasq uk.org.thekelleys.SetDomainServers array:string:/in-addr.arpa/127.0.0.1,/{{ openshift.common.dns_domain }}/127.0.0.1
-ExecStart=/usr/bin/docker run --name {{ openshift.common.service_type }}-node --rm --privileged --net=host --pid=host --env-file=/etc/sysconfig/{{ openshift.common.service_type }}-node -v /:/rootfs:ro,rslave -e CONFIG_FILE=${CONFIG_FILE} -e OPTIONS=${OPTIONS} -e HOST=/rootfs -e HOST_ETC=/host-etc -v {{ openshift.common.data_dir }}:{{ openshift.common.data_dir }}{{ ':rslave' if openshift.docker.gte_1_10 | default(False) | bool else '' }} -v {{ openshift.common.config_base }}/node:{{ openshift.common.config_base }}/node {% if openshift_cloudprovider_kind | default('') != '' -%} -v {{ openshift.common.config_base }}/cloudprovider:{{ openshift.common.config_base}}/cloudprovider {% endif -%} -v /etc/localtime:/etc/localtime:ro -v /etc/machine-id:/etc/machine-id:ro -v /run:/run -v /sys:/sys:rw -v /sys/fs/cgroup:/sys/fs/cgroup:rw -v /usr/bin/docker:/usr/bin/docker:ro -v /var/lib/docker:/var/lib/docker -v /lib/modules:/lib/modules -v /etc/origin/openvswitch:/etc/openvswitch -v /etc/origin/sdn:/etc/openshift-sdn -v /var/lib/cni:/var/lib/cni -v /etc/systemd/system:/host-etc/systemd/system -v /var/log:/var/log -v /dev:/dev $DOCKER_ADDTL_BIND_MOUNTS -v /etc/pki:/etc/pki:ro {{ openshift.node.node_image }}:${IMAGE_VERSION}
+ExecStart=/usr/bin/docker run --name {{ openshift.common.service_type }}-node --rm --privileged --net=host --pid=host --env-file=/etc/sysconfig/{{ openshift.common.service_type }}-node -v /:/rootfs:ro,rslave -e CONFIG_FILE=${CONFIG_FILE} -e OPTIONS=${OPTIONS} -e HOST=/rootfs -e HOST_ETC=/host-etc -v {{ openshift_node_data_dir }}:{{ openshift_node_data_dir }}{{ ':rslave' if openshift.docker.gte_1_10 | default(False) | bool else '' }} -v {{ openshift.common.config_base }}/node:{{ openshift.common.config_base }}/node {% if openshift_cloudprovider_kind | default('') != '' -%} -v {{ openshift.common.config_base }}/cloudprovider:{{ openshift.common.config_base}}/cloudprovider {% endif -%} -v /etc/localtime:/etc/localtime:ro -v /etc/machine-id:/etc/machine-id:ro -v /run:/run -v /sys:/sys:rw -v /sys/fs/cgroup:/sys/fs/cgroup:rw -v /usr/bin/docker:/usr/bin/docker:ro -v /var/lib/docker:/var/lib/docker -v /lib/modules:/lib/modules -v /etc/origin/openvswitch:/etc/openvswitch -v /etc/origin/sdn:/etc/openshift-sdn -v /var/lib/cni:/var/lib/cni -v /etc/systemd/system:/host-etc/systemd/system -v /var/log:/var/log -v /dev:/dev $DOCKER_ADDTL_BIND_MOUNTS -v /etc/pki:/etc/pki:ro {{ openshift.node.node_image }}:${IMAGE_VERSION}
ExecStartPost=/usr/bin/sleep 10
ExecStop=/usr/bin/docker stop {{ openshift.common.service_type }}-node
ExecStopPost=/usr/bin/rm /etc/dnsmasq.d/node-dnsmasq.conf
diff --git a/roles/openshift_persistent_volumes/README.md b/roles/openshift_persistent_volumes/README.md
index 1489cb0bd..0407d6ef1 100644
--- a/roles/openshift_persistent_volumes/README.md
+++ b/roles/openshift_persistent_volumes/README.md
@@ -17,13 +17,6 @@ From this role:
| persistent_volume_claims | [] | List of persistent volume claim dictionaries, keys: name, capacity, access_modes |
-From openshift_common:
-
-| Name | Default Value | |
-|-------------------------------|----------------|----------------------------------------|
-| openshift_debug_level | 2 | Global openshift debug log verbosity |
-
-
Dependencies
------------
diff --git a/roles/openshift_persistent_volumes/meta/main.yml b/roles/openshift_persistent_volumes/meta/main.yml
index 25e5a38dd..8d3d010e4 100644
--- a/roles/openshift_persistent_volumes/meta/main.yml
+++ b/roles/openshift_persistent_volumes/meta/main.yml
@@ -10,5 +10,4 @@ galaxy_info:
versions:
- 7
dependencies:
-- role: openshift_common
- role: openshift_hosted_facts
diff --git a/roles/openshift_prometheus/README.md b/roles/openshift_prometheus/README.md
new file mode 100644
index 000000000..c5a44bffb
--- /dev/null
+++ b/roles/openshift_prometheus/README.md
@@ -0,0 +1,95 @@
+OpenShift Prometheus
+====================
+
+OpenShift Prometheus Installation
+
+Requirements
+------------
+
+
+Role Variables
+--------------
+
+For default values, see [`defaults/main.yaml`](defaults/main.yaml).
+
+- `openshift_prometheus_state`: present - install/update. absent - uninstall.
+
+- `openshift_prometheus_namespace`: project (i.e. namespace) where the components will be
+ deployed.
+
+- `openshift_prometheus_replicas`: The number of replicas for prometheus deployment.
+
+- `openshift_prometheus_node_selector`: Selector for the nodes prometheus will be deployed on.
+
+- `openshift_prometheus_image_<COMPONENT>`: specify image for the component
+
+## Storage related variables
+Each prometheus component (prometheus, alertmanager, alert-buffer, oauth-proxy) can set pv claim by setting corresponding role variable:
+```
+openshift_prometheus_<COMPONENT>_storage_type: <VALUE>
+openshift_prometheus_<COMPONENT>_pvc_(name|size|access_modes|pv_selector): <VALUE>
+```
+e.g
+```
+openshift_prometheus_storage_type: pvc
+openshift_prometheus_alertmanager_pvc_name: alertmanager
+openshift_prometheus_alertbuffer_pvc_size: 10G
+openshift_prometheus_pvc_access_modes: [ReadWriteOnce]
+```
+
+## Additional Alert Rules file variable
+An external file with alert rules can be added by setting path to additional rules variable:
+```
+openshift_prometheus_additional_rules_file: <PATH>
+```
+
+File content should be in prometheus alert rules format.
+Following example sets rule to fire an alert when one of the cluster nodes is down:
+
+```
+groups:
+- name: example-rules
+ interval: 30s # defaults to global interval
+ rules:
+ - alert: Node Down
+ expr: up{job="kubernetes-nodes"} == 0
+ annotations:
+ miqTarget: "ContainerNode"
+ severity: "HIGH"
+ message: "{{ '{{' }}{{ '$labels.instance' }}{{ '}}' }} is down"
+```
+
+
+## Additional variables to control resource limits
+Each prometheus component (prometheus, alertmanager, alert-buffer, oauth-proxy) can specify a cpu and memory limits and requests by setting
+the corresponding role variable:
+```
+openshift_prometheus_<COMPONENT>_(limits|requests)_(memory|cpu): <VALUE>
+```
+e.g
+```
+openshift_prometheus_alertmanager_limits_memory: 1Gi
+openshift_prometheus_oath_proxy_requests_cpu: 100
+```
+
+Dependencies
+------------
+
+openshift_facts
+
+
+Example Playbook
+----------------
+
+```
+- name: Configure openshift-prometheus
+ hosts: oo_first_master
+ roles:
+ - role: openshift_prometheus
+```
+
+License
+-------
+
+Apache License, Version 2.0
+
diff --git a/roles/openshift_prometheus/defaults/main.yaml b/roles/openshift_prometheus/defaults/main.yaml
new file mode 100644
index 000000000..5aa8aecec
--- /dev/null
+++ b/roles/openshift_prometheus/defaults/main.yaml
@@ -0,0 +1,74 @@
+---
+# defaults file for openshift_prometheus
+openshift_prometheus_state: present
+
+openshift_prometheus_namespace: prometheus
+
+openshift_prometheus_replicas: 1
+openshift_prometheus_node_selector: {"region":"infra"}
+
+# images
+openshift_prometheus_image_proxy: "openshift/oauth-proxy:v1.0.0"
+openshift_prometheus_image_prometheus: "openshift/prometheus:v2.0.0-dev"
+openshift_prometheus_image_alertmanager: "openshift/prometheus-alertmanager:dev"
+openshift_prometheus_image_alertbuffer: "openshift/prometheus-alert-buffer:v0.0.1"
+
+# additional prometheus rules file
+openshift_prometheus_additional_rules_file: null
+
+# All the required exports
+openshift_prometheus_pv_exports:
+ - prometheus
+ - prometheus-alertmanager
+ - prometheus-alertbuffer
+# PV template files and their created object names
+openshift_prometheus_pv_data:
+ - pv_name: prometheus
+ pv_template: prom-pv-server.yml
+ pv_label: Prometheus Server PV
+ - pv_name: prometheus-alertmanager
+ pv_template: prom-pv-alertmanager.yml
+ pv_label: Prometheus Alertmanager PV
+ - pv_name: prometheus-alertbuffer
+ pv_template: prom-pv-alertbuffer.yml
+ pv_label: Prometheus Alert Buffer PV
+
+# Hostname/IP of the NFS server. Currently defaults to first master
+openshift_prometheus_nfs_server: "{{ groups.nfs.0 }}"
+
+# storage
+openshift_prometheus_storage_type: pvc
+openshift_prometheus_pvc_name: prometheus
+openshift_prometheus_pvc_size: 10G
+openshift_prometheus_pvc_access_modes: [ReadWriteOnce]
+openshift_prometheus_pvc_pv_selector: {}
+
+openshift_prometheus_alertmanager_storage_type: pvc
+openshift_prometheus_alertmanager_pvc_name: prometheus-alertmanager
+openshift_prometheus_alertmanager_pvc_size: 10G
+openshift_prometheus_alertmanager_pvc_access_modes: [ReadWriteOnce]
+openshift_prometheus_alertmanager_pvc_pv_selector: {}
+
+openshift_prometheus_alertbuffer_storage_type: pvc
+openshift_prometheus_alertbuffer_pvc_name: prometheus-alertbuffer
+openshift_prometheus_alertbuffer_pvc_size: 10G
+openshift_prometheus_alertbuffer_pvc_access_modes: [ReadWriteOnce]
+openshift_prometheus_alertbuffer_pvc_pv_selector: {}
+
+# container resources
+openshift_prometheus_cpu_limit: null
+openshift_prometheus_memory_limit: null
+openshift_prometheus_cpu_requests: null
+openshift_prometheus_memory_requests: null
+openshift_prometheus_alertmanager_cpu_limit: null
+openshift_prometheus_alertmanager_memory_limit: null
+openshift_prometheus_alertmanager_cpu_requests: null
+openshift_prometheus_alertmanager_memory_requests: null
+openshift_prometheus_alertbuffer_cpu_limit: null
+openshift_prometheus_alertbuffer_memory_limit: null
+openshift_prometheus_alertbuffer_cpu_requests: null
+openshift_prometheus_alertbuffer_memory_requests: null
+openshift_prometheus_oauth_proxy_cpu_limit: null
+openshift_prometheus_oauth_proxy_memory_limit: null
+openshift_prometheus_oauth_proxy_cpu_requests: null
+openshift_prometheus_oauth_proxy_memory_requests: null
diff --git a/roles/openshift_prometheus/files/openshift_prometheus.exports b/roles/openshift_prometheus/files/openshift_prometheus.exports
new file mode 100644
index 000000000..3ccedb1fd
--- /dev/null
+++ b/roles/openshift_prometheus/files/openshift_prometheus.exports
@@ -0,0 +1,3 @@
+/exports/prometheus *(rw,no_root_squash,no_wdelay)
+/exports/prometheus-alertmanager *(rw,no_root_squash,no_wdelay)
+/exports/prometheus-alertbuffer *(rw,no_root_squash,no_wdelay)
diff --git a/roles/openshift_prometheus/meta/main.yaml b/roles/openshift_prometheus/meta/main.yaml
new file mode 100644
index 000000000..33188bb7e
--- /dev/null
+++ b/roles/openshift_prometheus/meta/main.yaml
@@ -0,0 +1,19 @@
+---
+galaxy_info:
+ author: OpenShift Development <dev@lists.openshift.redhat.com>
+ description: Deploy OpenShift prometheus integration for the cluster
+ company: Red Hat, Inc.
+ license: license (Apache)
+ min_ansible_version: 2.2
+ platforms:
+ - name: EL
+ versions:
+ - 7
+ - name: Fedora
+ versions:
+ - all
+ categories:
+ - openshift
+dependencies:
+- { role: lib_openshift }
+- { role: openshift_facts }
diff --git a/roles/openshift_prometheus/tasks/create_pvs.yaml b/roles/openshift_prometheus/tasks/create_pvs.yaml
new file mode 100644
index 000000000..4e79da05f
--- /dev/null
+++ b/roles/openshift_prometheus/tasks/create_pvs.yaml
@@ -0,0 +1,36 @@
+---
+# Check for existance and then conditionally:
+# - evaluate templates
+# - PVs
+#
+# These tasks idempotently create required Prometheus PV objects. Do not
+# call this file directly. This file is intended to be ran as an
+# include that has a 'with_items' attached to it. Hence the use below
+# of variables like "{{ item.pv_label }}"
+
+- name: "Check if the {{ item.pv_label }} template has been created already"
+ oc_obj:
+ namespace: "{{ openshift_prometheus_namespace }}"
+ state: list
+ kind: pv
+ name: "{{ item.pv_name }}"
+ register: prom_pv_check
+
+# Skip all of this if the PV already exists
+- block:
+ - name: "Ensure the {{ item.pv_label }} template is evaluated"
+ template:
+ src: "{{ item.pv_template }}.j2"
+ dest: "{{ tempdir }}/templates/{{ item.pv_template }}"
+
+ - name: "Ensure {{ item.pv_label }} is created"
+ oc_obj:
+ namespace: "{{ openshift_prometheus_namespace }}"
+ kind: pv
+ name: "{{ item.pv_name }}"
+ state: present
+ delete_after: True
+ files:
+ - "{{ tempdir }}/templates/{{ item.pv_template }}"
+ when:
+ - not prom_pv_check.results.results.0
diff --git a/roles/openshift_prometheus/tasks/install_prometheus.yaml b/roles/openshift_prometheus/tasks/install_prometheus.yaml
new file mode 100644
index 000000000..a9bce2fb1
--- /dev/null
+++ b/roles/openshift_prometheus/tasks/install_prometheus.yaml
@@ -0,0 +1,244 @@
+---
+
+# namespace
+- name: Add prometheus project
+ oc_project:
+ state: "{{ state }}"
+ name: "{{ openshift_prometheus_namespace }}"
+ node_selector: "{{ openshift_prometheus_node_selector | oo_selector_to_string_list() }}"
+ description: Prometheus
+
+# secrets
+- name: Set alert and prometheus secrets
+ oc_secret:
+ state: "{{ state }}"
+ name: "{{ item }}-proxy"
+ namespace: "{{ openshift_prometheus_namespace }}"
+ contents:
+ - path: session_secret
+ data: "{{ 43 | oo_random_word }}="
+ with_items:
+ - prometheus
+ - alerts
+
+# serviceaccount
+- name: create prometheus serviceaccount
+ oc_serviceaccount:
+ state: "{{ state }}"
+ name: prometheus
+ namespace: "{{ openshift_prometheus_namespace }}"
+ # TODO add annotations when supproted
+ # annotations:
+ # serviceaccounts.openshift.io/oauth-redirectreference.prom: '{"kind":"OAuthRedirectReference","apiVersion":"v1","reference":{"kind":"Route","name":"prometheus"}}'
+ # serviceaccounts.openshift.io/oauth-redirectreference.alerts: '{"kind":"OAuthRedirectReference","apiVersion":"v1","reference":{"kind":"Route","name":"alerts"}}'
+
+ secrets:
+ - prometheus-secrets
+ changed_when: no
+
+# TODO remove this when annotations are supported by oc_serviceaccount
+- name: annotate serviceaccount
+ command: >
+ {{ openshift.common.client_binary }} annotate --overwrite -n {{ openshift_prometheus_namespace }}
+ serviceaccount prometheus
+ serviceaccounts.openshift.io/oauth-redirectreference.prom='{"kind":"OAuthRedirectReference","apiVersion":"v1","reference":{"kind":"Route","name":"prometheus"}}'
+ serviceaccounts.openshift.io/oauth-redirectreference.alerts='{"kind":"OAuthRedirectReference","apiVersion":"v1","reference":{"kind":"Route","name":"alerts"}}'
+
+
+# create clusterrolebinding for prometheus serviceaccount
+- name: Set cluster-reader permissions for prometheus
+ oc_adm_policy_user:
+ state: "{{ state }}"
+ namespace: "{{ openshift_prometheus_namespace }}"
+ resource_kind: cluster-role
+ resource_name: cluster-reader
+ user: "system:serviceaccount:{{ openshift_prometheus_namespace }}:prometheus"
+
+
+######################################################################
+# NFS
+# In the case that we are not running on a cloud provider, volumes must be statically provisioned
+
+- include: nfs.yaml
+ when: not (openshift_cloudprovider_kind is defined and (openshift_cloudprovider_kind == 'aws' or openshift_cloudprovider_kind == 'gce'))
+
+
+# create prometheus and alerts services
+# TODO join into 1 task with loop
+- name: Create prometheus service
+ oc_service:
+ state: "{{ state }}"
+ name: "{{ item.name }}"
+ namespace: "{{ openshift_prometheus_namespace }}"
+ selector:
+ app: prometheus
+ labels:
+ name: "{{ item.name }}"
+ # TODO add annotations when supported
+ # annotations:
+ # service.alpha.openshift.io/serving-cert-secret-name: "{{item.name}}-tls"
+ ports:
+ - port: 443
+ targetPort: 8443
+ with_items:
+ - name: prometheus
+
+- name: Create alerts service
+ oc_service:
+ state: "{{ state }}"
+ name: "{{ item.name }}"
+ namespace: "{{ openshift_prometheus_namespace }}"
+ selector:
+ app: prometheus
+ labels:
+ name: "{{ item.name }}"
+ # TODO add annotations when supported
+ # annotations:
+ # service.alpha.openshift.io/serving-cert-secret-name: "{{item.name}}-tls"
+ ports:
+ - port: 443
+ targetPort: 9443
+ with_items:
+ - name: alerts
+
+
+# Annotate services with secret name
+# TODO remove this when annotations are supported by oc_service
+- name: annotate prometheus service
+ command: >
+ {{ openshift.common.client_binary }} annotate --overwrite -n {{ openshift_prometheus_namespace }}
+ service prometheus
+ prometheus.io/scrape='true'
+ prometheus.io/scheme=https
+ service.alpha.openshift.io/serving-cert-secret-name=prometheus-tls
+
+- name: annotate alerts service
+ command: >
+ {{ openshift.common.client_binary }} annotate --overwrite -n {{ openshift_prometheus_namespace }}
+ service alerts 'service.alpha.openshift.io/serving-cert-secret-name=prometheus-alerts-tls'
+
+# create prometheus and alerts routes
+- name: create prometheus and alerts routes
+ oc_route:
+ state: "{{ state }}"
+ name: "{{ item.name }}"
+ namespace: "{{ openshift_prometheus_namespace }}"
+ service_name: "{{ item.name }}"
+ tls_termination: reencrypt
+ with_items:
+ - name: prometheus
+ - name: alerts
+
+# Storage
+- name: create prometheus pvc
+ oc_pvc:
+ namespace: "{{ openshift_prometheus_namespace }}"
+ name: "{{ openshift_prometheus_pvc_name }}"
+ access_modes: "{{ openshift_prometheus_pvc_access_modes }}"
+ volume_capacity: "{{ openshift_prometheus_pvc_size }}"
+ selector: "{{ openshift_prometheus_pvc_pv_selector }}"
+
+- name: create alertmanager pvc
+ oc_pvc:
+ namespace: "{{ openshift_prometheus_namespace }}"
+ name: "{{ openshift_prometheus_alertmanager_pvc_name }}"
+ access_modes: "{{ openshift_prometheus_alertmanager_pvc_access_modes }}"
+ volume_capacity: "{{ openshift_prometheus_alertmanager_pvc_size }}"
+ selector: "{{ openshift_prometheus_alertmanager_pvc_pv_selector }}"
+
+- name: create alertbuffer pvc
+ oc_pvc:
+ namespace: "{{ openshift_prometheus_namespace }}"
+ name: "{{ openshift_prometheus_alertbuffer_pvc_name }}"
+ access_modes: "{{ openshift_prometheus_alertbuffer_pvc_access_modes }}"
+ volume_capacity: "{{ openshift_prometheus_alertbuffer_pvc_size }}"
+ selector: "{{ openshift_prometheus_alertbuffer_pvc_pv_selector }}"
+
+# create prometheus deployment
+- name: Set prometheus deployment template
+ template:
+ src: prometheus_deployment.j2
+ dest: "{{ tempdir }}/templates/prometheus.yaml"
+ vars:
+ namespace: "{{ openshift_prometheus_namespace }}"
+ prom_replicas: "{{ openshift_prometheus_replicas }}"
+
+- name: Set prometheus deployment
+ oc_obj:
+ state: "{{ state }}"
+ name: "prometheus"
+ namespace: "{{ openshift_prometheus_namespace }}"
+ kind: deployment
+ files:
+ - "{{ tempdir }}/templates/prometheus.yaml"
+ delete_after: true
+
+# prometheus configmap
+# Copy the additional rules file if it is defined
+- name: Copy additional rules file to host
+ copy:
+ src: "{{ openshift_prometheus_additional_rules_file }}"
+ dest: "{{ tempdir }}/prometheus.additional.rules"
+ when:
+ - openshift_prometheus_additional_rules_file is defined
+ - openshift_prometheus_additional_rules_file is not none
+ - openshift_prometheus_additional_rules_file | trim | length > 0
+
+- stat:
+ path: "{{ tempdir }}/prometheus.additional.rules"
+ register: additional_rules_stat
+
+# The kubernetes version impacts the prometheus scraping endpoint
+# so gathering it before constructing the configmap
+- name: get oc version
+ oc_version:
+ register: oc_version
+
+- set_fact:
+ kubernetes_version: "{{ oc_version.results.kubernetes_short | float }}"
+
+- template:
+ src: prometheus.yml.j2
+ dest: "{{ tempdir }}/prometheus.yml"
+ changed_when: no
+
+- template:
+ src: prometheus.rules.j2
+ dest: "{{ tempdir }}/prometheus.rules"
+ changed_when: no
+
+# In prometheus configmap create "additional.rules" section if file exists
+- name: Set prometheus configmap
+ oc_configmap:
+ state: "{{ state }}"
+ name: "prometheus"
+ namespace: "{{ openshift_prometheus_namespace }}"
+ from_file:
+ prometheus.rules: "{{ tempdir }}/prometheus.rules"
+ prometheus.additional.rules: "{{ tempdir }}/prometheus.additional.rules"
+ prometheus.yml: "{{ tempdir }}/prometheus.yml"
+ when: additional_rules_stat.stat.exists == True
+
+- name: Set prometheus configmap
+ oc_configmap:
+ state: "{{ state }}"
+ name: "prometheus"
+ namespace: "{{ openshift_prometheus_namespace }}"
+ from_file:
+ prometheus.rules: "{{ tempdir }}/prometheus.rules"
+ prometheus.yml: "{{ tempdir }}/prometheus.yml"
+ when: additional_rules_stat.stat.exists == False
+
+# alertmanager configmap
+- template:
+ src: alertmanager.yml.j2
+ dest: "{{ tempdir }}/alertmanager.yml"
+ changed_when: no
+
+- name: Set alertmanager configmap
+ oc_configmap:
+ state: "{{ state }}"
+ name: "prometheus-alerts"
+ namespace: "{{ openshift_prometheus_namespace }}"
+ from_file:
+ alertmanager.yml: "{{ tempdir }}/alertmanager.yml"
diff --git a/roles/openshift_prometheus/tasks/main.yaml b/roles/openshift_prometheus/tasks/main.yaml
new file mode 100644
index 000000000..523a64334
--- /dev/null
+++ b/roles/openshift_prometheus/tasks/main.yaml
@@ -0,0 +1,26 @@
+---
+
+- name: Create temp directory for doing work in on target
+ command: mktemp -td openshift-prometheus-ansible-XXXXXX
+ register: mktemp
+ changed_when: False
+
+- set_fact:
+ tempdir: "{{ mktemp.stdout }}"
+
+- name: Create templates subdirectory
+ file:
+ state: directory
+ path: "{{ tempdir }}/templates"
+ mode: 0755
+ changed_when: False
+
+- include: install_prometheus.yaml
+ vars:
+ state: "{{ openshift_prometheus_state }}"
+
+- name: Delete temp directory
+ file:
+ name: "{{ tempdir }}"
+ state: absent
+ changed_when: False
diff --git a/roles/openshift_prometheus/tasks/nfs.yaml b/roles/openshift_prometheus/tasks/nfs.yaml
new file mode 100644
index 000000000..0b45f2cee
--- /dev/null
+++ b/roles/openshift_prometheus/tasks/nfs.yaml
@@ -0,0 +1,44 @@
+---
+# Tasks to statically provision NFS volumes
+# Include if not using dynamic volume provisioning
+- name: Ensure the /exports/ directory exists
+ file:
+ path: /exports/
+ state: directory
+ mode: 0755
+ owner: root
+ group: root
+
+- name: Ensure the prom-pv0X export directories exist
+ file:
+ path: "/exports/{{ item }}"
+ state: directory
+ mode: 0777
+ owner: nfsnobody
+ group: nfsnobody
+ with_items: "{{ openshift_prometheus_pv_exports }}"
+
+- name: Ensure the NFS exports for Prometheus PVs exist
+ copy:
+ src: openshift_prometheus.exports
+ dest: /etc/exports.d/openshift_prometheus.exports
+ register: nfs_exports_updated
+
+- name: Ensure the NFS export table is refreshed if exports were added
+ command: exportfs -ar
+ when:
+ - nfs_exports_updated.changed
+
+
+######################################################################
+# Create the required Prometheus PVs. Check out these online docs if you
+# need a refresher on includes looping with items:
+# * http://docs.ansible.com/ansible/playbooks_loops.html#loops-and-includes-in-2-0
+# * http://stackoverflow.com/a/35128533
+#
+# TODO: Handle the case where a PV template is updated in
+# openshift-ansible and the change needs to be landed on the managed
+# cluster.
+
+- include: create_pvs.yaml
+ with_items: "{{ openshift_prometheus_pv_data }}"
diff --git a/roles/openshift_prometheus/templates/alertmanager.yml.j2 b/roles/openshift_prometheus/templates/alertmanager.yml.j2
new file mode 100644
index 000000000..6c432a3d0
--- /dev/null
+++ b/roles/openshift_prometheus/templates/alertmanager.yml.j2
@@ -0,0 +1,20 @@
+global:
+
+# The root route on which each incoming alert enters.
+route:
+ # default route if none match
+ receiver: alert-buffer-wh
+
+ # The labels by which incoming alerts are grouped together. For example,
+ # multiple alerts coming in for cluster=A and alertname=LatencyHigh would
+ # be batched into a single group.
+ # TODO:
+ group_by: []
+
+ # All the above attributes are inherited by all child routes and can
+ # overwritten on each.
+
+receivers:
+- name: alert-buffer-wh
+ webhook_configs:
+ - url: http://localhost:9099/topics/alerts
diff --git a/roles/openshift_prometheus/templates/prom-pv-alertbuffer.yml.j2 b/roles/openshift_prometheus/templates/prom-pv-alertbuffer.yml.j2
new file mode 100644
index 000000000..55a5e19c3
--- /dev/null
+++ b/roles/openshift_prometheus/templates/prom-pv-alertbuffer.yml.j2
@@ -0,0 +1,15 @@
+apiVersion: v1
+kind: PersistentVolume
+metadata:
+ name: prometheus-alertbuffer
+ labels:
+ storage: prometheus-alertbuffer
+spec:
+ capacity:
+ storage: 15Gi
+ accessModes:
+ - ReadWriteOnce
+ nfs:
+ path: /exports/prometheus-alertbuffer
+ server: {{ openshift_prometheus_nfs_server }}
+ persistentVolumeReclaimPolicy: Retain
diff --git a/roles/openshift_prometheus/templates/prom-pv-alertmanager.yml.j2 b/roles/openshift_prometheus/templates/prom-pv-alertmanager.yml.j2
new file mode 100644
index 000000000..4ee518735
--- /dev/null
+++ b/roles/openshift_prometheus/templates/prom-pv-alertmanager.yml.j2
@@ -0,0 +1,15 @@
+apiVersion: v1
+kind: PersistentVolume
+metadata:
+ name: prometheus-alertmanager
+ labels:
+ storage: prometheus-alertmanager
+spec:
+ capacity:
+ storage: 15Gi
+ accessModes:
+ - ReadWriteOnce
+ nfs:
+ path: /exports/prometheus-alertmanager
+ server: {{ openshift_prometheus_nfs_server }}
+ persistentVolumeReclaimPolicy: Retain
diff --git a/roles/openshift_prometheus/templates/prom-pv-server.yml.j2 b/roles/openshift_prometheus/templates/prom-pv-server.yml.j2
new file mode 100644
index 000000000..933bf0f60
--- /dev/null
+++ b/roles/openshift_prometheus/templates/prom-pv-server.yml.j2
@@ -0,0 +1,15 @@
+apiVersion: v1
+kind: PersistentVolume
+metadata:
+ name: prometheus
+ labels:
+ storage: prometheus
+spec:
+ capacity:
+ storage: 15Gi
+ accessModes:
+ - ReadWriteOnce
+ nfs:
+ path: /exports/prometheus
+ server: {{ openshift_prometheus_nfs_server }}
+ persistentVolumeReclaimPolicy: Retain
diff --git a/roles/openshift_prometheus/templates/prometheus.rules.j2 b/roles/openshift_prometheus/templates/prometheus.rules.j2
new file mode 100644
index 000000000..e861dc127
--- /dev/null
+++ b/roles/openshift_prometheus/templates/prometheus.rules.j2
@@ -0,0 +1,4 @@
+groups:
+- name: example-rules
+ interval: 30s # defaults to global interval
+ rules:
diff --git a/roles/openshift_prometheus/templates/prometheus.yml.j2 b/roles/openshift_prometheus/templates/prometheus.yml.j2
new file mode 100644
index 000000000..63430f834
--- /dev/null
+++ b/roles/openshift_prometheus/templates/prometheus.yml.j2
@@ -0,0 +1,174 @@
+rule_files:
+ - 'prometheus.rules'
+{% if openshift_prometheus_additional_rules_file is defined and openshift_prometheus_additional_rules_file is not none %}
+ - 'prometheus.additional.rules'
+{% endif %}
+
+
+
+# A scrape configuration for running Prometheus on a Kubernetes cluster.
+# This uses separate scrape configs for cluster components (i.e. API server, node)
+# and services to allow each to use different authentication configs.
+#
+# Kubernetes labels will be added as Prometheus labels on metrics via the
+# `labelmap` relabeling action.
+
+# Scrape config for API servers.
+#
+# Kubernetes exposes API servers as endpoints to the default/kubernetes
+# service so this uses `endpoints` role and uses relabelling to only keep
+# the endpoints associated with the default/kubernetes service using the
+# default named port `https`. This works for single API server deployments as
+# well as HA API server deployments.
+scrape_configs:
+- job_name: 'kubernetes-apiservers'
+
+ kubernetes_sd_configs:
+ - role: endpoints
+
+ scheme: https
+ tls_config:
+ ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
+ bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
+
+ # Keep only the default/kubernetes service endpoints for the https port. This
+ # will add targets for each API server which Kubernetes adds an endpoint to
+ # the default/kubernetes service.
+ relabel_configs:
+ - source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]
+ action: keep
+ regex: default;kubernetes;https
+
+# Scrape config for nodes.
+#
+# Each node exposes a /metrics endpoint that contains operational metrics for
+# the Kubelet and other components.
+- job_name: 'kubernetes-nodes'
+
+ scheme: https
+ tls_config:
+ ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
+ bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
+
+ kubernetes_sd_configs:
+ - role: node
+
+ relabel_configs:
+ - action: labelmap
+ regex: __meta_kubernetes_node_label_(.+)
+
+# Scrape config for controllers.
+#
+# Each master node exposes a /metrics endpoint on :8444 that contains operational metrics for
+# the controllers.
+#
+# TODO: move this to a pure endpoints based metrics gatherer when controllers are exposed via
+# endpoints.
+- job_name: 'kubernetes-controllers'
+
+ scheme: https
+ tls_config:
+ ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
+ bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
+
+ kubernetes_sd_configs:
+ - role: endpoints
+
+ # Keep only the default/kubernetes service endpoints for the https port, and then
+ # set the port to 8444. This is the default configuration for the controllers on OpenShift
+ # masters.
+ relabel_configs:
+ - source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]
+ action: keep
+ regex: default;kubernetes;https
+ - source_labels: [__address__]
+ action: replace
+ target_label: __address__
+ regex: (.+)(?::\d+)
+ replacement: $1:8444
+
+# Scrape config for cAdvisor.
+#
+# Beginning in Kube 1.7, each node exposes a /metrics/cadvisor endpoint that
+# reports container metrics for each running pod. Scrape those by default.
+- job_name: 'kubernetes-cadvisor'
+
+ scheme: https
+ tls_config:
+ ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
+ bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
+
+{% if kubernetes_version | float() >= 1.7 | float() %}
+ metrics_path: /metrics/cadvisor
+{% else %}
+ metrics_path: /metrics
+{% endif %}
+
+ kubernetes_sd_configs:
+ - role: node
+
+ relabel_configs:
+ - action: labelmap
+ regex: __meta_kubernetes_node_label_(.+)
+
+# Scrape config for service endpoints.
+#
+# The relabeling allows the actual service scrape endpoint to be configured
+# via the following annotations:
+#
+# * `prometheus.io/scrape`: Only scrape services that have a value of `true`
+# * `prometheus.io/scheme`: If the metrics endpoint is secured then you will need
+# to set this to `https` & most likely set the `tls_config` of the scrape config.
+# * `prometheus.io/path`: If the metrics path is not `/metrics` override this.
+# * `prometheus.io/port`: If the metrics are exposed on a different port to the
+# service then set this appropriately.
+- job_name: 'kubernetes-service-endpoints'
+
+ tls_config:
+ ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
+ # TODO: this should be per target
+ insecure_skip_verify: true
+
+ kubernetes_sd_configs:
+ - role: endpoints
+
+ relabel_configs:
+ - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape]
+ action: keep
+ regex: true
+ - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scheme]
+ action: replace
+ target_label: __scheme__
+ regex: (https?)
+ - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_path]
+ action: replace
+ target_label: __metrics_path__
+ regex: (.+)
+ - source_labels: [__address__, __meta_kubernetes_service_annotation_prometheus_io_port]
+ action: replace
+ target_label: __address__
+ regex: (.+)(?::\d+);(\d+)
+ replacement: $1:$2
+ - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_username]
+ action: replace
+ target_label: __basic_auth_username__
+ regex: (.+)
+ - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_password]
+ action: replace
+ target_label: __basic_auth_password__
+ regex: (.+)
+ - action: labelmap
+ regex: __meta_kubernetes_service_label_(.+)
+ - source_labels: [__meta_kubernetes_namespace]
+ action: replace
+ target_label: kubernetes_namespace
+ - source_labels: [__meta_kubernetes_service_name]
+ action: replace
+ target_label: kubernetes_name
+
+alerting:
+ alertmanagers:
+ - scheme: http
+ static_configs:
+ - targets:
+ - "localhost:9093"
diff --git a/roles/openshift_prometheus/templates/prometheus_deployment.j2 b/roles/openshift_prometheus/templates/prometheus_deployment.j2
new file mode 100644
index 000000000..98c117f19
--- /dev/null
+++ b/roles/openshift_prometheus/templates/prometheus_deployment.j2
@@ -0,0 +1,240 @@
+apiVersion: extensions/v1beta1
+kind: Deployment
+metadata:
+ name: prometheus
+ namespace: {{ namespace }}
+ labels:
+ app: prometheus
+spec:
+ replicas: {{ prom_replicas|default(1) }}
+ selector:
+ provider: openshift
+ matchLabels:
+ app: prometheus
+ template:
+ metadata:
+ name: prometheus
+ labels:
+ app: prometheus
+ spec:
+ serviceAccountName: prometheus
+{% if openshift_prometheus_node_selector is iterable and openshift_prometheus_node_selector | length > 0 %}
+ nodeSelector:
+{% for key, value in openshift_prometheus_node_selector.iteritems() %}
+ {{key}}: "{{value}}"
+{% endfor %}
+{% endif %}
+ containers:
+ # Deploy Prometheus behind an oauth proxy
+ - name: prom-proxy
+ image: "{{ openshift_prometheus_image_proxy }}"
+ imagePullPolicy: IfNotPresent
+ resources:
+ requests:
+{% if openshift_prometheus_oauth_proxy_memory_requests is defined and openshift_prometheus_oauth_proxy_memory_requests is not none %}
+ memory: "{{openshift_prometheus_oauth_proxy_memory_requests}}"
+{% endif %}
+{% if openshift_prometheus_oauth_proxy_cpu_requests is defined and openshift_prometheus_oauth_proxy_cpu_requests is not none %}
+ cpu: "{{openshift_prometheus_oauth_proxy_cpu_requests}}"
+{% endif %}
+ limits:
+{% if openshift_prometheus_memory_requests_limit_proxy is defined and openshift_prometheus_oauth_proxy_memory_limit is not none %}
+ memory: "{{openshift_prometheus_oauth_proxy_memory_limit}}"
+{% endif %}
+{% if openshift_prometheus_oauth_proxy_cpu_limit is defined and openshift_prometheus_oauth_proxy_cpu_limit is not none %}
+ cpu: "{{openshift_prometheus_oauth_proxy_cpu_limit}}"
+{% endif %}
+ ports:
+ - containerPort: 8443
+ name: web
+ args:
+ - -provider=openshift
+ - -https-address=:8443
+ - -http-address=
+ - -email-domain=*
+ - -upstream=http://localhost:9090
+ - -client-id=system:serviceaccount:{{ namespace }}:prometheus
+ - '-openshift-sar={"resource": "namespaces", "verb": "get", "resourceName": "{{ namespace }}", "namespace": "{{ namespace }}"}'
+ - '-openshift-delegate-urls={"/": {"resource": "namespaces", "verb": "get", "resourceName": "{{ namespace }}", "namespace": "{{ namespace }}"}}'
+ - -tls-cert=/etc/tls/private/tls.crt
+ - -tls-key=/etc/tls/private/tls.key
+ - -client-secret-file=/var/run/secrets/kubernetes.io/serviceaccount/token
+ - -cookie-secret-file=/etc/proxy/secrets/session_secret
+ - -skip-auth-regex=^/metrics
+ volumeMounts:
+ - mountPath: /etc/tls/private
+ name: prometheus-tls
+ - mountPath: /etc/proxy/secrets
+ name: prometheus-secrets
+ - mountPath: /prometheus
+ name: prometheus-data
+
+ - name: prometheus
+ args:
+ - --storage.tsdb.retention=6h
+ - --config.file=/etc/prometheus/prometheus.yml
+ - --web.listen-address=localhost:9090
+ image: "{{ openshift_prometheus_image_prometheus }}"
+ imagePullPolicy: IfNotPresent
+ resources:
+ requests:
+{% if openshift_prometheus_memory_requests is defined and openshift_prometheus_memory_requests is not none %}
+ memory: "{{openshift_prometheus_memory_requests}}"
+{% endif %}
+{% if openshift_prometheus_cpu_requests is defined and openshift_prometheus_cpu_requests is not none %}
+ cpu: "{{openshift_prometheus_cpu_requests}}"
+{% endif %}
+ limits:
+{% if openshift_prometheus_memory_limit is defined and openshift_prometheus_memory_limit is not none %}
+ memory: "{{ openshift_prometheus_memory_limit }}"
+{% endif %}
+{% if openshift_prometheus_cpu_limit is defined and openshift_prometheus_cpu_limit is not none %}
+ cpu: "{{openshift_prometheus_cpu_limit}}"
+{% endif %}
+
+ volumeMounts:
+ - mountPath: /etc/prometheus
+ name: prometheus-config
+ - mountPath: /prometheus
+ name: prometheus-data
+
+ # Deploy alertmanager behind prometheus-alert-buffer behind an oauth proxy
+ - name: alerts-proxy
+ image: "{{ openshift_prometheus_image_proxy }}"
+ imagePullPolicy: IfNotPresent
+ resources:
+ requests:
+{% if openshift_prometheus_oauth_proxy_memory_requests is defined and openshift_prometheus_oauth_proxy_memory_requests is not none %}
+ memory: "{{openshift_prometheus_oauth_proxy_memory_requests}}"
+{% endif %}
+{% if openshift_prometheus_oauth_proxy_cpu_requests is defined and openshift_prometheus_oauth_proxy_cpu_requests is not none %}
+ cpu: "{{openshift_prometheus_oauth_proxy_cpu_requests}}"
+{% endif %}
+ limits:
+{% if openshift_prometheus_oauth_proxy_memory_limit is defined and openshift_prometheus_oauth_proxy_memory_limit is not none %}
+ memory: "{{openshift_prometheus_oauth_proxy_memory_limit}}"
+{% endif %}
+{% if openshift_prometheus_oauth_proxy_cpu_limit is defined and openshift_prometheus_oauth_proxy_cpu_limit is not none %}
+ cpu: "{{openshift_prometheus_oauth_proxy_cpu_limit}}"
+{% endif %}
+ ports:
+ - containerPort: 9443
+ name: web
+ args:
+ - -provider=openshift
+ - -https-address=:9443
+ - -http-address=
+ - -email-domain=*
+ - -upstream=http://localhost:9099
+ - -client-id=system:serviceaccount:{{ namespace }}:prometheus
+ - '-openshift-sar={"resource": "namespaces", "verb": "get", "resourceName": "{{ namespace }}", "namespace": "{{ namespace }}"}'
+ - '-openshift-delegate-urls={"/": {"resource": "namespaces", "verb": "get", "resourceName": "{{ namespace }}", "namespace": "{{ namespace }}"}}'
+ - -tls-cert=/etc/tls/private/tls.crt
+ - -tls-key=/etc/tls/private/tls.key
+ - -client-secret-file=/var/run/secrets/kubernetes.io/serviceaccount/token
+ - -cookie-secret-file=/etc/proxy/secrets/session_secret
+ volumeMounts:
+ - mountPath: /etc/tls/private
+ name: alerts-tls
+ - mountPath: /etc/proxy/secrets
+ name: alerts-secrets
+
+ - name: alert-buffer
+ args:
+ - --storage-path=/alert-buffer/messages.db
+ image: "{{ openshift_prometheus_image_alertbuffer }}"
+ imagePullPolicy: IfNotPresent
+ resources:
+ requests:
+{% if openshift_prometheus_alertbuffer_memory_requests is defined and openshift_prometheus_alertbuffer_memory_requests is not none %}
+ memory: "{{openshift_prometheus_alertbuffer_memory_requests}}"
+{% endif %}
+{% if openshift_prometheus_alertbuffer_cpu_requests is defined and openshift_prometheus_alertbuffer_cpu_requests is not none %}
+ cpu: "{{openshift_prometheus_alertbuffer_cpu_requests}}"
+{% endif %}
+ limits:
+{% if openshift_prometheus_alertbuffer_memory_limit is defined and openshift_prometheus_alertbuffer_memory_limit is not none %}
+ memory: "{{openshift_prometheus_alertbuffer_memory_limit}}"
+{% endif %}
+{% if openshift_prometheus_alertbuffer_cpu_limit is defined and openshift_prometheus_alertbuffer_cpu_limit is not none %}
+ cpu: "{{openshift_prometheus_alertbuffer_cpu_limit}}"
+{% endif %}
+ volumeMounts:
+ - mountPath: /alert-buffer
+ name: alert-buffer-data
+ ports:
+ - containerPort: 9099
+ name: alert-buf
+
+ - name: alertmanager
+ args:
+ - -config.file=/etc/alertmanager/alertmanager.yml
+ image: "{{ openshift_prometheus_image_alertmanager }}"
+ imagePullPolicy: IfNotPresent
+ resources:
+ requests:
+{% if openshift_prometheus_alertmanager_memory_requests is defined and openshift_prometheus_alertmanager_memory_requests is not none %}
+ memory: "{{openshift_prometheus_alertmanager_memory_requests}}"
+{% endif %}
+{% if openshift_prometheus_alertmanager_cpu_requests is defined and openshift_prometheus_alertmanager_cpu_requests is not none %}
+ cpu: "{{openshift_prometheus_alertmanager_cpu_requests}}"
+{% endif %}
+ limits:
+{% if openshift_prometheus_alertmanager_memory_limit is defined and openshift_prometheus_alertmanager_memory_limit is not none %}
+ memory: "{{openshift_prometheus_alertmanager_memory_limit}}"
+{% endif %}
+{% if openshift_prometheus_alertmanager_cpu_limit is defined and openshift_prometheus_alertmanager_cpu_limit is not none %}
+ cpu: "{{openshift_prometheus_alertmanager_cpu_limit}}"
+{% endif %}
+ ports:
+ - containerPort: 9093
+ name: web
+ volumeMounts:
+ - mountPath: /etc/alertmanager
+ name: alertmanager-config
+ - mountPath: /alertmanager
+ name: alertmanager-data
+
+ restartPolicy: Always
+ volumes:
+ - name: prometheus-config
+ configMap:
+ defaultMode: 420
+ name: prometheus
+ - name: prometheus-secrets
+ secret:
+ secretName: prometheus-proxy
+ - name: prometheus-tls
+ secret:
+ secretName: prometheus-tls
+ - name: prometheus-data
+{% if openshift_prometheus_storage_type == 'pvc' %}
+ persistentVolumeClaim:
+ claimName: {{ openshift_prometheus_pvc_name }}
+{% else %}
+ emptydir: {}
+{% endif %}
+ - name: alertmanager-config
+ configMap:
+ defaultMode: 420
+ name: prometheus-alerts
+ - name: alerts-secrets
+ secret:
+ secretName: alerts-proxy
+ - name: alerts-tls
+ secret:
+ secretName: prometheus-alerts-tls
+ - name: alertmanager-data
+{% if openshift_prometheus_alertmanager_storage_type == 'pvc' %}
+ persistentVolumeClaim:
+ claimName: {{ openshift_prometheus_alertmanager_pvc_name }}
+{% else %}
+ emptydir: {}
+{% endif %}
+ - name: alert-buffer-data
+{% if openshift_prometheus_alertbuffer_storage_type == 'pvc' %}
+ persistentVolumeClaim:
+ claimName: {{ openshift_prometheus_alertbuffer_pvc_name }}
+{% else %}
+ emptydir: {}
+{% endif %}
diff --git a/roles/openshift_prometheus/tests/inventory b/roles/openshift_prometheus/tests/inventory
new file mode 100644
index 000000000..878877b07
--- /dev/null
+++ b/roles/openshift_prometheus/tests/inventory
@@ -0,0 +1,2 @@
+localhost
+
diff --git a/roles/openshift_prometheus/tests/test.yaml b/roles/openshift_prometheus/tests/test.yaml
new file mode 100644
index 000000000..37baf573c
--- /dev/null
+++ b/roles/openshift_prometheus/tests/test.yaml
@@ -0,0 +1,5 @@
+---
+- hosts: localhost
+ remote_user: root
+ roles:
+ - openshift_prometheus
diff --git a/roles/openshift_repos/README.md b/roles/openshift_repos/README.md
index abd1997dd..ce3b51454 100644
--- a/roles/openshift_repos/README.md
+++ b/roles/openshift_repos/README.md
@@ -1,4 +1,4 @@
-OpenShift Repos
+OpenShift Repos
================
Configures repositories for an OpenShift installation
@@ -12,10 +12,10 @@ rhel-7-server-extra-rpms, and rhel-7-server-ose-3.0-rpms repos.
Role Variables
--------------
-| Name | Default value | |
-|-------------------------------|---------------|------------------------------------|
-| openshift_deployment_type | None | Possible values enterprise, origin |
-| openshift_additional_repos | {} | TODO |
+| Name | Default value | |
+|-------------------------------|---------------|----------------------------------------------|
+| openshift_deployment_type | None | Possible values openshift-enterprise, origin |
+| openshift_additional_repos | {} | TODO |
Dependencies
------------
diff --git a/roles/openshift_repos/tasks/main.yaml b/roles/openshift_repos/tasks/main.yaml
index 7458db87e..f972c0fd9 100644
--- a/roles/openshift_repos/tasks/main.yaml
+++ b/roles/openshift_repos/tasks/main.yaml
@@ -6,23 +6,24 @@
- when: not ostree_booted.stat.exists
block:
+ # TODO: This needs to be removed and placed into a role
- name: Ensure libselinux-python is installed
package: name=libselinux-python state=present
- name: Create any additional repos that are defined
- template:
- src: yum_repo.j2
- dest: /etc/yum.repos.d/openshift_additional.repo
- when:
- - openshift_additional_repos | length > 0
- notify: refresh cache
-
- - name: Remove the additional repos if no longer defined
- file:
- dest: /etc/yum.repos.d/openshift_additional.repo
- state: absent
- when:
- - openshift_additional_repos | length == 0
+ yum_repository:
+ description: "{{ item.description | default(item.name | default(item.id)) }}"
+ name: "{{ item.name | default(item.id) }}"
+ baseurl: "{{ item.baseurl }}"
+ gpgkey: "{{ item.gpgkey | default(omit)}}"
+ gpgcheck: "{{ item.gpgcheck | default(1) }}"
+ sslverify: "{{ item.sslverify | default(1) }}"
+ sslclientkey: "{{ item.sslclientkey | default(omit) }}"
+ sslclientcert: "{{ item.sslclientcert | default(omit) }}"
+ file: "{{ item.name }}"
+ enabled: "{{ item.enabled | default('no')}}"
+ with_items: "{{ openshift_additional_repos }}"
+ when: openshift_additional_repos | length > 0
notify: refresh cache
# Singleton block
diff --git a/roles/openshift_repos/templates/yum_repo.j2 b/roles/openshift_repos/templates/yum_repo.j2
deleted file mode 100644
index ef2cd6603..000000000
--- a/roles/openshift_repos/templates/yum_repo.j2
+++ /dev/null
@@ -1,14 +0,0 @@
-{% for repo in openshift_additional_repos %}
-[{{ repo.id }}]
-name={{ repo.name | default(repo.id) }}
-baseurl={{ repo.baseurl }}
-{% set enable_repo = repo.enabled | default(1) %}
-enabled={{ 1 if ( enable_repo == 1 or enable_repo == True ) else 0 }}
-{% set enable_gpg_check = repo.gpgcheck | default(1) %}
-gpgcheck={{ 1 if ( enable_gpg_check == 1 or enable_gpg_check == True ) else 0 }}
-{% for key, value in repo.iteritems() %}
-{% if key not in ['id', 'name', 'baseurl', 'enabled', 'gpgcheck'] and value is defined %}
-{{ key }}={{ value }}
-{% endif %}
-{% endfor %}
-{% endfor %}
diff --git a/roles/openshift_sanitize_inventory/tasks/main.yml b/roles/openshift_sanitize_inventory/tasks/main.yml
index 59ce505d3..47d7be05a 100644
--- a/roles/openshift_sanitize_inventory/tasks/main.yml
+++ b/roles/openshift_sanitize_inventory/tasks/main.yml
@@ -12,6 +12,27 @@
deployment_type is deprecated in favor of openshift_deployment_type.
Please specify only openshift_deployment_type, or make both the same.
+# osm_cluster_network_cidr, osm_host_subnet_length and openshift_portal_net are
+# now required to avoid changes that may occur between releases
+#
+# Note: We will skip these checks when some tests run which don't
+# actually do any insalling/upgrading/scaling/etc..
+# Reference: https://bugzilla.redhat.com/show_bug.cgi?id=1451023
+- when:
+ - not testing_skip_some_requirements|default(False)|bool
+ assert:
+ that:
+ - "osm_cluster_network_cidr is defined"
+ - "osm_host_subnet_length is defined"
+ - "openshift_portal_net is defined"
+ msg: >
+ osm_cluster_network_cidr, osm_host_subnet_length, and openshift_portal_net are required inventory
+ variables. If you are upgrading or scaling up these variables should match what is currently used
+ in the cluster. If you don't remember what these values are you can find them in
+ /etc/origin/master/master-config.yaml on a master with the names clusterNetworkCIDR
+ (osm_cluster_network_cidr), hostSubnetLength (osm_host_subnet_length),
+ and serviceNetworkCIDR (openshift_portal_net).
+
- name: Standardize on latest variable names
set_fact:
# goal is to deprecate deployment_type in favor of openshift_deployment_type.
diff --git a/roles/openshift_sanitize_inventory/vars/main.yml b/roles/openshift_sanitize_inventory/vars/main.yml
index da48e42c1..37e88758d 100644
--- a/roles/openshift_sanitize_inventory/vars/main.yml
+++ b/roles/openshift_sanitize_inventory/vars/main.yml
@@ -1,7 +1,4 @@
---
# origin uses community packages named 'origin'
-# online currently uses 'openshift' packages
-# enterprise is used for OSE 3.0 < 3.1 which uses packages named 'openshift'
-# atomic-enterprise uses Red Hat packages named 'atomic-openshift'
-# openshift-enterprise uses Red Hat packages named 'atomic-openshift' starting with OSE 3.1
-known_openshift_deployment_types: ['origin', 'online', 'enterprise', 'atomic-enterprise', 'openshift-enterprise']
+# openshift-enterprise uses Red Hat packages named 'atomic-openshift'
+known_openshift_deployment_types: ['origin', 'openshift-enterprise']
diff --git a/roles/openshift_service_catalog/defaults/main.yml b/roles/openshift_service_catalog/defaults/main.yml
index 01ee2544d..7c848cb12 100644
--- a/roles/openshift_service_catalog/defaults/main.yml
+++ b/roles/openshift_service_catalog/defaults/main.yml
@@ -1,3 +1,7 @@
---
openshift_service_catalog_remove: false
openshift_service_catalog_nodeselector: {"openshift-infra": "apiserver"}
+
+openshift_use_openshift_sdn: True
+# os_sdn_network_plugin_name: "{% if openshift_use_openshift_sdn %}redhat/openshift-ovs-subnet{% else %}{% endif %}"
+os_sdn_network_plugin_name: "redhat/openshift-ovs-subnet"
diff --git a/roles/openshift_service_catalog/files/openshift-ansible-catalog-console.js b/roles/openshift_service_catalog/files/openshift-ansible-catalog-console.js
index 1f25cc39f..16a307c06 100644
--- a/roles/openshift_service_catalog/files/openshift-ansible-catalog-console.js
+++ b/roles/openshift_service_catalog/files/openshift-ansible-catalog-console.js
@@ -1,2 +1 @@
window.OPENSHIFT_CONSTANTS.ENABLE_TECH_PREVIEW_FEATURE.service_catalog_landing_page = true;
-window.OPENSHIFT_CONSTANTS.ENABLE_TECH_PREVIEW_FEATURE.pod_presets = true;
diff --git a/roles/openshift_service_catalog/tasks/install.yml b/roles/openshift_service_catalog/tasks/install.yml
index 686857d94..746c73eaf 100644
--- a/roles/openshift_service_catalog/tasks/install.yml
+++ b/roles/openshift_service_catalog/tasks/install.yml
@@ -28,7 +28,7 @@
- name: Make kube-service-catalog project network global
command: >
oc adm pod-network make-projects-global kube-service-catalog
- when: os_sdn_network_plugin_name | default('') == 'redhat/openshift-ovs-multitenant'
+ when: os_sdn_network_plugin_name == 'redhat/openshift-ovs-multitenant'
- include: generate_certs.yml
@@ -168,19 +168,19 @@
- "{{ mktemp.stdout }}/service_catalog_api_server.yml"
delete_after: yes
-- template:
- src: api_server_service.j2
- dest: "{{ mktemp.stdout }}/service_catalog_api_service.yml"
-
- name: Set Service Catalog API Server service
- oc_obj:
- state: present
- namespace: "kube-service-catalog"
- kind: service
+ oc_service:
name: apiserver
- files:
- - "{{ mktemp.stdout }}/service_catalog_api_service.yml"
- delete_after: yes
+ namespace: kube-service-catalog
+ state: present
+ ports:
+ - name: secure
+ port: 443
+ protocol: TCP
+ targetPort: 6443
+ selector:
+ app: apiserver
+ session_affinity: None
- template:
src: api_server_route.j2
@@ -216,19 +216,19 @@
- "{{ mktemp.stdout }}/controller_manager.yml"
delete_after: yes
-- template:
- src: controller_manager_service.j2
- dest: "{{ mktemp.stdout }}/controller_manager_service.yml"
-
- name: Set Controller Manager service
- oc_obj:
- state: present
- namespace: "kube-service-catalog"
- kind: service
+ oc_service:
name: controller-manager
- files:
- - "{{ mktemp.stdout }}/controller_manager_service.yml"
- delete_after: yes
+ namespace: kube-service-catalog
+ state: present
+ ports:
+ - port: 6443
+ protocol: TCP
+ targetPort: 6443
+ selector:
+ app: controller-manager
+ session_affinity: None
+ service_type: ClusterIP
- include: start_api_server.yml
diff --git a/roles/openshift_service_catalog/templates/api_server_service.j2 b/roles/openshift_service_catalog/templates/api_server_service.j2
deleted file mode 100644
index bae337201..000000000
--- a/roles/openshift_service_catalog/templates/api_server_service.j2
+++ /dev/null
@@ -1,13 +0,0 @@
-apiVersion: v1
-kind: Service
-metadata:
- name: apiserver
-spec:
- ports:
- - name: secure
- port: 443
- protocol: TCP
- targetPort: 6443
- selector:
- app: apiserver
- sessionAffinity: None
diff --git a/roles/openshift_service_catalog/templates/controller_manager_service.j2 b/roles/openshift_service_catalog/templates/controller_manager_service.j2
deleted file mode 100644
index 2bac645fc..000000000
--- a/roles/openshift_service_catalog/templates/controller_manager_service.j2
+++ /dev/null
@@ -1,13 +0,0 @@
-apiVersion: v1
-kind: Service
-metadata:
- name: controller-manager
-spec:
- ports:
- - port: 6443
- protocol: TCP
- targetPort: 6443
- selector:
- app: controller-manager
- sessionAffinity: None
- type: ClusterIP
diff --git a/roles/openshift_storage_glusterfs/README.md b/roles/openshift_storage_glusterfs/README.md
index d3de2165a..d0bc0e028 100644
--- a/roles/openshift_storage_glusterfs/README.md
+++ b/roles/openshift_storage_glusterfs/README.md
@@ -55,7 +55,7 @@ defined:
| Name | Default value | Description |
|-------------------|---------------|-----------------------------------------|
-| glusterfs_devices | None | A list of block devices that will be completely managed as part of a GlusterFS cluster. There must be at least one device listed. Each device must be bare, e.g. no partitions or LVM PVs. **Example:** '[ "/dev/sdb" ]'
+| glusterfs_devices | None | A list of block devices that will be completely managed as part of a GlusterFS cluster. There must be at least one device listed. Each device must be bare, e.g. no partitions or LVM PVs. **Example:** '[ "/dev/sdb" ]' **NOTE:** You MUST set this as a host variable on each node host. For some reason, if you set this as a group variable it gets interpreted as a string rather than an array. See https://github.com/openshift/openshift-ansible/issues/5071
In addition, each host may specify the following variables to further control
their configuration as GlusterFS nodes:
@@ -76,10 +76,11 @@ GlusterFS cluster into a new or existing OpenShift cluster:
| Name | Default value | Description |
|--------------------------------------------------|-------------------------|-----------------------------------------|
| openshift_storage_glusterfs_timeout | 300 | Seconds to wait for pods to become ready
-| openshift_storage_glusterfs_namespace | 'glusterfs' | Namespace in which to create GlusterFS resources
+| openshift_storage_glusterfs_namespace | 'glusterfs' | Namespace/project in which to create GlusterFS resources
| openshift_storage_glusterfs_is_native | True | GlusterFS should be containerized
| openshift_storage_glusterfs_name | 'storage' | A name to identify the GlusterFS cluster, which will be used in resource names
| openshift_storage_glusterfs_nodeselector | 'glusterfs=storage-host'| Selector to determine which nodes will host GlusterFS pods in native mode. **NOTE:** The label value is taken from the cluster name
+| openshift_storage_glusterfs_use_default_selector | False | Whether to use a default node selector for the GlusterFS namespace/project. If False, the namespace/project will have no restricting node selector. If True, uses pre-existing or default (e.g. osm_default_node_selector) node selectors. **NOTE:** If True, nodes which will host GlusterFS pods must already have the additional labels.
| openshift_storage_glusterfs_storageclass | True | Automatically create a StorageClass for each GlusterFS cluster
| openshift_storage_glusterfs_image | 'gluster/gluster-centos'| Container image to use for GlusterFS pods, enterprise default is 'rhgs3/rhgs-server-rhel7'
| openshift_storage_glusterfs_version | 'latest' | Container image version to use for GlusterFS pods
@@ -91,7 +92,7 @@ GlusterFS cluster into a new or existing OpenShift cluster:
| openshift_storage_glusterfs_heketi_admin_key | auto-generated | String to use as secret key for performing heketi commands as admin
| openshift_storage_glusterfs_heketi_user_key | auto-generated | String to use as secret key for performing heketi commands as user that can only view or modify volumes
| openshift_storage_glusterfs_heketi_topology_load | True | Load the GlusterFS topology information into heketi
-| openshift_storage_glusterfs_heketi_url | Undefined | When heketi is native, this sets the hostname portion of the final heketi route URL. When heketi is external, this is the full URL to the heketi service.
+| openshift_storage_glusterfs_heketi_url | Undefined | When heketi is native, this sets the hostname portion of the final heketi route URL. When heketi is external, this is the FQDN or IP address to the heketi service.
| openshift_storage_glusterfs_heketi_port | 8080 | TCP port for external heketi service **NOTE:** This has no effect in native mode
| openshift_storage_glusterfs_heketi_executor | 'kubernetes' | Selects how a native heketi service will manage GlusterFS nodes: 'kubernetes' for native nodes, 'ssh' for external nodes
| openshift_storage_glusterfs_heketi_ssh_port | 22 | SSH port for external GlusterFS nodes via native heketi
diff --git a/roles/openshift_storage_glusterfs/defaults/main.yml b/roles/openshift_storage_glusterfs/defaults/main.yml
index a5887465e..148549887 100644
--- a/roles/openshift_storage_glusterfs/defaults/main.yml
+++ b/roles/openshift_storage_glusterfs/defaults/main.yml
@@ -3,6 +3,7 @@ openshift_storage_glusterfs_timeout: 300
openshift_storage_glusterfs_is_native: True
openshift_storage_glusterfs_name: 'storage'
openshift_storage_glusterfs_nodeselector: "glusterfs={{ openshift_storage_glusterfs_name }}-host"
+openshift_storage_glusterfs_use_default_selector: False
openshift_storage_glusterfs_storageclass: True
openshift_storage_glusterfs_image: "{{ 'rhgs3/rhgs-server-rhel7' | quote if deployment_type == 'openshift-enterprise' else 'gluster/gluster-centos' | quote }}"
openshift_storage_glusterfs_version: 'latest'
@@ -31,6 +32,7 @@ openshift_storage_glusterfs_registry_namespace: "{{ openshift.hosted.registry.na
openshift_storage_glusterfs_registry_is_native: "{{ openshift_storage_glusterfs_is_native }}"
openshift_storage_glusterfs_registry_name: 'registry'
openshift_storage_glusterfs_registry_nodeselector: "glusterfs={{ openshift_storage_glusterfs_registry_name }}-host"
+openshift_storage_glusterfs_registry_use_default_selector: "{{ openshift_storage_glusterfs_use_default_selector }}"
openshift_storage_glusterfs_registry_storageclass: False
openshift_storage_glusterfs_registry_image: "{{ openshift_storage_glusterfs_image }}"
openshift_storage_glusterfs_registry_version: "{{ openshift_storage_glusterfs_version }}"
@@ -52,15 +54,15 @@ openshift_storage_glusterfs_registry_heketi_ssh_port: "{{ openshift_storage_glus
openshift_storage_glusterfs_registry_heketi_ssh_user: "{{ openshift_storage_glusterfs_heketi_ssh_user }}"
openshift_storage_glusterfs_registry_heketi_ssh_sudo: "{{ openshift_storage_glusterfs_heketi_ssh_sudo }}"
openshift_storage_glusterfs_registry_heketi_ssh_keyfile: "{{ openshift_storage_glusterfs_heketi_ssh_keyfile | default(omit) }}"
-r_openshift_master_firewall_enabled: True
-r_openshift_master_use_firewalld: False
+r_openshift_storage_glusterfs_firewall_enabled: "{{ os_firewall_enabled | default(True) }}"
+r_openshift_storage_glusterfs_use_firewalld: "{{ os_firewall_use_firewalld | default(False) }}"
r_openshift_storage_glusterfs_os_firewall_deny: []
r_openshift_storage_glusterfs_os_firewall_allow:
- service: glusterfs_sshd
port: "2222/tcp"
-- service: glusterfs_daemon
- port: "24007/tcp"
- service: glusterfs_management
+ port: "24007/tcp"
+- service: glusterfs_rdma
port: "24008/tcp"
- service: glusterfs_bricks
port: "49152-49251/tcp"
diff --git a/roles/openshift_storage_glusterfs/files/v3.7/deploy-heketi-template.yml b/roles/openshift_storage_glusterfs/files/v3.7/deploy-heketi-template.yml
new file mode 100644
index 000000000..9ebb0d5ec
--- /dev/null
+++ b/roles/openshift_storage_glusterfs/files/v3.7/deploy-heketi-template.yml
@@ -0,0 +1,143 @@
+---
+kind: Template
+apiVersion: v1
+metadata:
+ name: deploy-heketi
+ labels:
+ glusterfs: heketi-template
+ deploy-heketi: support
+ annotations:
+ description: Bootstrap Heketi installation
+ tags: glusterfs,heketi,installation
+objects:
+- kind: Service
+ apiVersion: v1
+ metadata:
+ name: deploy-heketi-${CLUSTER_NAME}
+ labels:
+ glusterfs: deploy-heketi-${CLUSTER_NAME}-service
+ deploy-heketi: support
+ annotations:
+ description: Exposes Heketi service
+ spec:
+ ports:
+ - name: deploy-heketi-${CLUSTER_NAME}
+ port: 8080
+ targetPort: 8080
+ selector:
+ glusterfs: deploy-heketi-${CLUSTER_NAME}-pod
+- kind: Route
+ apiVersion: v1
+ metadata:
+ name: ${HEKETI_ROUTE}
+ labels:
+ glusterfs: deploy-heketi-${CLUSTER_NAME}-route
+ deploy-heketi: support
+ spec:
+ to:
+ kind: Service
+ name: deploy-heketi-${CLUSTER_NAME}
+- kind: DeploymentConfig
+ apiVersion: v1
+ metadata:
+ name: deploy-heketi-${CLUSTER_NAME}
+ labels:
+ glusterfs: deploy-heketi-${CLUSTER_NAME}-dc
+ deploy-heketi: support
+ annotations:
+ description: Defines how to deploy Heketi
+ spec:
+ replicas: 1
+ selector:
+ glusterfs: deploy-heketi-${CLUSTER_NAME}-pod
+ triggers:
+ - type: ConfigChange
+ strategy:
+ type: Recreate
+ template:
+ metadata:
+ name: deploy-heketi
+ labels:
+ glusterfs: deploy-heketi-${CLUSTER_NAME}-pod
+ deploy-heketi: support
+ spec:
+ serviceAccountName: heketi-${CLUSTER_NAME}-service-account
+ containers:
+ - name: heketi
+ image: ${IMAGE_NAME}:${IMAGE_VERSION}
+ env:
+ - name: HEKETI_USER_KEY
+ value: ${HEKETI_USER_KEY}
+ - name: HEKETI_ADMIN_KEY
+ value: ${HEKETI_ADMIN_KEY}
+ - name: HEKETI_EXECUTOR
+ value: ${HEKETI_EXECUTOR}
+ - name: HEKETI_FSTAB
+ value: /var/lib/heketi/fstab
+ - name: HEKETI_SNAPSHOT_LIMIT
+ value: '14'
+ - name: HEKETI_KUBE_GLUSTER_DAEMONSET
+ value: '1'
+ - name: HEKETI_KUBE_NAMESPACE
+ value: ${HEKETI_KUBE_NAMESPACE}
+ ports:
+ - containerPort: 8080
+ volumeMounts:
+ - name: db
+ mountPath: /var/lib/heketi
+ - name: topology
+ mountPath: ${TOPOLOGY_PATH}
+ - name: config
+ mountPath: /etc/heketi
+ readinessProbe:
+ timeoutSeconds: 3
+ initialDelaySeconds: 3
+ httpGet:
+ path: /hello
+ port: 8080
+ livenessProbe:
+ timeoutSeconds: 3
+ initialDelaySeconds: 30
+ httpGet:
+ path: /hello
+ port: 8080
+ volumes:
+ - name: db
+ - name: topology
+ secret:
+ secretName: heketi-${CLUSTER_NAME}-topology-secret
+ - name: config
+ secret:
+ secretName: heketi-${CLUSTER_NAME}-config-secret
+parameters:
+- name: HEKETI_USER_KEY
+ displayName: Heketi User Secret
+ description: Set secret for those creating volumes as type _user_
+- name: HEKETI_ADMIN_KEY
+ displayName: Heketi Administrator Secret
+ description: Set secret for administration of the Heketi service as user _admin_
+- name: HEKETI_EXECUTOR
+ displayName: heketi executor type
+ description: Set the executor type, kubernetes or ssh
+ value: kubernetes
+- name: HEKETI_KUBE_NAMESPACE
+ displayName: Namespace
+ description: Set the namespace where the GlusterFS pods reside
+ value: default
+- name: HEKETI_ROUTE
+ displayName: heketi route name
+ description: Set the hostname for the route URL
+ value: "heketi-glusterfs"
+- name: IMAGE_NAME
+ displayName: heketi container image name
+ required: True
+- name: IMAGE_VERSION
+ displayName: heketi container image version
+ required: True
+- name: CLUSTER_NAME
+ displayName: GlusterFS cluster name
+ description: A unique name to identify this heketi service, useful for running multiple heketi instances
+ value: glusterfs
+- name: TOPOLOGY_PATH
+ displayName: heketi topology file location
+ required: True
diff --git a/roles/openshift_storage_glusterfs/files/v3.7/glusterfs-template.yml b/roles/openshift_storage_glusterfs/files/v3.7/glusterfs-template.yml
new file mode 100644
index 000000000..8c5e1ded3
--- /dev/null
+++ b/roles/openshift_storage_glusterfs/files/v3.7/glusterfs-template.yml
@@ -0,0 +1,136 @@
+---
+kind: Template
+apiVersion: v1
+metadata:
+ name: glusterfs
+ labels:
+ glusterfs: template
+ annotations:
+ description: GlusterFS DaemonSet template
+ tags: glusterfs
+objects:
+- kind: DaemonSet
+ apiVersion: extensions/v1beta1
+ metadata:
+ name: glusterfs-${CLUSTER_NAME}
+ labels:
+ glusterfs: ${CLUSTER_NAME}-daemonset
+ annotations:
+ description: GlusterFS DaemonSet
+ tags: glusterfs
+ spec:
+ selector:
+ matchLabels:
+ glusterfs: ${CLUSTER_NAME}-pod
+ template:
+ metadata:
+ name: glusterfs-${CLUSTER_NAME}
+ labels:
+ glusterfs: ${CLUSTER_NAME}-pod
+ glusterfs-node: pod
+ spec:
+ nodeSelector: "${{NODE_LABELS}}"
+ hostNetwork: true
+ containers:
+ - name: glusterfs
+ image: ${IMAGE_NAME}:${IMAGE_VERSION}
+ imagePullPolicy: IfNotPresent
+ volumeMounts:
+ - name: glusterfs-heketi
+ mountPath: "/var/lib/heketi"
+ - name: glusterfs-run
+ mountPath: "/run"
+ - name: glusterfs-lvm
+ mountPath: "/run/lvm"
+ - name: glusterfs-etc
+ mountPath: "/etc/glusterfs"
+ - name: glusterfs-logs
+ mountPath: "/var/log/glusterfs"
+ - name: glusterfs-config
+ mountPath: "/var/lib/glusterd"
+ - name: glusterfs-dev
+ mountPath: "/dev"
+ - name: glusterfs-misc
+ mountPath: "/var/lib/misc/glusterfsd"
+ - name: glusterfs-cgroup
+ mountPath: "/sys/fs/cgroup"
+ readOnly: true
+ - name: glusterfs-ssl
+ mountPath: "/etc/ssl"
+ readOnly: true
+ securityContext:
+ capabilities: {}
+ privileged: true
+ readinessProbe:
+ timeoutSeconds: 3
+ initialDelaySeconds: 40
+ exec:
+ command:
+ - "/bin/bash"
+ - "-c"
+ - systemctl status glusterd.service
+ periodSeconds: 25
+ successThreshold: 1
+ failureThreshold: 15
+ livenessProbe:
+ timeoutSeconds: 3
+ initialDelaySeconds: 40
+ exec:
+ command:
+ - "/bin/bash"
+ - "-c"
+ - systemctl status glusterd.service
+ periodSeconds: 25
+ successThreshold: 1
+ failureThreshold: 15
+ resources: {}
+ terminationMessagePath: "/dev/termination-log"
+ volumes:
+ - name: glusterfs-heketi
+ hostPath:
+ path: "/var/lib/heketi"
+ - name: glusterfs-run
+ emptyDir: {}
+ - name: glusterfs-lvm
+ hostPath:
+ path: "/run/lvm"
+ - name: glusterfs-etc
+ hostPath:
+ path: "/etc/glusterfs"
+ - name: glusterfs-logs
+ hostPath:
+ path: "/var/log/glusterfs"
+ - name: glusterfs-config
+ hostPath:
+ path: "/var/lib/glusterd"
+ - name: glusterfs-dev
+ hostPath:
+ path: "/dev"
+ - name: glusterfs-misc
+ hostPath:
+ path: "/var/lib/misc/glusterfsd"
+ - name: glusterfs-cgroup
+ hostPath:
+ path: "/sys/fs/cgroup"
+ - name: glusterfs-ssl
+ hostPath:
+ path: "/etc/ssl"
+ restartPolicy: Always
+ terminationGracePeriodSeconds: 30
+ dnsPolicy: ClusterFirst
+ securityContext: {}
+parameters:
+- name: NODE_LABELS
+ displayName: Daemonset Node Labels
+ description: Labels which define the daemonset node selector. Must contain at least one label of the format \'glusterfs=<CLUSTER_NAME>-host\'
+ value: '{ "glusterfs": "storage-host" }'
+- name: IMAGE_NAME
+ displayName: GlusterFS container image name
+ required: True
+- name: IMAGE_VERSION
+ displayName: GlusterFS container image version
+ required: True
+- name: CLUSTER_NAME
+ displayName: GlusterFS cluster name
+ description: A unique name to identify which heketi service manages this cluster, useful for running multiple heketi instances
+ value: storage
diff --git a/roles/openshift_storage_glusterfs/files/v3.7/heketi-template.yml b/roles/openshift_storage_glusterfs/files/v3.7/heketi-template.yml
new file mode 100644
index 000000000..61b6a8c13
--- /dev/null
+++ b/roles/openshift_storage_glusterfs/files/v3.7/heketi-template.yml
@@ -0,0 +1,134 @@
+---
+kind: Template
+apiVersion: v1
+metadata:
+ name: heketi
+ labels:
+ glusterfs: heketi-template
+ annotations:
+ description: Heketi service deployment template
+ tags: glusterfs,heketi
+objects:
+- kind: Service
+ apiVersion: v1
+ metadata:
+ name: heketi-${CLUSTER_NAME}
+ labels:
+ glusterfs: heketi-${CLUSTER_NAME}-service
+ annotations:
+ description: Exposes Heketi service
+ spec:
+ ports:
+ - name: heketi
+ port: 8080
+ targetPort: 8080
+ selector:
+ glusterfs: heketi-${CLUSTER_NAME}-pod
+- kind: Route
+ apiVersion: v1
+ metadata:
+ name: ${HEKETI_ROUTE}
+ labels:
+ glusterfs: heketi-${CLUSTER_NAME}-route
+ spec:
+ to:
+ kind: Service
+ name: heketi-${CLUSTER_NAME}
+- kind: DeploymentConfig
+ apiVersion: v1
+ metadata:
+ name: heketi-${CLUSTER_NAME}
+ labels:
+ glusterfs: heketi-${CLUSTER_NAME}-dc
+ annotations:
+ description: Defines how to deploy Heketi
+ spec:
+ replicas: 1
+ selector:
+ glusterfs: heketi-${CLUSTER_NAME}-pod
+ triggers:
+ - type: ConfigChange
+ strategy:
+ type: Recreate
+ template:
+ metadata:
+ name: heketi-${CLUSTER_NAME}
+ labels:
+ glusterfs: heketi-${CLUSTER_NAME}-pod
+ spec:
+ serviceAccountName: heketi-${CLUSTER_NAME}-service-account
+ containers:
+ - name: heketi
+ image: ${IMAGE_NAME}:${IMAGE_VERSION}
+ imagePullPolicy: IfNotPresent
+ env:
+ - name: HEKETI_USER_KEY
+ value: ${HEKETI_USER_KEY}
+ - name: HEKETI_ADMIN_KEY
+ value: ${HEKETI_ADMIN_KEY}
+ - name: HEKETI_EXECUTOR
+ value: ${HEKETI_EXECUTOR}
+ - name: HEKETI_FSTAB
+ value: /var/lib/heketi/fstab
+ - name: HEKETI_SNAPSHOT_LIMIT
+ value: '14'
+ - name: HEKETI_KUBE_GLUSTER_DAEMONSET
+ value: '1'
+ - name: HEKETI_KUBE_NAMESPACE
+ value: ${HEKETI_KUBE_NAMESPACE}
+ ports:
+ - containerPort: 8080
+ volumeMounts:
+ - name: db
+ mountPath: /var/lib/heketi
+ - name: config
+ mountPath: /etc/heketi
+ readinessProbe:
+ timeoutSeconds: 3
+ initialDelaySeconds: 3
+ httpGet:
+ path: /hello
+ port: 8080
+ livenessProbe:
+ timeoutSeconds: 3
+ initialDelaySeconds: 30
+ httpGet:
+ path: /hello
+ port: 8080
+ volumes:
+ - name: db
+ glusterfs:
+ endpoints: heketi-db-${CLUSTER_NAME}-endpoints
+ path: heketidbstorage
+ - name: config
+ secret:
+ secretName: heketi-${CLUSTER_NAME}-config-secret
+parameters:
+- name: HEKETI_USER_KEY
+ displayName: Heketi User Secret
+ description: Set secret for those creating volumes as type _user_
+- name: HEKETI_ADMIN_KEY
+ displayName: Heketi Administrator Secret
+ description: Set secret for administration of the Heketi service as user _admin_
+- name: HEKETI_EXECUTOR
+ displayName: heketi executor type
+ description: Set the executor type, kubernetes or ssh
+ value: kubernetes
+- name: HEKETI_KUBE_NAMESPACE
+ displayName: Namespace
+ description: Set the namespace where the GlusterFS pods reside
+ value: default
+- name: HEKETI_ROUTE
+ displayName: heketi route name
+ description: Set the hostname for the route URL
+ value: "heketi-glusterfs"
+- name: IMAGE_NAME
+ displayName: heketi container image name
+ required: True
+- name: IMAGE_VERSION
+ displayName: heketi container image version
+ required: True
+- name: CLUSTER_NAME
+ displayName: GlusterFS cluster name
+ description: A unique name to identify this heketi service, useful for running multiple heketi instances
+ value: glusterfs
diff --git a/roles/openshift_storage_glusterfs/tasks/glusterfs_common.yml b/roles/openshift_storage_glusterfs/tasks/glusterfs_common.yml
index a31c5bd5e..bc0dde17d 100644
--- a/roles/openshift_storage_glusterfs/tasks/glusterfs_common.yml
+++ b/roles/openshift_storage_glusterfs/tasks/glusterfs_common.yml
@@ -15,6 +15,7 @@
oc_project:
state: present
name: "{{ glusterfs_namespace }}"
+ node_selector: "{% if glusterfs_use_default_selector %}{{ omit }}{% endif %}"
when: glusterfs_is_native or glusterfs_heketi_is_native or glusterfs_storageclass
- name: Delete pre-existing heketi resources
diff --git a/roles/openshift_storage_glusterfs/tasks/glusterfs_config.yml b/roles/openshift_storage_glusterfs/tasks/glusterfs_config.yml
index 7a2987883..012c722ff 100644
--- a/roles/openshift_storage_glusterfs/tasks/glusterfs_config.yml
+++ b/roles/openshift_storage_glusterfs/tasks/glusterfs_config.yml
@@ -5,6 +5,7 @@
glusterfs_is_native: "{{ openshift_storage_glusterfs_is_native | bool }}"
glusterfs_name: "{{ openshift_storage_glusterfs_name }}"
glusterfs_nodeselector: "{{ openshift_storage_glusterfs_nodeselector | default(['storagenode', openshift_storage_glusterfs_name] | join('=')) | map_from_pairs }}"
+ glusterfs_use_default_selector: "{{ openshift_storage_glusterfs_use_default_selector }}"
glusterfs_storageclass: "{{ openshift_storage_glusterfs_storageclass }}"
glusterfs_image: "{{ openshift_storage_glusterfs_image }}"
glusterfs_version: "{{ openshift_storage_glusterfs_version }}"
diff --git a/roles/openshift_storage_glusterfs/tasks/glusterfs_registry.yml b/roles/openshift_storage_glusterfs/tasks/glusterfs_registry.yml
index 17f87578d..1bcab8e49 100644
--- a/roles/openshift_storage_glusterfs/tasks/glusterfs_registry.yml
+++ b/roles/openshift_storage_glusterfs/tasks/glusterfs_registry.yml
@@ -5,6 +5,7 @@
glusterfs_is_native: "{{ openshift_storage_glusterfs_registry_is_native | bool }}"
glusterfs_name: "{{ openshift_storage_glusterfs_registry_name }}"
glusterfs_nodeselector: "{{ openshift_storage_glusterfs_registry_nodeselector | default(['storagenode', openshift_storage_glusterfs_registry_name] | join('=')) | map_from_pairs }}"
+ glusterfs_use_default_selector: "{{ openshift_storage_glusterfs_registry_use_default_selector }}"
glusterfs_storageclass: "{{ openshift_storage_glusterfs_registry_storageclass }}"
glusterfs_image: "{{ openshift_storage_glusterfs_registry_image }}"
glusterfs_version: "{{ openshift_storage_glusterfs_registry_version }}"
diff --git a/roles/openshift_storage_glusterfs/templates/v3.7/glusterfs-registry-endpoints.yml.j2 b/roles/openshift_storage_glusterfs/templates/v3.7/glusterfs-registry-endpoints.yml.j2
new file mode 100644
index 000000000..11c9195bb
--- /dev/null
+++ b/roles/openshift_storage_glusterfs/templates/v3.7/glusterfs-registry-endpoints.yml.j2
@@ -0,0 +1,12 @@
+---
+apiVersion: v1
+kind: Endpoints
+metadata:
+ name: glusterfs-{{ glusterfs_name }}-endpoints
+subsets:
+- addresses:
+{% for node in glusterfs_nodes %}
+ - ip: {{ hostvars[node].glusterfs_ip | default(hostvars[node].openshift.common.ip) }}
+{% endfor %}
+ ports:
+ - port: 1
diff --git a/roles/openshift_storage_glusterfs/templates/v3.7/glusterfs-registry-service.yml.j2 b/roles/openshift_storage_glusterfs/templates/v3.7/glusterfs-registry-service.yml.j2
new file mode 100644
index 000000000..3f869d2b7
--- /dev/null
+++ b/roles/openshift_storage_glusterfs/templates/v3.7/glusterfs-registry-service.yml.j2
@@ -0,0 +1,10 @@
+---
+apiVersion: v1
+kind: Service
+metadata:
+ name: glusterfs-{{ glusterfs_name }}-endpoints
+spec:
+ ports:
+ - port: 1
+status:
+ loadBalancer: {}
diff --git a/roles/openshift_storage_glusterfs/templates/v3.7/glusterfs-storageclass.yml.j2 b/roles/openshift_storage_glusterfs/templates/v3.7/glusterfs-storageclass.yml.j2
new file mode 100644
index 000000000..095fb780f
--- /dev/null
+++ b/roles/openshift_storage_glusterfs/templates/v3.7/glusterfs-storageclass.yml.j2
@@ -0,0 +1,13 @@
+---
+apiVersion: storage.k8s.io/v1
+kind: StorageClass
+metadata:
+ name: glusterfs-{{ glusterfs_name }}
+provisioner: kubernetes.io/glusterfs
+parameters:
+ resturl: "http://{% if glusterfs_heketi_is_native %}{{ glusterfs_heketi_route }}{% else %}{{ glusterfs_heketi_url }}:{{ glusterfs_heketi_port }}{% endif %}"
+ restuser: "admin"
+{% if glusterfs_heketi_admin_key is defined %}
+ secretNamespace: "{{ glusterfs_namespace }}"
+ secretName: "heketi-{{ glusterfs_name }}-admin-secret"
+{%- endif -%}
diff --git a/roles/openshift_storage_glusterfs/templates/v3.7/heketi-endpoints.yml.j2 b/roles/openshift_storage_glusterfs/templates/v3.7/heketi-endpoints.yml.j2
new file mode 100644
index 000000000..99cbdf748
--- /dev/null
+++ b/roles/openshift_storage_glusterfs/templates/v3.7/heketi-endpoints.yml.j2
@@ -0,0 +1,12 @@
+---
+apiVersion: v1
+kind: Endpoints
+metadata:
+ name: heketi-db-{{ glusterfs_name }}-endpoints
+subsets:
+- addresses:
+{% for node in glusterfs_nodes %}
+ - ip: {{ hostvars[node].glusterfs_ip | default(hostvars[node].openshift.common.ip) }}
+{% endfor %}
+ ports:
+ - port: 1
diff --git a/roles/openshift_storage_glusterfs/templates/v3.7/heketi-service.yml.j2 b/roles/openshift_storage_glusterfs/templates/v3.7/heketi-service.yml.j2
new file mode 100644
index 000000000..dcb896441
--- /dev/null
+++ b/roles/openshift_storage_glusterfs/templates/v3.7/heketi-service.yml.j2
@@ -0,0 +1,10 @@
+---
+apiVersion: v1
+kind: Service
+metadata:
+ name: heketi-db-{{ glusterfs_name }}-endpoints
+spec:
+ ports:
+ - port: 1
+status:
+ loadBalancer: {}
diff --git a/roles/openshift_storage_glusterfs/templates/v3.7/heketi.json.j2 b/roles/openshift_storage_glusterfs/templates/v3.7/heketi.json.j2
new file mode 100644
index 000000000..579b11bb7
--- /dev/null
+++ b/roles/openshift_storage_glusterfs/templates/v3.7/heketi.json.j2
@@ -0,0 +1,36 @@
+{
+ "_port_comment": "Heketi Server Port Number",
+ "port" : "8080",
+
+ "_use_auth": "Enable JWT authorization. Please enable for deployment",
+ "use_auth" : false,
+
+ "_jwt" : "Private keys for access",
+ "jwt" : {
+ "_admin" : "Admin has access to all APIs",
+ "admin" : {
+ "key" : "My Secret"
+ },
+ "_user" : "User only has access to /volumes endpoint",
+ "user" : {
+ "key" : "My Secret"
+ }
+ },
+
+ "_glusterfs_comment": "GlusterFS Configuration",
+ "glusterfs" : {
+
+ "_executor_comment": "Execute plugin. Possible choices: mock, kubernetes, ssh",
+ "executor" : "{{ glusterfs_heketi_executor }}",
+
+ "_db_comment": "Database file name",
+ "db" : "/var/lib/heketi/heketi.db",
+
+ "sshexec" : {
+ "keyfile" : "/etc/heketi/private_key",
+ "port" : "{{ glusterfs_heketi_ssh_port }}",
+ "user" : "{{ glusterfs_heketi_ssh_user }}",
+ "sudo" : {{ glusterfs_heketi_ssh_sudo | lower }}
+ }
+ }
+}
diff --git a/roles/openshift_storage_glusterfs/templates/v3.7/topology.json.j2 b/roles/openshift_storage_glusterfs/templates/v3.7/topology.json.j2
new file mode 100644
index 000000000..d6c28f6dd
--- /dev/null
+++ b/roles/openshift_storage_glusterfs/templates/v3.7/topology.json.j2
@@ -0,0 +1,49 @@
+{
+ "clusters": [
+{%- set clusters = {} -%}
+{%- for node in glusterfs_nodes -%}
+ {%- set cluster = hostvars[node].glusterfs_cluster if 'glusterfs_cluster' in node else '1' -%}
+ {%- if cluster in clusters -%}
+ {%- set _dummy = clusters[cluster].append(node) -%}
+ {%- else -%}
+ {%- set _dummy = clusters.update({cluster: [ node, ]}) -%}
+ {%- endif -%}
+{%- endfor -%}
+{%- for cluster in clusters -%}
+ {
+ "nodes": [
+{%- for node in clusters[cluster] -%}
+ {
+ "node": {
+ "hostnames": {
+ "manage": [
+{%- if 'glusterfs_hostname' in hostvars[node] -%}
+ "{{ hostvars[node].glusterfs_hostname }}"
+{%- elif 'openshift' in hostvars[node] -%}
+ "{{ hostvars[node].openshift.node.nodename }}"
+{%- else -%}
+ "{{ node }}"
+{%- endif -%}
+ ],
+ "storage": [
+{%- if 'glusterfs_ip' in hostvars[node] -%}
+ "{{ hostvars[node].glusterfs_ip }}"
+{%- else -%}
+ "{{ hostvars[node].openshift.common.ip }}"
+{%- endif -%}
+ ]
+ },
+ "zone": {{ hostvars[node].glusterfs_zone | default(1) }}
+ },
+ "devices": [
+{%- for device in hostvars[node].glusterfs_devices -%}
+ "{{ device }}"{% if not loop.last %},{% endif %}
+{%- endfor -%}
+ ]
+ }{% if not loop.last %},{% endif %}
+{%- endfor -%}
+ ]
+ }{% if not loop.last %},{% endif %}
+{%- endfor -%}
+ ]
+}
diff --git a/roles/openshift_storage_nfs/defaults/main.yml b/roles/openshift_storage_nfs/defaults/main.yml
index 4a2bc6141..e7e0b331b 100644
--- a/roles/openshift_storage_nfs/defaults/main.yml
+++ b/roles/openshift_storage_nfs/defaults/main.yml
@@ -1,6 +1,6 @@
---
-r_openshift_storage_nfs_firewall_enabled: True
-r_openshift_storage_nfs_use_firewalld: False
+r_openshift_storage_nfs_firewall_enabled: "{{ os_firewall_enabled | default(True) }}"
+r_openshift_storage_nfs_use_firewalld: "{{ os_firewall_use_firewalld | default(False) }}"
r_openshift_storage_nfs_os_firewall_deny: []
r_openshift_storage_nfs_os_firewall_allow:
diff --git a/roles/openshift_version/defaults/main.yml b/roles/openshift_version/defaults/main.yml
index 01a1a7472..53d10f1f8 100644
--- a/roles/openshift_version/defaults/main.yml
+++ b/roles/openshift_version/defaults/main.yml
@@ -1,2 +1,3 @@
---
openshift_protect_installed_version: True
+version_install_base_package: False
diff --git a/roles/openshift_version/tasks/main.yml b/roles/openshift_version/tasks/main.yml
index a6b8a40c8..1ff99adf8 100644
--- a/roles/openshift_version/tasks/main.yml
+++ b/roles/openshift_version/tasks/main.yml
@@ -5,6 +5,16 @@
is_containerized: "{{ openshift.common.is_containerized | default(False) | bool }}"
is_atomic: "{{ openshift.common.is_atomic | default(False) | bool }}"
+# This is only needed on masters and nodes; version_install_base_package
+# should be set by a play externally.
+- name: Install the base package for versioning
+ package:
+ name: "{{ openshift.common.service_type }}{{ openshift_pkg_version | default('') | oo_image_tag_to_rpm_version(include_dash=True) }}"
+ state: present
+ when:
+ - not is_containerized | bool
+ - version_install_base_package | bool
+
# Block attempts to install origin without specifying some kind of version information.
# This is because the latest tags for origin are usually alpha builds, which should not
# be used by default. Users must indicate what they want.
@@ -60,13 +70,16 @@
# It also allows for optional trailing data which:
# - must start with a dash
# - may contain numbers
+ # - may containe dots (https://github.com/openshift/openshift-ansible/issues/5192)
+ #
- name: (Enterprise) Verify openshift_image_tag is valid
when: openshift.common.deployment_type == 'openshift-enterprise'
assert:
that:
- - "{{ openshift_image_tag|match('(^v\\d+\\.\\d+[\\.\\d+]*(-\\d+)?$)') }}"
+ - "{{ openshift_image_tag|match('(^v\\d+\\.\\d+(\\.\\d+)*(-\\d+(\\.\\d+)*)?$)') }}"
msg: |-
- openshift_image_tag must be in the format v#.#[.#[.#]]. Examples: v1.2, v3.4.1, v3.5.1.3, v1.2-1, v1.2.3-4
+ openshift_image_tag must be in the format v#.#[.#[.#]]. Examples: v1.2, v3.4.1, v3.5.1.3,
+ v3.5.1.3.4, v1.2-1, v1.2.3-4, v1.2.3-4.5, v1.2.3-4.5.6
You specified openshift_image_tag={{ openshift_image_tag }}
# Make sure we copy this to a fact if given a var:
diff --git a/roles/openshift_version/tasks/set_version_containerized.yml b/roles/openshift_version/tasks/set_version_containerized.yml
index 4d9f72f01..a2a579e9d 100644
--- a/roles/openshift_version/tasks/set_version_containerized.yml
+++ b/roles/openshift_version/tasks/set_version_containerized.yml
@@ -1,6 +1,6 @@
---
- set_fact:
- l_use_crio: "{{ openshift_docker_use_crio | default(false) }}"
+ l_use_crio: "{{ openshift_use_crio | default(false) }}"
- name: Set containerized version to configure if openshift_image_tag specified
set_fact:
diff --git a/roles/os_firewall/defaults/main.yml b/roles/os_firewall/defaults/main.yml
index f96a80f1c..2cae94411 100644
--- a/roles/os_firewall/defaults/main.yml
+++ b/roles/os_firewall/defaults/main.yml
@@ -2,4 +2,4 @@
os_firewall_enabled: True
# firewalld is not supported on Atomic Host
# https://bugzilla.redhat.com/show_bug.cgi?id=1403331
-os_firewall_use_firewalld: "{{ False }}"
+os_firewall_use_firewalld: False
diff --git a/roles/os_firewall/tasks/iptables.yml b/roles/os_firewall/tasks/iptables.yml
index 0af5abf38..2d74f2e48 100644
--- a/roles/os_firewall/tasks/iptables.yml
+++ b/roles/os_firewall/tasks/iptables.yml
@@ -33,7 +33,7 @@
register: result
delegate_to: "{{item}}"
run_once: true
- with_items: "{{ ansible_play_hosts }}"
+ with_items: "{{ ansible_play_batch }}"
- name: need to pause here, otherwise the iptables service starting can sometimes cause ssh to fail
pause:
diff --git a/roles/rhel_subscribe/tasks/enterprise.yml b/roles/rhel_subscribe/tasks/enterprise.yml
index 39d59db70..9738929d2 100644
--- a/roles/rhel_subscribe/tasks/enterprise.yml
+++ b/roles/rhel_subscribe/tasks/enterprise.yml
@@ -3,20 +3,17 @@
command: subscription-manager repos --disable="*"
- set_fact:
- default_ose_version: '3.0'
- when: deployment_type == 'enterprise'
-
-- set_fact:
default_ose_version: '3.6'
- when: deployment_type in ['atomic-enterprise', 'openshift-enterprise']
+ when: deployment_type == 'openshift-enterprise'
- set_fact:
ose_version: "{{ lookup('oo_option', 'ose_version') | default(default_ose_version, True) }}"
- fail:
msg: "{{ ose_version }} is not a valid version for {{ deployment_type }} deployment type"
- when: ( deployment_type == 'enterprise' and ose_version not in ['3.0'] ) or
- ( deployment_type in ['atomic-enterprise', 'openshift-enterprise'] and ose_version not in ['3.1', '3.2', '3.3', '3.4', '3.5', '3.6'] )
+ when:
+ - deployment_type == 'openshift-enterprise'
+ - ose_version not in ['3.1', '3.2', '3.3', '3.4', '3.5', '3.6'] )
- name: Enable RHEL repositories
command: subscription-manager repos \
diff --git a/roles/rhel_subscribe/tasks/main.yml b/roles/rhel_subscribe/tasks/main.yml
index 453044a6e..c49512146 100644
--- a/roles/rhel_subscribe/tasks/main.yml
+++ b/roles/rhel_subscribe/tasks/main.yml
@@ -41,15 +41,19 @@
redhat_subscription:
username: "{{ rhel_subscription_user }}"
password: "{{ rhel_subscription_pass }}"
+ register: rh_subscription
+ until: rh_subscription | succeeded
- name: Retrieve the OpenShift Pool ID
command: subscription-manager list --available --matches="{{ rhel_subscription_pool }}" --pool-only
register: openshift_pool_id
+ until: openshift_pool_id | succeeded
changed_when: False
- name: Determine if OpenShift Pool Already Attached
command: subscription-manager list --consumed --matches="{{ rhel_subscription_pool }}" --pool-only
register: openshift_pool_attached
+ until: openshift_pool_attached | succeeded
changed_when: False
when: openshift_pool_id.stdout == ''
@@ -59,9 +63,11 @@
- name: Attach to OpenShift Pool
command: subscription-manager subscribe --pool {{ openshift_pool_id.stdout_lines[0] }}
+ register: subscribe_pool
+ until: subscribe_pool | succeeded
when: openshift_pool_id.stdout != ''
- include: enterprise.yml
when:
- - deployment_type in [ 'enterprise', 'atomic-enterprise', 'openshift-enterprise' ]
+ - deployment_type == 'openshift-enterprise'
- not ostree_booted.stat.exists | bool
diff --git a/setup.py b/setup.py
index b9c34a8b8..eaf23d47a 100644
--- a/setup.py
+++ b/setup.py
@@ -29,6 +29,7 @@ def find_files(base_dir, exclude_dirs, include_dirs, file_regex):
if exclude_dirs is not None:
exclude_regex = r'|'.join([fnmatch.translate(x) for x in exclude_dirs]) or r'$.'
+ # Don't use include_dirs, it is broken
if include_dirs is not None:
include_regex = r'|'.join([fnmatch.translate(x) for x in include_dirs]) or r'$.'
@@ -47,6 +48,57 @@ def find_files(base_dir, exclude_dirs, include_dirs, file_regex):
return found
+def recursive_search(search_list, field):
+ """
+ Takes a list with nested dicts, and searches all dicts for a key of the
+ field provided. If the items in the list are not dicts, the items are not
+ processed.
+ """
+ fields_found = []
+
+ for item in search_list:
+ if isinstance(item, dict):
+ for key, value in item.items():
+ if key == field:
+ fields_found.append(value)
+ elif isinstance(value, list):
+ results = recursive_search(value, field)
+ for result in results:
+ fields_found.append(result)
+
+ return fields_found
+
+
+def find_entrypoint_playbooks():
+ '''find entry point playbooks as defined by openshift-ansible'''
+ playbooks = set()
+ included_playbooks = set()
+
+ exclude_dirs = ['adhoc', 'tasks']
+ for yaml_file in find_files(
+ os.path.join(os.getcwd(), 'playbooks'),
+ exclude_dirs, None, r'\.ya?ml$'):
+ with open(yaml_file, 'r') as contents:
+ for task in yaml.safe_load(contents) or {}:
+ if not isinstance(task, dict):
+ # Skip yaml files which are not a dictionary of tasks
+ continue
+ if 'include' in task:
+ # Add the playbook and capture included playbooks
+ playbooks.add(yaml_file)
+ included_file_name = task['include'].split()[0]
+ included_file = os.path.normpath(
+ os.path.join(os.path.dirname(yaml_file),
+ included_file_name))
+ included_playbooks.add(included_file)
+ elif 'hosts' in task:
+ playbooks.add(yaml_file)
+ # Evaluate the difference between all playbooks and included playbooks
+ entrypoint_playbooks = sorted(playbooks.difference(included_playbooks))
+ print('Entry point playbook count: {}'.format(len(entrypoint_playbooks)))
+ return entrypoint_playbooks
+
+
class OpenShiftAnsibleYamlLint(Command):
''' Command to run yamllint '''
description = "Run yamllint tests"
@@ -206,7 +258,7 @@ class OpenShiftAnsibleSyntaxCheck(Command):
user_options = []
# Colors
- FAIL = '\033[91m' # Red
+ FAIL = '\033[31m' # Red
ENDC = '\033[0m' # Reset
def initialize_options(self):
@@ -217,47 +269,96 @@ class OpenShiftAnsibleSyntaxCheck(Command):
''' finalize_options '''
pass
+ def deprecate_jinja2_in_when(self, yaml_contents, yaml_file):
+ ''' Check for Jinja2 templating delimiters in when conditions '''
+ test_result = False
+ failed_items = []
+
+ search_results = recursive_search(yaml_contents, 'when')
+ for item in search_results:
+ if isinstance(item, str):
+ if '{{' in item or '{%' in item:
+ failed_items.append(item)
+ else:
+ for sub_item in item:
+ if '{{' in sub_item or '{%' in sub_item:
+ failed_items.append(sub_item)
+
+ if len(failed_items) > 0:
+ print('{}Error: Usage of Jinja2 templating delimiters in when '
+ 'conditions is deprecated in Ansible 2.3.\n'
+ ' File: {}'.format(self.FAIL, yaml_file))
+ for item in failed_items:
+ print(' Found: "{}"'.format(item))
+ print(self.ENDC)
+ test_result = True
+
+ return test_result
+
+ def deprecate_include(self, yaml_contents, yaml_file):
+ ''' Check for usage of include directive '''
+ test_result = False
+
+ search_results = recursive_search(yaml_contents, 'include')
+
+ if len(search_results) > 0:
+ print('{}Error: The `include` directive is deprecated in Ansible 2.4.\n'
+ 'https://github.com/ansible/ansible/blob/devel/CHANGELOG.md\n'
+ ' File: {}'.format(self.FAIL, yaml_file))
+ for item in search_results:
+ print(' Found: "include: {}"'.format(item))
+ print(self.ENDC)
+ test_result = True
+
+ return test_result
+
def run(self):
''' run command '''
has_errors = False
- playbooks = set()
- included_playbooks = set()
+ print('Ansible Deprecation Checks')
+ exclude_dirs = ['adhoc', 'files', 'meta', 'test', 'tests', 'vars', 'defaults', '.tox']
for yaml_file in find_files(
- os.path.join(os.getcwd(), 'playbooks', 'byo'),
- None, None, r'\.ya?ml$'):
+ os.getcwd(), exclude_dirs, None, r'\.ya?ml$'):
with open(yaml_file, 'r') as contents:
- for task in yaml.safe_load(contents):
- if not isinstance(task, dict):
- # Skip yaml files which do not contain plays or includes
- continue
- if 'include' in task:
- # Add the playbook and capture included playbooks
- playbooks.add(yaml_file)
- included_file_name = task['include'].split()[0]
- included_file = os.path.normpath(
- os.path.join(os.path.dirname(yaml_file),
- included_file_name))
- included_playbooks.add(included_file)
- elif 'hosts' in task:
- playbooks.add(yaml_file)
- # Evaluate the difference between all playbooks and included playbooks
- entrypoint_playbooks = sorted(playbooks.difference(included_playbooks))
- print('Entry point playbook count: {}'.format(len(entrypoint_playbooks)))
- # Syntax each entry point playbook
- for playbook in entrypoint_playbooks:
+ yaml_contents = yaml.safe_load(contents)
+ if not isinstance(yaml_contents, list):
+ continue
+
+ # Check for Jinja2 templating delimiters in when conditions
+ result = self.deprecate_jinja2_in_when(yaml_contents, yaml_file)
+ has_errors = result or has_errors
+
+ # TODO (rteague): This test will be enabled once we move to Ansible 2.4
+ # result = self.deprecate_include(yaml_contents, yaml_file)
+ # has_errors = result or has_errors
+
+ if not has_errors:
+ print('...PASSED')
+
+ print('Ansible Playbook Entry Point Syntax Checks')
+ for playbook in find_entrypoint_playbooks():
print('-' * 60)
print('Syntax checking playbook: {}'.format(playbook))
- try:
- subprocess.check_output(
- ['ansible-playbook', '-i localhost,',
- '--syntax-check', playbook]
- )
- except subprocess.CalledProcessError as cpe:
- print('{}Execution failed: {}{}'.format(
- self.FAIL, cpe, self.ENDC))
+
+ # Error on any entry points in 'common'
+ if 'common' in playbook:
+ print('{}Invalid entry point playbook. All playbooks must'
+ ' start in playbooks/byo{}'.format(self.FAIL, self.ENDC))
has_errors = True
+ # --syntax-check each entry point playbook
+ else:
+ try:
+ subprocess.check_output(
+ ['ansible-playbook', '-i localhost,',
+ '--syntax-check', playbook]
+ )
+ except subprocess.CalledProcessError as cpe:
+ print('{}Execution failed: {}{}'.format(
+ self.FAIL, cpe, self.ENDC))
+ has_errors = True
+
if has_errors:
raise SystemExit(1)
diff --git a/test/integration/openshift_health_checker/common.go b/test/integration/openshift_health_checker/common.go
index a92d6861d..8b79c48cb 100644
--- a/test/integration/openshift_health_checker/common.go
+++ b/test/integration/openshift_health_checker/common.go
@@ -25,7 +25,7 @@ func (p PlaybookTest) Run(t *testing.T) {
// A PlaybookTest is intended to be run in parallel with other tests.
t.Parallel()
- cmd := exec.Command("ansible-playbook", "-i", "/dev/null", p.Path)
+ cmd := exec.Command("ansible-playbook", "-e", "testing_skip_some_requirements=1", "-i", "/dev/null", p.Path)
cmd.Env = append(os.Environ(), "ANSIBLE_FORCE_COLOR=1")
b, err := cmd.CombinedOutput()
diff --git a/test/openshift_version_tests.py b/test/openshift_version_tests.py
index 393a4d6ba..6095beb95 100644
--- a/test/openshift_version_tests.py
+++ b/test/openshift_version_tests.py
@@ -17,39 +17,39 @@ class OpenShiftVersionTests(unittest.TestCase):
# Static tests for legacy filters.
legacy_gte_tests = [{'name': 'oo_version_gte_3_1_or_1_1',
- 'positive_enterprise_version': '3.2.0',
- 'negative_enterprise_version': '3.0.0',
+ 'positive_openshift-enterprise_version': '3.2.0',
+ 'negative_openshift-enterprise_version': '3.0.0',
'positive_origin_version': '1.2.0',
'negative_origin_version': '1.0.0'},
{'name': 'oo_version_gte_3_1_1_or_1_1_1',
- 'positive_enterprise_version': '3.2.0',
- 'negative_enterprise_version': '3.1.0',
+ 'positive_openshift-enterprise_version': '3.2.0',
+ 'negative_openshift-enterprise_version': '3.1.0',
'positive_origin_version': '1.2.0',
'negative_origin_version': '1.1.0'},
{'name': 'oo_version_gte_3_2_or_1_2',
- 'positive_enterprise_version': '3.3.0',
- 'negative_enterprise_version': '3.1.0',
+ 'positive_openshift-enterprise_version': '3.3.0',
+ 'negative_openshift-enterprise_version': '3.1.0',
'positive_origin_version': '1.3.0',
'negative_origin_version': '1.1.0'},
{'name': 'oo_version_gte_3_3_or_1_3',
- 'positive_enterprise_version': '3.4.0',
- 'negative_enterprise_version': '3.2.0',
+ 'positive_openshift-enterprise_version': '3.4.0',
+ 'negative_openshift-enterprise_version': '3.2.0',
'positive_origin_version': '1.4.0',
'negative_origin_version': '1.2.0'},
{'name': 'oo_version_gte_3_4_or_1_4',
- 'positive_enterprise_version': '3.5.0',
- 'negative_enterprise_version': '3.3.0',
+ 'positive_openshift-enterprise_version': '3.5.0',
+ 'negative_openshift-enterprise_version': '3.3.0',
'positive_origin_version': '1.5.0',
'negative_origin_version': '1.3.0'},
{'name': 'oo_version_gte_3_5_or_1_5',
- 'positive_enterprise_version': '3.6.0',
- 'negative_enterprise_version': '3.4.0',
+ 'positive_openshift-enterprise_version': '3.6.0',
+ 'negative_openshift-enterprise_version': '3.4.0',
'positive_origin_version': '3.6.0',
'negative_origin_version': '1.4.0'}]
def test_legacy_gte_filters(self):
for test in self.legacy_gte_tests:
- for deployment_type in ['enterprise', 'origin']:
+ for deployment_type in ['openshift-enterprise', 'origin']:
# Test negative case per deployment_type
self.assertFalse(
self.openshift_version_filters._filters[test['name']](
@@ -70,3 +70,7 @@ class OpenShiftVersionTests(unittest.TestCase):
self.assertFalse(
self.openshift_version_filters._filters["oo_version_gte_{}_{}".format(major, minor)](
"{}.{}".format(major, minor)))
+
+ def test_get_filters(self):
+ self.assertTrue(
+ self.openshift_version_filters.filters() == self.openshift_version_filters._filters)
diff --git a/tox.ini b/tox.ini
index 53a9222d8..899767833 100644
--- a/tox.ini
+++ b/tox.ini
@@ -22,6 +22,5 @@ commands =
pylint: python setup.py lint
yamllint: python setup.py yamllint
generate_validation: python setup.py generate_validation
- # TODO(rhcarvalho): check syntax of other important entrypoint playbooks
ansible_syntax: python setup.py ansible_syntax
integration: python -c 'print("run test/integration/run-tests.sh")'
diff --git a/utils/docs/config.md b/utils/docs/config.md
index 3677ffe2e..6d0c6896e 100644
--- a/utils/docs/config.md
+++ b/utils/docs/config.md
@@ -52,7 +52,6 @@ Indicates the version of configuration this file was written with. Current imple
The OpenShift variant to install. Currently valid options are:
* openshift-enterprise
- * atomic-enterprise
### variant_version (optional)