All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.fabric8.hubot.notifier.KubernetesHubotNotifier Maven / Gradle / Ivy

Go to download

Watches the OpenShift environment and notifies Hubot of events such as builds completing or failing

There is a newer version: 2.2.335
Show newest version
/**
 *
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package io.fabric8.hubot.notifier;

import io.fabric8.annotations.Eager;
import io.fabric8.annotations.External;
import io.fabric8.annotations.Protocol;
import io.fabric8.annotations.ServiceName;
import io.fabric8.hubot.HubotNotifier;
import io.fabric8.kubernetes.api.KubernetesHelper;
import io.fabric8.kubernetes.api.model.HasMetadata;
import io.fabric8.kubernetes.api.model.Pod;
import io.fabric8.kubernetes.api.model.ReplicationController;
import io.fabric8.kubernetes.api.model.Service;
import io.fabric8.kubernetes.api.model.Status;
import io.fabric8.kubernetes.client.DefaultKubernetesClient;
import io.fabric8.kubernetes.client.KubernetesClient;
import io.fabric8.kubernetes.client.KubernetesClientException;
import io.fabric8.kubernetes.client.Watch;
import io.fabric8.kubernetes.client.Watcher;
import io.fabric8.openshift.api.model.BuildConfig;
import io.fabric8.openshift.api.model.DeploymentConfig;
import io.fabric8.openshift.client.OpenShiftClient;
import io.fabric8.utils.Strings;

import org.apache.deltaspike.core.api.config.ConfigProperty;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;

import java.util.ArrayList;
import java.util.List;

import static java.beans.Introspector.decapitalize;

/**
 * Watches the kubernetes resources in the current namespace and notifies hubot
 */
@ApplicationScoped
@Eager
public class KubernetesHubotNotifier {
    public static final String DEFAULT_ROOM_EXPRESSION = "#fabric8_${namespace}";

    private static final transient Logger LOG = LoggerFactory.getLogger(KubernetesHubotNotifier.class);
    private final HubotNotifier notifier;
    private final String consoleLink;
    private final String roomExpression;

    private String namespace = KubernetesHelper.defaultNamespace();
    private KubernetesClient client = new DefaultKubernetesClient();
    private List watches = new ArrayList<>();

    private NotifyConfig serviceConfig = new NotifyConfig("service");
    private NotifyConfig podConfig = new NotifyConfig("pod");
    private NotifyConfig rcConfig = new NotifyConfig("rc");
    private NotifyConfig buildConfigConfig = new NotifyConfig("buildConfig");
    private NotifyConfig dcConfig = new NotifyConfig("dc");

    /**
     * Note this constructor is only added to help CDI work with the {@link Eager} extension
     */
    public KubernetesHubotNotifier() {
        this.notifier = null;
        this.consoleLink = null;
        this.roomExpression = DEFAULT_ROOM_EXPRESSION;
    }

    @Inject
    public KubernetesHubotNotifier(HubotNotifier notifier,
                                   @External @Protocol("http") @ServiceName("fabric8") String consoleLink,
                                   @ConfigProperty(name = "HUBOT_KUBERNETES_ROOM", defaultValue = DEFAULT_ROOM_EXPRESSION) String roomExpression) throws Exception {
        this.notifier = notifier;
        this.consoleLink = consoleLink;
        this.roomExpression = roomExpression;

        LOG.info("Starting watching Kubernetes namespace " + getNamespace() + " at " + client.getMasterUrl() + " using console link: " + consoleLink + " with roomExpression: " + roomExpression);

        addClient(client.services().watch(new WatcherSupport() {
            @Override
            public void eventReceived(Action action, Service service) {
                onWatchEvent(action, service, serviceConfig);
            }
        }));


        addClient(client.pods().watch(new WatcherSupport() {
            @Override
            public void eventReceived(Action action, Pod pod) {
                onWatchEvent(action, pod, podConfig);
            }
        }));

        addClient(client.replicationControllers().watch(new WatcherSupport() {
            @Override
            public void eventReceived(Action action, ReplicationController replicationController) {
                onWatchEvent(action, replicationController, rcConfig);
            }
        }));

        if (client.isAdaptable(OpenShiftClient.class)){
            addClient(client.adapt(OpenShiftClient.class).buildConfigs().watch(new WatcherSupport() {
                @Override
                public void eventReceived(Action action, BuildConfig buildConfig) {
                    onWatchEvent(action, buildConfig, buildConfigConfig);
                }
            }));

            addClient(client.adapt(OpenShiftClient.class).deploymentConfigs().watch(new WatcherSupport() {
                @Override
                public void eventReceived(Action action, DeploymentConfig deploymentConfig) {
                    onWatchEvent(action, deploymentConfig, dcConfig);
                }
            }));
            LOG.info("Now watching builds and deployments");
        }

        LOG.info("Now watching services, pods and replication controllers");
    }

    protected static abstract class WatcherSupport implements io.fabric8.kubernetes.client.Watcher {
        public void onClose(KubernetesClientException e) {
            LOG.info("Watcher " + this + " closed due to : " + e);
        }
    }
    public String getNamespace() {
        return namespace;
    }

    protected void addClient(Watch watch) {
        watches.add(watch);
    }

    protected void onWatchEvent(io.fabric8.kubernetes.client.Watcher.Action action, HasMetadata entity, NotifyConfig notifyConfig) {
        if (!notifyConfig.isEnabled(action)) {
            return;
        }
        String kind = KubernetesHelper.getKind(entity);
        String name = KubernetesHelper.getName(entity);
        String namespace = getNamespace();

        String actionText = action.toString().toLowerCase();
        String room = this.roomExpression.replace("${namespace}", namespace).replace("${kind}", kind).replace("${name}", name);

        String postfix = "";
        if (action.equals(Watcher.Action.ADDED) || action.equals(Watcher.Action.MODIFIED)) {
            if (Strings.isNotBlank(consoleLink)) {
                postfix += " " + consoleLink + "/kubernetes/namespace/" + namespace + "/" + kind.toLowerCase() + "s/" + name;
            }
        }

        String message = actionText + " " + decapitalize(kind) + " " + namespace + " / " + name + postfix;
        notifier.notifyRoom(room, message);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy