diff --git a/cluster/juju/layers/kubernetes-master/layer.yaml b/cluster/juju/layers/kubernetes-master/layer.yaml index 247f8c20720..44488b5ab2b 100644 --- a/cluster/juju/layers/kubernetes-master/layer.yaml +++ b/cluster/juju/layers/kubernetes-master/layer.yaml @@ -15,8 +15,9 @@ includes: - 'interface:kube-dns' - 'interface:kube-control' - 'interface:public-address' - - 'interface:aws' - - 'interface:gcp' + - 'interface:aws-integration' + - 'interface:gcp-integration' + - 'interface:openstack-integration' options: basic: packages: diff --git a/cluster/juju/layers/kubernetes-master/metadata.yaml b/cluster/juju/layers/kubernetes-master/metadata.yaml index 52aab0afa4d..c90813e2cbe 100644 --- a/cluster/juju/layers/kubernetes-master/metadata.yaml +++ b/cluster/juju/layers/kubernetes-master/metadata.yaml @@ -41,9 +41,11 @@ requires: ceph-storage: interface: ceph-admin aws: - interface: aws + interface: aws-integration gcp: - interface: gcp + interface: gcp-integration + openstack: + interface: openstack-integration resources: kubectl: type: file diff --git a/cluster/juju/layers/kubernetes-master/reactive/kubernetes_master.py b/cluster/juju/layers/kubernetes-master/reactive/kubernetes_master.py index f866471f934..4191fdcb182 100644 --- a/cluster/juju/layers/kubernetes-master/reactive/kubernetes_master.py +++ b/cluster/juju/layers/kubernetes-master/reactive/kubernetes_master.py @@ -432,9 +432,13 @@ def set_final_status(): return req_sent = is_state('kubernetes-master.cloud-request-sent') + openstack_joined = is_state('endpoint.openstack.joined') + cloud_req = req_sent or openstack_joined aws_ready = is_state('endpoint.aws.ready') gcp_ready = is_state('endpoint.gcp.ready') - if req_sent and not (aws_ready or gcp_ready): + openstack_ready = is_state('endpoint.openstack.ready') + cloud_ready = aws_ready or gcp_ready or openstack_ready + if cloud_req and not cloud_ready: hookenv.status_set('waiting', 'waiting for cloud integration') if addons_configured and not all_kube_system_pods_running(): @@ -1241,6 +1245,10 @@ def configure_apiserver(etcd_connection_string, leader_etcd_version): cloud_config_path = _cloud_config_path('kube-apiserver') api_opts['cloud-provider'] = 'gce' api_opts['cloud-config'] = str(cloud_config_path) + elif is_state('endpoint.openstack.ready'): + cloud_config_path = _cloud_config_path('kube-apiserver') + api_opts['cloud-provider'] = 'openstack' + api_opts['cloud-config'] = str(cloud_config_path) configure_kubernetes_service('kube-apiserver', api_opts, 'api-extra-args') restart_apiserver() @@ -1269,6 +1277,10 @@ def configure_controller_manager(): cloud_config_path = _cloud_config_path('kube-controller-manager') controller_opts['cloud-provider'] = 'gce' controller_opts['cloud-config'] = str(cloud_config_path) + elif is_state('endpoint.openstack.ready'): + cloud_config_path = _cloud_config_path('kube-controller-manager') + controller_opts['cloud-provider'] = 'openstack' + controller_opts['cloud-config'] = str(cloud_config_path) configure_kubernetes_service('kube-controller-manager', controller_opts, 'controller-manager-extra-args') @@ -1539,12 +1551,16 @@ def clear_requested_integration(): @when_any('endpoint.aws.ready', - 'endpoint.gcp.ready') + 'endpoint.gcp.ready', + 'endpoint.openstack.ready') @when_not('kubernetes-master.restarted-for-cloud') def restart_for_cloud(): if is_state('endpoint.gcp.ready'): _write_gcp_snap_config('kube-apiserver') _write_gcp_snap_config('kube-controller-manager') + elif is_state('endpoint.openstack.ready'): + _write_openstack_snap_config('kube-apiserver') + _write_openstack_snap_config('kube-controller-manager') set_state('kubernetes-master.restarted-for-cloud') remove_state('kubernetes-master.components.started') # force restart @@ -1592,3 +1608,18 @@ def _write_gcp_snap_config(component): daemon_env += '{}={}\n'.format(gcp_creds_env_key, creds_path) daemon_env_path.parent.mkdir(parents=True, exist_ok=True) daemon_env_path.write_text(daemon_env) + + +def _write_openstack_snap_config(component): + # openstack requires additional credentials setup + openstack = endpoint_from_flag('endpoint.openstack.ready') + + cloud_config_path = _cloud_config_path(component) + cloud_config_path.write_text('\n'.join([ + '[Global]', + 'auth-url = {}'.format(openstack.auth_url), + 'username = {}'.format(openstack.username), + 'password = {}'.format(openstack.password), + 'tenant-name = {}'.format(openstack.project_name), + 'domain-name = {}'.format(openstack.user_domain_name), + ])) diff --git a/cluster/juju/layers/kubernetes-worker/layer.yaml b/cluster/juju/layers/kubernetes-worker/layer.yaml index d8ee6489845..af247e80f0a 100644 --- a/cluster/juju/layers/kubernetes-worker/layer.yaml +++ b/cluster/juju/layers/kubernetes-worker/layer.yaml @@ -12,8 +12,9 @@ includes: - 'interface:kubernetes-cni' - 'interface:kube-dns' - 'interface:kube-control' - - 'interface:aws' - - 'interface:gcp' + - 'interface:aws-integration' + - 'interface:gcp-integration' + - 'interface:openstack-integration' - 'interface:mount' config: deletes: diff --git a/cluster/juju/layers/kubernetes-worker/metadata.yaml b/cluster/juju/layers/kubernetes-worker/metadata.yaml index df4a823c90c..120d27f2a59 100644 --- a/cluster/juju/layers/kubernetes-worker/metadata.yaml +++ b/cluster/juju/layers/kubernetes-worker/metadata.yaml @@ -30,9 +30,11 @@ requires: kube-control: interface: kube-control aws: - interface: aws + interface: aws-integration gcp: - interface: gcp + interface: gcp-integration + openstack: + interface: openstack-integration nfs: interface: mount provides: diff --git a/cluster/juju/layers/kubernetes-worker/reactive/kubernetes_worker.py b/cluster/juju/layers/kubernetes-worker/reactive/kubernetes_worker.py index 5e819f705c2..a53febba097 100644 --- a/cluster/juju/layers/kubernetes-worker/reactive/kubernetes_worker.py +++ b/cluster/juju/layers/kubernetes-worker/reactive/kubernetes_worker.py @@ -632,6 +632,10 @@ def configure_kubelet(dns, ingress_ip): cloud_config_path = _cloud_config_path('kubelet') kubelet_opts['cloud-provider'] = 'gce' kubelet_opts['cloud-config'] = str(cloud_config_path) + elif is_state('endpoint.openstack.ready'): + cloud_config_path = _cloud_config_path('kubelet') + kubelet_opts['cloud-provider'] = 'openstack' + kubelet_opts['cloud-config'] = str(cloud_config_path) configure_kubernetes_service('kubelet', kubelet_opts, 'kubelet-extra-args') @@ -1037,7 +1041,9 @@ def get_node_name(): if is_state('endpoint.aws.ready'): cloud_provider = 'aws' elif is_state('endpoint.gcp.ready'): - cloud_provider = 'gcp' + cloud_provider = 'gce' + elif is_state('endpoint.openstack.ready'): + cloud_provider = 'openstack' if cloud_provider == 'aws': return getfqdn() else: @@ -1119,11 +1125,14 @@ def clear_requested_integration(): @when_any('endpoint.aws.ready', - 'endpoint.gcp.ready') + 'endpoint.gcp.ready', + 'endpoint.openstack.ready') @when_not('kubernetes-worker.restarted-for-cloud') def restart_for_cloud(): if is_state('endpoint.gcp.ready'): _write_gcp_snap_config('kubelet') + elif is_state('endpoint.openstack.ready'): + _write_openstack_snap_config('kubelet') set_state('kubernetes-worker.restarted-for-cloud') set_state('kubernetes-worker.restart-needed') @@ -1173,6 +1182,21 @@ def _write_gcp_snap_config(component): daemon_env_path.write_text(daemon_env) +def _write_openstack_snap_config(component): + # openstack requires additional credentials setup + openstack = endpoint_from_flag('endpoint.openstack.ready') + + cloud_config_path = _cloud_config_path(component) + cloud_config_path.write_text('\n'.join([ + '[Global]', + 'auth-url = {}'.format(openstack.auth_url), + 'username = {}'.format(openstack.username), + 'password = {}'.format(openstack.password), + 'tenant-name = {}'.format(openstack.project_name), + 'domain-name = {}'.format(openstack.user_domain_name), + ])) + + def get_first_mount(mount_relation): mount_relation_list = mount_relation.mounts() if mount_relation_list and len(mount_relation_list) > 0: