diff --git a/.gitignore b/.gitignore
index b9f6532..7ede5c8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,3 +6,4 @@
build
out
server/ui
+server/src/main/resources/ui
diff --git a/Jenkinsfile b/Jenkinsfile
new file mode 100644
index 0000000..2f9ffd7
--- /dev/null
+++ b/Jenkinsfile
@@ -0,0 +1,3 @@
+library('jenkins-pipeline')
+
+demoServerUiPipeline("ripple")
\ No newline at end of file
diff --git a/k8s.yml b/k8s.yml
new file mode 100644
index 0000000..82d87a3
--- /dev/null
+++ b/k8s.yml
@@ -0,0 +1,31 @@
+---
+apiVersion: apps/v1
+kind: StatefulSet
+metadata:
+ name: demo-ripple
+ namespace: demo-ripple
+spec:
+ replicas: 1
+ selector:
+ matchLabels:
+ demo: ripple
+ serviceName: demo
+ template:
+ metadata:
+ labels:
+ demo: ripple
+ spec:
+ containers:
+ - image: DOCKER_IMAGE
+ imagePullPolicy: Always
+ name: demo
+ ports:
+ - containerPort: 9001
+ protocol: TCP
+ resources:
+ limits:
+ cpu: "1"
+ memory: 1Gi
+ requests:
+ cpu: "1"
+ memory: 1Gi
\ No newline at end of file
diff --git a/run.sh b/run.sh
index ad47efc..4839ca0 100755
--- a/run.sh
+++ b/run.sh
@@ -1,8 +1,9 @@
cd ui
npm install
npm run compile && npm run bundle
-mkdir -p ../server/ui
+mkdir -p ../server/ui ../server/src/main/resources/ui/
cp -rf index.html dist ../server/ui/
+cp -rf index.html dist ../server/src/main/resources/ui/
cd ../server
./gradlew clean run
diff --git a/server/build.gradle b/server/build.gradle
index a62a342..517cbdf 100644
--- a/server/build.gradle
+++ b/server/build.gradle
@@ -9,6 +9,11 @@ buildscript {
}
}
+plugins {
+ id 'com.google.cloud.tools.jib' version '3.3.1'
+}
+
+
apply plugin: 'java-library'
apply plugin: 'application'
apply plugin: 'nebula.ospackage-application'
@@ -19,6 +24,7 @@ version = project.property('application.version')
mainClassName = 'swim.ripple.RipplePlane'
ext.moduleName = 'swim.ripple'
ext.compilerArgs = ['-Xlint:all']
+ext.swimVersion = project.property('swim.version')
// Build with `gradle -Pno-modules` to force compatibility with legacy JVMs.
def javaVersion = System.getProperty('java.version').split('\\.')
@@ -31,9 +37,9 @@ repositories {
}
dependencies {
- implementation group: 'org.swimos', name: 'swim-recon', version: version
- api group: 'org.swimos', name: 'swim-api', version: version
- implementation group: 'org.swimos', name: 'swim-server', version: version
+ implementation group: 'org.swimos', name: 'swim-recon', version: swimVersion
+ api group: 'org.swimos', name: 'swim-api', version: swimVersion
+ implementation group: 'org.swimos', name: 'swim-server', version: swimVersion
}
afterEvaluate {
@@ -93,6 +99,34 @@ afterEvaluate {
}
}
+ jib {
+ from {
+ image = "openjdk:11"
+ }
+ to {
+ image = "nstream/demo-ripple:${version}"
+ auth {
+ username = "$System.env.REGISTRY_USERNAME"
+ password = "$System.env.REGISTRY_PASSWORD"
+ }
+ }
+ container {
+ mainClass = mainClassName
+ ports = ['9001/tcp']
+ jvmFlags = ['-Dswim.config=/config/server.recon']
+ }
+ extraDirectories {
+ paths {
+ path {
+ // copies a single-file.xml
+ from = 'src/main/resources'
+ into = '/config'
+ includes = ['*.recon']
+ }
+ }
+ }
+ }
+
run {
dependsOn jar
if (useModules) {
diff --git a/server/gradle.properties b/server/gradle.properties
index 7bea8ad..645e15c 100644
--- a/server/gradle.properties
+++ b/server/gradle.properties
@@ -1 +1,2 @@
-application.version=4.0.1
+application.version=1.0.0
+swim.version=4.0.1
diff --git a/server/src/main/java/module-info.java b/server/src/main/java/module-info.java
index e706cc4..b5abb85 100644
--- a/server/src/main/java/module-info.java
+++ b/server/src/main/java/module-info.java
@@ -20,4 +20,5 @@
exports swim.ripple;
provides swim.api.plane.Plane with swim.ripple.RipplePlane;
+ provides swim.kernel.Kernel with swim.ripple.RippleUiRouter;
}
diff --git a/server/src/main/java/swim/ripple/RippleUiRouter.java b/server/src/main/java/swim/ripple/RippleUiRouter.java
new file mode 100644
index 0000000..9a6287a
--- /dev/null
+++ b/server/src/main/java/swim/ripple/RippleUiRouter.java
@@ -0,0 +1,101 @@
+// Copyright 2015-2022 Swim.inc
+//
+// 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 swim.ripple;
+
+import swim.kernel.KernelProxy;
+import swim.structure.Value;
+import swim.uri.UriPath;
+import swim.web.WebRequest;
+import swim.web.WebResponse;
+import swim.web.WebRoute;
+import swim.web.route.ResourceDirectoryRoute;
+
+/**
+ * SwimOS kernel module for routing HTTP requests for the bundled UI.
+ */
+public class RippleUiRouter extends KernelProxy {
+ final double kernelPriority;
+ final WebRoute uiRoute;
+
+ public RippleUiRouter(double kernelPriority) {
+ this.kernelPriority = kernelPriority;
+ this.uiRoute = new ResourceDirectoryRoute(getClass().getClassLoader(), UriPath.parse("ui/"), "index.html");
+ }
+
+ public RippleUiRouter() {
+ this(KERNEL_PRIORITY);
+ }
+
+ @Override
+ public final double kernelPriority() {
+ return this.kernelPriority;
+ }
+
+ @Override
+ public WebResponse routeRequest(WebRequest request) {
+ final WebResponse response = this.uiRoute.routeRequest(request);
+ if (response.isAccepted()) {
+ return response;
+ } else {
+ return super.routeRequest(request);
+ }
+ }
+
+ @Override
+ public void trace(Object message) {
+ // Use this hook to intercept and forward trace log messages
+ }
+
+ @Override
+ public void debug(Object message) {
+ // Use this hook to intercept and forward debug log messages
+ }
+
+ @Override
+ public void info(Object message) {
+ super.info(message);
+ // Use this hook to intercept and forward info log messages
+ }
+
+ @Override
+ public void warn(Object message) {
+ super.warn(message);
+ // Use this hook to intercept and forward warning log messages
+ }
+
+ @Override
+ public void error(Object message) {
+ super.error(message);
+ // Use this hook to intercept and forward error log messages
+ }
+
+ @Override
+ public void fail(Object message) {
+ super.fail(message);
+ // Use this hook to intercept and forward failure log messages
+ }
+
+ private static final double KERNEL_PRIORITY = 100.0;
+
+ public static RippleUiRouter fromValue(Value moduleConfig) {
+ final Value header = moduleConfig.getAttr("kernel");
+ final String kernelClassName = header.get("class").stringValue(null);
+ if (kernelClassName == null || RippleUiRouter.class.getName().equals(kernelClassName)) {
+ final double kernelPriority = header.get("priority").doubleValue(KERNEL_PRIORITY);
+ return new RippleUiRouter(kernelPriority);
+ }
+ return null;
+ }
+}
diff --git a/server/src/main/resources/server.recon b/server/src/main/resources/server.recon
index bf009b4..da53d03 100644
--- a/server/src/main/resources/server.recon
+++ b/server/src/main/resources/server.recon
@@ -1,5 +1,6 @@
@kernel(class: 'swim.store.db.DbStoreKernel', optional: true)
@kernel(class: 'swim.reflect.ReflectKernel', optional: true)
+@kernel(class: "swim.ripple.RippleUiRouter")
ripple: @fabric {
@plane(class: "swim.ripple.RipplePlane")
@@ -14,7 +15,6 @@ ripple: @fabric {
@web(port: 9001) {
space: "ripple"
- documentRoot: "../ui/"
@websocket {
serverCompressionLevel: 0# -1 = default; 0 = off; 1-9 = deflate level
clientCompressionLevel: 0# -1 = default; 0 = off; 1-9 = deflate level
diff --git a/ui/index.html b/ui/index.html
index 0c284fc..a44cd00 100644
--- a/ui/index.html
+++ b/ui/index.html
@@ -22,7 +22,30 @@
var host = documentUri.query().get("host");
var room = documentUri.fragmentIdentifier() || "wall";
-var hostUri = host || "warp://localhost:9001";
+const baseUri = swim.Uri.parse(document.location.href);
+const hostParam = baseUri.host().toString();
+const schemeParam = baseUri.scheme().toString();
+const portParam = baseUri.port();
+const warpScheme = schemeParam === "https" ? "warps":"warp"
+
+let warpHost;
+
+if(hostParam.endsWith("swim.services")) {
+ warpHost = "ripple.swim.services"
+} else if(hostParam.endsWith("nstream-demo.io")) {
+ warpHost = "ripple.services.nstream-demo.io"
+} else {
+ warpHost = hostParam;
+}
+
+let hostUri;
+
+if (portParam === undefined) {
+ hostUri = `${warpScheme}://${warpHost}`
+} else {
+ hostUri = `${warpScheme}://${warpHost}:${portParam.toString()}`
+}
+
var nodeUri = swim.UriPath.from("mirror", room).toString();
var nodeRef = swim.client.nodeRef(hostUri, nodeUri);
var mirrorController = new swim.SwimMirrorViewController(nodeRef);
@@ -32,5 +55,13 @@
canvas.append(mirror);
+
+