Skip to content

Commit

Permalink
Change modules structure to work correclty with distutils
Browse files Browse the repository at this point in the history
  • Loading branch information
vadim.reyder committed Jan 11, 2019
1 parent e727854 commit cd0211b
Show file tree
Hide file tree
Showing 35 changed files with 101 additions and 65 deletions.
7 changes: 3 additions & 4 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,9 @@ LABEL description="Image with k8s-handle" \
ADD . /opt/k8s-handle/

RUN apk --no-cache add git ca-certificates bash openssl gcc libc-dev libffi-dev openssl-dev make \
&& pip install -r /opt/k8s-handle/requirements.txt \
&& apk del gcc libc-dev libffi-dev openssl-dev \
&& chmod +x /opt/k8s-handle/k8s-handle.py \
&& ln -s /opt/k8s-handle/k8s-handle.py /opt/k8s-handle/k8s-handle
&& cd /opt/k8s-handle \
&& python setup.py install \
&& apk del gcc libc-dev libffi-dev openssl-dev

ENV PATH="/opt/k8s-handle:${PATH}"

Expand Down
4 changes: 2 additions & 2 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
version: '2'
version: '3'
services:
k8s-handle:
build:
context: .
dockerfile: Dockerfile
image: 2gis/k8s-handle:${TAG}
image: 2gis/k8s-handle:${TAG:-latest}
12 changes: 6 additions & 6 deletions k8s-handle.py → k8s_handle/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@
from kubernetes import client
from kubernetes.config import list_kube_config_contexts, load_kube_config

import config
import settings
import templating
from filesystem import InvalidYamlError
from k8s.deprecation_checker import ApiDeprecationChecker, DeprecationError
from k8s.resource import Provisioner, ProvisioningError
from k8s_handle import config
from k8s_handle import settings
from k8s_handle import templating
from k8s_handle.filesystem import InvalidYamlError
from k8s_handle.k8s.deprecation_checker import ApiDeprecationChecker, DeprecationError
from k8s_handle.k8s.resource import Provisioner, ProvisioningError

log = logging.getLogger(__name__)
logging.basicConfig(level=settings.LOG_LEVEL, format=settings.LOG_FORMAT, datefmt=settings.LOG_DATE_FORMAT)
Expand Down
8 changes: 4 additions & 4 deletions config.py → k8s_handle/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@

from kubernetes import client

import settings
from dictionary import merge
from filesystem import load_yaml, write_file_tmp
from templating import b64decode
from k8s_handle import settings
from k8s_handle.dictionary import merge
from k8s_handle.filesystem import load_yaml, write_file_tmp
from k8s_handle.templating import b64decode

log = logging.getLogger(__name__)

Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import semver

from templating import get_template_contexts
from k8s_handle.templating import get_template_contexts

log = logging.getLogger(__name__)

Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
4 changes: 2 additions & 2 deletions k8s/resource.py → k8s_handle/k8s/resource.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
from kubernetes.client.models.v1_resource_requirements import V1ResourceRequirements
from kubernetes.client.rest import ApiException

import settings
from templating import get_template_contexts
from k8s_handle import settings
from k8s_handle.templating import get_template_contexts
from .mocks import K8sClientMock

log = logging.getLogger(__name__)
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import unittest

from k8s.deprecation_checker import ApiDeprecationChecker, DeprecationError
from k8s_handle.k8s.deprecation_checker import ApiDeprecationChecker, DeprecationError


class TestApiDeprecationChecker(unittest.TestCase):
Expand Down
51 changes: 26 additions & 25 deletions k8s/test_provisioner.py → k8s_handle/k8s/test_provisioner.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import unittest

import settings
from templating import get_template_contexts
from k8s_handle import settings
from k8s_handle.templating import get_template_contexts
from .mocks import K8sClientMock
from .mocks import ServiceMetadata
from .mocks import ServicePort
Expand Down Expand Up @@ -218,39 +218,39 @@ def test_missing_ports_strict(self):

def test_deploy_replace(self):
settings.CHECK_STATUS_TIMEOUT = 0
Provisioner('deploy', False, None).run("k8s/fixtures/deployment.yaml")
Provisioner('deploy', False, None).run("k8s_handle/k8s/fixtures/deployment.yaml")

def test_deploy_create(self):
Provisioner('deploy', False, None).run("k8s/fixtures/deployment_404.yaml")
Provisioner('deploy', False, None).run("k8s_handle/k8s/fixtures/deployment_404.yaml")

def test_deploy_unknown_api(self):
with self.assertRaises(RuntimeError) as context:
Provisioner('deploy', False, None).run("k8s/fixtures/deployment_no_api.yaml")
self.assertTrue('Unknown apiVersion "test" in template "k8s/fixtures/deployment_no_api.yaml"'
Provisioner('deploy', False, None).run("k8s_handle/k8s/fixtures/deployment_no_api.yaml")
self.assertTrue('Unknown apiVersion "test" in template "k8s_handle/k8s/fixtures/deployment_no_api.yaml"'
in str(context.exception), context.exception)

def test_service_replace(self):
Provisioner('deploy', False, None).run("k8s/fixtures/service.yaml")
Provisioner('deploy', False, None).run("k8s_handle/k8s/fixtures/service.yaml")

def test_service_replace_no_ports(self):
Provisioner('deploy', False, None).run("k8s/fixtures/service_no_ports.yaml")
Provisioner('deploy', False, None).run("k8s_handle/k8s/fixtures/service_no_ports.yaml")

def test_destroy_unknown_api(self):
with self.assertRaises(RuntimeError) as context:
Provisioner('destroy', False, None).run("k8s/fixtures/deployment_no_api.yaml")
self.assertTrue('Unknown apiVersion "test" in template "k8s/fixtures/deployment_no_api.yaml"'
Provisioner('destroy', False, None).run("k8s_handle/k8s/fixtures/deployment_no_api.yaml")
self.assertTrue('Unknown apiVersion "test" in template "k8s_handle/k8s/fixtures/deployment_no_api.yaml"'
in str(context.exception), context.exception)

def test_destroy_not_found(self):
Provisioner('destroy', False, None).run("k8s/fixtures/deployment_404.yaml")
Provisioner('destroy', False, None).run("k8s_handle/k8s/fixtures/deployment_404.yaml")

def test_destroy_fail(self):
with self.assertRaises(RuntimeError) as context:
Provisioner('destroy', False, None).run("k8s/fixtures/service.yaml")
Provisioner('destroy', False, None).run("k8s_handle/k8s/fixtures/service.yaml")
self.assertTrue('' in str(context.exception), context.exception)

def test_destroy_success(self):
Provisioner('destroy', False, None).run("k8s/fixtures/deployment.yaml")
Provisioner('destroy', False, None).run("k8s_handle/k8s/fixtures/deployment.yaml")

def test_get_apply_ports_case1(self):
# old_port=55, new_port=55, res: no apply ports
Expand Down Expand Up @@ -325,49 +325,50 @@ def test_get_apply_ports_case8(self):
self.assertDictEqual(apply_ports[2], {'port': 99, 'name': 'test2'})

def test_pvc_replace_equals(self):
Provisioner('deploy', False, None).run("k8s/fixtures/pvc.yaml")
Provisioner('deploy', False, None).run("k8s_handle/k8s/fixtures/pvc.yaml")

def test_pvc_replace_not_equals(self):
with self.assertRaises(ProvisioningError) as context:
Provisioner('deploy', False, None).run("k8s/fixtures/pvc2.yaml")
Provisioner('deploy', False, None).run("k8s_handle/k8s/fixtures/pvc2.yaml")
self.assertTrue('Replace persistent volume claim fail' in str(context.exception), context.exception)

# https://kubernetes.io/docs/concepts/storage/persistent-volumes/#volume-mode
def test_pvc_replace_new_attribute(self):
with self.assertRaises(ProvisioningError) as context:
Provisioner('deploy', False, None).run("k8s/fixtures/pvc3.yaml")
Provisioner('deploy', False, None).run("k8s_handle/k8s/fixtures/pvc3.yaml")
self.assertTrue('Replace persistent volume claim fail'
in str(context.exception))

def test_get_template_contexts(self):
with self.assertRaises(StopIteration):
next(get_template_contexts('k8s/fixtures/empty.yaml'))
next(get_template_contexts('k8s_handle/k8s/fixtures/empty.yaml'))

with self.assertRaises(RuntimeError) as context:
next(get_template_contexts('k8s/fixtures/nokind.yaml'))
next(get_template_contexts('k8s_handle/k8s/fixtures/nokind.yaml'))
self.assertTrue(
'Field "kind" not found (or empty) in file "k8s/fixtures/nokind.yaml"' in str(context.exception),
'Field "kind" not found (or empty) in file "k8s_handle/k8s/fixtures/nokind.yaml"' in str(context.exception),
context.exception)

with self.assertRaises(RuntimeError) as context:
next(get_template_contexts('k8s/fixtures/nometadata.yaml'))
next(get_template_contexts('k8s_handle/k8s/fixtures/nometadata.yaml'))
self.assertTrue(
'Field "metadata" not found (or empty) in file "k8s/fixtures/nometadata.yaml"' in str(context.exception),
'Field "metadata" not found (or empty) in file "k8s_handle/k8s/fixtures/nometadata.yaml"'
in str(context.exception),
context.exception)

with self.assertRaises(RuntimeError) as context:
next(get_template_contexts('k8s/fixtures/nometadataname.yaml'))
next(get_template_contexts('k8s_handle/k8s/fixtures/nometadataname.yaml'))
self.assertTrue(
'Field "metadata->name" not found (or empty) in file "k8s/fixtures/nometadataname.yaml"'
'Field "metadata->name" not found (or empty) in file "k8s_handle/k8s/fixtures/nometadataname.yaml"'
in str(context.exception), context.exception)

context = next(get_template_contexts('k8s/fixtures/valid.yaml'))
context = next(get_template_contexts('k8s_handle/k8s/fixtures/valid.yaml'))
self.assertEqual(context.get('kind'), 'Service')
self.assertEqual(context.get('apiVersion'), 'v1')
self.assertEqual(context.get('metadata').get('name'), 'my-service')
self.assertEqual(context.get('spec').get('selector').get('app'), 'my-app')

context = next(get_template_contexts('k8s/fixtures/deployment_wo_replicas.yaml'))
context = next(get_template_contexts('k8s_handle/k8s/fixtures/deployment_wo_replicas.yaml'))
self.assertEqual(context.get('spec').get('replicas'), 1)


Expand Down
File renamed without changes.
6 changes: 2 additions & 4 deletions templating.py → k8s_handle/templating.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import base64
import logging
import yaml
import settings
from k8s_handle import settings
from hashlib import sha256
from jinja2 import Environment, FileSystemLoader, StrictUndefined
from jinja2.exceptions import TemplateNotFound, UndefinedError, TemplateSyntaxError
Expand Down Expand Up @@ -87,10 +87,8 @@ def _create_dir(dir):


class Renderer:
def __init__(self, templates_dir=None):
def __init__(self, templates_dir):
self._templates_dir = templates_dir
if self._templates_dir is None:
self._templates_dir = os.path.join(os.path.dirname(__file__), 'templates')
self._env = get_env(self._templates_dir)

def generate_by_context(self, context):
Expand Down
36 changes: 36 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import os
from setuptools import setup, find_packages

readme_path = os.path.join(
os.path.dirname(os.path.abspath(__file__)),
'README.md')


def get_content(path):
with open(path, 'r') as f:
return f.read()


setup(name='k8s-handle',
version='0.2.3',
long_description=get_content(readme_path),
long_description_content_type="text/markdown",
description='Provisioning tool for Kubernetes apps',
url='http://github.com/2gis/k8s-handle',
author='Vadim Reyder',
author_email='vadim.reyder@gmail.com',
license='Apache 2.0',
packages=find_packages(exclude=("tests",)),
entry_points={
"console_scripts": [
"k8s-handle=k8s_handle:main",
]
},
install_requires=[
'requests>=2.20.1',
'jinja2>=2.10',
'PyYAML>=4.2b4',
'kubernetes>=6.0.0',
'semver>=2.8.1',
],
zip_safe=False)
18 changes: 12 additions & 6 deletions tests/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,18 @@
import shutil
import unittest

import config
import settings
from config import KEY_K8S_CA_BASE64, KEY_K8S_MASTER_URI, KEY_K8S_NAMESPACE, KEY_K8S_NAMESPACE_ENV, KEY_K8S_TOKEN
from config import KEY_K8S_CA_BASE64_URI_ENV_DEPRECATED, KEY_K8S_HANDLE_DEBUG, KEY_K8S_MASTER_URI_ENV_DEPRECATED
from config import PriorityEvaluator
from filesystem import InvalidYamlError
from k8s_handle import config
from k8s_handle import settings
from k8s_handle.config import KEY_K8S_CA_BASE64
from k8s_handle.config import KEY_K8S_MASTER_URI
from k8s_handle.config import KEY_K8S_NAMESPACE
from k8s_handle.config import KEY_K8S_NAMESPACE_ENV
from k8s_handle.config import KEY_K8S_TOKEN
from k8s_handle.config import KEY_K8S_CA_BASE64_URI_ENV_DEPRECATED
from k8s_handle.config import KEY_K8S_HANDLE_DEBUG
from k8s_handle.config import KEY_K8S_MASTER_URI_ENV_DEPRECATED
from k8s_handle.config import PriorityEvaluator
from k8s_handle.filesystem import InvalidYamlError

VALUE_CLI = 'value_cli'
VALUE_CONTEXT = 'value_context'
Expand Down
2 changes: 1 addition & 1 deletion tests/test_dictionary.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import unittest

import dictionary
from k8s_handle import dictionary


class TestDictionaryMerge(unittest.TestCase):
Expand Down
14 changes: 5 additions & 9 deletions tests/test_templating.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import os
import shutil
import unittest
import settings
import config
import templating
from templating import TemplateRenderingError
from k8s_handle import settings
from k8s_handle import config
from k8s_handle import templating
from k8s_handle.templating import TemplateRenderingError


class TestTemplating(unittest.TestCase):
Expand All @@ -22,15 +22,11 @@ def tearDown(self):
os.environ.pop('K8S_CONFIG_DIR')

def test_renderer_init(self):
r = templating.Renderer()
expected = os.path.join(os.path.dirname(__file__), '../templates')
self.assertEqual(r._templates_dir, os.path.abspath(expected))

r = templating.Renderer('/tmp/test')
self.assertEqual(r._templates_dir, '/tmp/test')

def test_none_context(self):
r = templating.Renderer()
r = templating.Renderer('templates')
with self.assertRaises(RuntimeError) as context:
r.generate_by_context(None)
self.assertTrue('Can\'t generate templates from None context' in str(context.exception), str(context.exception))
Expand Down

0 comments on commit cd0211b

Please sign in to comment.