Merge "cni health: Avoid capsh dependency"

This commit is contained in:
Zuul
2018-03-06 10:39:29 +00:00
committed by Gerrit Code Review
2 changed files with 25 additions and 14 deletions

View File

@@ -15,7 +15,6 @@ import os
import psutil import psutil
import requests import requests
from six.moves import http_client as httplib from six.moves import http_client as httplib
import subprocess
from flask import Flask from flask import Flask
from pyroute2 import IPDB from pyroute2 import IPDB
@@ -41,6 +40,16 @@ cni_health_server_opts = [
CONF.register_opts(cni_health_server_opts, "cni_health_server") CONF.register_opts(cni_health_server_opts, "cni_health_server")
BYTES_AMOUNT = 1048576 BYTES_AMOUNT = 1048576
CAP_NET_ADMIN = 12 # Taken from linux/capabilities.h
EFFECTIVE_CAPS = 'CapEff:\t'
def _has_cap(capability, entry):
with open('/proc/self/status', 'r') as pstat:
for line in pstat:
if line.startswith(entry):
caps = int(line[len(entry):], 16)
return (caps & (1 << capability)) != 0
class CNIHealthServer(object): class CNIHealthServer(object):
@@ -63,13 +72,10 @@ class CNIHealthServer(object):
self.headers = {'Connection': 'close'} self.headers = {'Connection': 'close'}
def readiness_status(self): def readiness_status(self):
net_admin_command = 'capsh --print | grep "Current:" | ' \
'cut -d" " -f3 | grep -q cap_net_admin'
return_code = subprocess.call(net_admin_command, shell=True)
data = 'ok' data = 'ok'
k8s_conn, k8s_status = self.verify_k8s_connection() k8s_conn, k8s_status = self.verify_k8s_connection()
if return_code != 0: if not _has_cap(CAP_NET_ADMIN, EFFECTIVE_CAPS):
error_message = 'NET_ADMIN capabilities not present.' error_message = 'NET_ADMIN capabilities not present.'
LOG.error(error_message) LOG.error(error_message)
return error_message, httplib.INTERNAL_SERVER_ERROR, self.headers return error_message, httplib.INTERNAL_SERVER_ERROR, self.headers

View File

@@ -32,30 +32,30 @@ class TestCNIHealthServer(base.TestCase):
self.srv.application.testing = True self.srv.application.testing = True
self.test_client = self.srv.application.test_client() self.test_client = self.srv.application.test_client()
@mock.patch('subprocess.call') @mock.patch('kuryr_kubernetes.cni.health._has_cap')
@mock.patch('kuryr_kubernetes.cni.health.CNIHealthServer.' @mock.patch('kuryr_kubernetes.cni.health.CNIHealthServer.'
'verify_k8s_connection') 'verify_k8s_connection')
def test_readiness_status(self, m_verify_k8s_conn, m_subprocess): def test_readiness_status(self, m_verify_k8s_conn, cap_tester):
m_subprocess.return_value = 0 cap_tester.return_value = True
m_verify_k8s_conn.return_value = True, 200 m_verify_k8s_conn.return_value = True, 200
resp = self.test_client.get('/ready') resp = self.test_client.get('/ready')
self.assertEqual(200, resp.status_code) self.assertEqual(200, resp.status_code)
@mock.patch('subprocess.call') @mock.patch('kuryr_kubernetes.cni.health._has_cap')
@mock.patch('kuryr_kubernetes.cni.health.CNIHealthServer.' @mock.patch('kuryr_kubernetes.cni.health.CNIHealthServer.'
'verify_k8s_connection') 'verify_k8s_connection')
def test_readiness_status_net_admin_error(self, m_verify_k8s_conn, def test_readiness_status_net_admin_error(self, m_verify_k8s_conn,
m_subprocess): cap_tester):
m_subprocess.return_value = 1 cap_tester.return_value = False
m_verify_k8s_conn.return_value = True, 200 m_verify_k8s_conn.return_value = True, 200
resp = self.test_client.get('/ready') resp = self.test_client.get('/ready')
self.assertEqual(500, resp.status_code) self.assertEqual(500, resp.status_code)
@mock.patch('subprocess.call') @mock.patch('kuryr_kubernetes.cni.health._has_cap')
@mock.patch('kuryr_kubernetes.cni.health.CNIHealthServer.' @mock.patch('kuryr_kubernetes.cni.health.CNIHealthServer.'
'verify_k8s_connection') 'verify_k8s_connection')
def test_readiness_status_k8s_error(self, m_verify_k8s_conn, m_subprocess): def test_readiness_status_k8s_error(self, m_verify_k8s_conn, cap_tester):
m_subprocess.return_value = 0 cap_tester.return_value = True
m_verify_k8s_conn.return_value = False, 503 m_verify_k8s_conn.return_value = False, 503
resp = self.test_client.get('/ready') resp = self.test_client.get('/ready')
self.assertEqual(503, resp.status_code) self.assertEqual(503, resp.status_code)
@@ -87,3 +87,8 @@ class TestCNIHealthServer(base.TestCase):
m_resource.return_value = cls m_resource.return_value = cls
resp = self.test_client.get('/alive') resp = self.test_client.get('/alive')
self.assertEqual(500, resp.status_code) self.assertEqual(500, resp.status_code)
class TestCNIHealthUtils(base.TestCase):
def test_has_cap(self):
self.assertTrue(health._has_cap(health.CAP_NET_ADMIN, 'CapBnd:\t'))