All Downloads are FREE. Search and download functionalities are using the official Maven repository.

pt.tecnico.dsi.openstack.neutron.models.FloatingIp.scala Maven / Gradle / Ivy

The newest version!
package pt.tecnico.dsi.openstack.neutron.models

import java.time.OffsetDateTime
import cats.derived
import cats.derived.ShowPretty
import cats.effect.Concurrent
import com.comcast.ip4s.IpAddress
import io.circe.derivation.{deriveCodec, deriveEncoder, renaming}
import io.circe.{Codec, Encoder}
import io.chrisdavenport.cats.time.offsetdatetimeInstances
import pt.tecnico.dsi.openstack.common.models.{Identifiable, Link}
import pt.tecnico.dsi.openstack.keystone.KeystoneClient
import pt.tecnico.dsi.openstack.keystone.models.Project
import pt.tecnico.dsi.openstack.neutron.NeutronClient
import pt.tecnico.dsi.openstack.neutron.models.FloatingIp.PortForwarding

object FloatingIp {
  object PortForwarding {
    implicit val codec: Codec[PortForwarding[IpAddress]] = deriveCodec(renaming.snakeCase)
    implicit val show: ShowPretty[PortForwarding[IpAddress]] = derived.semiauto.showPretty
  }
  case class PortForwarding[+IP <: IpAddress](
    protocol: String,
    internalIpAddress: IP,
    internalPort: Int,
    externalPort: Int,
  )
  
  object Create {
    implicit val decoder: Encoder[Create[IpAddress]] = deriveEncoder(renaming.snakeCase)
    implicit val show: ShowPretty[Create[IpAddress]] = derived.semiauto.showPretty
  }
  case class Create[+IP <: IpAddress](
    floatingNetworkId: String,
    portId: Option[String] = None,
    fixedIpAddress: Option[IP] = None,
    floatingIpAddress: Option[IP] = None,
    description: String = "",
    subnetId: Option[String] = None,
    dnsName: Option[String] = None,
    dnsDomain: Option[String] = None,
    projectId: Option[String] = None,
  )
  
  object Update {
    implicit val decoder: Encoder[Update[IpAddress]] = deriveEncoder(renaming.snakeCase)
    implicit val show: ShowPretty[Update[IpAddress]] = derived.semiauto.showPretty
  }
  case class Update[+IP <: IpAddress](
    portId: Option[String] = None,
    fixedIpAddress: Option[IP] = None,
    description: Option[String] = None,
  ) {
    lazy val needsUpdate: Boolean = {
      // We could implement this with the next line, but that implementation is less reliable if the fields of this class change
      //  productIterator.asInstanceOf[Iterator[Option[Any]]].exists(_.isDefined)
      List(portId, fixedIpAddress, description).exists(_.isDefined)
    }
  }
  
  implicit val codec: Codec[FloatingIp[IpAddress]] = deriveCodec(Map("revision" -> "revision_number").withDefault(renaming.snakeCase))
  implicit val show: ShowPretty[FloatingIp[IpAddress]] = derived.semiauto.showPretty
}
case class FloatingIp[+IP <: IpAddress](
  id: String,
  //name: String, // For consistency with other domain classes this one does not have a name  It could be s"$dnsName.${dnsDomain.}"
  description: String,
  projectId: String,
  
  status: String, // Values are ACTIVE, DOWN and ERROR.
  floatingNetworkId: String,
  dnsName: Option[String] = None,
  dnsDomain: Option[String] = None, // Cannot be ip4s Hostname because it ends with '.'
  fixedIpAddress: Option[IP] = None,
  floatingIpAddress: IP,
  routerId: Option[String] = None,
  portId: Option[String] = None,
  portForwardings: List[PortForwarding[IP]] = List.empty,
  
  revision: Int,
  createdAt: OffsetDateTime,
  updatedAt: OffsetDateTime,
  tags: List[String] = List.empty,
  links: List[Link] = List.empty,
) extends Identifiable {
  def project[F[_]](implicit keystone: KeystoneClient[F]): F[Project] = keystone.projects(projectId)
  def floatingNetwork[F[_]](implicit neutron: NeutronClient[F]): F[Network] = neutron.networks(floatingNetworkId)
  def router[F[_]: Concurrent](implicit neutron: NeutronClient[F]): F[Option[Router]] = routerId match {
    case None => Concurrent[F].pure(Option.empty)
    case Some(id) => neutron.routers.get(id)
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy