Commit 249b60a7 authored by Mathieu's avatar Mathieu

To scala 2.13

parent 0378f520
......@@ -19,7 +19,8 @@ object Application extends App {
def usage =
"""OpenMOLE-connect application options:
|[--secret secret] specify the keycloak secret
|[--secret secret] the token generation secret
|[-kubeOff ] do not request kubernetes (limited usage).
"""
def parse(args: List[String], c: Config = Config()): Config = {
......
......@@ -4,20 +4,20 @@ import org.scalajs.sbtplugin.ScalaJSPlugin.autoImport._
import scala.collection.mutable
val scalatraVersion = "2.6.5"
val jettyVersion = "9.4.19.v20190610"
val json4sVersion = "3.6.7"
val scalatagsVersion = "0.7.0"
val scaladgetVersion = "1.3.0-SNAPSHOT"
val scalajsDomVersion = "0.9.7"
val scalaJWTVersion = "4.0.0"
val rosHttpVersion = "2.2.4"
val skuberVersion = "2.2.0"
val httpComponentsVersion = "4.5.9"
val slickVersion = "3.3.1"
val scalatraVersion = "2.7.0"
val jettyVersion = "9.4.28.v20200408"
val json4sVersion = "3.6.8"
val scalatagsVersion = "0.9.1"
val scaladgetVersion = "1.3.3"
val scalajsDomVersion = "1.0.0"
val scalaJWTVersion = "4.2.0"
val rosHttpVersion = "3.0.0"
val skuberVersion = "2.4.0"
val httpComponentsVersion = "4.5.12"
val slickVersion = "3.3.2"
val h2Version = "1.4.200"
val autowireVersion = "0.2.6"
val boopickleVersion = "1.2.6"
val autowireVersion = "0.3.2"
val boopickleVersion = "1.3.2"
val Resolvers = Seq(Resolver.sonatypeRepo("snapshots"),
"Typesafe repository" at "http://repo.typesafe.com/typesafe/releases/",
......@@ -27,7 +27,7 @@ val Resolvers = Seq(Resolver.sonatypeRepo("snapshots"),
lazy val defaultSettings = Seq(
organization := "openmole.org",
version := "0.1.0-SNAPSHOT",
scalaVersion := "2.12.8",
scalaVersion := "2.13.2",
resolvers := Resolvers
)
......@@ -39,8 +39,8 @@ lazy val client = project.in(file("client")) enablePlugins (ExecNpmPlugin) setti
skip in packageJSDependencies := false,
libraryDependencies ++= Seq(
"com.lihaoyi" %%% "scalatags" % scalatagsVersion,
"fr.iscpif.scaladget" %%% "tools" % scaladgetVersion,
"fr.iscpif.scaladget" %%% "bootstrapnative" % scaladgetVersion,
"org.openmole.scaladget" %%% "tools" % scaladgetVersion,
"org.openmole.scaladget" %%% "bootstrapnative" % scaladgetVersion,
"org.scala-js" %%% "scalajs-dom" % scalajsDomVersion,
"com.lihaoyi" %%% "autowire" % autowireVersion,
"io.suzaku" %%% "boopickle" % boopickleVersion
......@@ -79,7 +79,8 @@ lazy val application = project.in(file("application")) settings (defaultSettings
Cmd("USER", "1001:0"),
ExecCmd("ENTRYPOINT", "/opt/docker/bin/application")
),
packageName in Docker := "openmole-connect"
packageName in Docker := "openmole-connect",
organization in Docker := "openmole"
)
......
......@@ -20,11 +20,8 @@ import scala.scalajs.js.typedarray.{ArrayBuffer, TypedArrayBuffer}
import scaladget.bootstrapnative.bsn._
import scaladget.tools.{ModifierSeq, _}
import scalatags.JsDom.all._
import scala.scalajs.js.timers._
import ConnectUtils._
import Utils._
import scala.scalajs.js.Date
object AdminPanel {
......@@ -175,8 +172,8 @@ object AdminPanel {
)
val editablePanel = div(maxWidth := 1000, margin := "40px auto")(
img(src := "img/logo.png", css.adminLogoStyle),
Utils.logoutItem(styles.display.flex, flexDirection.row, justifyContent.flexEnd),
img(src := "img/logo.png", Css.adminLogoStyle),
ConnectUtils.logoutItem(styles.display.flex, flexDirection.row, justifyContent.flexEnd),
div(styles.display.flex, flexDirection.row, justifyContent.flexStart, marginLeft := 50, marginBottom := 20, marginTop := 80)(
addUserButton(styles.display.flex, flexDirection.row, styles.justifyContent.flexEnd),
refreshButton(styles.display.flex, flexDirection.row, styles.justifyContent.flexEnd)
......
......@@ -8,7 +8,7 @@ import scalatags.JsDom.all._
import scala.scalajs.js.Date
object Utils {
object ConnectUtils {
val logoutLogo = toClass("glyphicon glyphicon-off")
......@@ -18,10 +18,10 @@ object Utils {
color := "#337ab7"
)
val logoutItem =
def logoutItem =
div(logoutLogo, itemStyle, onclick := { () org.scalajs.dom.window.location.href = s"${org.scalajs.dom.window.location.href}logout" })
implicit class FromInt(i: Int) {
implicit class FromDouble(i: Double) {
def toDayString = i match {
case 0 => "Mon"
case 1 => "Tue"
......
......@@ -69,10 +69,10 @@ object Connection {
val render = {
div(
div(css.connectionTabOverlay)(
div(Css.connectionTabOverlay)(
div(
img(src := "img/logo.png", css.openmoleLogo),
div(css.connectionFormStyle)(
img(src := "img/logo.png", Css.openmoleLogo),
div(Css.connectionFormStyle)(
connectionForm
)
)
......
......@@ -18,6 +18,8 @@ import scaladget.bootstrapnative.bsn._
import scaladget.tools.{ModifierSeq, _}
import scalatags.JsDom.all._
import ConnectUtils._
object UserPanel {
lazy val rowFlex = Seq(styles.display.flex, flexDirection.row, justifyContent.spaceAround)
......@@ -57,8 +59,8 @@ object UserPanel {
upserting = (userData: UserData) => upsert(userData)).build
div(maxWidth := 1000, margin := "40px auto")(
img(src := "img/logo.png", css.adminLogoStyle),
Utils.logoutItem(styles.display.flex, flexDirection.row, justifyContent.flexEnd),
img(src := "img/logo.png", Css.adminLogoStyle),
ConnectUtils.logoutItem(styles.display.flex, flexDirection.row, justifyContent.flexEnd),
div(styles.display.flex, flexDirection.row, justifyContent.flexStart, marginLeft := 50, marginBottom := 20, marginTop := 80)(
// div(width := 350, margin.auto, paddingTop := 200 )(
panel)
......@@ -84,7 +86,7 @@ object UserPanel {
editableRole: Boolean,
expanded: Boolean = false,
editing: Boolean = false,
upserting: (UserData) => Unit = (u: UserData) => Unit
upserting: (UserData) => Unit = (u: UserData) => ()
): GroupCell = {
def roleStyle(s: Role) =
......
......@@ -3,7 +3,7 @@ package org.openmoleconnect.client
import scalatags.JsDom.all._
import scaladget.tools._
package object css {
object Css {
lazy val connectionTabOverlay: ModifierSeq = Seq(
display.flex,
flexDirection.column,
......
resolvers += "Typesafe repository" at "http://repo.typesafe.com/typesafe/releases/"
addSbtPlugin("org.scala-js" % "sbt-scalajs" % "0.6.28")
addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.1.0")
addSbtPlugin("org.scalatra.sbt" % "sbt-scalatra" % "1.0.3")
addSbtPlugin("org.scalatra.sbt" % "sbt-scalatra" % "1.0.4")
addSbtPlugin("fr.iscpif" % "scalajs-execnpm" % "0.7")
addSbtPlugin("org.openmole" % "scalajs-execnpm" % "0.10")
addSbtPlugin("com.typesafe.sbt" % "sbt-native-packager" % "1.3.25")
addSbtPlugin("com.typesafe.sbt" % "sbt-native-packager" % "1.7.2")
......@@ -6,7 +6,7 @@ import java.nio.ByteBuffer
import org.openmoleconnect.server.JWT._
import org.scalatra._
import scala.collection.JavaConversions._
import scala.collection.JavaConverters._
import scalatags.Text.all._
import scalatags.Text.{all => tags}
......@@ -36,10 +36,10 @@ class ConnectServlet(arguments: ConnectServer.ServletArguments) extends Scalatra
val httpClient = HttpClients.createDefault()
def uriBuilder(hostIP: String, path: String) = new URIBuilder()
def uriBuilder(hostIP: String, path: String, port: Int =80) = new URIBuilder()
.setScheme("http")
.setHost(hostIP)
.setPort(80)
.setPort(port)
.setPath(path)
def uri(hostIP: String, path: String) = uriBuilder(hostIP, path).build()
......@@ -113,7 +113,7 @@ class ConnectServlet(arguments: ConnectServer.ServletArguments) extends Scalatra
httpPost.setEntity(new InputStreamEntity(is))
val filtred = Seq("Content-Length")
request.getHeaderNames.filter(n => !filtred.contains(n)).foreach {
request.getHeaderNames.asScala.filter(n => !filtred.contains(n)).foreach {
n => httpPost.setHeader(n, request.getHeader(n))
}
......@@ -191,6 +191,7 @@ class ConnectServlet(arguments: ConnectServer.ServletArguments) extends Scalatra
val host = {
if (arguments.kubeOff) Host(uuid, None)
else {
println("INgress :: " + K8sService.ingressIP)
Host(uuid, K8sService.hostIP(uuid))
}
}
......@@ -233,7 +234,7 @@ class ConnectServlet(arguments: ConnectServer.ServletArguments) extends Scalatra
tokenData.host.hostIP.map { hip =>
val u = uriBuilder(hip, path)
request.getParameterNames.foreach { pn =>
request.getParameterNames.asScala.foreach { pn =>
u.addParameter(pn, request.getParameter(pn))
}
......@@ -247,6 +248,7 @@ class ConnectServlet(arguments: ConnectServer.ServletArguments) extends Scalatra
def getFromURI(uri: URI, requestContentType: String): Int = {
println("GET FROM URI " + uri.toString)
val httpGet = new HttpGet(uri)
httpGet.setHeader("Content-Type", requestContentType)
......
......@@ -94,7 +94,9 @@ object DB {
def initDB = {
runTransaction(userTable.schema.createIfNotExists)
if (DB.users.isEmpty) {
DB.addUser("admin", DB.Email("admin@admin.com"), DB.Password("admin"), Utils.openmoleversion.stable, JWT.now, DB.admin, UUID("foo-123-567-foo"))
DB.addUser("admin", DB.Email("admin@admin.com"), DB.Password("admin"), Utils.openmoleversion.stable, JWT.now, DB.admin, UUID("admin-123-567-admin"))
DB.addUser("foo", DB.Email("foo@foo.com"), DB.Password("foo"), Utils.openmoleversion.stable, JWT.now, DB.simpleUser, UUID("foo"))
DB.addUser("toto", DB.Email("toto@toto.com"), DB.Password("toto"), Utils.openmoleversion.stable, JWT.now, DB.simpleUser, UUID("openmole-toto"))
}
}
......
package org.openmoleconnect.server
import java.time.temporal.ChronoField
import org.openmoleconnect.server.DB.UUID
import shared.Data
import skuber._
import skuber.json.ext.format._
import skuber.json.format._
import akka.actor.ActorSystem
import skuber.json.format._
import akka.stream.ActorMaterializer
import shared.Data._
import skuber.api.client.KubernetesClient
import skuber.ext.Deployment
import org.openmoleconnect.server.Utils._
import skuber.ext.{Deployment, Ingress, IngressList}
import scala.concurrent.duration._
import scala.concurrent.{Await, Future}
import scala.util.{Failure, Success, Try}
import scala.concurrent.ExecutionContext
object K8sService {
def listPods = {
withK8s { k8s =>
implicit val system = ActorSystem()
implicit val materializer = ActorMaterializer()
implicit val dispatcher = system.dispatcher
// val k8s = k8sInit
Await.result (
withK8s { k8s =>
implicit val system = ActorSystem()
implicit val materializer = ActorMaterializer()
implicit val dispatcher = system.dispatcher
val allPodsMapFut: Future[Map[String, PodList]] = k8s listByNamespace[PodList]()
val allPodsFuture: Future[List[Pod]] = allPodsMapFut map { allPodsMap =>
allPodsMap.values.flatMap(_.items).toList
}
val allPodsMapFut: Future[Map[String, PodList]] = k8s.listByNamespace[PodList]()
val allPodsFuture: Future[List[Pod]] = allPodsMapFut map { allPodsMap =>
allPodsMap.values.flatMap(_.items).toList
}
def listPods0(pods: List[Pod]) = {
pods.flatMap { pod: Pod =>
val name = pod.name
val ns = pod.namespace
for {
stat <- pod.status.toList
containerStat <- stat.containerStatuses
status <- containerStat.state
restarts <- stat.containerStatuses.headOption
createTime <- pod.metadata.creationTimestamp
podIP <- stat.podIP
} yield {
val st: Status = status match {
case Container.Waiting(reason) => Data.Waiting(reason.getOrElse(""))
case _: Container.Running => Data.Running()
case Container.Terminated(_, _, _, message, _, finishedAt, _) => Data.Terminated(message.getOrElse(""), finishedAt.map {
_.toEpochSecond
}.getOrElse(0L))
}
PodInfo(pod.name, st.value, restarts.restartCount, createTime.toEpochSecond, podIP, DB.email(UUID(pod.metadata.name)).map {
_.value
})
def listPods0(pods: List[Pod]) = {
pods.flatMap { pod: Pod =>
val name = pod.name
val ns = pod.namespace
for {
stat <- pod.status.toList
containerStat <- stat.containerStatuses
status <- containerStat.state
restarts <- stat.containerStatuses.headOption
createTime <- pod.metadata.creationTimestamp
podIP <- stat.podIP
} yield {
val st: Status = status match {
case Container.Waiting(reason) => Data.Waiting(reason.getOrElse(""))
case _: Container.Running => Data.Running()
case Container.Terminated(_, _, _, message, _, finishedAt, _) => Data.Terminated(message.getOrElse(""), finishedAt.map {
_.toEpochSecond
}.getOrElse(0L))
}
PodInfo(pod.name, st.value, restarts.restartCount, createTime.toEpochSecond, podIP, DB.email(UUID(pod.metadata.name)).map {
_.value
})
}
}
}
allPodsFuture map { pods => listPods0(pods) }
allPodsFuture map { pods => listPods0(pods) }
}, Duration.Inf)
}
}
def withK8s[T](kubeAction: KubernetesClient => Future[T]) = {
def withK8s[T](kubeAction: KubernetesClient => Future[T]) = {
implicit val system = ActorSystem()
implicit val materializer = ActorMaterializer()
implicit val dispatcher = system.dispatcher
val k8s = k8sInit
kubeAction(k8s)
implicit val system = ActorSystem()
implicit val materializer = ActorMaterializer()
implicit val dispatcher = system.dispatcher
val k8s = k8sInit
Await.result(kubeAction(k8s), Duration.Inf)
}
def getIngress = withK8s { k8s =>
implicit val system = ActorSystem()
implicit val materializer = ActorMaterializer()
implicit val dispatcher = system.dispatcher
val allIngressMapFut: Future[ListResource[Ingress]] = k8s listInNamespace[IngressList] ("ingress-nginx")
val allIngressFuture: Future[List[Ingress]] = allIngressMapFut map { allIngressMap =>
allIngressMap.items
}
def withK8sToResult(k8Action: String)(kubeAction: KubernetesClient => Future[_ <: ObjectResource]): K8ActionResult = {
implicit val system = ActorSystem()
implicit val materializer = ActorMaterializer()
implicit val dispatcher = system.dispatcher
val k8s = k8sInit(K8SConfiguration.useLocalProxyDefault)
Try {
Await.result({
kubeAction(k8s)
}, Duration.Inf)
} match {
case Success(o: ObjectResource) => K8Success(s"$k8Action successfully completed " + o.name + " // " + o.metadata.generateName)
case Failure(t: Throwable) => K8Failure(t.getMessage, t.toStackTrace)
def listIngress(ingresses: List[Ingress]) = ingresses.headOption
allIngressFuture map { ingresses => listIngress(ingresses) }
}
def ingressIP: Option[String] =
getIngress.flatMap { ing =>
ing.status.flatMap {
_.loadBalancer.flatMap {
_.ingress.headOption.flatMap {
_.ip
}
}
}
}
def deployOpenMOLE(uuid: UUID) = {
withK8sToResult("OpenMOLE depolyment for user " + DB.email(uuid).map {
_.value
}.getOrElse("")) {
k8s =>
// def withK8sToResult(k8Action: String)(kubeAction: KubernetesClient => Future[_ <: ObjectResource]): K8ActionResult = {
//
// implicit val system = ActorSystem()
// implicit val materializer = ActorMaterializer()
// implicit val dispatcher = system.dispatcher
// val k8s = k8sInit(K8SConfiguration.useLocalProxyDefault)
//
// Try {
// Await.result({
// kubeAction(k8s)
// }, Duration.Inf)
// } match {
// case Success(o: ObjectResource) => K8Success(s"$k8Action successfully completed " + o.name + " // " + o.metadata.generateName)
// case Failure(t: Throwable) => K8Failure(t.getMessage, t.toStackTrace)
// }
// }
// implicit class OResourceToK8ActionResult[OR <: ObjectResource](o: OR) {
// def toK8ActionResult = o match {
// case Success(o: ObjectResource) => K8Success(s"$k8Action successfully completed " + o.name + " // " + o.metadata.generateName)
// case Failure(t: Throwable) => K8Failure(t.getMessage, t.toStackTrace)
// }
//}
def deployOpenMOLE(uuid: UUID) = {
withK8s { k8s =>
val openmoleLabel = "app" -> "openmole"
val openmoleContainer = Container(name = "openmole", image = "openmole/openmole", command = List("bin/bash", "-c", "openmole --port 80 --password password --http --remote")).exposePort(80)
val openmoleTemplate = Pod.Template.Spec(ObjectMeta(name = uuid.value, namespace = "ingress-nginx"))
val openmoleTemplate = Pod.Template.Spec(ObjectMeta(name = uuid.value, namespace = "default"))
.addContainer(openmoleContainer)
.addLabel(openmoleLabel)
//.named("openmole")
......@@ -120,43 +142,48 @@ object K8sService {
println("\nCreating openmole deployment")
k8s create openmoleDeployment
}
}
}
def deployIfNotDeployedYet(uuid: UUID) = {
if (!isDeploymentExists(uuid))
deployOpenMOLE(uuid)
def deployIfNotDeployedYet(uuid: UUID) = {
if (!isDeploymentExists(uuid))
deployOpenMOLE(uuid)
}
}
private def podInfo(uuid: UUID)
private def podInfo(uuid: UUID)
=
{
=
// import monix.execution.Scheduler.Implicits.global
listPods.find {
_.name.contains(uuid.value)
}
// import monix.execution.Scheduler.Implicits.global
val lp = listPods
println("pods " + lp)
lp.find {
_.name.contains(uuid.value)
}
}
def isServiceUp(uuid: UUID): Boolean = {
podInfo(uuid).map {
_.status
} == Some(Running)
}
def isServiceUp(uuid: UUID): Boolean = {
podInfo(uuid).map {
_.status
} == Some(Running)
}
def isDeploymentExists(uuid: UUID) = podInfo(uuid).isDefined
def isDeploymentExists(uuid: UUID) = podInfo(uuid).isDefined
def podInfos: Seq[PodInfo] = {
def podInfos: Seq[PodInfo] = {
for {
uuid <- DB.uuids
podInfo <- podInfo(uuid)
} yield (podInfo)
}
for {
uuid <- DB.uuids
podInfo <- podInfo(uuid)
} yield (podInfo)
}
def hostIP(uuid: UUID) = {
podInfo(uuid).map {
_.podIP
def hostIP(uuid: UUID) = {
podInfo(uuid).map {
_.podIP
}
}
}
}
}
\ No newline at end of file
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment