def update_res(name, image, password, database, body):
    api = kubernetes.client.AppsV1Api()
    apiBatch = kubernetes.client.BatchV1Api()
    print(f"delete job: restore-{name}-job")
    try:
        #удаляем деплоймент
        api.delete_namespaced_deployment(name,
                                         'default',
                                         propagation_policy='Background')
    except kubernetes.client.rest.ApiException:
        pass
    #Инициализируем деплоймент с новым паролем
    deployment = render_template('mysql-deployment.yml.j2', {
        'name': name,
        'image': image,
        'password': password,
        'database': database
    })
    kopf.append_owner_reference(deployment, owner=body)
    #Создаем деплоймент и задание
    try:
        api.create_namespaced_deployment('default', deployment)
        api = kubernetes.client.BatchV1Api()
    except kubernetes.client.rest.ApiException:
        pass
async def adopt_service(meta, spec, body, namespace, labels, name, **kwargs):
    """Handler function for new services
    
    If the service has an oda.tmforum.org/componentName label, it makes the service a child of the named component.
    This can help with navigating around the different resources that belong to the component. It also ensures that the kubernetes garbage collection
    will delete these resources automatically if the component is deleted.

    Args:
        * meta (Dict): The metadata from the yaml service definition 
        * spec (Dict): The spec from the yaml service definition showing the intent (or desired state) 
        * status (Dict): The status from the yaml service definition showing the actual state.
        * body (Dict): The entire yaml service definition
        * namespace (String): The namespace for the service
        * labels (Dict): The labels attached to the service. All ODA Components (and their children) should have a oda.tmforum.org/componentName label
        * name (String): The name of the service

    Returns:
        No return value.

    :meta public:
    """
    logger.debug(
        f"[adopt_service/{namespace}/{name}] handler called with spec: {spec}")
    logger.debug("adopt_service called for service - if it is part of a component (oda.tmforum.org/componentName as a label) then make it a child ")

    if 'oda.tmforum.org/componentName' in labels.keys():

        # get the parent component object
        # str | the custom object's name
        component_name = labels['oda.tmforum.org/componentName']
        try:
            custom_objects_api = kubernetes.client.CustomObjectsApi()
            parent_component = custom_objects_api.get_namespaced_custom_object(
                GROUP, VERSION, namespace, COMPONENTS_PLURAL, component_name)
        except ApiException as e:
            # Cant find parent component (if component in same chart as other kubernetes resources it may not be created yet)
            if e.status == HTTP_NOT_FOUND:
                raise kopf.TemporaryError(
                    "Cannot find parent component " + component_name)
            else:
                logger.error(
                    "Exception when calling custom_objects_api.get_namespaced_custom_object: %s", e)

        # append oener reference to parent component
        newBody = dict(body)  # cast the service body to a dict
        kopf.append_owner_reference(newBody, owner=parent_component)
        core_api_instance = kubernetes.client.CoreV1Api()
        try:
            api_response = core_api_instance.patch_namespaced_service(
                newBody['metadata']['name'], newBody['metadata']['namespace'], newBody)
            logger.debug(
                'Patch service with owner. api_response = %s', api_response)
            logger.info(
                f'[adopt_service/{namespace}/{name}] Adding component {component_name} as parent of service')
        except ApiException as e:
            if e.status == HTTP_CONFLICT:  # Conflict = try again
                raise kopf.TemporaryError("Conflict updating service.")
            else:
                logger.error(
                    "Exception when calling core_api_instance.patch_namespaced_service: %s", e)
def test_removal_from_kubernetes_model(kubernetes_model):
    kubernetes_model.metadata = None
    kopf.append_owner_reference(kubernetes_model, owner=Body(OWNER))
    kopf.remove_owner_reference(kubernetes_model, owner=Body(OWNER))
    assert kubernetes_model.metadata is not None
    assert kubernetes_model.metadata.owner_references is not None
    assert isinstance(kubernetes_model.metadata.owner_references, list)
    assert len(kubernetes_model.metadata.owner_references) == 0
def test_removal_from_pykube_object(pykube_object):
    del pykube_object.obj['metadata']
    kopf.append_owner_reference(pykube_object, owner=Body(OWNER))
    kopf.remove_owner_reference(pykube_object, owner=Body(OWNER))
    assert 'metadata' in pykube_object.obj
    assert 'ownerReferences' in pykube_object.obj['metadata']
    assert isinstance(pykube_object.obj['metadata']['ownerReferences'], list)
    assert len(pykube_object.obj['metadata']['ownerReferences']) == 0
Exemple #5
0
def test_removal_from_dict():
    obj = {}

    kopf.append_owner_reference(obj, owner=Body(OWNER))  # assumed to work, tested above
    kopf.remove_owner_reference(obj, owner=Body(OWNER))  # this one is being tested here

    assert 'metadata' in obj
    assert 'ownerReferences' in obj['metadata']
    assert isinstance(obj['metadata']['ownerReferences'], list)
    assert len(obj['metadata']['ownerReferences']) == 0
def test_appending_to_kubernetes_model(kubernetes_model):
    kubernetes_model.metadata = None
    kopf.append_owner_reference(kubernetes_model, owner=Body(OWNER))
    assert kubernetes_model.metadata is not None
    assert kubernetes_model.metadata.owner_references is not None
    assert isinstance(kubernetes_model.metadata.owner_references, list)
    assert len(kubernetes_model.metadata.owner_references) == 1
    assert kubernetes_model.metadata.owner_references[
        0].api_version == OWNER_API_VERSION
    assert kubernetes_model.metadata.owner_references[0].kind == OWNER_KIND
    assert kubernetes_model.metadata.owner_references[0].name == OWNER_NAME
    assert kubernetes_model.metadata.owner_references[0].uid == OWNER_UID
