Bump openshift dep

The openshift library has been completely redesigned with recent
releases so bump the dep and adapt to the new api. The update is
necessary in order to fix a urllib3 version conflict [1].

[1] Trace:
ERROR: nodepool 3.14.1.dev3 has requirement urllib3<1.26,>=1.25.4, but you'll have urllib3 1.24 which is incompatible.
ERROR: kubernetes 8.0.2 has requirement urllib3>=1.24.2, but you'll have urllib3 1.24 which is incompatible.
ERROR: botocore 1.19.30 has requirement urllib3<1.27,>=1.25.4; python_version != "3.4", but you'll have urllib3 1.24 which is incompatible.

Change-Id: Ia4d09fd0a4a49d644bb575b74184de930c62ce89
Co-Authored-By: Tobias Henkel <tobias.henkel@bmw.de>
Story: 2008427
Task: 41373
This commit is contained in:
Clark Boylan 2020-12-07 12:46:20 -08:00 committed by Tobias Henkel
parent d1a123111b
commit e7f831c34e
No known key found for this signature in database
GPG Key ID: 03750DEC158E5FA2
8 changed files with 118 additions and 57 deletions

View File

@ -14,16 +14,21 @@
# See the License for the specific language governing permissions and
# limitations under the License.
from kubernetes import config as k8s_config
from nodepool.driver import Driver
from nodepool.driver.kubernetes.config import KubernetesProviderConfig
from nodepool.driver.kubernetes.provider import KubernetesProvider
from openshift import config
class KubernetesDriver(Driver):
def reset(self):
try:
config.load_kube_config(persist_config=True)
k8s_config.load_kube_config(persist_config=True)
except k8s_config.config_exception.ConfigException as e:
if 'Invalid kube-config file. No configuration found.' in str(e):
pass
else:
raise
except FileNotFoundError:
pass

View File

@ -18,9 +18,8 @@ import math
import urllib3
import time
from kubernetes.config import config_exception as kce
from kubernetes import client as k8s_client
from openshift import config
from kubernetes import config as k8s_config
from nodepool import exceptions
from nodepool.driver import Provider
@ -41,10 +40,10 @@ class KubernetesProvider(Provider, QuotaSupport):
try:
self.k8s_client, self.rbac_client = self._get_client(
provider.context)
except kce.ConfigException:
except k8s_config.config_exception.ConfigException:
self.log.exception("Couldn't load client from config")
self.log.info("Get context list using this command: "
"python3 -c \"from openshift import config; "
"python3 -c \"from kubernetes import config; "
"print('\\n'.join([i['name'] for i in "
"config.list_kube_config_contexts()[0]]))\"")
self.k8s_client = None
@ -55,11 +54,11 @@ class KubernetesProvider(Provider, QuotaSupport):
def _get_client(self, context):
try:
conf = config.new_client_from_config(context=context)
conf = k8s_config.new_client_from_config(context=context)
except FileNotFoundError:
self.log.debug("Kubernetes config file not found, attempting "
"to load in-cluster configs")
conf = config.load_incluster_config()
conf = k8s_config.load_incluster_config()
return (
k8s_client.CoreV1Api(conf),

View File

@ -14,10 +14,10 @@
# See the License for the specific language governing permissions and
# limitations under the License.
from kubernetes import config as k8s_config
from nodepool.driver import Driver
from nodepool.driver.openshift.config import OpenshiftProviderConfig
from nodepool.driver.openshift.provider import OpenshiftProvider
from openshift import config
class OpenshiftDriver(Driver):
@ -26,7 +26,12 @@ class OpenshiftDriver(Driver):
def reset(self):
try:
config.load_kube_config(persist_config=True)
k8s_config.load_kube_config(persist_config=True)
except k8s_config.config_exception.ConfigException as e:
if 'Invalid kube-config file. No configuration found.' in str(e):
pass
else:
raise
except FileNotFoundError:
pass

View File

@ -17,10 +17,9 @@ import logging
import urllib3
import time
from kubernetes.config import config_exception as kce
from kubernetes import client as k8s_client
from openshift import client as os_client
from openshift import config
from kubernetes import config as k8s_config
from openshift.dynamic import DynamicClient as os_client
from nodepool import exceptions
from nodepool.driver import Provider
@ -38,7 +37,7 @@ class OpenshiftProvider(Provider):
try:
self.os_client, self.k8s_client = self._get_client(
provider.context)
except kce.ConfigException:
except k8s_config.config_exception.ConfigException:
self.log.exception(
"Couldn't load context %s from config", provider.context)
self.os_client = None
@ -48,9 +47,9 @@ class OpenshiftProvider(Provider):
self.project_names.add(pool.name)
def _get_client(self, context):
conf = config.new_client_from_config(context=context)
conf = k8s_config.new_client_from_config(context=context)
return (
os_client.OapiApi(conf),
os_client(conf),
k8s_client.CoreV1Api(conf))
def start(self, zk_conn):
@ -87,7 +86,9 @@ class OpenshiftProvider(Provider):
return getattr(self, name, default)
if self.ready:
for project in self.os_client.list_project().items:
projects = self.os_client.resources.get(api_version='v1',
kind='Project')
for project in projects.get().items:
servers.append(FakeServer(
project, self.provider.name, self.project_names))
return servers
@ -107,16 +108,20 @@ class OpenshiftProvider(Provider):
return
self.log.debug("%s: removing project" % server_id)
try:
self.os_client.delete_project(server_id)
project = self.os_client.resources.get(api_version='v1',
kind='Project')
project.delete(name=server_id)
self.log.info("%s: project removed" % server_id)
except Exception:
# TODO: implement better exception handling
self.log.exception("Couldn't remove project %s" % server_id)
def waitForNodeCleanup(self, server_id):
project = self.os_client.resources.get(api_version='v1',
kind='Project')
for retry in range(300):
try:
self.os_client.read_project(server_id)
project.get(name=server_id)
except Exception:
break
time.sleep(1)
@ -125,13 +130,15 @@ class OpenshiftProvider(Provider):
self.log.debug("%s: creating project" % project)
# Create the project
proj_body = {
'apiVersion': 'v1',
'apiVersion': 'project.openshift.io/v1',
'kind': 'ProjectRequest',
'metadata': {
'name': project,
}
}
self.os_client.create_project_request(proj_body)
projects = self.os_client.resources.get(
api_version='project.openshift.io/v1', kind='ProjectRequest')
projects.create(body=proj_body)
return project
def prepareProject(self, project):
@ -170,8 +177,8 @@ class OpenshiftProvider(Provider):
(project, sa))
# Give service account admin access
role_body = {
'apiVersion': 'v1',
role_binding_body = {
'apiVersion': 'authorization.openshift.io/v1',
'kind': 'RoleBinding',
'metadata': {'name': 'admin-0'},
'roleRef': {'name': 'admin'},
@ -180,18 +187,21 @@ class OpenshiftProvider(Provider):
'name': user,
'namespace': project,
}],
'userNames': ['system:serviceaccount:%s:zuul-worker' % project]
'userNames': ['system:serviceaccount:%s:%s' % (project, user)]
}
try:
self.os_client.create_namespaced_role_binding(project, role_body)
role_bindings = self.os_client.resources.get(
api_version='authorization.openshift.io/v1',
kind='RoleBinding')
role_bindings.create(body=role_binding_body, namespace=project)
except ValueError:
# https://github.com/ansible/ansible/issues/36939
pass
resource = {
'namespace': project,
'host': self.os_client.api_client.configuration.host,
'skiptls': not self.os_client.api_client.configuration.verify_ssl,
'host': self.os_client.configuration.host,
'skiptls': not self.os_client.configuration.verify_ssl,
'token': token,
'user': user,
}

View File

@ -14,10 +14,10 @@
# See the License for the specific language governing permissions and
# limitations under the License.
from kubernetes import config as k8s_config
from nodepool.driver import Driver
from nodepool.driver.openshiftpods.config import OpenshiftPodsProviderConfig
from nodepool.driver.openshiftpods.provider import OpenshiftPodsProvider
from openshift import config
class OpenshiftPodsDriver(Driver):
@ -26,7 +26,12 @@ class OpenshiftPodsDriver(Driver):
def reset(self):
try:
config.load_kube_config(persist_config=True)
k8s_config.load_kube_config(persist_config=True)
except k8s_config.config_exception.ConfigException as e:
if 'Invalid kube-config file. No configuration found.' in str(e):
pass
else:
raise
except FileNotFoundError:
pass

