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

pt.tecnico.dsi.openstack.keystone.services.Services.scala Maven / Gradle / Ivy

The newest version!
package pt.tecnico.dsi.openstack.keystone.services

import cats.effect.Concurrent
import cats.syntax.flatMap.*
import org.http4s.Status.Conflict
import org.http4s.client.Client
import org.http4s.{Header, Query, Uri}
import org.log4s.getLogger
import pt.tecnico.dsi.openstack.common.services.CrudService
import pt.tecnico.dsi.openstack.keystone.models.{KeystoneError, Service, Session}

/**
 * The service class for services.
 * @define domainModel service
 */
final class Services[F[_]: Concurrent: Client](baseUri: Uri, session: Session)
  extends CrudService[F, Service, Service.Create, Service.Update](baseUri, "service", session.authToken)
    with EnableDisableEndpoints[F, Service] {
  
  /**
    * @param name Filters the response by a service name.
    * @param `type` Filters the response by a service type.
    * @return a stream of services filtered by the various parameters.
    */
  def list(name: Option[String] = None, `type`: Option[String] = None): F[List[Service]] = list(Query(
    "name" -> name,
    "type" -> `type`,
  ).filter((_, value) => value.isDefined))
  
  override def defaultResolveConflict(existing: Service, create: Service.Create, keepExistingElements: Boolean, extraHeaders: Seq[Header.ToRaw]): F[Service] =
    val updated = Service.Update(
      description = if create.description != existing.description then create.description else None,
      enabled = Option(create.enabled).filter(_ != existing.enabled),
    )
    if updated.needsUpdate then update(existing.id, updated, extraHeaders*)
    else Concurrent[F].pure(existing)
  override def createOrUpdate(create: Service.Create, keepExistingElements: Boolean = true, extraHeaders: Seq[Header.ToRaw] = Seq.empty)
    (resolveConflict: (Service, Service.Create) => F[Service] = defaultResolveConflict(_, _, keepExistingElements, extraHeaders)): F[Service] =
    // Openstack always creates a new service now matter what.
    list(Some(create.name), Some(create.`type`)).flatMap:
      case Nil => this.create(create, extraHeaders*)
      case List(existing) =>
        getLogger.info(s"createOrUpdate: found unique $name (id: ${existing.id}) with the correct name and type")
        resolveConflict(existing, create)
      case _ =>
        val message = s"Cannot create a service idempotently because more than one service with name: ${create.name} and type: ${create.`type`} exists."
        Concurrent[F].raiseError(KeystoneError(message, Conflict.code, Conflict.reason))
  
  override def update(id: String, update: Service.Update, extraHeaders: Header.ToRaw*): F[Service] =
    super.patch(wrappedAt, update, uri / id, extraHeaders*)
  
  override protected def updateEnable(id: String, enabled: Boolean): F[Service] =
    update(id, Service.Update(enabled = Some(enabled)))
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy