/** * Copyright 2015 StreamSets Inc. * * Licensed under 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 com.streamsets.datacollector.execution; import com.streamsets.datacollector.config.PipelineConfiguration; import com.streamsets.datacollector.creation.PipelineConfigBean; import com.streamsets.datacollector.email.EmailSender; import com.streamsets.datacollector.event.handler.remote.RemoteDataCollector; import com.streamsets.datacollector.execution.alerts.EmailNotifier; import com.streamsets.datacollector.execution.alerts.WebHookNotifier; import com.streamsets.datacollector.execution.runner.common.PipelineRunnerException; import com.streamsets.datacollector.main.RuntimeInfo; import com.streamsets.datacollector.stagelibrary.StageLibraryTask; import com.streamsets.datacollector.store.AclStoreTask; import com.streamsets.datacollector.store.PipelineStoreException; import com.streamsets.datacollector.store.PipelineStoreTask; import com.streamsets.datacollector.util.Configuration; import com.streamsets.datacollector.util.ContainerError; import com.streamsets.datacollector.util.PipelineException; import com.streamsets.datacollector.util.ValidationUtil; import com.streamsets.datacollector.validation.PipelineConfigurationValidator; import com.streamsets.lib.security.acl.dto.Acl; import com.streamsets.pipeline.api.StageException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.inject.Inject; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.Callable; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; public abstract class AbstractRunner implements Runner { private static final Logger LOG = LoggerFactory.getLogger(AbstractRunner.class); @Inject protected AclStoreTask aclStoreTask; @Inject protected EventListenerManager eventListenerManager; @Inject protected PipelineStoreTask pipelineStore; @Inject protected StageLibraryTask stageLibrary; @Inject protected RuntimeInfo runtimeInfo; @Inject protected Configuration configuration; protected Map<String, Object> runtimeParameters; protected PipelineConfiguration getPipelineConf(String name, String rev) throws PipelineException { PipelineConfiguration load = pipelineStore.load(name, rev); PipelineConfigurationValidator validator = new PipelineConfigurationValidator(stageLibrary, name, load); PipelineConfiguration validate = validator.validate(); if(validator.getIssues().hasIssues()) { throw new PipelineRunnerException(ContainerError.CONTAINER_0158, ValidationUtil.getFirstIssueAsString(name, validator.getIssues())); } return validate; } protected Acl getAcl(String name) throws PipelineException { return aclStoreTask.getAcl(name); } protected void registerEmailNotifierIfRequired( PipelineConfigBean pipelineConfigBean, String pipelineId, String pipelineTitle, String rev ) { //remove existing email notifier StateEventListener toRemove = null; List<StateEventListener> stateEventListenerList = eventListenerManager.getStateEventListenerList(); for(StateEventListener s : stateEventListenerList) { if(s instanceof EmailNotifier && ((EmailNotifier)s).getPipelineId().equals(pipelineId) && ((EmailNotifier)s).getRev().equals(rev)) { toRemove = s; } } if(toRemove != null) { eventListenerManager.removeStateEventListener(toRemove); } //register new one if required if(pipelineConfigBean.notifyOnStates != null && !pipelineConfigBean.notifyOnStates.isEmpty() && pipelineConfigBean.emailIDs != null && !pipelineConfigBean.emailIDs.isEmpty()) { Set<String> states = new HashSet<>(); for(com.streamsets.datacollector.config.PipelineState s : pipelineConfigBean.notifyOnStates) { states.add(s.name()); } EmailNotifier emailNotifier = new EmailNotifier( pipelineId, pipelineTitle, rev, runtimeInfo, new EmailSender(configuration), pipelineConfigBean.emailIDs, states ); eventListenerManager.addStateEventListener(emailNotifier); } } protected void registerWebhookNotifierIfRequired( PipelineConfigBean pipelineConfigBean, String pipelineId, String pipelineTitle, String rev ) { //remove existing Webhook notifier StateEventListener toRemove = null; List<StateEventListener> stateEventListenerList = eventListenerManager.getStateEventListenerList(); for(StateEventListener s : stateEventListenerList) { if(s instanceof WebHookNotifier && ((WebHookNotifier)s).getPipelineId().equals(pipelineId) && ((WebHookNotifier)s).getRev().equals(rev)) { toRemove = s; } } if(toRemove != null) { eventListenerManager.removeStateEventListener(toRemove); } //register new one if required if(pipelineConfigBean.notifyOnStates != null && !pipelineConfigBean.notifyOnStates.isEmpty() && pipelineConfigBean.webhookConfigs != null && !pipelineConfigBean.webhookConfigs.isEmpty()) { WebHookNotifier webHookNotifier = new WebHookNotifier( pipelineId, pipelineTitle, rev, pipelineConfigBean, runtimeInfo ); eventListenerManager.addStateEventListener(webHookNotifier); } } protected boolean isRemotePipeline() throws PipelineStoreException { Object isRemote = getState().getAttributes().get(RemoteDataCollector.IS_REMOTE_PIPELINE); // remote attribute will be null for pipelines with version earlier than 1.3 return isRemote != null && (boolean) isRemote; } protected ScheduledFuture<Void> scheduleForRetries( String user, ScheduledExecutorService runnerExecutor ) throws PipelineStoreException { long delay = 0; long retryTimeStamp = getState().getNextRetryTimeStamp(); long currentTime = System.currentTimeMillis(); if (retryTimeStamp > currentTime) { delay = retryTimeStamp - currentTime; } LOG.info("Scheduling retry in '{}' milliseconds", delay); return runnerExecutor.schedule(() -> { LOG.info("Starting the runner now"); prepareForStart(user); start(user, runtimeParameters); return null; }, delay, TimeUnit.MILLISECONDS); } @Override public void start(String user) throws PipelineException, StageException { start(user, null); } }