diff options
author | Valerij Fredriksen <freva@users.noreply.github.com> | 2019-08-08 12:37:37 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-08-08 12:37:37 +0200 |
commit | a57f471086808aa58ddace94c59f30f7ca99173b (patch) | |
tree | dcefe511194ca791b2771161bd790ad257cf7a1e | |
parent | 4ba21966182d5086b9039395ed4ba15a5632eea9 (diff) |
Revert "Revert "Revert "Revert "Automatically file a JIRA ticket for AWS events." """
10 files changed, 145 insertions, 5 deletions
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/aws/AwsEventFetcher.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/aws/AwsEventFetcher.java new file mode 100644 index 00000000000..d17f046c5ca --- /dev/null +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/aws/AwsEventFetcher.java @@ -0,0 +1,11 @@ +package com.yahoo.vespa.hosted.controller.api.integration.aws; + +import com.yahoo.config.provision.zone.ZoneId; +import com.yahoo.vespa.hosted.controller.api.integration.organization.Issue; + +import java.util.List; + +public interface AwsEventFetcher { + List<CloudEvent> getEvents(ZoneId zoneId); + Issue createIssue(CloudEvent event); +} diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/aws/CloudEvent.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/aws/CloudEvent.java new file mode 100644 index 00000000000..59fd84aec74 --- /dev/null +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/aws/CloudEvent.java @@ -0,0 +1,30 @@ +package com.yahoo.vespa.hosted.controller.api.integration.aws; + +import java.util.Date; +import java.util.Optional; +import java.util.Set; + +public final class CloudEvent { + public final String instanceEventId; + public final String code; + public final String description; + public final Optional<Date> notBefore; + public final Optional<Date> notBeforeDeadline; + public final Optional<Date> notAfter; + + public String awsRegionName; + public Set<String> affectedHostnames; + + public CloudEvent(String instanceEventId, String code, String description, Date notAfter, Date notBefore, Date notBeforeDeadline, + String awsRegionName, Set<String> affectedHostnames) { + this.instanceEventId = instanceEventId; + this.code = code; + this.description = description; + this.notBefore = Optional.ofNullable(notBefore); + this.notBeforeDeadline = Optional.ofNullable(notBeforeDeadline); + this.notAfter = Optional.ofNullable(notAfter); + + this.awsRegionName = awsRegionName; + this.affectedHostnames = affectedHostnames; + } +} diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/aws/MockAwsEventFetcher.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/aws/MockAwsEventFetcher.java new file mode 100644 index 00000000000..73b1942de44 --- /dev/null +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/aws/MockAwsEventFetcher.java @@ -0,0 +1,19 @@ +package com.yahoo.vespa.hosted.controller.api.integration.aws; + +import com.yahoo.config.provision.zone.ZoneId; +import com.yahoo.vespa.hosted.controller.api.integration.organization.Issue; + +import java.util.List; +import java.util.Optional; + +public class MockAwsEventFetcher implements AwsEventFetcher { + @Override + public List<CloudEvent> getEvents(ZoneId zoneId) { + return List.of(); + } + + @Override + public Issue createIssue(CloudEvent event) { + return new Issue("summary", "description", "VESPA", Optional.empty()); + } +} diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/aws/package-info.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/aws/package-info.java new file mode 100644 index 00000000000..31aa5291547 --- /dev/null +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/aws/package-info.java @@ -0,0 +1,5 @@ +// Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +@ExportPackage +package com.yahoo.vespa.hosted.controller.api.integration.aws; + +import com.yahoo.osgi.annotation.ExportPackage; diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/organization/IssueHandler.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/organization/IssueHandler.java index db4f0eb5c59..80e23249daa 100644 --- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/organization/IssueHandler.java +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/organization/IssueHandler.java @@ -83,4 +83,12 @@ public interface IssueHandler { */ Optional<User> escalate(IssueId issueId, Contact contact); + /** + * Returns whether there exists an issue with an exactly matching summary. + * + * @param issue The summary of the issue. + * @return Whether the issue exists. + */ + boolean issueExists(Issue issue); + } diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/organization/MockIssueHandler.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/organization/MockIssueHandler.java index 674523ba26b..2e92c993686 100644 --- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/organization/MockIssueHandler.java +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/organization/MockIssueHandler.java @@ -101,6 +101,11 @@ public class MockIssueHandler implements IssueHandler { return Optional.empty(); } + @Override + public boolean issueExists(Issue issue) { + return issues.values().stream().anyMatch(i -> i.issue.summary().equals(issue.summary())); + } + public MockIssueHandler close(IssueId issueId) { issues.get(issueId).open = false; touch(issueId); diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/AwsEventReporterMaintainer.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/AwsEventReporterMaintainer.java new file mode 100644 index 00000000000..14a39109c61 --- /dev/null +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/AwsEventReporterMaintainer.java @@ -0,0 +1,55 @@ +package com.yahoo.vespa.hosted.controller.maintenance; + +import com.yahoo.config.provision.CloudName; +import com.yahoo.config.provision.zone.ZoneList; +import com.yahoo.vespa.hosted.controller.Controller; +import com.yahoo.vespa.hosted.controller.api.integration.aws.AwsEventFetcher; +import com.yahoo.vespa.hosted.controller.api.integration.aws.CloudEvent; +import com.yahoo.vespa.hosted.controller.api.integration.organization.Issue; +import com.yahoo.vespa.hosted.controller.api.integration.organization.IssueHandler; + +import java.time.Duration; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * @author mgimle + * Automatically fetches scheduled events from AWS and submits issues detailing them to Jira. + */ +public class AwsEventReporterMaintainer extends Maintainer { + private static final Logger log = Logger.getLogger(AwsEventReporterMaintainer.class.getName()); + + private final IssueHandler issueHandler; + private final AwsEventFetcher eventFetcher; + private final ZoneList cloudZones; + + AwsEventReporterMaintainer(Controller controller, Duration interval, JobControl jobControl, + IssueHandler issueHandler, AwsEventFetcher eventFetcher) { + super(controller, interval, jobControl); + this.cloudZones = awsZones(controller); + this.issueHandler = issueHandler; + this.eventFetcher = eventFetcher; + } + + private ZoneList awsZones(Controller controller) { + return controller.zoneRegistry().zones() + .ofCloud(CloudName.from("aws")) + .reachable(); + } + + @Override + protected void maintain() { + log.log(Level.INFO, "Fetching events for cloud hosts."); + for (var cloudZoneId : cloudZones.ids()) { + List<CloudEvent> events = eventFetcher.getEvents(cloudZoneId); + for (var event : events) { + Issue issue = eventFetcher.createIssue(event); + if (!issueHandler.issueExists(issue)) { + issueHandler.file(issue); + log.log(Level.INFO, String.format("Filed an issue with the title '%s'", issue.summary())); + } + } + } + } +} diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ControllerMaintenance.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ControllerMaintenance.java index 116ea532a11..0a894a1031f 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ControllerMaintenance.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ControllerMaintenance.java @@ -5,12 +5,10 @@ import com.yahoo.component.AbstractComponent; import com.yahoo.config.provision.zone.ZoneApi; import com.yahoo.jdisc.Metric; import com.yahoo.vespa.hosted.controller.Controller; +import com.yahoo.vespa.hosted.controller.api.integration.aws.AwsEventFetcher; import com.yahoo.vespa.hosted.controller.api.integration.configserver.NodeRepository; import com.yahoo.vespa.hosted.controller.api.integration.dns.NameService; -import com.yahoo.vespa.hosted.controller.api.integration.organization.Billing; -import com.yahoo.vespa.hosted.controller.api.integration.organization.ContactRetriever; -import com.yahoo.vespa.hosted.controller.api.integration.organization.DeploymentIssues; -import com.yahoo.vespa.hosted.controller.api.integration.organization.OwnershipIssues; +import com.yahoo.vespa.hosted.controller.api.integration.organization.*; import com.yahoo.vespa.hosted.controller.api.integration.resource.ResourceSnapshotConsumer; import com.yahoo.vespa.hosted.controller.authority.config.ApiAuthorityConfig; import com.yahoo.vespa.hosted.controller.maintenance.config.MaintainerConfig; @@ -55,6 +53,7 @@ public class ControllerMaintenance extends AbstractComponent { private final ResourceMeterMaintainer resourceMeterMaintainer; private final NameServiceDispatcher nameServiceDispatcher; private final BillingMaintainer billingMaintainer; + private final AwsEventReporterMaintainer awsEventReporterMaintainer; @SuppressWarnings("unused") // instantiated by Dependency Injection public ControllerMaintenance(MaintainerConfig maintainerConfig, ApiAuthorityConfig apiAuthorityConfig, Controller controller, CuratorDb curator, @@ -65,7 +64,9 @@ public class ControllerMaintenance extends AbstractComponent { CostReportConsumer reportConsumer, ResourceSnapshotConsumer resourceSnapshotConsumer, Billing billing, - SelfHostedCostConfig selfHostedCostConfig) { + SelfHostedCostConfig selfHostedCostConfig, + IssueHandler issueHandler, + AwsEventFetcher awsEventFetcher) { Duration maintenanceInterval = Duration.ofMinutes(maintainerConfig.intervalMinutes()); this.jobControl = jobControl; deploymentExpirer = new DeploymentExpirer(controller, maintenanceInterval, jobControl); @@ -88,6 +89,7 @@ public class ControllerMaintenance extends AbstractComponent { resourceMeterMaintainer = new ResourceMeterMaintainer(controller, Duration.ofMinutes(60), jobControl, nodeRepository, Clock.systemUTC(), metric, resourceSnapshotConsumer); nameServiceDispatcher = new NameServiceDispatcher(controller, Duration.ofSeconds(10), jobControl, nameService); billingMaintainer = new BillingMaintainer(controller, Duration.ofDays(3), jobControl, billing); + awsEventReporterMaintainer = new AwsEventReporterMaintainer(controller, Duration.ofDays(1), jobControl, issueHandler, awsEventFetcher); } public Upgrader upgrader() { return upgrader; } @@ -117,6 +119,7 @@ public class ControllerMaintenance extends AbstractComponent { resourceMeterMaintainer.deconstruct(); nameServiceDispatcher.deconstruct(); billingMaintainer.deconstruct(); + awsEventReporterMaintainer.deconstruct(); } /** Create one OS upgrader per cloud found in the zone registry of controller */ diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ControllerContainerTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ControllerContainerTest.java index 83a43287880..af6684002a5 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ControllerContainerTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ControllerContainerTest.java @@ -73,6 +73,7 @@ public class ControllerContainerTest { " <component id='com.yahoo.vespa.hosted.controller.api.integration.stubs.MockRunDataStore'/>\n" + " <component id='com.yahoo.vespa.hosted.controller.api.integration.organization.MockContactRetriever'/>\n" + " <component id='com.yahoo.vespa.hosted.controller.api.integration.organization.MockIssueHandler'/>\n" + + " <component id='com.yahoo.vespa.hosted.controller.api.integration.aws.MockAwsEventFetcher' />\n" + " <component id='com.yahoo.vespa.hosted.controller.api.integration.organization.MockBilling'/>\n" + " <component id='com.yahoo.vespa.hosted.controller.api.integration.stubs.MockResourceSnapshotConsumer'/>\n" + " <component id='com.yahoo.vespa.hosted.controller.integration.ConfigServerMock'/>\n" + diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/controller/responses/maintenance.json b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/controller/responses/maintenance.json index d4f3e20ac14..1b5b679cb8a 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/controller/responses/maintenance.json +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/controller/responses/maintenance.json @@ -4,6 +4,9 @@ "name": "ApplicationOwnershipConfirmer" }, { + "name": "AwsEventReporterMaintainer" + }, + { "name": "BillingMaintainer" }, { |