Exemple #1
0
def deploy_webhook_dispatcher_landscape(
    cfg_set,
    webhook_dispatcher_deployment_cfg: WebhookDispatcherDeploymentConfig,
    chart_dir: str,
    deployment_name: str,
):
    not_empty(deployment_name)

    chart_dir = os.path.abspath(chart_dir)
    cfg_factory = global_ctx().cfg_factory()

    # Set the global context to the cluster specified in KubernetesConfig
    kubernetes_config_name = webhook_dispatcher_deployment_cfg.kubernetes_config_name(
    )
    kubernetes_config = cfg_factory.kubernetes(kubernetes_config_name)
    kube_ctx.set_kubecfg(kubernetes_config.kubeconfig())

    kubernetes_cfg_name = webhook_dispatcher_deployment_cfg.kubernetes_config_name(
    )
    kubernetes_cfg = cfg_factory.kubernetes(kubernetes_cfg_name)

    whd_helm_values = create_webhook_dispatcher_helm_values(
        cfg_set=cfg_set,
        webhook_dispatcher_deployment_cfg=webhook_dispatcher_deployment_cfg,
        config_factory=cfg_factory,
    )

    execute_helm_deployment(kubernetes_cfg, deployment_name, chart_dir,
                            deployment_name, whd_helm_values)
Exemple #2
0
def deploy_oauth2_proxy(
    kubernetes_config: KubernetesConfig,
    oauth2_proxy_config: Oauth2ProxyConfig,
    deployment_name: str,
):
    not_empty(deployment_name)

    cfg_factory = global_ctx().cfg_factory()

    kube_ctx.set_kubecfg(kubernetes_config.kubeconfig())
    ensure_cluster_version(kubernetes_config)

    ingress_config = cfg_factory.ingress(oauth2_proxy_config.ingress_config())
    helm_values = create_oauth2_proxy_helm_values(
        oauth2_proxy_config=oauth2_proxy_config,
        ingress_config=ingress_config,
        deployment_name=deployment_name,
    )

    execute_helm_deployment(
        kubernetes_config,
        oauth2_proxy_config.namespace(),
        'stable/oauth2-proxy',
        deployment_name,
        helm_values,
    )
Exemple #3
0
    def _cfg_element_names(self, cfg_type_name: str):
        '''Returns cfg-elements of the given cfg_type

        Parameters
        ----------
        cfg_type_name: str
            The cfg type name

        Returns
        -------
        Iterable[str]
            Contains the names of all cfg-elements of the given cfg_type known to this ConfigFactory.

        Raises
        ------
        ValueError
            If the specified cfg_type is unknown.
        '''
        not_empty(cfg_type_name)
        self._retrieve_cfg_elements(cfg_type_name=cfg_type_name)

        self._ensure_type_is_known(cfg_type_name=cfg_type_name)
        if cfg_type_name in self.raw:
            return set(self.raw[cfg_type_name].keys())
        else:
            return set()
Exemple #4
0
    def _cfg_elements(self, cfg_type_name: str):
        '''Returns all cfg_elements for the given cfg_type.

        Parameters
        ----------
        cfg_type_name: str
            The name of the cfg_type whose instances should be retrieved.

        Yields
        -------
        NamedModelElement
            Instance of the given cfg_type.

        Raises
        ------
        ValueError
            If the specified cfg_type is unknown.
        '''
        not_empty(cfg_type_name)

        self._retrieve_cfg_elements(cfg_type_name=cfg_type_name)

        self._ensure_type_is_known(cfg_type_name=cfg_type_name)

        for element_name in self._cfg_element_names(cfg_type_name):
            yield self._cfg_element(cfg_type_name, element_name)
def deploy_tekton_dashboard_ingress(
    kubernetes_config: KubernetesConfig,
    tekton_dashboard_ingress_config: TektonDashboardIngressConfig,
    chart_dir: str,
    deployment_name: str,
):
    not_empty(deployment_name)

    cfg_factory = global_ctx().cfg_factory()
    chart_dir = os.path.abspath(chart_dir)

    kube_ctx.set_kubecfg(kubernetes_config.kubeconfig())
    ensure_cluster_version(kubernetes_config)

    ingress_config = cfg_factory.ingress(
        tekton_dashboard_ingress_config.ingress_config())
    helm_values = create_tekton_dashboard_helm_values(
        tekton_dashboard_ingress_config=tekton_dashboard_ingress_config,
        ingress_config=ingress_config,
    )

    execute_helm_deployment(
        kubernetes_config,
        tekton_dashboard_ingress_config.namespace(),
        chart_dir,
        deployment_name,
        helm_values,
    )
Exemple #6
0
def deploy_oauth2_proxy(
    oauth2_proxy_config: Oauth2ProxyConfig,
    chart_dir: str,
    deployment_name: str,
):
    not_empty(deployment_name)

    cfg_factory = global_ctx().cfg_factory()

    kubernetes_config = cfg_factory.kubernetes(
        oauth2_proxy_config.kubernetes_config_name())
    kube_ctx.set_kubecfg(kubernetes_config.kubeconfig())

    ingress_config = cfg_factory.ingress(oauth2_proxy_config.ingress_config())
    helm_values = create_oauth2_proxy_helm_values(
        oauth2_proxy_config=oauth2_proxy_config,
        ingress_config=ingress_config,
        deployment_name=deployment_name,
        config_factory=cfg_factory,
    )

    execute_helm_deployment(
        kubernetes_config,
        oauth2_proxy_config.namespace(),
        chart_dir,
        deployment_name,
        helm_values,
    )
Exemple #7
0
def deploy_gardenlinux_cache(
    kubernetes_config: KubernetesConfig,
    gardenlinux_cache_config: GardenlinuxCacheConfig,
    chart_dir: str,
    deployment_name: str,
):
    not_empty(deployment_name)

    cfg_factory = global_ctx().cfg_factory()
    chart_dir = os.path.abspath(chart_dir)

    kube_ctx.set_kubecfg(kubernetes_config.kubeconfig())
    ensure_cluster_version(kubernetes_config)

    ingress_config = cfg_factory.ingress(
        gardenlinux_cache_config.ingress_config())
    helm_values = create_gardenlinux_cache_helm_values(
        gardenlinux_cache_config=gardenlinux_cache_config,
        ingress_config=ingress_config,
    )

    execute_helm_deployment(
        kubernetes_config,
        gardenlinux_cache_config.namespace(),
        chart_dir,
        deployment_name,
        helm_values,
    )
Exemple #8
0
def create_tls_secret(tls_config: TlsConfig,
                      tls_secret_name: str,
                      namespace: str,
                      basic_auth_cred: BasicAuthCred = None):
    """ Creates a secret with the configured TLS certificates in the K8s cluster.
        Optionally adds credentials for Basic Authentication"""
    not_none(tls_config)
    not_empty(tls_secret_name)
    not_empty(namespace)

    ctx = kube_ctx
    namespace_helper = ctx.namespace_helper()
    namespace_helper.create_if_absent(namespace)

    secret_helper = ctx.secret_helper()
    if not secret_helper.get_secret(tls_secret_name, namespace):
        data = {
            'tls.key': tls_config.private_key(),
            'tls.crt': tls_config.certificate(),
        }
        if basic_auth_cred:
            ht = HtpasswdFile()
            ht.set_password(basic_auth_cred.user, basic_auth_cred.password)
            data['auth'] = ht.to_string().decode('utf-8')
        secret_helper.put_secret(
            name=tls_secret_name,
            data=data,
            namespace=namespace,
        )