View File

@ -17,9 +17,8 @@ import logging
import urllib3
import time
from kubernetes.config import config_exception as kce
from kubernetes import client as k8s_client
from openshift import config
from kubernetes import config as k8s_config
from nodepool.driver.openshift.provider import OpenshiftProvider
from nodepool.driver.openshiftpods import handler
@ -37,10 +36,10 @@ class OpenshiftPodsProvider(OpenshiftProvider):
try:
self.token, self.ca_crt, self.k8s_client = self._get_client(
provider.context)
except kce.ConfigException:
except k8s_config.config_exception.ConfigException:
self.log.exception("Couldn't load client from config")
self.log.info("Get context list using this command: "
"python3 -c \"from openshift import config; "
"python3 -c \"from kubernetes import config; "
"print('\\n'.join([i['name'] for i in "
"config.list_kube_config_contexts()[0]]))\"")
self.token = None
@ -51,7 +50,7 @@ class OpenshiftPodsProvider(OpenshiftProvider):
self.pod_names.update(pool.labels.keys())
def _get_client(self, context):
conf = config.new_client_from_config(context=context)
conf = k8s_config.new_client_from_config(context=context)
token = conf.configuration.api_key.get('authorization', '').split()[-1]
ca = None
if conf.configuration.ssl_ca_cert:

View File

@ -21,42 +21,77 @@ from nodepool import zk
from nodepool.driver.openshift import provider
class FakeOpenshiftClient(object):
def __init__(self):
self.projects = []
class FakeOpenshiftProjectsQuery:
class FakeApi:
class configuration:
host = "http://localhost:8080"
verify_ssl = False
self.api_client = FakeApi()
def __init__(self, client):
self.client = client
def list_project(self):
class FakeProjects:
items = self.projects
return FakeProjects
def get(self):
class FakeProjectsResult:
def __init__(self, items):
self.items = items
def create_project_request(self, proj_body):
class FakeProject:
class metadata:
name = proj_body['metadata']['name']
self.projects.append(FakeProject)
return FakeProject
return FakeProjectsResult(self.client.projects)
def delete_project(self, name):
def delete(self, name):
to_delete = None
for project in self.projects:
for project in self.client.projects:
if project.metadata.name == name:
to_delete = project
break
if not to_delete:
raise RuntimeError("Unknown project %s" % name)
self.projects.remove(to_delete)
self.client.projects.remove(to_delete)
def create_namespaced_role_binding(self, ns, role_binding_body):
class FakeOpenshiftProjectRequestQuery:
def __init__(self, client):
self.client = client
def create(self, body):
class FakeProject:
class metadata:
name = body['metadata']['name']
self.client.projects.append(FakeProject)
return FakeProject
class FakeOpenshiftRoleBindingQuery:
def __init__(self, client):
self.client = client
def create(self, body, namespace):
return
class FakeOpenshiftResources:
def __init__(self, client):
self.client = client
def get(self, api_version=None, kind=None):
if kind == 'Project':
return FakeOpenshiftProjectsQuery(self.client)
if kind == 'ProjectRequest':
return FakeOpenshiftProjectRequestQuery(self.client)
if kind == 'RoleBinding':
return FakeOpenshiftRoleBindingQuery(self.client)
raise NotImplementedError
class FakeOpenshiftClient(object):
def __init__(self):
self.projects = []
class FakeConfiguration:
host = "http://localhost:8080"
verify_ssl = False
self.configuration = FakeConfiguration()
self.resources = FakeOpenshiftResources(self)
class FakeCoreClient(object):
def create_namespaced_service_account(self, ns, sa_body):
return
@ -153,3 +188,6 @@ class TestDriverOpenshift(tests.DBTestCase):
self.zk.storeNode(node)
self.waitForNodeDeletion(node)
self.assertEqual(len(self.fake_os_client.projects), 0,
'Project must be cleaned up')

View File

@ -15,7 +15,7 @@ voluptuous
kazoo>=2.8.0
Paste
WebOb>=1.8.1
openshift<=0.8.9
openshift<0.12.0
boto3
google-api-python-client
azure-mgmt-compute<17.0.0