/** * Licensed 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 org.apache.aurora.scheduler.cron; import java.util.Objects; import javax.annotation.Nullable; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.MoreObjects; import com.google.common.base.Optional; import com.google.common.base.Strings; import org.apache.aurora.gen.CronCollisionPolicy; import org.apache.aurora.scheduler.configuration.ConfigurationManager; import org.apache.aurora.scheduler.configuration.SanitizedConfiguration; import org.apache.aurora.scheduler.storage.entities.IJobConfiguration; import static java.util.Objects.requireNonNull; /** * Used by functions that expect field validation before being called. */ public final class SanitizedCronJob { @VisibleForTesting public static final String NO_CRON_SCHEDULE = "Job has an empty cron schedule."; private final SanitizedConfiguration config; private final CrontabEntry crontabEntry; private SanitizedCronJob(ConfigurationManager configurationManager, IJobConfiguration unsanitized) throws CronException, ConfigurationManager.TaskDescriptionException { this(SanitizedConfiguration.fromUnsanitized(configurationManager, unsanitized)); } private SanitizedCronJob(SanitizedConfiguration config) throws CronException { final IJobConfiguration job = config.getJobConfig(); if (!hasCronSchedule(job)) { throw new CronException(NO_CRON_SCHEDULE); } Optional<CrontabEntry> entry = CrontabEntry.tryParse(job.getCronSchedule()); if (!entry.isPresent()) { throw new CronException("Invalid cron schedule: " + job.getCronSchedule()); } this.config = config; this.crontabEntry = entry.get(); } /** * Get the default cron collision policy. * * @param policy A (possibly null) policy. * @return The given policy or a default if the policy was null. */ public static CronCollisionPolicy orDefault(@Nullable CronCollisionPolicy policy) { return Optional.fromNullable(policy).or(CronCollisionPolicy.KILL_EXISTING); } /** * Create a SanitizedCronJob from a SanitizedConfiguration. SanitizedCronJob performs additional * validation to ensure that the provided job contains all properties needed to run it on a * cron schedule. * * @param config Config to validate. * @return Config wrapped in defaults. * @throws CronException If a cron-specific validation error occured. */ public static SanitizedCronJob from(SanitizedConfiguration config) throws CronException { return new SanitizedCronJob(config); } /** * Create a cron job from an unsanitized input job. Suitable for RPC input validation. * * @param unsanitized Unsanitized input job. * @return A sanitized job if all validation succeeds. * @throws CronException If validation fails with a cron-specific error. * @throws ConfigurationManager.TaskDescriptionException If validation fails with a non * cron-specific error. */ public static SanitizedCronJob fromUnsanitized( ConfigurationManager configurationManager, IJobConfiguration unsanitized) throws CronException, ConfigurationManager.TaskDescriptionException { return new SanitizedCronJob(configurationManager, unsanitized); } /** * Get this job's cron collision policy. * * @return This job's cron collision policy. */ public CronCollisionPolicy getCronCollisionPolicy() { return orDefault(config.getJobConfig().getCronCollisionPolicy()); } private static boolean hasCronSchedule(IJobConfiguration job) { requireNonNull(job); return !Strings.isNullOrEmpty(job.getCronSchedule()); } /** * Returns the cron schedule associated with this job. * * @return The cron schedule associated with this job. */ public CrontabEntry getCrontabEntry() { return crontabEntry; } /** * Returns the sanitized job configuration associated with the cron job. * * @return This cron job's sanitized job configuration. */ public SanitizedConfiguration getSanitizedConfig() { return config; } @Override public boolean equals(Object o) { if (!(o instanceof SanitizedCronJob)) { return false; } SanitizedCronJob other = (SanitizedCronJob) o; return Objects.equals(config, other.config) && Objects.equals(crontabEntry, other.crontabEntry); } @Override public int hashCode() { return Objects.hash(config, crontabEntry); } @Override public String toString() { return MoreObjects.toStringHelper(this) .add("config", config) .add("crontabEntry", crontabEntry) .toString(); } }