Exemple #9
0
def create_image_pull_secret(
    credentials: GcrCredentials,
    image_pull_secret_name: str,
    namespace: str,
):
    """Create an image pull secret in the K8s cluster to allow pods to download images from gcr"""
    not_none(credentials)
    not_empty(image_pull_secret_name)
    not_empty(namespace)

    ctx = kube_ctx
    namespace_helper = ctx.namespace_helper()
    namespace_helper.create_if_absent(namespace)

    secret_helper = ctx.secret_helper()
    if not secret_helper.get_secret(image_pull_secret_name, namespace):
        secret_helper.create_gcr_secret(
            namespace=namespace,
            name=image_pull_secret_name,
            password=credentials.passwd(),
            user_name=credentials.username(),
            email=credentials.email(),
            server_url=credentials.host(),
        )

        service_account_helper = ctx.service_account_helper()
        service_account_helper.patch_image_pull_secret_into_service_account(
            name="default",
            namespace=namespace,
            image_pull_secret_name=image_pull_secret_name)
Exemple #10
0
    def __init__(
        self,
        git_helper: GitHelper,
        repo_dir: str,
        release_version: str,
        repository_version_file_path: str,
        repository_branch: str,
        commit_message_prefix: str,
        publishing_policy: ReleaseCommitPublishingPolicy,
        release_commit_callback: str = None,
    ):
        self.git_helper = not_none(git_helper)
        self.repository_branch = not_empty(repository_branch)
        repo_dir_absolute = os.path.abspath(not_empty(repo_dir))
        self.repo_dir = repo_dir_absolute
        self.release_version = not_empty(release_version)
        self.repository_version_file_path = os.path.join(
            repo_dir_absolute,
            repository_version_file_path,
        )
        self.commit_message_prefix = commit_message_prefix
        self.publishing_policy = publishing_policy

        if release_commit_callback:
            self.release_commit_callback = os.path.join(
                repo_dir_absolute,
                release_commit_callback,
            )
        else:
            self.release_commit_callback = None

        self.head_commit = None  # stored while applying - used for revert
Exemple #11
0
def create_basic_auth_secret(
    secret_name: str,
    namespace: str,
    basic_auth_cred: BasicAuthCred = None,
):
    """ Creates a secret with the configured TLS certificates in the K8s cluster.
        Optionally adds credentials for Basic Authentication"""
    not_empty(secret_name)
    not_empty(namespace)

    ctx = kube_ctx
    namespace_helper = ctx.namespace_helper()
    namespace_helper.create_if_absent(namespace)

    secret_helper = ctx.secret_helper()
    if not secret_helper.get_secret(secret_name, namespace):
        ht = HtpasswdFile()
        ht.set_password(basic_auth_cred.user, basic_auth_cred.password)
        data = {
            'auth': ht.to_string().decode('utf-8'),
        }
        secret_helper.put_secret(
            name=secret_name,
            data=data,
            namespace=namespace,
        )
Exemple #12
0
    def _cfg_element_names(self, cfg_type_name: str):
        '''Returns cfg-elements of the given cfg_type

        Parameters
        ----------
        cfg_type_name: str
            The cfg type name

        Returns
        -------
        Iterable[str]
            Contains the names of all cfg-elements of the given cfg_type known to this ConfigFactory.

        Raises
        ------
        ValueError
            If the specified cfg_type is unknown.
        '''
        not_empty(cfg_type_name)

        known_types = self._cfg_types()
        if cfg_type_name not in known_types:
            raise ValueError("Unknown config type '{c}'. Known types: {k}".format(
                c=cfg_type_name,
                k=', '.join(known_types.keys()),
            ))
        if cfg_type_name in self.raw:
            return set(self.raw[cfg_type_name].keys())
        else:
            return set()
Exemple #13
0
    def __init__(
        self,
        git_helper: GitHelper,
        repo_dir: str,
        release_version: str,
        repository_version_file_path: str,
        repository_branch: str,
        release_commit_message_prefix: str,
        publishing_policy: ReleaseCommitPublishingPolicy,
        release_commit_callback_image_reference: str,
        release_commit_callback: str = None,
    ):
        self.git_helper = not_none(git_helper)
        self.repository_branch = not_empty(repository_branch)
        self.repo_dir = os.path.abspath(repo_dir)
        self.release_version = not_empty(release_version)
        self.repository_version_file_path = os.path.join(
            self.repo_dir,
            repository_version_file_path,
        )
        self.release_commit_message_prefix = release_commit_message_prefix
        self.publishing_policy = publishing_policy
        self.release_commit_callback_image_reference = release_commit_callback_image_reference

        self.release_commit_callback = release_commit_callback

        self.head_commit = None  # stored while applying - used for revert
Exemple #14
0
    def __init__(
        self,
        git_helper: GitHelper,
        repo_dir: str,
        release_version: str,
        repository_version_file_path: str,
        repository_branch: str,
        version_operation: str,
        prerelease_suffix: str,
        publishing_policy: ReleaseCommitPublishingPolicy,
        next_cycle_commit_message_prefix: str = None,
        next_version_callback: str = None,
    ):
        self.git_helper = not_none(git_helper)
        self.repository_branch = not_empty(repository_branch)
        self.repo_dir = os.path.abspath(repo_dir)
        self.release_version = not_empty(release_version)
        self.version_operation = not_empty(version_operation)
        self.prerelease_suffix = not_empty(prerelease_suffix)
        self.publishing_policy = publishing_policy
        self.next_cycle_commit_message_prefix = next_cycle_commit_message_prefix

        self.repository_version_file_path = os.path.join(
            self.repo_dir,
            repository_version_file_path,
        )

        self.next_version_callback = next_version_callback
Exemple #15
0
    def create_if_absent(self, namespace: str):
        '''Create a new namespace iff it does not already exist'''
        not_empty(namespace)

        existing_namespace = self.get_namespace(namespace)
        if not existing_namespace:
            self.create_namespace(namespace)
Exemple #16
0
    def wait_until_deployment_available(self,
                                        namespace: str,
                                        name: str,
                                        timeout_seconds: int = 60):
        '''Block until the given deployment has at least one available replica (or timeout)
        Return `True` if the deployment is available, `False` if a timeout occured.
        '''
        not_empty(namespace)
        not_empty(name)

        w = watch.Watch()
        # Work around IncompleteRead errors resulting in ProtocolErrors - no fault of our own
        start_time = int(time.time())
        while (start_time + timeout_seconds) > time.time():
            try:
                for event in w.stream(self.apps_api.list_namespaced_deployment,
                                      namespace=namespace,
                                      timeout_seconds=timeout_seconds):
                    deployment_spec = event['object']
                    if deployment_spec is not None:
                        if deployment_spec.metadata.name == name:
                            if deployment_spec.status.available_replicas is not None \
                                    and deployment_spec.status.available_replicas > 0:
                                return True
                    # Check explicitly if timeout occurred
                    if (start_time + timeout_seconds) < time.time():
                        return False
                # Regular Watch.stream() timeout occurred, no need for further checks
                return False
            except ProtocolError:
                info('http connection error - ignored')
Exemple #17
0
    def create_ingress(self, namespace: str, ingress: V1beta1Ingress):
        '''Create an ingress in a given namespace. Raises an `ApiException` if such an ingress
        already exists.'''
        not_empty(namespace)
        not_none(ingress)

        self.extensions_v1beta1_api.create_namespaced_ingress(namespace=namespace, body=ingress)
Exemple #18
0
    def create_deployment(self, namespace: str, deployment: V1Deployment):
        '''Create a deployment in a given namespace. Raises an `ApiException` if such a deployment
        already exists.'''
        not_empty(namespace)
        not_none(deployment)

        self.apps_api.create_namespaced_deployment(namespace=namespace, body=deployment)
Exemple #19
0
    def __init__(
        self,
        git_helper: GitHelper,
        repo_dir: str,
        release_version: str,
        repository_version_file_path: str,
        repository_branch: str,
        version_operation: str,
        prerelease_suffix: str,
        publishing_policy: ReleaseCommitPublishingPolicy,
        next_version_callback: str = None,
    ):
        self.git_helper = not_none(git_helper)
        self.repository_branch = not_empty(repository_branch)
        repo_dir_absolute = os.path.abspath(not_empty(repo_dir))
        self.repo_dir = repo_dir_absolute
        self.release_version = not_empty(release_version)
        self.version_operation = not_empty(version_operation)
        self.prerelease_suffix = not_empty(prerelease_suffix)
        self.publishing_policy = publishing_policy

        self.repository_version_file_path = os.path.join(
            repo_dir_absolute,
            repository_version_file_path,
        )

        if next_version_callback:
            self.next_version_callback = os.path.join(
                repo_dir_absolute,
                next_version_callback,
            )
        else:
            self.next_version_callback = None
Exemple #20
0
    def create_service(self, namespace: str, service: V1Service):
        '''Create a service in a given namespace. Raises an `ApiException` if such a Service
        already exists.
        '''
        not_empty(namespace)
        not_none(service)

        self.core_api.create_namespaced_service(namespace=namespace, body=service)
Exemple #21
0
    def create_or_update_config_map(self, namespace: str, name: str, data: dict):
        not_empty(namespace)
        not_empty(name)
        not_none(data)

        if self.read_config_map(namespace=namespace, name=name):
            self.replace_config_map(namespace=namespace, name=name, data=data)
        else:
            self.create_config_map(namespace=namespace, name=name, data=data)
Exemple #22
0
def _send_mail(
    email_cfg: EmailConfig,
    recipients: typing.Iterable[str],
    mail_template: str,
    subject: str,
    replace_tokens: dict={},
    cc_recipients: typing.Iterable[str]=[],
    mimetype='text',
):
    not_none(email_cfg)
    not_empty(recipients)
    not_none(mail_template)
    not_empty(subject)

    # create body from template
    mail_body = mailer.create_body(
        mail_template=mail_template,
        replace_tokens=replace_tokens,
    )

    recipients = {r.lower() for r in recipients}
    cc_recipients = {r.lower() for r in cc_recipients}

    sender_name = email_cfg.sender_name() # used for the header
    sender = sender_name # passed as from-address to the mailserver

    if email_cfg.use_tls():
        smtp_server = smtplib.SMTP_SSL(email_cfg.smtp_host())
    else:
        smtp_server = smtplib.SMTP(email_cfg.smtp_host())

    if email_cfg.has_credentials():
        credentials = email_cfg.credentials()
        sender = credentials.username()
        sender_name = email_cfg.sender_name() or sender
        smtp_server.login(user=credentials.username(), password=credentials.passwd())

    # create mail envelope
    mail = mailer.create_mail(
        subject=subject,
        sender=sender_name,
        recipients=recipients,
        cc_recipients=cc_recipients,
        text=mail_body,
        mimetype=mimetype,
    )

    recipients.update(cc_recipients)

    mailer.send_mail(
        smtp_server=smtp_server,
        msg=mail,
        sender=sender,
        recipients=recipients
    )
Exemple #23
0
 def __init__(
     self,
     githubrepobranch: GitHubRepoBranch,
     github_helper: GitHubRepositoryHelper,
     release_version: str,
     repo_dir: str,
 ):
     self.githubrepobranch = not_none(githubrepobranch)
     self.github_helper = not_none(github_helper)
     self.release_version = not_empty(release_version)
     self.repo_dir = os.path.abspath(not_empty(repo_dir))
Exemple #24
0
    def create_config_map(self, namespace: str, name: str, data: dict):
        not_empty(namespace)
        not_empty(name)
        not_none(data)

        self.core_api.create_namespaced_config_map(
            namespace=namespace,
            body=V1ConfigMap(
                data=data,
                metadata=V1ObjectMeta(name=name, namespace=namespace),
            ),
        )
Exemple #25
0
 def read_config_map(self, namespace: str, name: str):
     '''Return the `V1ConfigMap` with the given name in the given namespace, or `None` if
     no such config map exists.'''
     not_empty(namespace)
     not_empty(name)
     try:
         config_map = self.core_api.read_namespaced_config_map(namespace=namespace, name=name)
     except ApiException as ae:
         if ae.status == 404:
             return None
         raise ae
     return config_map
Exemple #26
0
    def _cfg_elements(self, cfg_type_name: str):
        '''Returns all container cfg elements of the given cfg_type

        Raises
        ------
        ValueError
            If the specified cfg_type is unknown.
        '''
        not_empty(cfg_type_name)

        for element_name in self._cfg_element_names(cfg_type_name):
            yield self._cfg_element(cfg_type_name, element_name)
Exemple #27
0
def _send_mail(
    email_cfg: EmailConfig,
    recipients: typing.Iterable[str],
    mail_template: str,
    subject: str,
    attachments: typing.Sequence[mail.model.Attachment] = (),
    replace_tokens: dict = {},
    cc_recipients: typing.Iterable[str] = [],
    mimetype='text',
):
    not_none(email_cfg)
    not_empty(recipients)
    not_none(mail_template)
    not_empty(subject)

    # create body from template
    mail_body = mailer.create_body(
        mail_template=mail_template,
        replace_tokens=replace_tokens,
    )

    recipients = {r.lower() for r in recipients}
    cc_recipients = {r.lower() for r in cc_recipients}

    sender_name = email_cfg.sender_name()

    if email_cfg.use_tls():
        smtp_server = smtplib.SMTP_SSL(email_cfg.smtp_host())
    else:
        smtp_server = smtplib.SMTP(email_cfg.smtp_host())

    if email_cfg.has_credentials():
        credentials = email_cfg.credentials()
        smtp_server.login(user=credentials.username(),
                          password=credentials.passwd())

    # create mail envelope
    mail = mailer.create_mail(
        subject=subject,
        sender=sender_name,
        recipients=recipients,
        cc_recipients=cc_recipients,
        text=mail_body,
        mimetype=mimetype,
        attachments=attachments,
    )

    recipients.update(cc_recipients)
    recipients = email_cfg.filter_recipients(recipients)

    smtp_server.send_message(
        msg=mail, to_addrs=recipients)  # from_addr is taken from header
Exemple #28
0
    def test_not_empty(self):
        result = examinee.not_empty('foo')

        self.assertEqual('foo', result)

        forbidden = ['', None, [], ()]

        for value in forbidden:
            with capture_out() as (stdout, stderr):
                with self.assertRaises(Failure):
                    examinee.not_empty(value)
            self.assertIn('must not be empty', stderr.getvalue().strip())
            self.assertTrue(len(stdout.getvalue()) == 0)
Exemple #29
0
 def __init__(
     self,
     slack_cfg_name: str,
     slack_channel: str,
     release_version: str,
     release_notes: ReleaseNotes,
     githubrepobranch: GitHubRepoBranch,
 ):
     self.slack_cfg_name = not_empty(slack_cfg_name)
     self.slack_channel = not_empty(slack_channel)
     self.release_version = not_empty(release_version)
     self.githubrepobranch = not_none(githubrepobranch)
     self.release_notes = not_none(release_notes)
Exemple #30
0
 def validate(self):
     version.parse_to_semver(self.release_version)
     # if a tag with the given release version exists, we cannot create another release
     # pointing to it
     if self.github_helper.tag_exists(tag_name=self.release_version):
         raise RuntimeError(
             f"Cannot create tag '{self.release_version}' for release: Tag already exists"
         )
     if self.component_descriptor_file_path:
         existing_file(self.component_descriptor_file_path)
         with open(self.component_descriptor_file_path) as f:
             # TODO: Proper validation
             not_empty(f.read().strip())