diff options
30 files changed, 284 insertions, 574 deletions
diff --git a/application-model/OWNERS b/application-model/OWNERS index 27e1155db8b..e131dacde49 100644 --- a/application-model/OWNERS +++ b/application-model/OWNERS @@ -1,2 +1 @@ hakonhall -bjorncs diff --git a/application-model/pom.xml b/application-model/pom.xml index 69b7101029d..f68deb83993 100644 --- a/application-model/pom.xml +++ b/application-model/pom.xml @@ -15,6 +15,21 @@ <description>Model classes for Vespa application entities such as host name, application id etc.</description> <dependencies> <dependency> + <groupId>org.scala-lang</groupId> + <artifactId>scala-library</artifactId> + </dependency> + <dependency> + <groupId>org.json4s</groupId> + <artifactId>json4s-native_${scala.major-version}</artifactId> + <scope>test</scope> + <exclusions> + <exclusion> + <groupId>org.scala-lang</groupId> + <artifactId>scalap</artifactId> + </exclusion> + </exclusions> + </dependency> + <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-annotations</artifactId> <version>${jackson2.version}</version> @@ -29,6 +44,33 @@ <build> <plugins> <plugin> + <groupId>org.scala-tools</groupId> + <artifactId>maven-scala-plugin</artifactId> + <executions> + <execution> + <goals> + <goal>add-source</goal> + <goal>compile</goal> + <goal>testCompile</goal> + </goals> + </execution> + <execution> + <id>compile-scala-classes-for-use-in-java-classes</id> + <phase>process-resources</phase> + <goals> + <goal>compile</goal> + </goals> + </execution> + </executions> + <configuration> + <args> + <arg>-unchecked</arg> + <arg>-deprecation</arg> + <arg>-feature</arg> + </args> + </configuration> + </plugin> + <plugin> <groupId>com.yahoo.vespa</groupId> <artifactId>bundle-plugin</artifactId> <extensions>true</extensions> diff --git a/application-model/src/main/java/com/yahoo/vespa/applicationmodel/ApplicationInstance.java b/application-model/src/main/java/com/yahoo/vespa/applicationmodel/ApplicationInstance.java deleted file mode 100644 index 31c6861b706..00000000000 --- a/application-model/src/main/java/com/yahoo/vespa/applicationmodel/ApplicationInstance.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.yahoo.vespa.applicationmodel; - -import com.fasterxml.jackson.annotation.JsonProperty; - -import java.util.Objects; -import java.util.Set; - -/** - * @author bjorncs - */ -public class ApplicationInstance<STATUS> { - private final TenantId tenantId; - private final ApplicationInstanceId applicationInstanceId; - private final Set<ServiceCluster<STATUS>> serviceClusters; - - public ApplicationInstance(TenantId tenantId, ApplicationInstanceId applicationInstanceId, Set<ServiceCluster<STATUS>> serviceClusters) { - this.tenantId = tenantId; - this.applicationInstanceId = applicationInstanceId; - this.serviceClusters = serviceClusters; - } - - @JsonProperty("tenantId") - public TenantId tenantId() { - return tenantId; - } - - @JsonProperty("applicationInstanceId") - public ApplicationInstanceId applicationInstanceId() { - return applicationInstanceId; - } - - @JsonProperty("serviceClusters") - public Set<ServiceCluster<STATUS>> serviceClusters() { - return serviceClusters; - } - - @JsonProperty("reference") - public ApplicationInstanceReference reference() { - return new ApplicationInstanceReference(tenantId, applicationInstanceId); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - ApplicationInstance<?> that = (ApplicationInstance<?>) o; - return Objects.equals(tenantId, that.tenantId) && - Objects.equals(applicationInstanceId, that.applicationInstanceId) && - Objects.equals(serviceClusters, that.serviceClusters); - } - - @Override - public int hashCode() { - return Objects.hash(tenantId, applicationInstanceId, serviceClusters); - } - - @Override - public String toString() { - return "ApplicationInstance{" + - "tenantId=" + tenantId + - ", applicationInstanceId=" + applicationInstanceId + - ", serviceClusters=" + serviceClusters + - '}'; - } -} diff --git a/application-model/src/main/java/com/yahoo/vespa/applicationmodel/ApplicationInstanceId.java b/application-model/src/main/java/com/yahoo/vespa/applicationmodel/ApplicationInstanceId.java deleted file mode 100644 index 17d60690820..00000000000 --- a/application-model/src/main/java/com/yahoo/vespa/applicationmodel/ApplicationInstanceId.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.yahoo.vespa.applicationmodel; - -import com.fasterxml.jackson.annotation.JsonValue; - -import java.util.Objects; - -/** - * @author bjorncs - */ -// TODO: Remove this and use ApplicationName/InstanceName instead (if you need it for the JSON stuff move it to that layer and don't let it leak) -public class ApplicationInstanceId { - private final String id; - - public ApplicationInstanceId(String id) { - this.id = id; - } - - // Jackson's StdKeySerializer uses toString() (and ignores annotations) for objects used as Map keys. - // Therefore, we use toString() as the JSON-producing method, which is really sad. - @Override - @JsonValue - public String toString() { - return id; - } - - // For compatibility with original Scala case class - public String s() { - return id; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - ApplicationInstanceId that = (ApplicationInstanceId) o; - return Objects.equals(id, that.id); - } - - @Override - public int hashCode() { - return Objects.hash(id); - } -} diff --git a/application-model/src/main/java/com/yahoo/vespa/applicationmodel/ApplicationInstanceReference.java b/application-model/src/main/java/com/yahoo/vespa/applicationmodel/ApplicationInstanceReference.java deleted file mode 100644 index d8feec5af3b..00000000000 --- a/application-model/src/main/java/com/yahoo/vespa/applicationmodel/ApplicationInstanceReference.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.yahoo.vespa.applicationmodel; - -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.annotation.JsonValue; - -import java.util.Objects; - -/** - * @author bjorncs - */ -// TODO: Remove this and use ApplicationId instead (if you need it for the JSON stuff move it to that layer and don't let it leak) -public class ApplicationInstanceReference { - private final TenantId tenantId; - private final ApplicationInstanceId applicationInstanceId; - - public ApplicationInstanceReference(TenantId tenantId, ApplicationInstanceId applicationInstanceId) { - this.tenantId = tenantId; - this.applicationInstanceId = applicationInstanceId; - } - - @JsonProperty("tenantId") - public TenantId tenantId() { - return tenantId; - } - - @JsonProperty("applicationInstanceId") - public ApplicationInstanceId applicationInstanceId() { - return applicationInstanceId; - } - - // Jackson's StdKeySerializer uses toString() (and ignores annotations) for objects used as Map keys. - // Therefore, we use toString() as the JSON-producing method, which is really sad. - @JsonValue - @Override - public String toString() { - return tenantId.s() + ":" + applicationInstanceId.s(); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - ApplicationInstanceReference that = (ApplicationInstanceReference) o; - return Objects.equals(tenantId, that.tenantId) && - Objects.equals(applicationInstanceId, that.applicationInstanceId); - } - - @Override - public int hashCode() { - return Objects.hash(tenantId, applicationInstanceId); - } -} diff --git a/application-model/src/main/java/com/yahoo/vespa/applicationmodel/ClusterId.java b/application-model/src/main/java/com/yahoo/vespa/applicationmodel/ClusterId.java deleted file mode 100644 index b502eaff3fa..00000000000 --- a/application-model/src/main/java/com/yahoo/vespa/applicationmodel/ClusterId.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.yahoo.vespa.applicationmodel; - -import com.fasterxml.jackson.annotation.JsonValue; - -import java.util.Objects; - -/** - * @author bjorncs - */ -public class ClusterId { - - private final String id; - - public ClusterId(String id) { - this.id = id; - } - - // Jackson's StdKeySerializer uses toString() (and ignores annotations) for objects used as Map keys. - // Therefore, we use toString() as the JSON-producing method, which is really sad. - @JsonValue - @Override - public String toString() { - return id; - } - - // For compatibility with original Scala case class - public String s() { - return id; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - ClusterId clusterId = (ClusterId) o; - return Objects.equals(id, clusterId.id); - } - - @Override - public int hashCode() { - return Objects.hash(id); - } -} diff --git a/application-model/src/main/java/com/yahoo/vespa/applicationmodel/ConfigId.java b/application-model/src/main/java/com/yahoo/vespa/applicationmodel/ConfigId.java deleted file mode 100644 index 63794066352..00000000000 --- a/application-model/src/main/java/com/yahoo/vespa/applicationmodel/ConfigId.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.yahoo.vespa.applicationmodel; - -import com.fasterxml.jackson.annotation.JsonValue; - -import java.util.Objects; - -/** - * @author bjorncs - */ -public class ConfigId { - - private final String id; - - public ConfigId(String id) { - this.id = id; - } - - // Jackson's StdKeySerializer uses toString() (and ignores annotations) for objects used as Map keys. - // Therefore, we use toString() as the JSON-producing method, which is really sad. - @JsonValue - @Override - public String toString() { - return super.toString(); - } - - public String s() { // For compatibility with original Scala case class - return id; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - ConfigId configId = (ConfigId) o; - return Objects.equals(id, configId.id); - } - - @Override - public int hashCode() { - return Objects.hash(id); - } -} diff --git a/application-model/src/main/java/com/yahoo/vespa/applicationmodel/DummyJavadocTrigger.java b/application-model/src/main/java/com/yahoo/vespa/applicationmodel/DummyJavadocTrigger.java new file mode 100644 index 00000000000..79406276885 --- /dev/null +++ b/application-model/src/main/java/com/yahoo/vespa/applicationmodel/DummyJavadocTrigger.java @@ -0,0 +1,13 @@ +// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.applicationmodel; + +/** + * Dummy class present only to satisfy javadoc plugin. + * + * See http://stackoverflow.com/questions/1138390/javadoc-for-package-info-java-only + * + * @author bakksjo + */ +final class DummyJavadocTrigger { + private DummyJavadocTrigger() {} // Prevents instantiation. +} diff --git a/application-model/src/main/java/com/yahoo/vespa/applicationmodel/HostName.java b/application-model/src/main/java/com/yahoo/vespa/applicationmodel/HostName.java deleted file mode 100644 index e6f8cd81fec..00000000000 --- a/application-model/src/main/java/com/yahoo/vespa/applicationmodel/HostName.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.yahoo.vespa.applicationmodel; - -import com.fasterxml.jackson.annotation.JsonValue; - -import java.util.Objects; - -/** - * @author bjorncs - */ -public class HostName { - - private final String id; - - public HostName(String id) { - this.id = id; - } - - // Jackson's StdKeySerializer uses toString() (and ignores annotations) for objects used as Map keys. - // Therefore, we use toString() as the JSON-producing method, which is really sad. - @JsonValue - @Override - public String toString() { - return super.toString(); - } - - // For compatibility with original Scala case class - public String s() { - return id; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - HostName hostName = (HostName) o; - return Objects.equals(id, hostName.id); - } - - @Override - public int hashCode() { - return Objects.hash(id); - } -} diff --git a/application-model/src/main/java/com/yahoo/vespa/applicationmodel/ServiceCluster.java b/application-model/src/main/java/com/yahoo/vespa/applicationmodel/ServiceCluster.java deleted file mode 100644 index 205dbf5a2e6..00000000000 --- a/application-model/src/main/java/com/yahoo/vespa/applicationmodel/ServiceCluster.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.yahoo.vespa.applicationmodel; - -import com.fasterxml.jackson.annotation.JsonProperty; - -import java.util.Objects; -import java.util.Set; - -/** - * Represents a collection of service instances that together make up a service with a single cluster id. - * - * @author bjorncs - */ -public class ServiceCluster<STATUS> { - private final ClusterId clusterId; - private final ServiceType serviceType; - private final Set<ServiceInstance<STATUS>> serviceInstances; - - public ServiceCluster(ClusterId clusterId, ServiceType serviceType, Set<ServiceInstance<STATUS>> serviceInstances) { - this.clusterId = clusterId; - this.serviceType = serviceType; - this.serviceInstances = serviceInstances; - } - - @JsonProperty("clusterId") - public ClusterId clusterId() { - return clusterId; - } - - @JsonProperty("serviceType") - public ServiceType serviceType() { - return serviceType; - } - - @JsonProperty("serviceInstances") - public Set<ServiceInstance<STATUS>> serviceInstances() { - return serviceInstances; - } - - @Override - public String toString() { - return "ServiceCluster{" + - "clusterId=" + clusterId + - ", serviceType=" + serviceType + - ", serviceInstances=" + serviceInstances + - '}'; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - ServiceCluster<?> that = (ServiceCluster<?>) o; - return Objects.equals(clusterId, that.clusterId) && - Objects.equals(serviceType, that.serviceType) && - Objects.equals(serviceInstances, that.serviceInstances); - } - - @Override - public int hashCode() { - return Objects.hash(clusterId, serviceType, serviceInstances); - } -} diff --git a/application-model/src/main/java/com/yahoo/vespa/applicationmodel/ServiceClusterKey.java b/application-model/src/main/java/com/yahoo/vespa/applicationmodel/ServiceClusterKey.java deleted file mode 100644 index 2c4653245e4..00000000000 --- a/application-model/src/main/java/com/yahoo/vespa/applicationmodel/ServiceClusterKey.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.yahoo.vespa.applicationmodel; - -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.annotation.JsonValue; - -import java.util.Objects; - -/** - * @author bjorncs - */ -public class ServiceClusterKey { - - private final ClusterId clusterId; - private final ServiceType serviceType; - - public ServiceClusterKey(ClusterId clusterId, ServiceType serviceType) { - this.clusterId = clusterId; - this.serviceType = serviceType; - } - - @JsonProperty("clusterId") - public ClusterId clusterId() { - return clusterId; - } - - @JsonProperty("serviceType") - public ServiceType serviceType() { - return serviceType; - } - - // Jackson's StdKeySerializer uses toString() (and ignores annotations) for objects used as Map keys. - // Therefore, we use toString() as the JSON-producing method, which is really sad. - @JsonValue - @Override - public String toString() { - return clusterId.s() + ":" + serviceType.s(); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - ServiceClusterKey that = (ServiceClusterKey) o; - return Objects.equals(clusterId, that.clusterId) && - Objects.equals(serviceType, that.serviceType); - } - - @Override - public int hashCode() { - return Objects.hash(clusterId, serviceType); - } -} diff --git a/application-model/src/main/java/com/yahoo/vespa/applicationmodel/ServiceInstance.java b/application-model/src/main/java/com/yahoo/vespa/applicationmodel/ServiceInstance.java deleted file mode 100644 index 160e0a39d5b..00000000000 --- a/application-model/src/main/java/com/yahoo/vespa/applicationmodel/ServiceInstance.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.yahoo.vespa.applicationmodel; - -import com.fasterxml.jackson.annotation.JsonProperty; - -import java.util.Objects; - -/** - * @author bjorncs - */ -public class ServiceInstance<STATUS> { - private final ConfigId configId; - private final HostName hostName; - private final STATUS serviceStatus; - - public ServiceInstance(ConfigId configId, HostName hostName, STATUS serviceStatus) { - this.configId = configId; - this.hostName = hostName; - this.serviceStatus = serviceStatus; - } - - @JsonProperty("configId") - public ConfigId configId() { - return configId; - } - - @JsonProperty("hostName") - public HostName hostName() { - return hostName; - } - - @JsonProperty("serviceStatus") - public STATUS serviceStatus() { - return serviceStatus; - } - - @Override - public String toString() { - return "ServiceInstance{" + - "configId=" + configId + - ", hostName=" + hostName + - ", serviceStatus=" + serviceStatus + - '}'; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - ServiceInstance<?> that = (ServiceInstance<?>) o; - return Objects.equals(configId, that.configId) && - Objects.equals(hostName, that.hostName) && - Objects.equals(serviceStatus, that.serviceStatus); - } - - @Override - public int hashCode() { - return Objects.hash(configId, hostName, serviceStatus); - } -} diff --git a/application-model/src/main/java/com/yahoo/vespa/applicationmodel/ServiceType.java b/application-model/src/main/java/com/yahoo/vespa/applicationmodel/ServiceType.java deleted file mode 100644 index 609f5b5c0f7..00000000000 --- a/application-model/src/main/java/com/yahoo/vespa/applicationmodel/ServiceType.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.yahoo.vespa.applicationmodel; - -import com.fasterxml.jackson.annotation.JsonValue; - -import java.util.Objects; - -/** - * @author bjorncs - */ -public class ServiceType { - - private final String id; - - public ServiceType(String id) { - this.id = id; - } - - // Jackson's StdKeySerializer uses toString() (and ignores annotations) for objects used as Map keys. - // Therefore, we use toString() as the JSON-producing method, which is really sad. - @JsonValue - @Override - public String toString() { - return id; - } - - // For compatibility with original Scala case class - public String s() { - return id; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - ServiceType that = (ServiceType) o; - return Objects.equals(id, that.id); - } - - @Override - public int hashCode() { - return Objects.hash(id); - } -} diff --git a/application-model/src/main/java/com/yahoo/vespa/applicationmodel/TenantId.java b/application-model/src/main/java/com/yahoo/vespa/applicationmodel/TenantId.java deleted file mode 100644 index ab656b55a2d..00000000000 --- a/application-model/src/main/java/com/yahoo/vespa/applicationmodel/TenantId.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.yahoo.vespa.applicationmodel; - -import com.fasterxml.jackson.annotation.JsonValue; - -import java.util.Objects; - -/** - * @author bjorncs - */ -// TODO: Remove this and use TenantName instead (if you need it for the JSON stuff move it to that layer and don't let it leak) -public class TenantId { - private final String id; - - public TenantId(String id) { - this.id = id; - } - - // Jackson's StdKeySerializer uses toString() (and ignores annotations) for objects used as Map keys. - // Therefore, we use toString() as the JSON-producing method, which is really sad. - @Override - @JsonValue - public String toString() { - return id; - } - - // For compatibility with original Scala case class - public String s() { - return id; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - TenantId tenantId = (TenantId) o; - return Objects.equals(id, tenantId.id); - } - - @Override - public int hashCode() { - return Objects.hash(id); - } -} diff --git a/application-model/src/main/scala/com/yahoo/vespa/applicationmodel/ApplicationInstance.scala b/application-model/src/main/scala/com/yahoo/vespa/applicationmodel/ApplicationInstance.scala new file mode 100644 index 00000000000..68f32db22dd --- /dev/null +++ b/application-model/src/main/scala/com/yahoo/vespa/applicationmodel/ApplicationInstance.scala @@ -0,0 +1,17 @@ +// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.applicationmodel + +/** + * TODO: What is this + * + * @author bakksjo + */ +case class ApplicationInstance[S]( + tenantId: TenantId, + applicationInstanceId: ApplicationInstanceId, + + // TODO: What is this for? + serviceClusters: java.util.Set[ServiceCluster[S]]) { + + def reference = ApplicationInstanceReference(tenantId, applicationInstanceId) +} diff --git a/application-model/src/main/scala/com/yahoo/vespa/applicationmodel/ApplicationInstanceId.scala b/application-model/src/main/scala/com/yahoo/vespa/applicationmodel/ApplicationInstanceId.scala new file mode 100644 index 00000000000..8c1bfe284fa --- /dev/null +++ b/application-model/src/main/scala/com/yahoo/vespa/applicationmodel/ApplicationInstanceId.scala @@ -0,0 +1,15 @@ +// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.applicationmodel + +import com.fasterxml.jackson.annotation.JsonValue + +/** + * @author bakksjo + */ + // TODO: Remove this and use ApplicationName/InstanceName instead (if you need it for the JSON stuff move it to that layer and don't let it leak) +case class ApplicationInstanceId(s: String) { + // Jackson's StdKeySerializer uses toString() (and ignores annotations) for objects used as Map keys. + // Therefore, we use toString() as the JSON-producing method, which is really sad. + @JsonValue + override def toString(): String = s +} diff --git a/application-model/src/main/scala/com/yahoo/vespa/applicationmodel/ApplicationInstanceReference.scala b/application-model/src/main/scala/com/yahoo/vespa/applicationmodel/ApplicationInstanceReference.scala new file mode 100644 index 00000000000..35e00d31ba2 --- /dev/null +++ b/application-model/src/main/scala/com/yahoo/vespa/applicationmodel/ApplicationInstanceReference.scala @@ -0,0 +1,15 @@ +// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.applicationmodel + +import com.fasterxml.jackson.annotation.JsonValue + +/** + * @author bakksjo + */ + // TODO: Remove this and use ApplicationId instead (if you need it for the JSON stuff move it to that layer and don't let it leak) +case class ApplicationInstanceReference(tenantId: TenantId, applicationInstanceId: ApplicationInstanceId) { + // Jackson's StdKeySerializer uses toString() (and ignores annotations) for objects used as Map keys. + // Therefore, we use toString() as the JSON-producing method, which is really sad. + @JsonValue + override def toString(): String = s"${tenantId.s}:${applicationInstanceId.s}" +} diff --git a/application-model/src/main/scala/com/yahoo/vespa/applicationmodel/ClusterId.scala b/application-model/src/main/scala/com/yahoo/vespa/applicationmodel/ClusterId.scala new file mode 100644 index 00000000000..929d79c2f8e --- /dev/null +++ b/application-model/src/main/scala/com/yahoo/vespa/applicationmodel/ClusterId.scala @@ -0,0 +1,14 @@ +// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.applicationmodel + +import com.fasterxml.jackson.annotation.JsonValue + +/** + * @author bakksjo + */ +case class ClusterId(s: String) { + // Jackson's StdKeySerializer uses toString() (and ignores annotations) for objects used as Map keys. + // Therefore, we use toString() as the JSON-producing method, which is really sad. + @JsonValue + override def toString(): String = s +} diff --git a/application-model/src/main/scala/com/yahoo/vespa/applicationmodel/ConfigId.scala b/application-model/src/main/scala/com/yahoo/vespa/applicationmodel/ConfigId.scala new file mode 100644 index 00000000000..013f2cd976b --- /dev/null +++ b/application-model/src/main/scala/com/yahoo/vespa/applicationmodel/ConfigId.scala @@ -0,0 +1,14 @@ +// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.applicationmodel + +import com.fasterxml.jackson.annotation.JsonValue + +/** + * @author bakksjo + */ +case class ConfigId(s: String) { + // Jackson's StdKeySerializer uses toString() (and ignores annotations) for objects used as Map keys. + // Therefore, we use toString() as the JSON-producing method, which is really sad. + @JsonValue + override def toString(): String = s +} diff --git a/application-model/src/main/scala/com/yahoo/vespa/applicationmodel/HostName.scala b/application-model/src/main/scala/com/yahoo/vespa/applicationmodel/HostName.scala new file mode 100644 index 00000000000..1715ed9fa80 --- /dev/null +++ b/application-model/src/main/scala/com/yahoo/vespa/applicationmodel/HostName.scala @@ -0,0 +1,14 @@ +// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.applicationmodel + +import com.fasterxml.jackson.annotation.JsonValue + +/** + * @author bakksjo + */ +case class HostName(s: String) { + // Jackson's StdKeySerializer uses toString() (and ignores annotations) for objects used as Map keys. + // Therefore, we use toString() as the JSON-producing method, which is really sad. + @JsonValue + override def toString(): String = s +} diff --git a/application-model/src/main/scala/com/yahoo/vespa/applicationmodel/ServiceCluster.scala b/application-model/src/main/scala/com/yahoo/vespa/applicationmodel/ServiceCluster.scala new file mode 100644 index 00000000000..6e5bb0d35b3 --- /dev/null +++ b/application-model/src/main/scala/com/yahoo/vespa/applicationmodel/ServiceCluster.scala @@ -0,0 +1,12 @@ +// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.applicationmodel + +/** + * Represents a collection of service instances that together make up a service with a single cluster id. + * + * @author bakksjo + */ +case class ServiceCluster[S]( + clusterId: ClusterId, + serviceType: ServiceType, + serviceInstances: java.util.Set[ServiceInstance[S]]) diff --git a/application-model/src/main/scala/com/yahoo/vespa/applicationmodel/ServiceClusterKey.scala b/application-model/src/main/scala/com/yahoo/vespa/applicationmodel/ServiceClusterKey.scala new file mode 100644 index 00000000000..48a19311ffe --- /dev/null +++ b/application-model/src/main/scala/com/yahoo/vespa/applicationmodel/ServiceClusterKey.scala @@ -0,0 +1,15 @@ +// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.applicationmodel + +import com.fasterxml.jackson.annotation.JsonValue + +/** + * @author bakksjo + */ +case class ServiceClusterKey(clusterId: ClusterId, serviceType: ServiceType) { + // Jackson's StdKeySerializer uses toString() (and ignores annotations) for objects used as Map keys. + // Therefore, we use toString() as the JSON-producing method, which is really sad. + @JsonValue + override def toString(): String = s"${clusterId}:${serviceType}" +} + diff --git a/application-model/src/main/scala/com/yahoo/vespa/applicationmodel/ServiceInstance.scala b/application-model/src/main/scala/com/yahoo/vespa/applicationmodel/ServiceInstance.scala new file mode 100644 index 00000000000..473e47f9d33 --- /dev/null +++ b/application-model/src/main/scala/com/yahoo/vespa/applicationmodel/ServiceInstance.scala @@ -0,0 +1,7 @@ +// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.applicationmodel + +/** + * @author bakksjo + */ +case class ServiceInstance[S](configId: ConfigId, hostName: HostName, serviceStatus: S) diff --git a/application-model/src/main/scala/com/yahoo/vespa/applicationmodel/ServiceType.scala b/application-model/src/main/scala/com/yahoo/vespa/applicationmodel/ServiceType.scala new file mode 100644 index 00000000000..c1a91039ae5 --- /dev/null +++ b/application-model/src/main/scala/com/yahoo/vespa/applicationmodel/ServiceType.scala @@ -0,0 +1,14 @@ +// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.applicationmodel + +import com.fasterxml.jackson.annotation.JsonValue + +/** + * @author tonytv + */ +case class ServiceType(s: String) { + // Jackson's StdKeySerializer uses toString() (and ignores annotations) for objects used as Map keys. + // Therefore, we use toString() as the JSON-producing method, which is really sad. + @JsonValue + override def toString(): String = s +} diff --git a/application-model/src/main/scala/com/yahoo/vespa/applicationmodel/TenantId.scala b/application-model/src/main/scala/com/yahoo/vespa/applicationmodel/TenantId.scala new file mode 100644 index 00000000000..17e9d1f1c7a --- /dev/null +++ b/application-model/src/main/scala/com/yahoo/vespa/applicationmodel/TenantId.scala @@ -0,0 +1,15 @@ +// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.applicationmodel + +import com.fasterxml.jackson.annotation.JsonValue + +/** + * @author bakksjo + */ + // TODO: Remove this and use TenantName instead (if you need it for the JSON stuff move it to that layer and don't let it leak) +case class TenantId(s: String) { + // Jackson's StdKeySerializer uses toString() (and ignores annotations) for objects used as Map keys. + // Therefore, we use toString() as the JSON-producing method, which is really sad. + @JsonValue + override def toString(): String = s +} diff --git a/orchestrator/pom.xml b/orchestrator/pom.xml index dd87082a90d..717eab0d92e 100644 --- a/orchestrator/pom.xml +++ b/orchestrator/pom.xml @@ -68,6 +68,11 @@ <scope>test</scope> </dependency> <dependency> + <groupId>org.scala-lang</groupId> + <artifactId>scala-library</artifactId> + <scope>compile</scope> + </dependency> + <dependency> <groupId>commons-lang</groupId> <artifactId>commons-lang</artifactId> </dependency> @@ -92,6 +97,29 @@ </exclusions> </dependency> <dependency> + <groupId>com.fasterxml.jackson.module</groupId> + <artifactId>jackson-module-scala_${scala.major-version}</artifactId> + <version>${jackson2.version}</version> + <exclusions> + <exclusion> + <groupId>com.fasterxml.jackson.core</groupId> + <artifactId>jackson-core</artifactId> + </exclusion> + <exclusion> + <groupId>com.fasterxml.jackson.core</groupId> + <artifactId>jackson-annotations</artifactId> + </exclusion> + <exclusion> + <groupId>com.fasterxml.jackson.core</groupId> + <artifactId>jackson-databind</artifactId> + </exclusion> + <exclusion> + <groupId>com.google.code.findbugs</groupId> + <artifactId>findbugs</artifactId> + </exclusion> + </exclusions> + </dependency> + <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-annotations</artifactId> <version>${jackson2.version}</version> diff --git a/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/resources/providers/ObjectMapperContextResolver.java b/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/resources/providers/ObjectMapperContextResolver.java new file mode 100644 index 00000000000..23a84d007d4 --- /dev/null +++ b/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/resources/providers/ObjectMapperContextResolver.java @@ -0,0 +1,26 @@ +package com.yahoo.vespa.orchestrator.resources.providers; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.module.scala.DefaultScalaModule$; + +import javax.ws.rs.ext.ContextResolver; +import javax.ws.rs.ext.Provider; + +/** + * Allow Scala case classes to be serialized to JSON + * @author bjorncs + */ +@Provider +public class ObjectMapperContextResolver implements ContextResolver<ObjectMapper> { + private final ObjectMapper objectMapper; + + public ObjectMapperContextResolver() { + objectMapper = new ObjectMapper(); + objectMapper.registerModule(DefaultScalaModule$.MODULE$); + } + + @Override + public ObjectMapper getContext(Class<?> type) { + return objectMapper; + } +} diff --git a/service-monitor/src/main/scala/com/yahoo/vespa/service/monitor/SlobrokAndConfigIntersector.scala b/service-monitor/src/main/scala/com/yahoo/vespa/service/monitor/SlobrokAndConfigIntersector.scala index 62f21a7d12c..a39c82bb0e3 100644 --- a/service-monitor/src/main/scala/com/yahoo/vespa/service/monitor/SlobrokAndConfigIntersector.scala +++ b/service-monitor/src/main/scala/com/yahoo/vespa/service/monitor/SlobrokAndConfigIntersector.scala @@ -52,12 +52,12 @@ class SlobrokAndConfigIntersector( private val zoneConfigServerCluster: Map[ApplicationInstanceReference, ApplicationInstance[Void]] = if (multiTenantConfigServerHostNames.isEmpty) Map() else Map( - new ApplicationInstanceReference(syntheticHostedVespaTenantId, configServerApplicationInstanceId ) -> - new ApplicationInstance[Void]( + ApplicationInstanceReference(syntheticHostedVespaTenantId, configServerApplicationInstanceId ) -> + ApplicationInstance[Void]( syntheticHostedVespaTenantId, configServerApplicationInstanceId, - Collections.singleton(new ServiceCluster[Void]( - new ClusterId("zone-config-servers"), + Collections.singleton(ServiceCluster[Void]( + ClusterId("zone-config-servers"), SlobrokServiceNameUtil.configServerServiceType, configServer_ServerInstances(multiTenantConfigServerHostNames) )))) @@ -79,13 +79,10 @@ class SlobrokAndConfigIntersector( } val serviceClustersWithStatus = applicationInstance.serviceClusters.asScala.map { serviceCluster => - val serviceInstancesWithStatus = serviceCluster.serviceInstances().asScala.map { serviceInstance => - new ServiceInstance[ServiceMonitorStatus]( - serviceInstance.configId(), - serviceInstance.hostName(), - monitoredStatus(serviceCluster.serviceType, serviceInstance.configId)) + val serviceInstancesWithStatus = serviceCluster.serviceInstances.asScala.map { serviceInstance => + serviceInstance.copy(serviceStatus = monitoredStatus(serviceCluster.serviceType, serviceInstance.configId)) } - new ServiceCluster[ServiceMonitorStatus](serviceCluster.clusterId(), serviceCluster.serviceType(), serviceInstancesWithStatus.asJava) + serviceCluster.copy(serviceInstances = serviceInstancesWithStatus.asJava) } val applicationInstanceWithStatus: ApplicationInstance[ServiceMonitorStatus] = new ApplicationInstance( applicationInstanceReference.tenantId, @@ -143,8 +140,8 @@ class SlobrokAndConfigIntersector( object SlobrokAndConfigIntersector { private val log = Logger.getLogger(getClass.getName) - val syntheticHostedVespaTenantId = new TenantId("hosted-vespa") - val configServerApplicationInstanceId = new ApplicationInstanceId("zone-config-servers") + val syntheticHostedVespaTenantId = TenantId("hosted-vespa") + val configServerApplicationInstanceId = ApplicationInstanceId("zone-config-servers") implicit class AsJavaOptional[T <: AnyRef](private val option: Option[T]) extends AnyVal { def asJava: Optional[T] = option match { @@ -169,10 +166,10 @@ object SlobrokAndConfigIntersector { val serviceInstances = for { serviceCluster <- applicationInstance.serviceClusters.asScala - serviceInstance <- serviceCluster.serviceInstances().asScala + serviceInstance <- serviceCluster.serviceInstances.asScala } yield serviceInstance - val serviceInstancesGroupedByStatus = serviceInstances.groupBy(_.serviceStatus()) + val serviceInstancesGroupedByStatus = serviceInstances.groupBy(_.serviceStatus) def mkString(services: Traversable[ServiceInstance[ServiceMonitorStatus]]) = services.mkString("\t", "\n\t", "\n") @@ -188,15 +185,15 @@ object SlobrokAndConfigIntersector { private def configServerHostNames(config: ConfigserverConfig): Set[HostName] = //Each Zookeeper server in this config is started by a config server. //Each config server starts a single zookeeper server. - config.zookeeperserver().asScala map {server => new HostName(server.hostname())} toSet + config.zookeeperserver().asScala map {server => HostName(server.hostname())} toSet private def configServer_ServerInstances(multiTenantConfigServerHostNames: Set[HostName]) : java.util.Set[ServiceInstance[Void]] = { - def serviceInstance(hostName: HostName) = new ServiceInstance[Void]( - new ConfigId("configId." + hostName.s), + def serviceInstance(hostName: HostName) = ServiceInstance[Void]( + ConfigId("configId." + hostName.s), hostName, - null) + serviceStatus = null) multiTenantConfigServerHostNames map serviceInstance asJava } diff --git a/service-monitor/src/main/scala/com/yahoo/vespa/service/monitor/config/InstancesObservables.scala b/service-monitor/src/main/scala/com/yahoo/vespa/service/monitor/config/InstancesObservables.scala index 7d27d37ad9f..a78744d184a 100644 --- a/service-monitor/src/main/scala/com/yahoo/vespa/service/monitor/config/InstancesObservables.scala +++ b/service-monitor/src/main/scala/com/yahoo/vespa/service/monitor/config/InstancesObservables.scala @@ -44,7 +44,7 @@ class InstancesObservables(configSourceSet: ConfigSourceSet) { val servicesPerInstance: Observable[Map[ApplicationInstanceReference, ApplicationInstance[Void]]] = lbServicesConfigObservable.map( _.map { case (applicationInstanceReference, x) => val serviceClusters: java.util.Set[ServiceCluster[Void]] = asServiceClusterSet(x) - val applicationInstance = new ApplicationInstance( + val applicationInstance = ApplicationInstance( applicationInstanceReference.tenantId, applicationInstanceReference.applicationInstanceId, serviceClusters) @@ -66,9 +66,9 @@ object InstancesObservables { (tenantIdString, tenantConfig) <- config.tenants() (applicationIdString, applicationConfig) <- tenantConfig.applications() } yield { - val applicationInstanceReference: ApplicationInstanceReference = new ApplicationInstanceReference( - new TenantId(tenantIdString), - new ApplicationInstanceId(applicationIdString)) + val applicationInstanceReference: ApplicationInstanceReference = ApplicationInstanceReference( + TenantId(tenantIdString), + ApplicationInstanceId(applicationIdString)) (applicationInstanceReference, applicationConfig.hosts()) } @@ -94,13 +94,13 @@ object InstancesObservables { (hostName, hostConfig) <- hostsConfigs.view (serviceName, servicesConfig) <- hostConfig.services() } yield { - (new ServiceClusterKey(new ClusterId(servicesConfig.clustername()), new ServiceType(servicesConfig.`type`())), - new ServiceInstance(new ConfigId(servicesConfig.configId()), new HostName(hostName), null.asInstanceOf[Void])) + (ServiceClusterKey(ClusterId(servicesConfig.clustername()), ServiceType(servicesConfig.`type`())), + ServiceInstance(ConfigId(servicesConfig.configId()), HostName(hostName), null.asInstanceOf[Void])) }).groupByKeyWithValue(_._1, _._2) val serviceClusterSet: Set[ServiceCluster[Void]] = serviceInstancesGroupedByCluster.map { case (serviceClusterKey, serviceInstances) => - new ServiceCluster( + ServiceCluster( serviceClusterKey.clusterId, serviceClusterKey.serviceType, serviceInstances.toSet.asJava) diff --git a/service-monitor/src/test/scala/PrintServiceStates.scala b/service-monitor/src/test/scala/PrintServiceStates.scala index e6e02ae7aed..e93cdb95dee 100644 --- a/service-monitor/src/test/scala/PrintServiceStates.scala +++ b/service-monitor/src/test/scala/PrintServiceStates.scala @@ -13,7 +13,7 @@ object PrintServiceStates { def main(args: Array[String]): Unit = { val intersector = new SlobrokAndConfigIntersector( new ConfigSourceSet("tcp/test1-node:19070"), - multiTenantConfigServerHostNames = Set("config-server1", "config-server2").map(s => new HostName(s)), + multiTenantConfigServerHostNames = Set("config-server1", "config-server2") map HostName, new GenerationCounter { override def increment = ??? override def get = 1L |