Exemple #7
0
def test_appending_to_dict():
    obj = {}

    kopf.append_owner_reference(obj, owner=Body(OWNER))

    assert 'metadata' in obj
    assert 'ownerReferences' in obj['metadata']
    assert isinstance(obj['metadata']['ownerReferences'], list)
    assert len(obj['metadata']['ownerReferences']) == 1
    assert isinstance(obj['metadata']['ownerReferences'][0], dict)
    assert obj['metadata']['ownerReferences'][0]['apiVersion'] == OWNER_API_VERSION
    assert obj['metadata']['ownerReferences'][0]['kind'] == OWNER_KIND
    assert obj['metadata']['ownerReferences'][0]['name'] == OWNER_NAME
    assert obj['metadata']['ownerReferences'][0]['uid'] == OWNER_UID
Exemple #8
0
def test_appending_distinguishes_by_uid():
    """
    Changing only the uid should be sufficient to consider a new owner.
    Here, all other non-id fields are the same, and must be ignored.
    """
    owner1 = copy.deepcopy(OWNER)
    owner2 = copy.deepcopy(OWNER)
    owner1['metadata']['uid'] = 'uid-a'
    owner2['metadata']['uid'] = 'uid-b'
    obj = {}

    kopf.append_owner_reference(obj, owner=Body(owner1))
    kopf.append_owner_reference(obj, owner=Body(owner2))

    uids = {ref['uid'] for ref in obj['metadata']['ownerReferences']}
    assert uids == {'uid-a', 'uid-b'}
Exemple #9
0
def test_removal_from_multiple_objects(multicls):
    obj1 = {}
    obj2 = {}
    objs = multicls([obj1, obj2])

    kopf.append_owner_reference(objs, owner=Body(OWNER))  # assumed to work, tested above
    kopf.remove_owner_reference(objs, owner=Body(OWNER))  # this one is being tested here

    assert 'metadata' in obj1
    assert 'ownerReferences' in obj1['metadata']
    assert isinstance(obj1['metadata']['ownerReferences'], list)
    assert len(obj1['metadata']['ownerReferences']) == 0

    assert 'metadata' in obj2
    assert 'ownerReferences' in obj2['metadata']
    assert isinstance(obj2['metadata']['ownerReferences'], list)
    assert len(obj2['metadata']['ownerReferences']) == 0
def mysql_on_create(body, spec, **kwargs):
    name = body['metadata']['name']
    image = body['spec']['image'] # cохраняем в переменные содержимое описания MySQL из CR
    password = body['spec']['password']
    database = body['spec']['database']
    storage_size = body['spec']['storage_size']

    # Генерируем JSON манифесты для деплоя
    persistent_volume = render_template('mysql-pv.yml.j2', {'name': name, 'storage_size': storage_size})
    persistent_volume_claim = render_template('mysql-pvc.yml.j2', {'name': name, 'storage_size': storage_size})
    service = render_template('mysql-service.yml.j2', {'name': name})
    deployment = render_template('mysql-deployment.yml.j2', {'name': name, 'image': image, 'password': password, 'database': database})
    restore_job = render_template('restore-job.yml.j2', {'name': name, 'image': image, 'password': password, 'database': database})
    
    # Определяем, что созданные ресурсы являются дочерними к управляемому CustomResource:
    kopf.append_owner_reference(persistent_volume, owner=body)
    kopf.append_owner_reference(persistent_volume_claim, owner=body)  # addopt
    kopf.append_owner_reference(service, owner=body)
    kopf.append_owner_reference(deployment, owner=body)
    # ^ Таким образом при удалении CR удалятся все, связанные с ним pv,pvc,svc, deployments

    # Используем api k8s
    api = kubernetes.client.CoreV1Api()
    # Создаем mysql PV:
    api.create_persistent_volume(persistent_volume)
    # Создаем mysql PVC:
    api.create_namespaced_persistent_volume_claim('default', persistent_volume_claim)
    # Создаем mysql SVC:
    api.create_namespaced_service('default', service)

    # Создаем mysql Deployment:
    api = kubernetes.client.AppsV1Api()
    api.create_namespaced_deployment('default', deployment)

    # Пытаемся восстановиться из backup
    try:
        api = kubernetes.client.BatchV1Api()
        api.create_namespaced_job('default', restore_job)
    except kubernetes.client.rest.ApiException:
        pass

    # Cоздаем PVC  и PV для бэкапов:
    try:
        backup_pv = render_template('backup-pv.yml.j2', {'name': name})
        api = kubernetes.client.CoreV1Api()
        print(api.create_persistent_volume(backup_pv))
        api.create_persistent_volume(backup_pv)
    except kubernetes.client.rest.ApiException:
        pass

    try:
        backup_pvc = render_template('backup-pvc.yml.j2', {'name': name})
        api = kubernetes.client.CoreV1Api()
        api.create_namespaced_persistent_volume_claim('default', backup_pvc)
    except kubernetes.client.rest.ApiException:
        pass
def test_appending_to_pykube_object(pykube_object):
    del pykube_object.obj['metadata']
    kopf.append_owner_reference(pykube_object, owner=Body(OWNER))
    assert 'metadata' in pykube_object.obj
    assert 'ownerReferences' in pykube_object.obj['metadata']
    assert isinstance(pykube_object.obj['metadata']['ownerReferences'], list)
    assert len(pykube_object.obj['metadata']['ownerReferences']) == 1
    assert isinstance(pykube_object.obj['metadata']['ownerReferences'][0],
                      dict)
    assert pykube_object.obj['metadata']['ownerReferences'][0][
        'apiVersion'] == OWNER_API_VERSION
    assert pykube_object.obj['metadata']['ownerReferences'][0][
        'kind'] == OWNER_KIND
    assert pykube_object.obj['metadata']['ownerReferences'][0][
        'name'] == OWNER_NAME
    assert pykube_object.obj['metadata']['ownerReferences'][0][
        'uid'] == OWNER_UID
Exemple #12
0
def test_appending_to_multiple_objects(multicls):
    obj1 = {}
    obj2 = {}
    objs = multicls([obj1, obj2])

    kopf.append_owner_reference(objs, owner=Body(OWNER))

    assert isinstance(obj1['metadata']['ownerReferences'], list)
    assert len(obj1['metadata']['ownerReferences']) == 1
    assert obj1['metadata']['ownerReferences'][0]['apiVersion'] == OWNER_API_VERSION
    assert obj1['metadata']['ownerReferences'][0]['kind'] == OWNER_KIND
    assert obj1['metadata']['ownerReferences'][0]['name'] == OWNER_NAME
    assert obj1['metadata']['ownerReferences'][0]['uid'] == OWNER_UID

    assert isinstance(obj2['metadata']['ownerReferences'], list)
    assert len(obj2['metadata']['ownerReferences']) == 1
    assert obj2['metadata']['ownerReferences'][0]['apiVersion'] == OWNER_API_VERSION
    assert obj2['metadata']['ownerReferences'][0]['kind'] == OWNER_KIND
    assert obj2['metadata']['ownerReferences'][0]['name'] == OWNER_NAME
    assert obj2['metadata']['ownerReferences'][0]['uid'] == OWNER_UID
Exemple #13
0
def test_removal_identifies_by_uid():
    owner1 = copy.deepcopy(OWNER)
    owner2 = copy.deepcopy(OWNER)
    owner3 = copy.deepcopy(OWNER)
    owner1['kind'] = 'KindA'
    owner2['kind'] = 'KindA'
    owner3['kind'] = 'KindB'
    owner1['metadata']['name'] = 'name-a'
    owner2['metadata']['name'] = 'name-b'
    owner3['metadata']['name'] = 'name-b'
    owner1['metadata']['uid'] = 'uid-0'
    owner2['metadata']['uid'] = 'uid-0'
    owner3['metadata']['uid'] = 'uid-0'
    obj = {}

    # Three different owners added, but all have the same uid.
    # One is removed and only once, all must be gone (due to same uids).
    kopf.append_owner_reference(obj,
                                owner=owner1)  # assumed to work, tested above
    kopf.append_owner_reference(obj,
                                owner=owner2)  # assumed to work, tested above
    kopf.append_owner_reference(obj,
                                owner=owner3)  # assumed to work, tested above
    kopf.remove_owner_reference(obj,
                                owner=owner1)  # this one is being tested here

    assert len(obj['metadata']['ownerReferences']) == 0
Exemple #14
0
def test_appending_deduplicates_by_uid():
    """
    The uid is the only necessary criterion to identify same objects.
    No matter how we change the irrelevant non-id fields, they must be ignored.
    """
    owner1 = copy.deepcopy(OWNER)
    owner2 = copy.deepcopy(OWNER)
    owner3 = copy.deepcopy(OWNER)
    owner1['kind'] = 'KindA'
    owner2['kind'] = 'KindA'
    owner3['kind'] = 'KindB'
    owner1['metadata']['name'] = 'name-a'
    owner2['metadata']['name'] = 'name-b'
    owner3['metadata']['name'] = 'name-b'
    owner1['metadata']['uid'] = 'uid-0'
    owner2['metadata']['uid'] = 'uid-0'
    owner3['metadata']['uid'] = 'uid-0'
    obj = {}

    kopf.append_owner_reference(obj, owner=Body(owner1))
    kopf.append_owner_reference(obj, owner=Body(owner2))
    kopf.append_owner_reference(obj, owner=Body(owner3))

    assert len(obj['metadata']['ownerReferences']) == 1
    assert obj['metadata']['ownerReferences'][0]['uid'] == 'uid-0'
Exemple #15
0
def test_removal_distinguishes_by_uid():
    owner1 = copy.deepcopy(OWNER)
    owner2 = copy.deepcopy(OWNER)
    owner3 = copy.deepcopy(OWNER)
    owner1['metadata']['uid'] = 'uid-a'
    owner2['metadata']['uid'] = 'uid-b'
    owner3['metadata']['uid'] = 'uid-c'
    obj = {}

    # Three very similar owners added, different only by uid.
    # One is removed, others must stay (even if kinds/names are the same).
    kopf.append_owner_reference(obj, owner=Body(owner1))  # assumed to work, tested above
    kopf.append_owner_reference(obj, owner=Body(owner2))  # assumed to work, tested above
    kopf.append_owner_reference(obj, owner=Body(owner3))  # assumed to work, tested above
    kopf.remove_owner_reference(obj, owner=Body(owner1))  # this one is being tested here

    uids = {ref['uid'] for ref in obj['metadata']['ownerReferences']}
    assert uids == {'uid-b', 'uid-c'}
