Skip to content

Commit

Permalink
Update to Ciris 2.x (#70)
Browse files Browse the repository at this point in the history
  • Loading branch information
Rui Morais authored Jun 1, 2021
1 parent 7778974 commit cefc4df
Show file tree
Hide file tree
Showing 6 changed files with 123 additions and 106 deletions.
35 changes: 32 additions & 3 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,41 @@ lazy val metadataSettings = Seq(

lazy val scalaSettings = Seq(
scalaVersion := "2.13.5",
crossScalaVersions := Seq(scalaVersion.value, "2.12.13")
crossScalaVersions := Seq(scalaVersion.value, "2.12.13"),
scalacOptions ++= {
val commonScalacOptions =
Seq(
"-deprecation",
"-encoding",
"UTF-8",
"-feature",
"-unchecked",
// "-Xfatal-warnings",
"-language:higherKinds",
"-Xlint",
"-Ywarn-dead-code",
"-Ywarn-numeric-widen",
"-Ywarn-value-discard",
"-Ywarn-unused",
"Wunused:nowarn",
"-Xlint:unused"
)

val scala212ScalacOptions =
if (scalaVersion.value.startsWith("2.12")) {
Seq("-Yno-adapted-args", "-Ypartial-unification")
} else Seq()

commonScalacOptions ++
scala212ScalacOptions
},
Compile / console / scalacOptions --= Seq("-Xlint", "-Ywarn-unused")
)

libraryDependencies ++= Seq(
"is.cir" %% "ciris" % "1.2.1",
"io.kubernetes" % "client-java" % "12.0.0"
"io.kubernetes" % "client-java" % "12.0.0",
"io.kubernetes" % "client-java-api" % "12.0.0",
"is.cir" %% "ciris" % "2.0.0-RC3"
)

licenses += ("MIT", url("https://opensource.org/licenses/MIT"))
Expand Down
72 changes: 35 additions & 37 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ To get started with [sbt](https://www.scala-sbt.org), simply add the following l
```scala
resolvers += "Artifactory" at "https://kaluza.jfrog.io/artifactory/maven/"

libraryDependencies += "com.ovoenergy" %% "ciris-kubernetes" % "1.2.4"
libraryDependencies += "com.ovoenergy" %% "ciris-kubernetes" % "2.0.0"
```

The library is published for Scala 2.12 and 2.13.
Expand All @@ -23,7 +23,7 @@ The library supports Kubernetes secrets and config maps.
Start with `import ciris.kubernetes._` and then set the namespace for your secrets with `secretInNamespace`. You can then load secrets by specifying the secret name. If there is more than one entry for the secret, you can also specify the key to retrieve.

```scala
import cats.effect.{Blocker, ExitCode, IO, IOApp}
import cats.effect.{ExitCode, IO, IOApp}
import cats.implicits._
import ciris.kubernetes._
import ciris.Secret
Expand All @@ -37,25 +37,24 @@ final case class Config(

object Main extends IOApp {
def run(args: List[String]): IO[ExitCode] =
Blocker[IO].use { blocker =>
val config =
secretInNamespace("secrets", blocker).flatMap { secret =>
(
secret("apiKey").secret, // Key can be omitted if secret has only one entry
secret("username"),
secret("defaults", "timeoutt").as[Int] // Key is necessary if secret has multiple entries
).parMapN { (apiKey, username, timeout) =>
Config(
appName = "my-api",
apiKey = apiKey,
username = username,
timeout = timeout
)
}

val config =
secretInNamespace[IO]("secrets").flatMap { secret =>
(
secret("apiKey").secret, // Key can be omitted if secret has only one entry
secret("username"),
secret("defaults", "timeoutt").as[Int] // Key is necessary if secret has multiple entries
).parMapN { (apiKey, username, timeout) =>
Config(
appName = "my-api",
apiKey = apiKey,
username = username,
timeout = timeout
)
}
}

config.load[IO].as(ExitCode.Success)
}
config.load[IO].as(ExitCode.Success)
}
```

Expand All @@ -74,7 +73,7 @@ In the example above, the `apiKey` secret is missing, the `username` secret has
Config maps are supported in a similar fashion to how secrets are supported.

```scala
import cats.effect.{Blocker, ExitCode, IO, IOApp}
import cats.effect.{ExitCode, IO, IOApp}
import cats.implicits._
import ciris.kubernetes._
import ciris.Secret
Expand All @@ -88,25 +87,24 @@ final case class Config(

object Main extends IOApp {
def run(args: List[String]): IO[ExitCode] =
Blocker[IO].use { blocker =>
val config =
configMapInNamespace("pizza", blocker).flatMap { configMap =>
(
configMap("pizzaBrand"), // Key can be omitted if config map has only one entry
configMap("delivery", "radius").as[Int], // Key is necessary if config map has multiple entries
configMap("delivery", "charge").as[Boolean]
).parMapN { (pizzaBrand, deliveryRadius, isDeliveryCharge) =>
Config(
appName = "my-pizza-api",
pizzaBrand = pizzaBrand,
deliveryRadius = deliveryRadius,
isDeliveryCharge = isDeliveryCharge
)
}
val config =
configMapInNamespace[IO]("pizza").flatMap { configMap =>
(
configMap("pizzaBrand"), // Key can be omitted if config map has only one entry
configMap("delivery", "radius").as[Int], // Key is necessary if config map has multiple entries
configMap("delivery", "charge").as[Boolean]
).parMapN { (pizzaBrand, deliveryRadius, isDeliveryCharge) =>
Config(
appName = "my-pizza-api",
pizzaBrand = pizzaBrand,
deliveryRadius = deliveryRadius,
isDeliveryCharge = isDeliveryCharge
)
}
}

config.load[IO].as(ExitCode.Success)

config.load[IO].as(ExitCode.Success)
}
}
```

Expand Down
19 changes: 9 additions & 10 deletions src/main/scala/ciris/ConfigMapInNamespace.scala
Original file line number Diff line number Diff line change
@@ -1,23 +1,22 @@
package ciris.kubernetes

import cats.effect.Blocker
import ciris.ConfigValue
import io.kubernetes.client.openapi.ApiClient

sealed abstract class ConfigMapInNamespace {
def apply(name: String): ConfigValue[String]
sealed abstract class ConfigMapInNamespace[F[_]] {
def apply(name: String): ConfigValue[F, String]

def apply(name: String, key: String): ConfigValue[String]
def apply(name: String, key: String): ConfigValue[F, String]
}

private[kubernetes] final object ConfigMapInNamespace {
final def apply(namespace: String, client: ApiClient, blocker: Blocker): ConfigMapInNamespace =
new ConfigMapInNamespace {
override final def apply(name: String): ConfigValue[String] =
configMap(client, name, namespace, None, blocker)
final def apply[F[_]](namespace: String, client: ApiClient): ConfigMapInNamespace[F] =
new ConfigMapInNamespace[F] {
override final def apply(name: String): ConfigValue[F, String] =
configMap(client, name, namespace, None)

override final def apply(name: String, key: String): ConfigValue[String] =
configMap(client, name, namespace, Some(key), blocker)
override final def apply(name: String, key: String): ConfigValue[F, String] =
configMap(client, name, namespace, Some(key))

override final def toString: String =
s"ConfigMapInNamespace($namespace)"
Expand Down
19 changes: 9 additions & 10 deletions src/main/scala/ciris/SecretInNamespace.scala
Original file line number Diff line number Diff line change
@@ -1,23 +1,22 @@
package ciris.kubernetes

import cats.effect.Blocker
import ciris.ConfigValue
import io.kubernetes.client.openapi.ApiClient

sealed abstract class SecretInNamespace {
def apply(name: String): ConfigValue[String]
sealed abstract class SecretInNamespace[F[_]] {
def apply(name: String): ConfigValue[F, String]

def apply(name: String, key: String): ConfigValue[String]
def apply(name: String, key: String): ConfigValue[F, String]
}

private[kubernetes] final object SecretInNamespace {
final def apply(namespace: String, client: ApiClient, blocker: Blocker): SecretInNamespace =
new SecretInNamespace {
override final def apply(name: String): ConfigValue[String] =
secret(client, name, namespace, None, blocker)
final def apply[F[_]](namespace: String, client: ApiClient): SecretInNamespace[F] =
new SecretInNamespace[F] {
override final def apply(name: String): ConfigValue[F, String] =
secret(client, name, namespace, None)

override final def apply(name: String, key: String): ConfigValue[String] =
secret(client, name, namespace, Some(key), blocker)
override final def apply(name: String, key: String): ConfigValue[F, String] =
secret(client, name, namespace, Some(key))

override final def toString: String =
s"SecretInNamespace($namespace)"
Expand Down
82 changes: 37 additions & 45 deletions src/main/scala/ciris/kubernetes.scala
Original file line number Diff line number Diff line change
@@ -1,78 +1,72 @@
package ciris

import cats.effect.Blocker
import cats.implicits._
import io.kubernetes.client.openapi.{ApiClient, ApiException}
import io.kubernetes.client.openapi.ApiClient
import io.kubernetes.client.openapi.ApiException
import io.kubernetes.client.openapi.apis.CoreV1Api
import io.kubernetes.client.util.Config

import java.nio.charset.StandardCharsets
import scala.collection.JavaConverters._

package object kubernetes {
final def configMapInNamespace(
namespace: String,
blocker: Blocker
): ConfigValue[ConfigMapInNamespace] =
defaultApiClient(blocker).map(configMapInNamespace(namespace, blocker, _))
final def configMapInNamespace[F[_]](
namespace: String
): ConfigValue[F, ConfigMapInNamespace[F]] =
defaultApiClient.map(configMapInNamespace(namespace, _))

final def configMapInNamespace(
final def configMapInNamespace[F[_]](
namespace: String,
blocker: Blocker,
client: ApiClient
): ConfigMapInNamespace =
ConfigMapInNamespace(namespace, client, blocker)
): ConfigMapInNamespace[F] =
ConfigMapInNamespace(namespace, client)

final def defaultApiClient(blocker: Blocker): ConfigValue[ApiClient] =
ConfigValue.blockOn(blocker) {
final def defaultApiClient[F[_]]: ConfigValue[F, ApiClient] =
ConfigValue.blocking {
ConfigValue.suspend {
val client = Config.defaultClient()
ConfigValue.default(client)
}
}

final def secretInNamespace(
namespace: String,
blocker: Blocker
): ConfigValue[SecretInNamespace] =
defaultApiClient(blocker).map(secretInNamespace(namespace, blocker, _))
final def secretInNamespace[F[_]](
namespace: String
): ConfigValue[F, SecretInNamespace[F]] =
defaultApiClient.map(secretInNamespace(namespace, _))

final def secretInNamespace(
final def secretInNamespace[F[_]](
namespace: String,
blocker: Blocker,
client: ApiClient
): SecretInNamespace =
SecretInNamespace(namespace, client, blocker)
): SecretInNamespace[F] =
SecretInNamespace(namespace, client)

private[kubernetes] final def secret(
private[kubernetes] final def secret[F[_]](
client: ApiClient,
name: String,
namespace: String,
key: Option[String],
blocker: Blocker
): ConfigValue[String] = {
key: Option[String]
): ConfigValue[F, String] = {
val configKey = secretConfigKey(namespace, name, key)
secretEntries(client, configKey, name, namespace, blocker)
secretEntries(client, configKey, name, namespace)
.flatMap(selectConfigEntry(key, configKey, _))
.map(new String(_, StandardCharsets.UTF_8))
}

private[kubernetes] final def configMap(
private[kubernetes] final def configMap[F[_]](
client: ApiClient,
name: String,
namespace: String,
key: Option[String],
blocker: Blocker
): ConfigValue[String] = {
key: Option[String]
): ConfigValue[F, String] = {
val configKey = configMapConfigKey(namespace, name, key)
configMapEntries(client, configKey, name, namespace, blocker)
configMapEntries(client, configKey, name, namespace)
.flatMap(selectConfigEntry(key, configKey, _))
}

private[this] final def selectConfigEntry[A](
private[this] final def selectConfigEntry[F[_], A](
key: Option[String],
configKey: ConfigKey,
entries: Map[String, A]
): ConfigValue[A] = {
): ConfigValue[F, A] = {

key match {
case Some(key) =>
Expand All @@ -95,14 +89,13 @@ package object kubernetes {
}
}

private[this] final def secretEntries(
private[this] final def secretEntries[F[_]](
client: ApiClient,
configKey: ConfigKey,
name: String,
namespace: String,
blocker: Blocker
): ConfigValue[Map[String, Array[Byte]]] =
ConfigValue.blockOn(blocker) {
namespace: String
): ConfigValue[F, Map[String, Array[Byte]]] =
ConfigValue.blocking {
ConfigValue.suspend {
try {
val entries =
Expand All @@ -120,14 +113,13 @@ package object kubernetes {
}
}

private[this] final def configMapEntries(
private[this] final def configMapEntries[F[_]](
client: ApiClient,
configKey: ConfigKey,
name: String,
namespace: String,
blocker: Blocker
): ConfigValue[Map[String, String]] =
ConfigValue.blockOn(blocker) {
namespace: String
): ConfigValue[F, Map[String, String]] =
ConfigValue.blocking {
ConfigValue.suspend {
try {
val entries =
Expand Down
2 changes: 1 addition & 1 deletion version.sbt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
ThisBuild / version := "1.2.5-SNAPSHOT"
ThisBuild / version := "2.0.0-SNAPSHOT"

0 comments on commit cefc4df

Please sign in to comment.