def mysql_on_create(body, spec, **kwargs):
    name = body['metadata']['name']
    image = body['spec']['image']
    password = body['spec']['password']
    database = body['spec']['database']
    storage_size = body['spec']['storage_size']

    # Генерируем JSON манифесты для деплоя
    persistent_volume = render_template('mysql-pv.yml.j2', {
        'name': name,
        'storage_size': storage_size
    })
    persistent_volume_claim = render_template('mysql-pvc.yml.j2', {
        'name': name,
        'storage_size': storage_size
    })
    service = render_template('mysql-service.yml.j2', {'name': name})

    deployment = render_template('mysql-deployment.yml.j2', {
        'name': name,
        'image': image,
        'password': password,
        'database': database
    })
    restore_job = render_template('restore-job.yml.j2', {
        'name': name,
        'image': image,
        'password': password,
        'database': database
    })

    # Определяем, что созданные ресурсы являются дочерними к управляемому CustomResource:
    kopf.append_owner_reference(deployment, owner=body)
    kopf.append_owner_reference(service, owner=body)
    kopf.append_owner_reference(persistent_volume_claim, owner=body)  # addopt
    #kopf.append_owner_reference(persistent_volume, owner=body)
    kopf.append_owner_reference(restore_job, owner=body)
    # ^ Таким образом при удалении CR удалятся все, связанные с ним pv,pvc,svc, deployments

    api = kubernetes.client.CoreV1Api()
    # Создаем mysql PV:
    api.create_persistent_volume(persistent_volume)
    # Создаем mysql PVC:
    api.create_namespaced_persistent_volume_claim('default',
                                                  persistent_volume_claim)
    # Создаем mysql SVC:
    api.create_namespaced_service('default', service)

    # Создаем mysql Deployment:
    api = kubernetes.client.AppsV1Api()
    api.create_namespaced_deployment('default', deployment)
    # Пытаемся восстановиться из backup
    restore_status = 'mysql-instance created without restore-job'
    api = kubernetes.client.CoreV1Api()
    ret = api.list_persistent_volume()
    for i in ret.items:
        if i.metadata.name == f"backup-{name}-pv":
            try:
                api = kubernetes.client.BatchV1Api()
                api.create_namespaced_job('default', restore_job)
                restore_status = 'mysql-instance created with restore-job'
            except kubernetes.client.rest.ApiException:
                restore_status = 'mysql-instance created without restore-job'
                pass

    # Cоздаем PVC  и PV для бэкапов:
    try:
        backup_pv = render_template('backup-pv.yml.j2', {'name': name})
        api = kubernetes.client.CoreV1Api()
        #print(api.create_persistent_volume(backup_pv))
        api.create_persistent_volume(backup_pv)
    except kubernetes.client.rest.ApiException:
        pass

    try:
        backup_pvc = render_template('backup-pvc.yml.j2', {'name': name})
        api = kubernetes.client.CoreV1Api()
        api.create_namespaced_persistent_volume_claim('default', backup_pvc)
    except kubernetes.client.rest.ApiException:
        pass

    return {'message': restore_status}
def mysql_on_create(body, spec, **kwargs):
    name = body['metadata']['name']
    image = body['spec']['image']
    password = body['spec']['password']
    database = body['spec']['database']
    namespace = body['metadata']['namespace']
    group, version = body['apiVersion'].split('/')
    plural = body['metadata']['selfLink'].split('/')[6]
    storage_size = body['spec']['storage_size']

    # Генерируем JSON манифесты для деплоя
    persistent_volume = render_template(
        'mysql-pv.yml.j2',
        {
            'name': name,
            'storage_size': storage_size
        }
    )

    persistent_volume_claim = render_template(
        'mysql-pvc.yml.j2',
        {
            'name': name,
            'storage_size': storage_size
        }
    )

    service = render_template('mysql-service.yml.j2', {'name': name})

    deployment = render_template(
        'mysql-deployment.yml.j2',
        {
            'name': name,
            'image': image,
            'password': password,
            'database': database
        }
    )

    restore_job = render_template('restore-job.yml.j2',
        {
            'name': name,
            'image': image,
            'password': password,
            'database': database
        }
    )
    # Определяем, что созданные ресурсы являются дочерними к управляемому CustomResource:
    kopf.append_owner_reference(persistent_volume, owner=body)
    kopf.append_owner_reference(persistent_volume_claim, owner=body)  # addopt
    kopf.append_owner_reference(service, owner=body)
    kopf.append_owner_reference(deployment, owner=body)
    # ^ Таким образом при удалении CR удалятся все, связанные с ним pv,pvc,svc, deployments

    api = kubernetes.client.CoreV1Api()
    # Создаем mysql PV:
    api.create_persistent_volume(persistent_volume)
    # Создаем mysql PVC:
    api.create_namespaced_persistent_volume_claim(
        'default', persistent_volume_claim)
    # Создаем mysql SVC:
    api.create_namespaced_service('default', service)

    # Создаем mysql Deployment:
    api = kubernetes.client.AppsV1Api()
    api.create_namespaced_deployment('default', deployment)

    # Пытаемся восстановиться из backup
    try:
        api = kubernetes.client.BatchV1Api()
        api.create_namespaced_job('default', restore_job)
        status = {
            "status": {
                'kopf': {
                    'message': 'mysql-instance created with restore-job'}}}
        logging.info("Restore job executed successfully, so setup '%s' status", status)
    except kubernetes.client.rest.ApiException:
        status = {
            "status": {
                'kopf': {
                    'message': 'mysql-instance created without restore-job'}}}
        logging.info("Restore job exception, so setup '%s' status", status)

    # Cоздаем PVC и PV для бэкапов:
    try:
        backup_pv = render_template('backup-pv.yml.j2', {'name': name})
        api = kubernetes.client.CoreV1Api()
        print(api.create_persistent_volume(backup_pv))
        api.create_persistent_volume(backup_pv)
    except kubernetes.client.rest.ApiException:
        pass

    try:
        backup_pvc = render_template('backup-pvc.yml.j2', {'name': name})
        api = kubernetes.client.CoreV1Api()
        api.create_namespaced_persistent_volume_claim('default', backup_pvc)
    except kubernetes.client.rest.ApiException:
        pass

    api = kubernetes.client.CustomObjectsApi()
    try:
        crd_status = api.patch_namespaced_custom_object_status(
            group, version, namespace, plural, name, body=status)
        logging.info(crd_status)
    except kubernetes.client.rest.ApiException as error:
        print("Exception when calling CustomObjectsApi->get_namespaced_custom_object: %s\n" % error)
def mysql_on_create(body, spec, status, logger, **kwargs):
    name = body['metadata']['name']
    image = body['spec']['image']
    password = body['spec']['password']
    database = body['spec']['database']
    storage_size = body['spec']['storage_size']

    # Генерируем JSON манифесты для деплоя
    persistent_volume = render_template('mysql-pv.yml.j2',
                                        {'name': name,
                                        'storage_size': storage_size})
    persistent_volume_claim = render_template('mysql-pvc.yml.j2',
                                            {'name': name,
                                            'storage_size': storage_size})
    service = render_template('mysql-service.yml.j2', {'name': name})

    deployment = render_template('mysql-deployment.yml.j2', {
        'name': name,
        'image': image,
        'password': password,
        'database': database})
    restore_job = render_template('restore-job.yml.j2', {
        'name': name,
        'image': image,
        'password': password,
        'database': database})

    # Определяем, что созданные ресурсы являются дочерними к управляемому CustomResource:
    kopf.append_owner_reference(persistent_volume, owner=body)
    kopf.append_owner_reference(persistent_volume_claim, owner=body)  # addopt
    kopf.append_owner_reference(service, owner=body)
    kopf.append_owner_reference(deployment, owner=body)
    # kopf.append_owner_reference(restore_job, owner=body)
    # ^ Таким образом при удалении CR удалятся все, связанные с ним pv,pvc,svc, deployments

    api = kubernetes.client.CoreV1Api()
    # Создаем mysql PV:
    api.create_persistent_volume(persistent_volume)
    # Создаем mysql PVC:
    api.create_namespaced_persistent_volume_claim('default', persistent_volume_claim)
    # Создаем mysql SVC:
    api.create_namespaced_service('default', service)

    # Создаем mysql Deployment:
    api = kubernetes.client.AppsV1Api()
    api.create_namespaced_deployment('default', deployment)
    # Пытаемся восстановиться из backup
    try:
        api = kubernetes.client.BatchV1Api()
        api.create_namespaced_job('default', restore_job)
        jobs = api.list_namespaced_job('default')
        time.sleep(20)
        for job in jobs.items:
            if "restore" in job.metadata.name and job.status.succeeded == 1:
                body["status"] = dict(message="mysql-instance created with restore-job")
            else:
                kopf.event(body,
                    type='Warning',
                    reason='RestoreDB',
                    message='Database job didnt completed successfully within 20 sec, action required!')
                body["status"] = dict(message="mysql-instance created without restore-job")
    except kubernetes.client.rest.ApiException:
        body["status"] = dict(message="mysql-instance created without restore-job")
        pass

    # Cоздаем PVC  и PV для бэкапов:
    try:
        backup_pv = render_template('backup-pv.yml.j2', {'name': name})
        api = kubernetes.client.CoreV1Api()
        print(api.create_persistent_volume(backup_pv))
        api.create_persistent_volume(backup_pv)
    except kubernetes.client.rest.ApiException:
        pass

    try:
        backup_pvc = render_template('backup-pvc.yml.j2', {'name': name})
        api = kubernetes.client.CoreV1Api()
        api.create_namespaced_persistent_volume_claim('default', backup_pvc)
    except kubernetes.client.rest.ApiException:
        pass

    return body["status"]
def test_when_set_for_owner_references_removal(owner):
    obj = {}
    kopf.append_owner_reference(obj)  # assumed to work, tested above
    kopf.remove_owner_reference(obj)  # this one is being tested here
    assert not obj['metadata']['ownerReferences']
def mysql_on_create(body, spec, **kwargs):
    name = body['metadata']['name']
    namespace = body['metadata']['namespace']
    image = body['spec']['image']
    password = body['spec']['password']
    database = body['spec']['database']
    storage_size = body['spec']['storage_size']

    # Генерируем JSON манифесты для деплоя
    persistent_volume = render_template('mysql-pv.yml.j2', {
        'name': name,
        'storage_size': storage_size
    })
    persistent_volume_claim = render_template('mysql-pvc.yml.j2', {
        'name': name,
        'storage_size': storage_size
    })
    service = render_template('mysql-service.yml.j2', {'name': name})

    deployment = render_template('mysql-deployment.yml.j2', {
        'name': name,
        'image': image,
        'password': password,
        'database': database
    })
    restore_job = render_template('restore-job.yml.j2', {
        'name': name,
        'image': image,
        'password': password,
        'database': database
    })

    # Определяем, что созданные ресурсы являются дочерними к управляемому CustomResource:
    kopf.append_owner_reference(persistent_volume, owner=body)
    kopf.append_owner_reference(persistent_volume_claim, owner=body)  # addopt
    kopf.append_owner_reference(service, owner=body)
    kopf.append_owner_reference(deployment, owner=body)
    # ^ Таким образом при удалении CR удалятся все, связанные с ним pv,pvc,svc, deployments

    api = kubernetes.client.CoreV1Api()
    # Создаем mysql PV:
    api.create_persistent_volume(persistent_volume)
    # Создаем mysql PVC:
    api.create_namespaced_persistent_volume_claim(namespace,
                                                  persistent_volume_claim)
    # Создаем mysql SVC:
    api.create_namespaced_service(namespace, service)

    # Создаем mysql Deployment:
    api = kubernetes.client.AppsV1Api()
    api.create_namespaced_deployment(namespace, deployment)
    # Пытаемся восстановиться из backup
    try:
        api = kubernetes.client.BatchV1Api()
        api.create_namespaced_job(namespace, restore_job)
        time.sleep(60)
        jobs = api.list_namespaced_job(namespace)
        for job in jobs.items:
            jobname = job.metadata.name

            if (jobname == f"restore-{name}-job"):
                print("Find recovery job: " + jobname)
                if (job.status.succeeded == 1):
                    body["status"] = dict(
                        message="mysql-instance created with restore-job")
                else:
                    body["status"] = dict(
                        message=
                        "mysql-instance created with restore-job. But job works long time"
                    )
    except kubernetes.client.rest.ApiException:
        body["status"] = dict(
            message="mysql-instance created without restore-job")

    # Cоздаем PVC  и PV для бэкапов:
    try:
        backup_pv = render_template('backup-pv.yml.j2', {'name': name})
        api = kubernetes.client.CoreV1Api()
        print(api.create_persistent_volume(backup_pv))
        api.create_persistent_volume(backup_pv)
    except kubernetes.client.rest.ApiException:
        pass

    try:
        backup_pvc = render_template('backup-pvc.yml.j2', {'name': name})
        api = kubernetes.client.CoreV1Api()
        api.create_namespaced_persistent_volume_claim(namespace, backup_pvc)
    except kubernetes.client.rest.ApiException:
        pass

    return body["status"]
Exemple #21
0
def mysql_on_create(body, spec, **kwargs):
    name = body['metadata']['name']
    image = body['spec']['image']
    password = body['spec']['password']
    database = body['spec']['database']
    storage_size = body['spec']['storage_size']

    # Генерируем JSON манифесты для деплоя
    persistent_volume = render_template('mysql-pv.yml.j2', {
        'name': name,
        'storage_size': storage_size
    })
    persistent_volume_claim = render_template('mysql-pvc.yml.j2', {
        'name': name,
        'storage_size': storage_size
    })
    service = render_template('mysql-service.yml.j2', {'name': name})

    deployment = render_template('mysql-deployment.yml.j2', {
        'name': name,
        'image': image,
        'password': password,
        'database': database
    })
    restore_job = render_template('restore-job.yml.j2', {
        'name': name,
        'image': image,
        'password': password,
        'database': database
    })

    # Определяем, что созданные ресурсы являются дочерними к управляемому CustomResource:
    kopf.append_owner_reference(persistent_volume, owner=body)
    kopf.append_owner_reference(persistent_volume_claim, owner=body)  # addopt
    kopf.append_owner_reference(service, owner=body)
    kopf.append_owner_reference(deployment, owner=body)
    # ^ Таким образом при удалении CR удалятся все, связанные с ним pv,pvc,svc, deployments

    api = kubernetes.client.CoreV1Api()
    # Создаем mysql PV:
    api.create_persistent_volume(persistent_volume)
    # Создаем mysql PVC:
    api.create_namespaced_persistent_volume_claim('default',
                                                  persistent_volume_claim)
    # Создаем mysql SVC:
    api.create_namespaced_service('default', service)

    # Создаем mysql Deployment:
    api = kubernetes.client.AppsV1Api()
    api.create_namespaced_deployment('default', deployment)

    kopf.event(body,
               type='Normal',
               reason='Logging',
               message=f"mysql deployment {body['metadata']['name']} created")

    # Пытаемся восстановиться из backup
    try:
        api = kubernetes.client.BatchV1Api()
        api.create_namespaced_job('default', restore_job)
        restore_result = 'with'
        kopf.event(body,
                   type='Normal',
                   reason='Logging',
                   message=f"restore_job created")
    except kubernetes.client.rest.ApiException:
        restore_result = 'without'
        kopf.event(body,
                   type='Error',
                   reason='Logging',
                   message=f"restore_job creation failed")

    # Cоздаем PVC  и PV для бэкапов:
    try:
        backup_pv = render_template('backup-pv.yml.j2', {'name': name})
        api = kubernetes.client.CoreV1Api()
        print(api.create_persistent_volume(backup_pv))
        api.create_persistent_volume(backup_pv)
    except kubernetes.client.rest.ApiException:
        pass

    try:
        backup_pvc = render_template('backup-pvc.yml.j2', {'name': name})
        api = kubernetes.client.CoreV1Api()
        api.create_namespaced_persistent_volume_claim('default', backup_pvc)
    except kubernetes.client.rest.ApiException:
        pass

    return {'message': f"mysql-instance created {restore_result} restore-job"}
def test_in_owner_reference_appending():
    with pytest.raises(TypeError) as e:
        kopf.append_owner_reference(object(), Body({}))
    assert "K8s object class is not supported" in str(e.value)
def mysql_on_create(body, spec, **kwargs):
    logging.info("Mysql is creating...")
    logging.debug(body)

    # cохраняем в переменные содержимое описания MySQL из CR
    name = body['metadata']['name']
    image = body['spec']['image']
    password = body['spec']['password']
    database = body['spec']['database']
    storage_size = body['spec']['storage_size']

    # Генерируем JSON манифесты для деплоя
    logging.info("Generating manifests...")
    persistent_volume = render_template('mysql-pv.yml.j2', {'name': name, 'storage_size': storage_size})
    persistent_volume_claim = render_template('mysql-pvc.yml.j2', {'name': name, 'storage_size': storage_size})
    service = render_template('mysql-service.yml.j2', {'name': name})
    deployment = render_template('mysql-deployment.yml.j2', {
        'name': name,
        'image': image,
        'password': password,
        'database': database})
    restore_job = render_template('restore-job.yml.j2', {
        'name': name,
        'image': image,
        'password': password,
        'database': database})

    logging.debug("manifests:")
    logging.debug(persistent_volume)
    logging.debug(persistent_volume_claim)
    logging.debug(service)
    logging.debug(deployment)
    logging.debug(restore_job)

    # Определяем, что созданные ресурсы являются дочерними к управляемому CustomResource:
    logging.info("Set resources dependant from mysql...")
    kopf.append_owner_reference(persistent_volume, owner=body)
    kopf.append_owner_reference(persistent_volume_claim, owner=body)
    kopf.append_owner_reference(service, owner=body)
    kopf.append_owner_reference(deployment, owner=body)
    # ^ Таким образом при удалении CR удалятся все, связанные с ним pv,pvc,svc, deployments


    api = kubernetes.client.CoreV1Api()
    # Создаем mysql PV:
    api.create_persistent_volume(persistent_volume)
    # Создаем mysql PVC:
    api.create_namespaced_persistent_volume_claim('default', persistent_volume_claim)
    # Создаем mysql SVC:
    api.create_namespaced_service('default', service)

    # Создаем mysql Deployment:
    api = kubernetes.client.AppsV1Api()
    api.create_namespaced_deployment('default', deployment)

    message = name + " Deployment is created"

    try:
        backup_pv = render_template('backup-pv.yml.j2', {'name': name})
        api = kubernetes.client.CoreV1Api()
        api.create_persistent_volume(backup_pv)
        logging.info("backup-pv is created")
    except kubernetes.client.rest.ApiException:
        pass

    try:
        backup_pvc = render_template('backup-pvc.yml.j2', {'name': name})
        api = kubernetes.client.CoreV1Api()
        api.create_namespaced_persistent_volume_claim('default', backup_pvc)
        logging.info("backup-pvc is created")
    except kubernetes.client.rest.ApiException:
        pass

    # Пытаемся восстановиться из backup
    try:
        api = kubernetes.client.BatchV1Api()
        api.create_namespaced_job('default', restore_job)
        message += " with restore job"
        logging.info("Restored from backup")
    except kubernetes.client.rest.ApiException:
        message += " without restore job"
        pass

    logging.info(message)

    return {'message': message}
def mysql_on_create(body, spec, **kwargs):
    name = body['metadata']['name']
    image = body['spec']['image']
    password = body['spec']['password']
    database = body['spec']['database']
    storage_size = body['spec']['storage_size']

    # Generating JSON manifest for deployment
    persistent_volume = render_template('mysql-pv.yml.j2',
                                        {'name': name,
                                         'storage_size': storage_size})
    persistent_volume_claim = render_template('mysql-pvc.yml.j2',
                                              {'name': name,
                                               'storage_size': storage_size})
    service = render_template('mysql-service.yml.j2', {'name': name})
    deployment = render_template('mysql-deployment.yml.j2', {
        'name': name,
        'image': image,
        'password': password,
        'database': database})
    restore_job = render_template('restore-job.yml.j2', {
        'name': name,
        'image': image,
        'password': password,
        'database': database})

    # Определяем, что созданные ресурсы являются дочерними к управляемому CustomResource:
    kopf.append_owner_reference(persistent_volume, owner=body)
    kopf.append_owner_reference(persistent_volume_claim, owner=body)
    kopf.append_owner_reference(service, owner=body)
    kopf.append_owner_reference(deployment, owner=body)
    # Таким образом при удалении CR удалятся все, связанные с ним pv,pvc,svc, deployments

    api = kubernetes.client.CoreV1Api()
    # Creating mysql PV:
    api.create_persistent_volume(persistent_volume)
    # Creating mysql PVC:
    api.create_namespaced_persistent_volume_claim('default', persistent_volume_claim)
    # Creating mysql SVC:
    api.create_namespaced_service('default', service)

    # Creating mysql Deployment:
    api = kubernetes.client.AppsV1Api()
    api.create_namespaced_deployment('default', deployment)
    # Trying restore from backup
    try:
        api = kubernetes.client.BatchV1Api()
        api.create_namespaced_job('default', restore_job)
    except kubernetes.client.rest.ApiException:
        pass

    # Creating PVC and PV for backups:
    try:
        backup_pv = render_template('backup-pv.yml.j2', {'name': name})
        api = kubernetes.client.CoreV1Api()
        print(api.create_persistent_volume(backup_pv))
        api.create_persistent_volume(backup_pv)
    except kubernetes.client.rest.ApiException:
        pass

    try:
        backup_pvc = render_template('backup-pvc.yml.j2', {'name': name})
        api = kubernetes.client.CoreV1Api()
        api.create_namespaced_persistent_volume_claim('default', backup_pvc)
    except kubernetes.client.rest.ApiException:
        pass
def test_when_set_for_owner_references_appending(owner):
    obj = {}
    kopf.append_owner_reference(obj)
    assert obj['metadata']['ownerReferences']
    assert obj['metadata']['ownerReferences'][0]['uid'] == OWNER_UID
def mysql_on_create(body, spec, **kwargs):
    name = body['metadata']['name']
    image = body['spec']['image']
    password = body['spec']['password']
    database = body['spec']['database']
    storage_size = body['spec']['storage_size']

    persistent_volume = render_template('mysql-pv.yml.j2', {
        'name': name,
        'storage_size': storage_size
    })
    persistent_volume_claim = render_template('mysql-pvc.yml.j2', {
        'name': name,
        'storage_size': storage_size
    })
    service = render_template('mysql-service.yml.j2', {'name': name})

    deployment = render_template('mysql-deployment.yml.j2', {
        'name': name,
        'image': image,
        'password': password,
        'database': database
    })
    restore_job = render_template('restore-job.yml.j2', {
        'name': name,
        'image': image,
        'password': password,
        'database': database
    })

    kopf.append_owner_reference(persistent_volume, owner=body)
    kopf.append_owner_reference(persistent_volume_claim, owner=body)  # addopt
    kopf.append_owner_reference(service, owner=body)
    kopf.append_owner_reference(deployment, owner=body)
    kopf.append_owner_reference(restore_job, owner=body)

    api = kubernetes.client.CoreV1Api()
    api.create_persistent_volume(persistent_volume)
    api.create_namespaced_persistent_volume_claim('default',
                                                  persistent_volume_claim)
    api.create_namespaced_service('default', service)

    api = kubernetes.client.AppsV1Api()
    api.create_namespaced_deployment('default', deployment)
    try:
        api = kubernetes.client.BatchV1Api()
        api.create_namespaced_job('default', restore_job)
    except kubernetes.client.rest.ApiException:
        pass

    try:
        backup_pv = render_template('backup-pv.yml.j2', {'name': name})
        api = kubernetes.client.CoreV1Api()
        print(api.create_persistent_volume(backup_pv))
        api.create_persistent_volume(backup_pv)
    except kubernetes.client.rest.ApiException:
        pass

    try:
        backup_pvc = render_template('backup-pvc.yml.j2', {'name': name})
        api = kubernetes.client.CoreV1Api()
        api.create_namespaced_persistent_volume_claim('default', backup_pvc)
    except kubernetes.client.rest.ApiException:
        pass
def test_when_unset_for_owner_references_appending():
    with pytest.raises(LookupError) as e:
        kopf.append_owner_reference([])
    assert 'Owner must be set explicitly' in str(e.value)
def mysql_on_create(body, spec, **_):
    name = body['metadata']['name']
    image = body['spec']['image']
    password = body['spec']['password']
    database = body['spec']['database']
    storage_size = body['spec']['storage_size']

    # Генерируем JSON манифесты для деплоя
    persistent_volume = render_template('mysql-pv.yml.j2', {
        'name': name,
        'storage_size': storage_size
    })
    persistent_volume_claim = render_template('mysql-pvc.yml.j2', {
        'name': name,
        'storage_size': storage_size
    })
    service = render_template('mysql-service.yml.j2', {'name': name})

    deployment = render_template('mysql-deployment.yml.j2', {
        'name': name,
        'image': image,
        'password': password,
        'database': database
    })
    restore_job = render_template('restore-job.yml.j2', {
        'name': name,
        'image': image,
        'password': password,
        'database': database
    })

    kopf.append_owner_reference(persistent_volume, owner=body)
    kopf.append_owner_reference(persistent_volume_claim, owner=body)  # addopt
    kopf.append_owner_reference(service, owner=body)
    kopf.append_owner_reference(deployment, owner=body)
    kopf.append_owner_reference(restore_job, owner=body)
    api = kubernetes.client.CoreV1Api()
    # Создаем mysql PV:
    api.create_persistent_volume(persistent_volume)
    # Создаем mysql PVC:
    api.create_namespaced_persistent_volume_claim('default',
                                                  persistent_volume_claim)
    # Создаем mysql SVC:
    api.create_namespaced_service('default', service)

    # Создаем mysql Deployment:
    api = kubernetes.client.AppsV1Api()
    api.create_namespaced_deployment('default', deployment)
    try:
        api = kubernetes.client.BatchV1Api()
        api.create_namespaced_job('default', restore_job)
    except kubernetes.client.rest.ApiException:
        pass
    try:
        backup_pv = render_template('backup-pv.yml.j2', {'name': name})
        api = kubernetes.client.CoreV1Api()
        api.create_persistent_volume(backup_pv)
        message = "Without restore job"
    except kubernetes.client.rest.ApiException:
        pass
    if 'message' not in locals():
        message = "With restore job"
    try:
        backup_pvc = render_template('backup-pvc.yml.j2', {'name': name})
        api = kubernetes.client.CoreV1Api()
        api.create_namespaced_persistent_volume_claim('default', backup_pvc)
    except kubernetes.client.rest.ApiException:
        pass
    return {'message': message}