From 5aac1b633174eb2f2bb451affeca0091cc94695a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Pra=C5=BCak?= Date: Wed, 15 May 2024 13:06:34 +0200 Subject: [PATCH 01/15] Add auto module --- Justfile | 37 +++++++++++++++++++++++++++++++------ auto/project.scala | 25 +++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 6 deletions(-) create mode 100644 auto/project.scala diff --git a/Justfile b/Justfile index 24929109..a7c84072 100644 --- a/Justfile +++ b/Justfile @@ -35,19 +35,19 @@ default: #################### # Cleans everything -clean-all: clean-json clean-sdk clean-out clean-compiler-plugin clean-codegen clean-scripts clean-test-integration clean-test-templates clean-test-examples clean-test-markdown +clean-all: clean-json clean-sdk clean-auto clean-out clean-compiler-plugin clean-codegen clean-scripts clean-test-integration clean-test-templates clean-test-examples clean-test-markdown # Compiles everything -compile-all: compile-json compile-sdk compile-codegen compile-scripts compile-compiler-plugin build-language-plugin +compile-all: compile-json compile-sdk compile-auto compile-codegen compile-scripts compile-compiler-plugin build-language-plugin # Tests everything -test-all: test-json test-sdk test-codegen test-scripts test-integration test-templates test-examples test-markdown +test-all: test-json test-sdk test-auto test-codegen test-scripts test-integration test-templates test-examples test-markdown # Publishes everything locally -publish-local-all: publish-local-json publish-local-sdk publish-local-codegen publish-local-scripts install-language-plugin +publish-local-all: publish-local-json publish-local-sdk publish-local-auto publish-local-codegen publish-local-scripts install-language-plugin # Publishes everything to Maven -publish-maven-all: publish-maven-json publish-maven-sdk publish-maven-codegen publish-maven-scripts +publish-maven-all: publish-maven-json publish-maven-sdk publish-maven-auto publish-maven-codegen publish-maven-scripts # Runs all necessary checks before committing before-commit: compile-all test-all @@ -168,7 +168,7 @@ compile-json: # Runs tests for json module test-json: - scala-cli --power test besom-json --suppress-experimental-feature-warning -v -v -v + scala-cli --power test besom-json --suppress-experimental-feature-warning # Cleans json module clean-json: @@ -182,6 +182,31 @@ publish-local-json: publish-maven-json: scala-cli --power publish besom-json --project-version {{besom-version}} {{publish-maven-auth-options}} --suppress-experimental-feature-warning + +#################### +# Auto +#################### + +# Compiles auto module +compile-auto: publish-local-core + scala-cli --power compile auto --suppress-experimental-feature-warning + +# Runs tests for auto module +test-auto: compile-auto + scala-cli --power test auto --suppress-experimental-feature-warning + +# Cleans auto module +clean-auto: + scala-cli --power clean auto + +# Publishes locally auto module +publish-local-auto: test-auto + scala-cli --power publish local auto --project-version {{besom-version}} --suppress-experimental-feature-warning + +# Publishes auto module +publish-maven-auto: test-auto + scala-cli --power publish auto --project-version {{besom-version}} {{publish-maven-auth-options}} + #################### # Language plugin #################### diff --git a/auto/project.scala b/auto/project.scala new file mode 100644 index 00000000..6ace65ab --- /dev/null +++ b/auto/project.scala @@ -0,0 +1,25 @@ +//> using scala 3.3.1 +//> using options -java-output-version:11 +//> using options -deprecation -feature -Werror -Wunused:all + +//> using dep org.virtuslab::besom-json:0.4.0-SNAPSHOT +//> using dep org.virtuslab::besom-core:0.4.0-SNAPSHOT +//> using dep org.virtuslab::scala-yaml:0.0.8 +//> using dep com.lihaoyi::os-lib:0.9.3 +//> using dep com.lihaoyi::os-lib-watch:0.9.1 +//> using dep commons-io:commons-io:2.15.1 +//> using dep org.eclipse.jgit:org.eclipse.jgit:6.8.0.202311291450-r +//> using dep org.eclipse.jgit:org.eclipse.jgit.ssh.jsch:6.8.0.202311291450-r +//> using dep org.slf4j:slf4j-nop:2.0.5 + +//> using test.dep org.scalameta::munit:1.0.0-M10 + +//> using publish.name "besom-auto" +//> using publish.organization "org.virtuslab" +//> using publish.url "https://github.com/VirtusLab/besom" +//> using publish.vcs "github:VirtusLab/besom" +//> using publish.license "Apache-2.0" +//> using publish.repository "central" +//> using publish.developer "lbialy|Łukasz Biały|https://github.com/lbialy" +//> using publish.developer "pawelprazak|Paweł Prażak|https://github.com/pawelprazak" +//> using repository sonatype:snapshots From 93a5c45408377268daf740345f9f4cb7ffcd591f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Pra=C5=BCak?= Date: Wed, 15 May 2024 14:35:40 +0200 Subject: [PATCH 02/15] Add auto module --- .../src/main/scala/besom/auto/AutoError.scala | 142 ++ auto/src/main/scala/besom/auto/Git.scala | 141 ++ .../scala/besom/auto/LocalWorkspace.scala | 1146 ++++++++++++ auto/src/main/scala/besom/auto/Stack.scala | 1545 +++++++++++++++++ .../src/main/scala/besom/auto/Workspace.scala | 859 +++++++++ auto/src/main/scala/besom/auto/auto.scala | 484 ++++++ auto/src/main/scala/besom/auto/shell.scala | 254 +++ .../besom/internal/HackedSerializer.scala | 35 + auto/src/main/scala/besom/model/Names.scala | 124 ++ .../src/main/scala/besom/model/Versions.scala | 70 + .../scala/besom/auto/LocalWorkspaceTest.scala | 57 + .../src/test/scala/besom/auto/ShellTest.scala | 29 + .../src/test/scala/besom/auto/StackTest.scala | 23 + .../test/scala/besom/model/NamesTest.scala | 146 ++ .../scala/besom/test/CompileAssertions.scala | 13 + auto/src/test/scala/besom/test/Naming.scala | 22 + 16 files changed, 5090 insertions(+) create mode 100644 auto/src/main/scala/besom/auto/AutoError.scala create mode 100644 auto/src/main/scala/besom/auto/Git.scala create mode 100644 auto/src/main/scala/besom/auto/LocalWorkspace.scala create mode 100644 auto/src/main/scala/besom/auto/Stack.scala create mode 100644 auto/src/main/scala/besom/auto/Workspace.scala create mode 100644 auto/src/main/scala/besom/auto/auto.scala create mode 100644 auto/src/main/scala/besom/auto/shell.scala create mode 100644 auto/src/main/scala/besom/internal/HackedSerializer.scala create mode 100644 auto/src/main/scala/besom/model/Names.scala create mode 100644 auto/src/main/scala/besom/model/Versions.scala create mode 100644 auto/src/test/scala/besom/auto/LocalWorkspaceTest.scala create mode 100644 auto/src/test/scala/besom/auto/ShellTest.scala create mode 100644 auto/src/test/scala/besom/auto/StackTest.scala create mode 100644 auto/src/test/scala/besom/model/NamesTest.scala create mode 100644 auto/src/test/scala/besom/test/CompileAssertions.scala create mode 100644 auto/src/test/scala/besom/test/Naming.scala diff --git a/auto/src/main/scala/besom/auto/AutoError.scala b/auto/src/main/scala/besom/auto/AutoError.scala new file mode 100644 index 00000000..befe61b2 --- /dev/null +++ b/auto/src/main/scala/besom/auto/AutoError.scala @@ -0,0 +1,142 @@ +package besom.auto + +import scala.util.matching.Regex + +@SerialVersionUID(1L) +sealed abstract class BaseAutoError(message: Option[String], cause: Option[Throwable]) + extends Exception(message.orElse(cause.map(_.toString)).orNull, cause.orNull) + with Product + with Serializable + +@SerialVersionUID(1L) +case class AutoError(message: Option[String], cause: Option[Throwable]) extends BaseAutoError(message, cause) +object AutoError: + def apply(message: String) = new AutoError(Some(message), None) + def apply(message: String, cause: Throwable) = new AutoError(Some(message), Some(cause)) + def apply(cause: Throwable) = new AutoError(None, Some(cause)) + +@SerialVersionUID(1L) +case class ShellAutoError( + message: Option[String], + cause: Option[Throwable], + exitCode: Int, + stdout: String, + stderr: String, + command: Seq[String], + envVars: Map[String, String] +) extends BaseAutoError(message, cause): + def withMessage(message: String): ShellAutoError = copy(message = this.message.map(message + "; " + _).orElse(Some(message))) + + /** Returns true if the error was a result of selecting a stack that does not exist. + * + * @return + * `true` if the error was due to a non-existent stack. + */ + def isSelectStack404Error: Boolean = + val regex: Regex = "no stack named.*found".r + regex.findFirstIn(stderr).isDefined + + /** Returns true if the error was a result of a conflicting update locking the stack. + * + * @return + * `true` if the error was due to a conflicting update. + */ + def isConcurrentUpdateError: Boolean = + val conflictText = "[409] Conflict: Another update is currently in progress." + val localBackendConflictText = "the stack is currently locked by" + stderr.contains(conflictText) || stderr.contains(localBackendConflictText) + + /** Returns true if the error was a result of creating a stack that already exists. + * + * @return + * `true` if the error was due to a stack that already exists. + */ + def isCreateStack409Error: Boolean = + val regex: Regex = "stack.*already exists".r + regex.findFirstIn(stderr).isDefined + + /** Returns true if the pulumi core engine encountered an error (most likely a bug). + * + * @return + * `true` if the error was due to an unexpected engine error. + */ + def isUnexpectedEngineError: Boolean = + stdout.contains("The Pulumi CLI encountered a fatal error. This is a bug!") + +end ShellAutoError +object ShellAutoError: + def apply(message: String, exitCode: Int, stdout: String, stderr: String, command: Seq[String], envVars: Map[String, String]) = + new ShellAutoError( + Some(msg(Some(message), None, exitCode, stdout, stderr, command, envVars)), + None, + exitCode, + stdout, + stderr, + command, + envVars + ) + def apply( + message: String, + cause: Throwable, + exitCode: Int, + stdout: String, + stderr: String, + command: Seq[String], + envVars: Map[String, String] + ) = + new ShellAutoError( + Some(msg(Some(message), Some(cause), exitCode, stdout, stderr, command, envVars)), + Some(cause), + exitCode, + stdout, + stderr, + command, + envVars + ) + def apply(cause: Throwable, exitCode: Int, stdout: String, stderr: String, command: Seq[String], envVars: Map[String, String]) = + new ShellAutoError( + Some(msg(None, Some(cause), exitCode, stdout, stderr, command, envVars)), + Some(cause), + exitCode, + stdout, + stderr, + command, + envVars + ) + def apply(exitCode: Int, stdout: String, stderr: String, command: Seq[String], envVars: Map[String, String]) = + new ShellAutoError( + Some(msg(None, None, exitCode, stdout, stderr, command, envVars)), + None, + exitCode, + stdout, + stderr, + command, + envVars + ) + + private def msg( + message: Option[String], + cause: Option[Throwable], + exitCode: Int, + stdout: String, + stderr: String, + command: Seq[String], + envVars: Map[String, String] + ): String = { + s"""|${message.map(_ + "\n").getOrElse("")}${cause.map("cause: " + _.getMessage + "\n").getOrElse("")} + |command: ${redacted(command)} + |code: $exitCode + |stdout: + |$stdout + |stderr: + |$stderr + |env: + |${envVars.map { case (k, v) => s" $k=$v" }.mkString("\n")} + |""".stripMargin + } + + private def redacted(command: Seq[String]) = + val parts = if command.contains("-secret") then command.take(2) :+ "...[REDACTED]" else command + parts.mkString(" ") + +end ShellAutoError diff --git a/auto/src/main/scala/besom/auto/Git.scala b/auto/src/main/scala/besom/auto/Git.scala new file mode 100644 index 00000000..da1c31b3 --- /dev/null +++ b/auto/src/main/scala/besom/auto/Git.scala @@ -0,0 +1,141 @@ +package besom.auto + +import besom.util.* +import com.jcraft.jsch.JSch +import org.eclipse.jgit.api.{CloneCommand, TransportConfigCallback} +import org.eclipse.jgit.lib.ObjectId +import org.eclipse.jgit.revwalk.RevWalk +import org.eclipse.jgit.transport.ssh.jsch.JschConfigSessionFactory +import org.eclipse.jgit.transport.{CredentialsProvider, RefSpec, SshTransport, UsernamePasswordCredentialsProvider} + +import java.util.Collections +import scala.util.Using + +object Git: + private val RefPrefix = "refs/" + private val RefHeadPrefix = RefPrefix + "heads/" + private val RefTagPrefix = RefPrefix + "tags/" + private val RefRemotePrefix = RefPrefix + "remotes/" + + private class RichCloneCommand(private var depth: Option[Int] = None) extends CloneCommand: + def getCredentialsProvider: CredentialsProvider = credentialsProvider + def getTransportConfigCallback: TransportConfigCallback = transportConfigCallback + def getDepth: Option[Int] = depth + override def setDepth(depth: Int): CloneCommand = + val cmd = super.setDepth(depth) + this.depth = Some(depth) + cmd + + def setupGitRepo(workDir: os.Path, repoArgs: GitRepo): Either[Exception, os.Path] = + try + val cloneCommand = new RichCloneCommand() + + cloneCommand + .setRemote("origin") // be explicit so we can require it in remote refs + .setURI(repoArgs.url) + .setDirectory(workDir.toIO) + + if repoArgs.shallow then + cloneCommand + .setDepth(1) + .setCloneAllBranches(false) + + repoArgs.auth match + case GitAuth.UsernameAndPassword(username, password) => + cloneCommand.setCredentialsProvider(new UsernamePasswordCredentialsProvider(username, password)) + case GitAuth.PersonalAccessToken(token) => + // With Personal Access Token the username for use with a PAT can be + // *anything* but an empty string so we are setting this to 'git' + cloneCommand.setCredentialsProvider(new UsernamePasswordCredentialsProvider("git", token)) + case GitAuth.SSHPrivateKey(key, passphrase) => + val sshSessionFactory = new JschConfigSessionFactory(): + override protected def configureJSch(jsch: JSch): Unit = + jsch.removeAllIdentity() + jsch.addIdentity("key", key.getBytes(), null /* no pub key */, passphrase.asOption.orNull.getBytes()) + cloneCommand.setTransportConfigCallback { transport => + transport.asInstanceOf[SshTransport].setSshSessionFactory(sshSessionFactory) + } + case GitAuth.SSHPrivateKeyPath(keyPath, passphrase) => + val sshSessionFactory = new JschConfigSessionFactory(): + override protected def configureJSch(jsch: JSch): Unit = + jsch.removeAllIdentity() + jsch.addIdentity(keyPath, passphrase.asOption.orNull.getBytes()) + cloneCommand.setTransportConfigCallback { transport => + transport.asInstanceOf[SshTransport].setSshSessionFactory(sshSessionFactory) + } + case NotProvided => // do nothing + repoArgs.branch match + case branch: String => + // `Git.cloneRepository` will do appropriate fetching given a branch name. We must deal with + // different varieties, since people have been advised to use these as a workaround while only + // "refs/heads/" worked. + // + // If a reference name is not supplied, then clone will fetch all refs (and all objects + // referenced by those), and checking out a commit later will work as expected. + val ref = { + try + val refSpec = RefSpec(branch) + if refSpec.matchSource(RefRemotePrefix) + then + refSpec.getDestination match + case s"origin/$branch" => s"$RefHeadPrefix/$branch" + case _ => throw AutoError("a remote ref must begin with 'refs/remote/origin/', but got: '$branch'") + else if refSpec.matchSource(RefTagPrefix) then + branch // looks like `refs/tags/v1.0.0` -- respect this even though the field is `.Branch` + else if !refSpec.matchSource(RefHeadPrefix) then + s"$RefHeadPrefix/$branch" // not a remote, not refs/heads/branch; treat as a simple branch name + else + // already looks like a full branch name or tag, so use as is + refSpec.toString + catch case e: IllegalArgumentException => throw AutoError(s"Invalid branch name: '$branch'", e) + } + cloneCommand.setBranchesToClone(Collections.singletonList(ref)) + + case NotProvided => // do nothing + end match + // NOTE: pulumi has a workaround here for Azure DevOps requires, we might add if needed + val git = cloneCommand.call() + val repository = git.getRepository + + repoArgs.commitHash match + case commitHash: String => + // ensure that the commit has been fetched + val fetchCommand = git + .fetch() + .setRemote("origin") + .setRefSpecs(new RefSpec(s"$commitHash:$commitHash")) + .setCredentialsProvider(cloneCommand.getCredentialsProvider) + .setTransportConfigCallback(cloneCommand.getTransportConfigCallback) + + cloneCommand.getDepth.foreach { + fetchCommand.setDepth(_) + } + val _ = fetchCommand.call() + + // If a commit hash is provided, then we must check it out explicitly. Otherwise, the + // repository will be in a detached HEAD state, and the commit hash will be the only + // commit in the repository. + val commitId = ObjectId.fromString(commitHash) + Using.resource(new RevWalk(repository)) { revWalk => + val commit = revWalk.parseCommit(commitId) + val _ = git + .checkout() + .setName(commit.getName) + .setForced(true) // this method guarantees 'git --force' semantics + .call() + } + case NotProvided => // do nothing + end match + + val finalWorkDir = + if repoArgs.projectPath.asOption.nonEmpty then + val projectPath = os.rel / repoArgs.projectPath.asOption.get + workDir / projectPath + else workDir + + Right(finalWorkDir) + + catch case e: Exception => Left(e) + + end setupGitRepo +end Git diff --git a/auto/src/main/scala/besom/auto/LocalWorkspace.scala b/auto/src/main/scala/besom/auto/LocalWorkspace.scala new file mode 100644 index 00000000..9d57ce2a --- /dev/null +++ b/auto/src/main/scala/besom/auto/LocalWorkspace.scala @@ -0,0 +1,1146 @@ +package besom.auto + +import besom.json.* +import besom.json.DefaultJsonProtocol.* +import besom.model.{PackageName, SemanticVersion} +import besom.util.* +import besom.{FullyQualifiedStackName, StackName, model} +import os.Path + +import java.util.concurrent.atomic.AtomicReference +import scala.collection.immutable.Map +import scala.collection.mutable +import scala.language.implicitConversions +import scala.util.Try + +/** LocalWorkspace is a default implementation of the [[Workspace]] trait. A [[Workspace]] is the execution context containing a single + * Pulumi project, a program, and multiple stacks. Workspaces are used to manage the execution environment, providing various utilities + * such as plugin installation, environment configuration (`$PULUMI_HOME`), and creation, deletion, and listing of Stacks. + * [[LocalWorkspace]] relies on `Pulumi.yaml` and `Pulumi.[stack].yaml` as the intermediate format for [[Project]] and [[Stack]] settings. + * Modifying [[projectSettings]] will alter the [[Workspace]] `Pulumi.yaml` file, and setting config on a [[Stack]] will modify the + * `Pulumi.[stack].yaml` file. This is identical to the behavior of Pulumi CLI driven workspaces. + */ +trait LocalWorkspace extends Workspace: + import LocalWorkspace.* + + given Workspace = this + + /** Returns the settings object for the current project if any. [[LocalWorkspace]] reads settings from the `Pulumi.yaml` in the workspace. + * A workspace can contain only a single project at a time. + * @return + * a [[Project]] settings or error if any + */ + def projectSettings: Either[Exception, Project] = readProjectSettingsFromDir(workDir) + + /** Overwrites the settings object in the current project. There can only be a single project per workspace. Fails if new project name + * does not match old. Writes this value to a `Pulumi.yaml` file in [[workDir]]. + * + * @param settings + * the project settings to save + * @return + * an exception if the save failed, otherwise nothing + */ + def saveProjectSettings(settings: Project): Either[Exception, Unit] = Try { + val pulumiYamlPath = workDir / shell.pulumi.ProjectFileName() + settings.save(pulumiYamlPath) + }.toEither.flatten.left.map(e => AutoError(s"failed to save project settings: ${e.getMessage}", e)) + + /** Returns the settings object for the stack matching the specified stack name if any. Reads this from a `Pulumi.[stack].yaml` file in + * [[workDir]]. + * + * @param stackName + * the name of the stack + * @return + * a [[ProjectStack]] or an error if any + */ + def stackSettings(stackName: String): Either[Exception, ProjectStack] = + readStackSettingFromDir(workDir, stackName) + + /** Overwrites the settings object for the stack matching the specified stack name. Saves this to a `Pulumi.[stack].yaml` file in + * [[workDir]]. + * + * @param stackName + * the name of the stack + * @param settings + * The stack settings to save. + * @return + * an exception if the save failed, otherwise nothing. + */ + def saveStackSettings(stackName: String, settings: ProjectStack): Either[Exception, Unit] = Try { + val actualStackName = getStackSettingsName(stackName) + val pulumiYamlPath = workDir / shell.pulumi.StackFileName(actualStackName) + settings.save(pulumiYamlPath) + }.toEither.left.map(e => AutoError(s"failed to save stack settings: ${e.getMessage}", e)) + + /** This is a hook to provide additional args to every CLI commands before they are executed. Provided with stack name, returns a list of + * args to append to an invoked command `["--config=...", ]`. + * + * LocalWorkspace does not utilize this extensibility point. + * + * @param stackName + * the name of the stack + * @return + * a list of args to append to an invoked command + */ + def serializeArgsForOp(stackName: String): Either[Exception, List[String]] = + // not utilized for LocalWorkspace + Left(AutoError("LocalWorkspace does not utilize this extensibility point")) + + /** This is a hook executed after every command. Called with the stack name. An extensibility point to perform workspace cleanup. CLI + * operations may create/modify a `Pulumi.[stack].yaml` in [[workDir]]. + * + * LocalWorkspace does not utilize this extensibility point. + * + * @param stackName + * the name of the stack + * @return + * an exception if the cleanup failed, otherwise nothing + */ + def postCommandCallback(stackName: String): Either[Exception, Unit] = + // not utilized for LocalWorkspace + Left(AutoError("LocalWorkspace does not utilize this extensibility point")) + + /** Adds the specified environments to the provided stack's configuration. + * + * @param stackName + * the name of the stack + * @param envs + * the environments to add + * @return + * an exception if the add failed, otherwise nothing + */ + def addEnvironments( + stackName: String, + envs: String* + ): Either[Exception, Unit] = + + // 3.95 added this command (https://github.com/pulumi/pulumi/releases/tag/v3.95.0) + if pulumiVersion < model.SemanticVersion(3, 95, 0) + then Left(AutoError("addEnvironments requires Pulumi version >= 3.95.0")) + else + val args = Seq("config", "env", "add") ++ envs ++ Seq("--yes", "--stack", stackName) + pulumi(args)().fold( + e => Left(e.withMessage(s"failed to add environments to stack: '$stackName'")), + _ => Right(()) + ) + end if + end addEnvironments + + /** Lists the environments from the provided stack's configuration. + * + * @param stackName + * The name of the stack. + * @return + * Either an Exception or a list of environments. + */ + def listEnvironments(stackName: String): Either[Exception, List[String]] = + // 3.99 added this command (https://github.com/pulumi/pulumi/releases/tag/v3.99.0) + if pulumiVersion < model.SemanticVersion(3, 99, 0) + then Left(AutoError("listEnvironments requires Pulumi version >= 3.99.0")) + else + val args = Seq("config", "env", "ls", "--stack", stackName, "--json") + pulumi(args)().fold( + e => Left(e.withMessage(s"failed to list environments for stack: '$stackName'")), + r => r.out.parseJson[List[String]].left.map(e => AutoError(s"failed to parse environments for stack: '$stackName'", e)) + ) + end listEnvironments + + /** Removes the specified environment from the provided stack's configuration. + * + * @param stackName + * the name of the stack + * @param env + * the environment to remove + * @return + * an exception if the remove failed, otherwise nothing + */ + def removeEnvironment(stackName: String, env: String): Either[Exception, Unit] = + // 3.95 added this command (https://github.com/pulumi/pulumi/releases/tag/v3.95.0) + if pulumiVersion < model.SemanticVersion(3, 95, 0) + then Left(AutoError("removeEnvironment requires Pulumi version >= 3.95.0")) + else + val args = Seq("--stack", stackName, "config", "env", "rm", env, "--yes") + pulumi(args)() + .fold( + e => Left(e.withMessage(s"failed to remove environment from stack: '$stackName'")), + _ => Right(()) + ) + end removeEnvironment + + /** Returns the value associated with the specified stack name and key using the optional [[ConfigOption]]s, scoped to the current + * workspace. [[LocalWorkspace]] reads this config from the matching `Pulumi.[stack].yaml` file in [[workDir]]. + * + * @param stackName + * the name of the stack + * @param key + * the key to retrieve the value for + * @param options + * the optional [[ConfigOption]]s to use + * @return + * the config value or an error if any + */ + def getConfig( + stackName: String, + key: String, + options: ConfigOption* + ): Either[Exception, ConfigValue] = + val maybePath = options.collectFirst { case ConfigOption.Path => "--path" } + val args = Seq("--stack", stackName, "config", "get") ++ maybePath ++ Seq(key, "--show-secrets", "--json") + pulumi(args)() match + case Left(e) => Left(e.withMessage(s"failed to get config '$key' for stack: '$stackName'")) + case Right(r) => ConfigValue.fromJson(r.out) + end getConfig + + /** Returns the config map for the specified stack name, scoped to the current workspace. [[LocalWorkspace]] reads this config from the + * matching `Pulumi.stack.yaml` file in [[workDir]]. + * + * @param stackName + * the name of the stack + * @return + * the config map or an error if any + */ + def getAllConfig(stackName: String): Either[Exception, ConfigMap] = + val args = Seq("--stack", stackName, "config", "--show-secrets", "--json") + pulumi(args)() match + case Left(e) => Left(e.withMessage(s"failed to get all configs for stack: '$stackName'")) + case Right(r) => ConfigMap.fromJson(r.out) + end getAllConfig + + /** Sets the specified key-value pair on the provided stack name. [[LocalWorkspace]] writes this value to the matching + * `Pulumi.[stack].yaml` file in [[workDir]]. + * + * @param stackName + * the name of the stack + * @param key + * the key to set the value for + * @param value + * the config value to set + * @param options + * the optional [[ConfigOption]]s to use + * @return + * an exception if the set failed, otherwise nothing + */ + def setConfig( + stackName: String, + key: String, + value: ConfigValue, + options: ConfigOption* + ): Either[Exception, Unit] = + val maybePath = options.collectFirst { case ConfigOption.Path => "--path" } + val maybeSecret = if value.secret then "--secret" else "--plaintext" + val args = Seq("--stack", stackName, "config", "set") ++ maybePath ++ Seq(key, maybeSecret, "--", value.value) + pulumi(args)() match + case Left(e) => Left(e.withMessage(s"failed to set config '$key' for stack: '$stackName'")) + case Right(_) => Right(()) + end setConfig + + /** Sets all values in the provided config map for the specified stack name. [[LocalWorkspace]] writes the config to the matching + * `Pulumi.[stack].yaml` file in [[workDir]]. + * + * @param stackName + * the name of the stack + * @param config + * the [[ConfigMap]] to upsert against the existing config + * @param options + * the optional [[ConfigOption]]s to use + * @return + * an exception if the set failed, otherwise nothing + */ + def setAllConfig( + stackName: String, + config: ConfigMap, + options: ConfigOption* + ): Either[Exception, Unit] = + val maybePath = options.collectFirst { case ConfigOption.Path => "--path" } + val pairs: Seq[String] = config.flatMap { case (k, v) => + Seq(if v.secret then "--secret" else "--plaintext", s"$k=${v.value}") + }.toSeq + val args = Seq("--stack", stackName, "config", "set-all") ++ maybePath ++ ("--" +: pairs) + pulumi(args)() match + case Left(e) => Left(e.withMessage(s"failed to set all configs for stack: '$stackName'")) + case Right(_) => Right(()) + end setAllConfig + + /** Removes the specified key-value pair on the provided stack name. It will remove any matching values in the `Pulumi.[stack].yaml` file + * in [[workDir]]. + * + * @param stackName + * the name of the stack + * @param key + * the config key to remove + * @param options + * the optional [[ConfigOption]]s to use + * @return + * an exception if the remove failed, otherwise nothing + */ + def removeConfig( + stackName: String, + key: String, + options: ConfigOption* + ): Either[Exception, Unit] = + val maybePath = options.collectFirst { case ConfigOption.Path => "--path" } + val args = Seq("--stack", stackName, "config", "rm") ++ maybePath ++ Seq(key) + pulumi(args)() match + case Left(e) => Left(e.withMessage(s"failed to remove config '$key' for stack: '$stackName'")) + case _ => Right(()) + end removeConfig + + /** Removes all values in the provided key list for the specified stack name It will remove any matching values in the + * `Pulumi.[stack].yaml` file in [[workDir]]. + * + * @param stackName + * the name of the stack + * @param keys + * the list of keys to remove from the underlying config + * @param options + * the optional [[ConfigOption]]s to use + * @return + * an exception if the remove failed, otherwise nothing + */ + def removeAllConfig( + stackName: String, + keys: List[String], + options: ConfigOption* + ): Either[Exception, Unit] = + val maybePath = options.collectFirst { case ConfigOption.Path => "--path" } + val args = Seq("--stack", stackName, "config", "rm-all") ++ maybePath ++ keys + pulumi(args)() match + case Left(e) => Left(e.withMessage(s"failed to remove config '$keys' for stack: '$stackName'")) + case _ => Right(()) + end removeAllConfig + + /** Gets and sets the config map used with the last update for Stack matching stack name. It will overwrite all configuration in the + * `Pulumi.[stack].yaml` file in [[workDir]]. + * + * @param stackName + * the name of the stack + */ + def refreshConfig(stackName: String): Either[Exception, ConfigMap] = + val args = Seq("--stack", stackName, "config", "refresh", "--force") + pulumi(args)() match + case Left(e) => Left(e.withMessage(s"failed to refresh config for stack: '$stackName'")) + case _ => Right(()) + getAllConfig(stackName) + end refreshConfig + + /** Returns the value associated with the specified stack name and key, scoped to the [[LocalWorkspace]]. + * + * @param stackName + * the stack to read tag metadata from + * @param key + * the key to use for the tag lookup + * @return + * the tag value or an error if any + */ + def getTag(stackName: String, key: String): Either[Exception, String] = + val args = Seq("--stack", stackName, "stack", "tag", "get", key) + pulumi(args)() match + case Left(e) => Left(e.withMessage(s"failed to get stack tag '$key' for stack: '$stackName'")) + case Right(r) => Right(r.out) + end getTag + + /** Sets the specified key-value pair on the provided stack name. + * + * @param stackName + * the stack to set tag metadata on + * @param key + * the tag key to set + * @param value + * the tag value to set + * @return + * an exception if the set failed, otherwise nothing + */ + def setTag(stackName: String, key: String, value: String): Either[Exception, Unit] = + val args = Seq("--stack", stackName, "stack", "tag", "set", key, value) + pulumi(args)() match + case Left(e) => Left(e.withMessage(s"failed to set stack tag '$key' for stack: '$stackName'")) + case _ => Right(()) + end setTag + + /** Removes the specified key-value pair on the provided stack name. + * + * @param stackName + * the stack to remove tag metadata from + * @param key + * the tag key to remove + * @return + * an exception if the remove failed, otherwise nothing + */ + def removeTag(stackName: String, key: String): Either[Exception, Unit] = + val args = Seq("--stack", stackName, "stack", "tag", "rm", key) + pulumi(args)() match + case Left(e) => Left(e.withMessage(s"failed to remove stack tag '$key' for stack: '$stackName'")) + case _ => Right(()) + end removeTag + + /** Returns the tag map for the specified tag name, scoped to the current LocalWorkspace. + * + * @param stackName + * the stack to read tag metadata from + * @return + * the tag map or an error if any + */ + def listTags(stackName: String): Either[Exception, TagMap] = + val args = Seq("--stack", stackName, "stack", "tag", "list", "--json") + pulumi(args)() match + case Left(e) => Left(e.withMessage(s"failed to list stack tags for stack: '$stackName'")) + case Right(r) => TagMap.fromJson(r.out) + end listTags + + protected def envVars: AtomicReference[mutable.Map[String, String]] + def getEnvVars: Map[String, String] = envVars.get().toMap + def setEnvVars(variables: Map[String, String]): Unit = envVars.getAndUpdate(_ ++= variables) + def setEnvVar(key: String, value: String): Unit = envVars.getAndUpdate(_ += (key -> value)) + def unsetEnvVar(key: String): Unit = envVars.getAndUpdate(_ -= key) + + protected def rawSecretsProvider: AtomicReference[Option[String]] + def secretsProvider: Option[String] = rawSecretsProvider.get() + + /** Returns detailed information about the currently authenticated user, the logged-in Pulumi identity. + * @return + * the currently authenticated user details + */ + def whoAmI: Either[Exception, WhoAmIResult] = + // 3.58 added the --json flag (https://github.com/pulumi/pulumi/releases/tag/v3.58.0) + if pulumiVersion < model.SemanticVersion(3, 58, 0) + then Left(AutoError("whoAmI requires Pulumi version >= 3.58.0")) + else + val args = Seq("whoami", "--json") + pulumi(args)() match + case Left(e) => Left(e.withMessage(s"failed to get the currently authenticated user")) + case Right(r) => WhoAmIResult.fromJson(r.out) + end whoAmI + + /** The secrets provider to use for encryption and decryption of stack secrets. See: + * https://www.pulumi.com/docs/intro/concepts/secrets/#available-encryption-providers + * + * Valid secret providers types are `default`, `passphrase`, `awskms`, `azurekeyvault`, `gcpkms`, `hashivault`. + * + * To change the stack to use a cloud secrets backend, use the URL format, e.g.: `awskms://alias/ExampleAlias?region=us-east-1` + * + * @param stackName + * the name of the stack + * @param newSecretsProvider + * the new secrets provider to use + * @param options + * the optional [[ChangeSecretsProviderOption]]s to use + * @return + * the currently configured secrets provider + */ + def changeStackSecretsProvider( + stackName: String, + newSecretsProvider: String | SecretsProviderType, + options: ChangeSecretsProviderOption* + ): Either[Exception, Unit] = + val args: Seq[String] = Seq("stack", "change-secrets-provider", "--stack", stackName, newSecretsProvider) + + // If we're changing to a passphrase provider, we need to pass the new passphrase. + val maybeStdin = + if newSecretsProvider == "passphrase" then + options + .collectFirst { case NewPassphraseOption(newPassphrase) => + Seq(shell.ShellOption.Stdin(newPassphrase)) + } + .toRight { + AutoError("failed to change stack secrets provider, no new passphrase provided") + } + else Right(Seq.empty) + + for { + stdin <- maybeStdin + result <- pulumi(args)(stdin*) match + case Left(e) => Left(e.withMessage(s"failed to change stack secrets provider: '$newSecretsProvider'")) + case _ => Right(()) + } yield + // make sure we update the workspace secrets provider + this.rawSecretsProvider.set(Some(newSecretsProvider)) + result + end changeStackSecretsProvider + + /** Returns a summary of the currently selected stack, if any. + * @return + * the currently selected stack summary + */ + def stack: Either[Exception, Option[StackSummary]] = + listStacks.map(_.collectFirst { case s @ StackSummary(_, true, _, _, _, _) => s }) + + /** Creates and sets a new stack with the stack name, failing if one already exists. + * + * @param stackName + * the stack to create + * @return + * an exception if the create failed, otherwise nothing + */ + def createStack(stackName: String): Either[Exception, Stack] = + /*val maybeStackArgs = StackName.parse(stackName) match + case Left(e) => Left(e) + case Right(value) => + value.parts match + case (Some("organization"), _, stack) => Right(Seq(stack)) + case (Some(_), _, _) => Right(Seq("--stack", value)) + case (None, _, stack) => Right(Seq(stack)) + */ + val maybeSecretsProvider = secretsProvider.toSeq.flatMap(sp => Seq("--secrets-provider", sp)) + val maybeRemote = if remote then Seq("--remote") else Seq.empty + for + // stackArgs <- maybeStackArgs + res <- { + val args: Seq[String] = Seq("stack", "init") ++ Seq("--stack", stackName) ++ maybeSecretsProvider ++ maybeRemote + pulumi(args)() match + case Left(e) => Left(e.withMessage(s"failed to create stack: '$stackName'")) + case _ => + FullyQualifiedStackName + .parse(stackName) + .map(Stack(_, this)) + .left + .map(e => AutoError(s"failed to create stack: ${e.getMessage}", e)) + } + yield res + end createStack + + /** Selects and sets an existing stack matching the stack name, failing if none exists. + * + * @param stackName + * the stack to select + * @return + * an exception if the select failed, otherwise nothing + */ + def selectStack(stackName: String): Either[Exception, Stack] = + val maybeSelect = if !remote then Seq("select") else Seq.empty + val args = Seq("--stack", stackName, "stack") ++ maybeSelect + pulumi(args)() match + case Left(e) => Left(e.withMessage(s"failed to select stack: '$stackName'")) + case _ => FullyQualifiedStackName.parse(stackName).map(Stack(_, this)) + end selectStack + + /** Deletes the stack and all associated configuration and history. */ + def removeStack(stackName: String, options: RemoveOption*): Either[Exception, Unit] = + val maybeForce = options.collectFirst { case RemoveOption.Force => "--force" } + val args = Seq("--stack", stackName, "stack", "rm", "--yes") ++ maybeForce + pulumi(args)() match + case Left(e) => Left(e.withMessage(s"failed to remove stack: '$stackName'")) + case _ => Right(()) + end removeStack + + /** Returns all Stacks created under the current Project. This queries underlying backend may return stacks not present in the + * [[Workspace]] (as `Pulumi.[stack].yaml` files). + * @return + * a list of stack summaries + */ + def listStacks: Either[Exception, List[StackSummary]] = + pulumi("stack", "ls", "--json")() match + case Left(e) => Left(e.withMessage(s"failed to list stacks")) + case Right(r) => StackSummary.fromJsonList(r.out) + end listStacks + + /** Installs a plugin in the [[Workspace]], for example to use cloud providers like AWS or GCP. + * + * @param name + * the name of the plugin + * @param version + * the version of the plugin e.g. "v1.0.0" + * @param kind + * the kind of plugin, defaults to "resource" + * @param server + * the optional server to install the plugin from + * @return + * an exception if the install failed, otherwise nothing + */ + def installPlugin( + name: String, + version: String, + kind: String = "resource", + server: NotProvidedOr[String] = NotProvided + ): Either[Exception, Unit] = + val maybeServer = server.asOption.toSeq.flatMap(s => Seq("--server", s)) + val args = Seq("plugin", "install", kind, name, version) ++ maybeServer + pulumi(args)() match + case Left(e) => Left(e.withMessage(s"failed to install plugin: '$name'")) + case _ => Right(()) + end installPlugin + + /** Removes a plugin from the [[Workspace]] matching the specified name and version. + * + * @param name + * the optional name of the plugin + * @param versionRange + * optional semver range to check when removing plugins matching the given name e.g. "1.0.0", ">1.0.0". + * @param kind + * he kind of plugin, defaults to "resource" + * @return + * an exception if the remove failed, otherwise nothing + */ + def removePlugin( + name: NotProvidedOr[String] = NotProvided, + versionRange: NotProvidedOr[String] = NotProvided, + kind: String = "resource" + ): Either[Exception, Unit] = + val args = Seq("plugin", "rm", kind) ++ name.asOption ++ versionRange.asOption ++ Seq("--yes") + pulumi(args)() match + case Left(e) => Left(e.withMessage(s"failed to remove plugin: '$name'")) + case _ => Right(()) + end removePlugin + + /** Returns a list of all plugins installed in the [[Workspace]]. + * @return + * a list of plugin info + */ + def listPlugins: Either[Exception, List[PluginInfo]] = + pulumi("plugin", "ls", "--json")() match + case Left(e) => Left(e.withMessage(s"failed to list plugins")) + case Right(r) => PluginInfo.fromJsonList(r.out) + end listPlugins + + /** exports the deployment state of the stack. This can be combined with [[importStack]] to edit a stack's state (such as recovery from + * failed deployments). + * + * @param stackName + * the name of the stack + * @return + * the deployment state of the stack + */ + def exportStack(stackName: String): Either[Exception, UntypedDeployment] = + pulumi("--stack", stackName, "stack", "export", "--show-secrets")() match + case Left(e) => Left(e.withMessage(s"failed to export stack: '$stackName'")) + case Right(r) => UntypedDeployment.fromJson(r.out) + end exportStack + + /** imports the specified deployment state into a pre-existing stack. This can be combined with [[exportStack]] to edit a stack's state + * (such as recovery from failed deployments). + * + * @param stackName + * the name of the stack + * @param state + * the stack state to import + * @return + * an exception if the import failed, otherwise nothing + */ + def importStack(stackName: String, state: UntypedDeployment): Either[Exception, Unit] = + val maybeState = Try { + val tempFile = os.temp(prefix = "pulumi_auto", suffix = ".json") + os.write(tempFile, state.toJson) + }.toEither.left.map(e => AutoError(s"failed to import stack: ${e.getMessage}", e)) + + for tempFile <- maybeState + yield pulumi("--stack", stackName, "stack", "import", "--file", tempFile.toString)() match + case Left(e) => Left(e.withMessage(s"failed to import stack: '$stackName'")) + case _ => Right(()) + end importStack + + /** Gets the current set of [[Stack]] outputs from the last Stack.up operation. + * + * @param stackName + * the name of the stack + * @return + * the current set of [[Stack]] outputs from the last Stack.up + */ + def stackOutputs(stackName: String): Either[Exception, OutputMap] = + val maskedResult: Either[Exception, String] = pulumi("--stack", stackName, "stack", "output", "--json")() match + case Left(e) => Left(e.withMessage(s"failed to get stack outputs for stack: '$stackName'")) + case Right(r) => Right(r.out) + val plaintextResult: Either[Exception, String] = pulumi("--stack", stackName, "stack", "output", "--json", "--show-secrets")() match + case Left(e) => Left(e.withMessage(s"failed to get stack outputs for stack: '$stackName'")) + case Right(r) => Right(r.out) + // merge the masked and plaintext results, and mark any masked values as secret + for + masked <- maskedResult + plaintext <- plaintextResult + outputs <- OutputMap.fromJson(masked, plaintext) + yield outputs + + protected[auto] def repo: Option[GitRepo] + protected[auto] def remoteEnvVars: Map[String, EnvVarValue] + protected[auto] def preRunCommands: List[String] + protected[auto] def remoteSkipInstallDependencies: Boolean + +end LocalWorkspace + +object LocalWorkspace: + // minimal version of the Pulumi CLI that supports the Automation API + private val MinVersion = model.SemanticVersion(3, 2, 0) + // the extensions for Pulumi settings files + private val SettingsExtensions = List(".yaml", ".yml", ".json") + + /** Creates a new LocalWorkspace with the default options. + * + * @param options + * the configuration options for the workspace + * @return + * a new LocalWorkspace + */ + def apply(options: LocalWorkspaceOption*): Either[Exception, LocalWorkspace] = + val opts = LocalWorkspaceOptions.from(options*) + + val workDir: os.Path = { + val wd: os.Path = opts.workDir match + case NotProvided => os.temp.dir(prefix = "pulumi_auto") + case wd: os.Path => wd + + // if we have a repo, but no remote, then we need to clone the repo + opts.repo match + case repo: GitRepo if !opts.remote => + // now do the git clone + Git.setupGitRepo(wd, repo) match + case Left(e) => throw AutoError(s"failed to create workspace, unable to enlist in git repo: ${e.getMessage}", e) + case Right(projectDir) => projectDir + case _ => wd + } + + val pulumiHome = opts.pulumiHome.asOption + val envVars = AtomicReference(mutable.Map.from(opts.envVars)) + + // optOut indicates we should skip the version check. + val optOut: Boolean = shell.pulumi.env.pulumiAutomationApiSkipVersionCheck || + opts.envVars + .get(shell.pulumi.env.PulumiAutomationApiSkipVersionCheckEnv) + .map(isTruthy) + .getOrElse(false) + + val maybeCurrentVersion: Either[Exception, model.SemanticVersion] = pulumiVersion match + case Left(e) => Left(AutoError(s"failed to create workspace, unable to determine pulumi version: ${e.getMessage}", e)) + case Right(v) => + parseAndValidatePulumiVersion(MinVersion, v, optOut) match + case Left(e) => Left(AutoError(s"failed to create workspace, pulumi version is not supported: ${e.getMessage}", e)) + case r => r + + val remoteSupportChecked: Either[Exception, Unit] = + if !optOut && opts.remote then + // See if `--remote` is present in `pulumi preview --help`'s output. + supportsPulumiCmdFlag("--remote", "preview") match + case Left(e) => + Left(AutoError(s"failed to create workspace, unable to determine pulumi remote support: ${e.getMessage}", e)) + case Right(false) => Left(AutoError("Pulumi CLI does not support remote operations; please upgrade")) + case Right(true) => Right(()) + end match + else Right(()) + + val maybeWorkspace = for + currentVersion <- maybeCurrentVersion + _ <- remoteSupportChecked + yield InitializedLocalWorkspace( + workDir = workDir, + pulumiHome = pulumiHome, + envVars = envVars, + pulumiVersion = currentVersion, + program = opts.program.asOption, + remote = opts.remote, + project = opts.project.asOption, + stacks = opts.stacks, + rawSecretsProvider = AtomicReference(opts.secretsProvider.asOption), + repo = opts.repo.asOption, + remoteEnvVars = opts.remoteEnvVars, + preRunCommands = opts.preRunCommands, + remoteSkipInstallDependencies = opts.remoteSkipInstallDependencies + ) + + // save the project settings if provided + def saveProjectSettings(ws: Workspace): Either[Exception, Unit] = + opts.project match + case project: Project => + ws.saveProjectSettings(project) match + case Left(e) => Left(AutoError(s"failed to create workspace, unable to save project settings: ${e.getMessage}", e)) + case Right(_) => Right(()) // OK, saved + case NotProvided => Right(()) // no project to save, skip + end match + end saveProjectSettings + + // save all provided stack settings + def saveAllStackSettings(ws: Workspace): Either[Exception, Unit] = + def save(el: (String, ProjectStack)) = + val (stackName, stack) = el + ws.saveStackSettings(stackName, stack).left.map { e => + AutoError(s"failed to create workspace, unable to save stack settings: ${e.getMessage}", e) + } + end save + + val it = opts.stacks.iterator + while it.hasNext do + save(it.next()) match + case left @ Left(_) => return left + case Right(_) => // OK, saved + Right(()) + end saveAllStackSettings + + // run setup callback if we have a repo and we're not remote + def runRepoSetupFn(ws: Workspace): Either[Exception, Unit] = + opts.repo match + case repo: GitRepo if !opts.remote => + repo.setup.asOption match + // now run the setup callback + case Some(f: SetupFn) => + f.apply(ws).left.map { e => + AutoError(s"failed to create workspace, error while running git repository setup function: ${e.getMessage}", e) + } + case None => Right(()) // no repo setup callback, skip + case _ => Right(()) // no repo to setup or remote, skip the setup callback + end match + end runRepoSetupFn + + for + ws <- maybeWorkspace + _ <- saveProjectSettings(ws) + _ <- saveAllStackSettings(ws) + _ <- runRepoSetupFn(ws) + yield ws + end apply + + private def pulumiVersion: Either[Exception, String] = + shell.pulumi("version")() match + case Left(e) => Left(e.withMessage("could not determine pulumi version")) + case Right(r) => Right(r.out.trim) + end pulumiVersion + + private def parseAndValidatePulumiVersion( + minimalVersion: model.SemanticVersion, + currentVersion: String, + optOut: Boolean + ): Either[Exception, model.SemanticVersion] = + model.SemanticVersion.parseTolerant(currentVersion) match + case Left(e) => + Left( + AutoError( + s"Unable to parse Pulumi CLI version (skip with ${shell.pulumi.env.PulumiAutomationApiSkipVersionCheckEnv}=true): ${e.getMessage}" + ) + ) + case r @ Right(v) => + if !optOut && v < minimalVersion then + Left( + AutoError( + s"Pulumi CLI version is too old (skip with ${shell.pulumi.env.PulumiAutomationApiSkipVersionCheckEnv}=true): ${currentVersion} < ${v}" + ) + ) + else r + end parseAndValidatePulumiVersion + + /** Checks if a specified flag is supported by running a command with `--help` and checking if the flag is found within the resulting + * output. + * + * @param flag + * The flag to check for support + * @param additional + * The additional command arguments + * @return + * A boolean indicating if the flag is supported or an exception if the command failed + */ + private def supportsPulumiCmdFlag(flag: String, additional: os.Shellable*): Either[Exception, Boolean] = + import shell.ShellOption.* + // Run the command with `--help`, and then we'll look for the flag in the output. + val allArgs: Seq[os.Shellable] = "--help" +: additional + shell.pulumi(allArgs*)( + Env(shell.pulumi.env.PulumiDebugCommandsEnv, "true"), + Env(shell.pulumi.env.PulumiExperimentalEnv, "true") + ) match + case Left(e) => Left(e.withMessage(s"could not determine pulumi supported flags")) + case Right(r) => + // Does the help test in stdout mention the flag? If so, assume it's supported. + Right(r.out.contains(flag)) + + end supportsPulumiCmdFlag + + private[auto] final case class InitializedLocalWorkspace private[auto] ( + workDir: os.Path, + pulumiHome: Option[os.Path], + protected val envVars: AtomicReference[mutable.Map[String, String]], + program: Option[RunFunc], + protected val rawSecretsProvider: AtomicReference[Option[String]], + pulumiVersion: model.SemanticVersion, + remote: Boolean, + project: Option[Project], + stacks: Map[String, ProjectStack], + repo: Option[GitRepo], + remoteEnvVars: Map[String, EnvVarValue], + preRunCommands: List[String], + remoteSkipInstallDependencies: Boolean + ) extends LocalWorkspace + + // stack names come in many forms: + // s, o/p/s, u/p/s o/s + // so just return the last chunk which is what will be used in pulumi..yaml + private def getStackSettingsName(stackName: String) = StackName(stackName).parts._3 + + private def readProjectSettingsFromDir(workDir: os.Path): Either[Exception, Project] = + SettingsExtensions + .map { ext => workDir / shell.pulumi.ProjectFileName(ext) } + .collectFirst { + case projectPath if os.exists(projectPath) => + Project + .load(projectPath) + .left + .map(e => AutoError(s"failed to load project settings: ${e.getMessage}", e)) + } match + case Some(value) => value + case None => Left(AutoError("unable to find project settings in workspace")) + end readProjectSettingsFromDir + + private def readStackSettingFromDir(workDir: os.Path, stackName: String): Either[Exception, ProjectStack] = + val actualStackName = getStackSettingsName(stackName) + SettingsExtensions + .map { ext => workDir / shell.pulumi.StackFileName(actualStackName, ext) } + .collectFirst { + case projectPath if os.exists(projectPath) => + ProjectStack + .load(projectPath) + .left + .map(e => AutoError(s"failed to load stack settings: ${e.getMessage}", e)) + } match + case Some(value) => value + case None => Left(AutoError("unable to find stack settings in workspace")) + + private[auto] def getProjectSettings( + projectName: String, + opts: Seq[LocalWorkspaceOption] + ): Either[Exception, Project] = + val options = LocalWorkspaceOptions.from(opts*) + + options.project match + // If the Project is included in the opts, just use that. + case project: Project => Right(project) + case NotProvided => + // If WorkDir is specified, try to read any existing project settings before resorting to + // creating a default project. + options.workDir match + case path: os.Path => + readProjectSettingsFromDir(path) match + case Left(AutoError(Some(msg), _)) if msg == "unable to find project settings in workspace" => + defaultInlineProject(projectName) + case Left(e) => Left(AutoError(s"failed to load project '$projectName' settings: $e", e)) + case r => r + case NotProvided => + // If there was no workdir specified, create the default project. + defaultInlineProject(projectName) + end getProjectSettings + + private def defaultInlineProject(projectName: String): Either[Exception, Project] = + Try { + Project( + name = PackageName.parse(projectName), + runtime = "scala", + main = Some(os.pwd.toString()) + ) + }.toEither.left.map(e => AutoError(s"failed to create default project settings: ${e.getMessage}", e)) + end defaultInlineProject +end LocalWorkspace + +sealed trait LocalWorkspaceOption +object LocalWorkspaceOption: + + /** The directory to execute commands from and store state. Defaults to a tmp dir. + * @param path + * work directory to use + */ + case class WorkDir(path: os.Path) extends LocalWorkspaceOption + + /** The Pulumi program to execute. If none is supplied, the program identified in `$WORKDIR/Pulumi.yaml` will be used instead. + * @param program + * the Pulumi program to execute + */ + // not a case class because function won't be useful in equality checks + class Program(val program: RunFunc) extends LocalWorkspaceOption + object Program: + def apply(program: RunFunc): Program = new Program(program) + def unapply(p: Program): Option[RunFunc] = Some(p.program) + + /** The path to the Pulumi home directory. + * + * Overrides the metadata directory for pulumi commands. This customizes the location of `$PULUMI_HOME` where metadata is stored and + * plugins are installed. If not provided, will be read from the environment variable `PULUMI_HOME` or default to `~/.pulumi` + */ + case class PulumiHome(path: os.Path) extends LocalWorkspaceOption + + /** The project settings for the workspace. + */ + case class Project(project: besom.auto.Project) extends LocalWorkspaceOption + + /** A map of `[stackName -> stack settings objects]` to seed the workspace. + */ + case class Stacks(stacks: Map[String, besom.auto.ProjectStack]) extends LocalWorkspaceOption + + /** A git repo with a Pulumi Project to clone into the `workDir`. + */ + case class Repo(repo: GitRepo) extends LocalWorkspaceOption + + /** The Secrets Provider to use with the current Stack. + */ + case class SecretsProvider(provider: String) extends LocalWorkspaceOption + + /** A map of environment values scoped to the workspace. These values will be passed to all Workspace and Stack level commands. + */ + case class EnvVars(envVars: Map[String, String]) extends LocalWorkspaceOption + object EnvVars: + def apply(env: (String, String)*): EnvVars = new EnvVars(env.toMap) + def apply(key: String, value: String): EnvVars = EnvVars(Map(key -> value)) + + /** Whether the workspace represents a remote workspace. + */ + case object Remote extends LocalWorkspaceOption + + /** Remote environment variables to be passed to the remote Pulumi operation. + */ + case class RemoteEnvVars(envVars: Map[String, EnvVarValue]) extends LocalWorkspaceOption + + /** An optional list of arbitrary commands to run before the remote Pulumi operation is invoked. + */ + case class PreRunCommands(commands: List[String]) extends LocalWorkspaceOption + + /** Sets whether to skip the default dependency installation step. + */ + case object RemoteSkipInstallDependencies extends LocalWorkspaceOption + +end LocalWorkspaceOption + +/** The configuration options for a [[LocalWorkspace]]. + * + * @param workDir + * the directory to execute commands from and store state. Defaults to a tmp dir. + * @param program + * the Pulumi Program to execute. If none is supplied, the program identified in `$WORKDIR/Pulumi.yaml` will be used instead. + * @param pulumiHome + * the path to the Pulumi home directory.* Overrides the metadata directory for pulumi commands. This customizes the location of + * `$PULUMI_HOME` where metadata is stored and plugins are installed. If not provided, will be read from the environment variable + * `PULUMI_HOME` or default to `~/.pulumi` + * @param project + * the project settings for the workspace. + * @param stacks + * a map of `[stackName -> stack settings objects]` to seed the workspace. + * @param repo + * a git repo with a Pulumi Project to clone into the `workDir`. + * @param secretsProvider + * the Secrets Provider to use with the current Stack. + * @param envVars + * a map of environment values scoped to the workspace. These values will be passed to all Workspace and Stack level commands. + * @param remote + * whether the workspace represents a remote workspace. + * @param remoteEnvVars + * remote environment variables to be passed to the remote Pulumi operation. + * @param preRunCommands + * an optional list of arbitrary commands to run before the remote Pulumi operation is invoked. + * @param remoteSkipInstallDependencies + * sets whether to skip the default dependency installation step. + */ +case class LocalWorkspaceOptions( + workDir: NotProvidedOr[os.Path] = NotProvided, + program: NotProvidedOr[RunFunc] = NotProvided, + pulumiHome: NotProvidedOr[os.Path] = NotProvided, + project: NotProvidedOr[Project] = NotProvided, + stacks: Map[String, ProjectStack] = Map.empty, + repo: NotProvidedOr[GitRepo] = NotProvided, + secretsProvider: NotProvidedOr[String] = NotProvided, + envVars: Map[String, String] = Map.empty, + remote: Boolean = false, + remoteEnvVars: Map[String, EnvVarValue] = Map.empty, + preRunCommands: List[String] = List.empty, + remoteSkipInstallDependencies: Boolean = false +) +object LocalWorkspaceOptions: + /** Merge options, last specified value wins + * @return + * a new [[LocalWorkspaceOptions]] + */ + def from(opts: LocalWorkspaceOption*): LocalWorkspaceOptions = from(opts.toList) + def from(opts: List[LocalWorkspaceOption]): LocalWorkspaceOptions = + opts match + case LocalWorkspaceOption.WorkDir(path) :: tail => from(tail).copy(workDir = path) + case LocalWorkspaceOption.Program(program) :: tail => from(tail).copy(program = program) + case LocalWorkspaceOption.PulumiHome(path) :: tail => from(tail).copy(pulumiHome = path) + case LocalWorkspaceOption.Project(project) :: tail => from(tail).copy(project = project) + case LocalWorkspaceOption.Stacks(stacks) :: tail => from(tail).copy(stacks = stacks) + case LocalWorkspaceOption.Repo(repo) :: tail => from(tail).copy(repo = repo) + case LocalWorkspaceOption.SecretsProvider(provider) :: tail => from(tail).copy(secretsProvider = provider) + case LocalWorkspaceOption.Remote :: tail => from(tail).copy(remote = true) + case LocalWorkspaceOption.RemoteEnvVars(envVars) :: tail => from(tail).copy(remoteEnvVars = envVars) + case LocalWorkspaceOption.PreRunCommands(commands) :: tail => from(tail).copy(preRunCommands = commands) + case LocalWorkspaceOption.RemoteSkipInstallDependencies :: tail => from(tail).copy(remoteSkipInstallDependencies = true) + case LocalWorkspaceOption.EnvVars(env) :: tail => { + val old = from(tail*) + old.copy(envVars = old.envVars ++ env) + } + case Nil => LocalWorkspaceOptions() + case o => throw AutoError(s"Unknown LocalWorkspaceOption: $o") + +/** GitRepo contains info to acquire and setup a Pulumi program from a git repository. + * + * @param url + * URL to clone git repo + * @param projectPath + * Optional path relative to the repo root specifying location of the pulumi program. Specifying this option will update the + * [[Workspace.workDir]] accordingly. + * @param branch + * Optional branch to checkout. + * @param commitHash + * Optional commit to checkout. + * @param setup + * Optional function to execute after enlisting in the specified repo. + * @param auth + * GitAuth is the different Authentication options for the Git repository + * @param shallow + * Shallow disables fetching the repo's entire history. + */ +case class GitRepo( + url: String, + projectPath: NotProvidedOr[String] = NotProvided, + branch: NotProvidedOr[String] = NotProvided, + commitHash: NotProvidedOr[String] = NotProvided, + setup: NotProvidedOr[SetupFn] = NotProvided, + auth: NotProvidedOr[GitAuth] = NotProvided, + shallow: Boolean = false +) + +type SetupFn = Workspace => Either[Exception, Unit] + +/** GitAuth is the authentication details that can be specified for a private Git repo. + * + * There are 3 different authentication paths: + * - [[PersonalAccessToken]] + * - [[SSHPrivateKeyPath]] or [[SSHPrivateKey]] (and it's potential passphrase) + * - [[UsernameAndPassword]] + */ +sealed trait GitAuth +object GitAuth: + + /** Use GitHub Personal Access Token + * @param token + * a GitHub personal access token in replacement of your password + */ + case class PersonalAccessToken(token: String) extends GitAuth + + /** Use SSH Private Key + * + * When using [[SSHPrivateKeyPath]], the URL of the repository must be in the format `git@github.com:org/repository.git` - if the url is + * not in this format, then an error 'unable to clone repo: invalid auth method' will be returned + * + * @param path + * the absolute path to a private key for access to the git repo + * @param passphrase + * the optional passphrase for the SSH Private Key + */ + case class SSHPrivateKeyPath(path: String, passphrase: NotProvidedOr[String]) extends GitAuth + + /** Use SSH Private Key + * + * When using [[SSHPrivateKey]] the URL of the repository must be in the format `git@github.com:org/repository.git` - if the url is not + * in this format, then an error 'unable to clone repo: invalid auth method' will be returned + * @param key + * the (contents) private key for access to the git repo + * @param passphrase + * the optional passphrase for the SSH Private Key + */ + case class SSHPrivateKey(key: String, passphrase: NotProvidedOr[String]) extends GitAuth + + /** Use Username and Password + * @param username + * the username to use when authenticating to a git repository + * @param password + * the password that pairs with a username for authentication to a git repository + */ + case class UsernameAndPassword(username: String, password: String) extends GitAuth +end GitAuth + +/** EnvVarValue represents the value of an envvar. A value can be a secret, which is passed along to remote operations when used with remote + * workspaces, otherwise, it has no effect. + * + * @param value + * the value of the environment variable + * @param secret + * a boolean indicating whether the value is a secret or not + */ +case class EnvVarValue(value: String, secret: Boolean = false) diff --git a/auto/src/main/scala/besom/auto/Stack.scala b/auto/src/main/scala/besom/auto/Stack.scala new file mode 100644 index 00000000..80a50588 --- /dev/null +++ b/auto/src/main/scala/besom/auto/Stack.scala @@ -0,0 +1,1545 @@ +package besom.auto + +import besom.internal.{LanguageRuntimeServer, LanguageRuntimeService} +import besom.json.* +import besom.json.DefaultJsonProtocol.* +import besom.util.* + +import scala.util.Try + +/** Stack is an isolated, independently configurable instance of a Pulumi program. Stack exposes methods for the full pulumi lifecycle + * (up/preview/refresh/destroy), as well as managing configuration. Multiple Stacks are commonly used to denote different phases of + * development (such as development, staging and production) or feature branches (such as feature-x-dev, jane-feature-x-dev). + * + * @param name + * the name identifying the stack + * @param workspace + * the underlying [[Workspace]] backing the [[Stack]] + */ +case class Stack(name: String, workspace: Workspace): + import besom.auto.Stack.* + + protected[auto] def pulumi(additional: os.Shellable*)(opts: shell.ShellOption*): Either[ShellAutoError | AutoError, shell.Result] = + for + _ <- + if workspace.remote then + workspace + .serializeArgsForOp(name) + .left + .map(e => AutoError("Failed to run command, error getting additional args", e)) + else Right(()) + + result <- workspace.pulumi(additional)(opts*) + + _ <- + if workspace.remote then + workspace + .postCommandCallback(name) + .left + .map(e => AutoError("Command ran successfully, but failed to run post command callback", e)) + else Right(()) + yield result + end pulumi + + /** Edits the secrets provider for the stack. + * + * @see + * [[Workspace.changeStackSecretsProvider]] + * + * @param newSecretsProvider + * The new secrets provider. + * @param options + * The options for changing the secrets provider. + * @return + * Unit indicating success or failure. + */ + def changeSecretsProvider(newSecretsProvider: String, options: ChangeSecretsProviderOption*): Either[Exception, Unit] = + workspace.changeStackSecretsProvider(name, newSecretsProvider, options*) + + /** Preview preforms a dry-run update to a stack, returning pending changes. + * @see + * [[https://www.pulumi.com/docs/reference/cli/pulumi_preview/]] + * @param options + * the options for the preview operation + * @return + * the preview result or an error if any + */ + def preview(options: PreviewOption*): Either[Exception, PreviewResult] = + val opts = PreviewOptions.from(options*) + + val sharedArgs: Seq[String] = opts.debugLogOpts.asArgs + ++ opts.message.map(s"--message=" + _) + ++ Option.when(opts.expectNoChanges)("--expect-no-changes") + ++ Option.when(opts.diff)("--diff") + ++ opts.replace.map("--replace=" + _) + ++ opts.target.map("--target=" + _) + ++ opts.policyPacks.map("--policy-pack=" + _) + ++ opts.policyPackConfigs.map("--policy-pack-config=" + _) + ++ Option.when(opts.targetDependents)("--target-dependents") + ++ opts.parallel.filter(_ > 0).map(s"--parallel=" + _) + ++ opts.userAgent.map(s"--exec-agent=" + _) + ++ opts.color.map(s"--color=" + _) + ++ opts.plan.map(s"--save-plan=" + _) + ++ remoteArgs // Apply the remote args, if needed + + val kindArgs: Seq[String] = + if workspace.program.isDefined then + val address = startLanguageRuntimeServer() + Seq(s"--exec-kind=${ExecKind.AutoInline}", s"--client=$address") + else Seq(s"--exec-kind=${ExecKind.AutoLocal}") + + /* case class EventLogListener(path: os.Path, private val acc: scala.collection.mutable.ArrayBuffer[EngineEvent]) + extends shell.Tailer.Listener: + import shell.Tailer.Listener + override def handle(event: Listener.Event): Unit = event match + case Listener.Event.FileNotFound(path) => println(s"Event log listener file not found: $path") // TODO: log + case Listener.Event.FileRotated(path) => println(s"Event log listener file rotated: $path") // TODO: log + case Listener.Event.Error(ex) => throw AutoError("Event log listener error", ex) + case Listener.Event.Line(line) => + EngineEvent + .fromJson(line) + .fold( + ex => throw AutoError(s"Failed to parse engine event: $line", ex), + ee => acc += ee + ) + end handle + def events: Seq[EngineEvent] = acc.toSeq + def summary: Either[AutoError, SummaryEvent] = + val l = events.filter(_.summaryEvent.isDefined) + if l.isEmpty then Left(AutoError("Failed to get preview summary, got no engine events")) + else if l.size > 1 then Left(AutoError("Failed to get preview summary, got multiple engine events, expected a singleton")) + else l.head.summaryEvent.toRight(AutoError("Failed to get preview summary, got no summary event")) + end summary + end EventLogListener + object EventLogListener: + def apply(path: os.Path): EventLogListener = EventLogListener(path, scala.collection.mutable.ArrayBuffer.empty) + */ + for + tailerPath <- tailLogsPath("preview") + /*resultAndListener <- shell.Tailer(path = tailerPath, listener = EventLogListener.apply) { listener => + val watchArgs: Seq[String] = Seq("--event-log=" + tailerPath) + val args: Seq[String] = Seq("preview") ++ sharedArgs ++ kindArgs ++ watchArgs + val result = pulumi(args)( + // FIXME: implement progressStreams and errorProgressStreams + // shell.Option.Stdout(opts.progressStreams), + // shell.Option.Stderr(opts.errorProgressStreams) + ).left.map(AutoError("Preview failed", _)) + println(os.proc("cat", tailerPath).call().out.text()) + println(s"Preview result: $result") + (result, listener) + } + r <- resultAndListener._1 + summary <- resultAndListener._2.summary.left.map(e => AutoError("Failed to get preview summary", e))*/ + r <- { + val watchArgs: Seq[String] = Seq("--event-log=" + tailerPath) + val args: Seq[String] = Seq("preview") ++ sharedArgs ++ kindArgs ++ watchArgs + pulumi(args)().left.map(AutoError("Preview failed", _)) + } + summary <- + os.read + .lines(tailerPath) + .map(EngineEvent.fromJson(_)) + .collectFirst { + case Right(ee) if ee.summaryEvent.isDefined => ee.summaryEvent.get + } + .toRight(AutoError("Failed to get preview summary, got no summary event")) + /*r <- shell.Tailer2() { + val watchArgs: Seq[String] = Seq("--event-log=" + tailerPath) + val args: Seq[String] = Seq("preview") ++ sharedArgs ++ kindArgs ++ watchArgs + pulumi(args)().left.map(AutoError("Preview failed", _)) + }*/ + yield PreviewResult(stdout = r.out, stderr = r.err, summary = summary.resourceChanges) + end for + end preview + + /** Create or update the resources in a stack by executing the program in the Workspace. Update updates the resources in a stack by + * executing the program in the Workspace associated with this stack, if one is provided. + * @see + * [[https://www.pulumi.com/docs/reference/cli/pulumi_up/]] + * @param options + * the options for the update operation + * @return + * the update result or an error if any + */ + def up(options: UpOption*): Either[Exception, UpResult] = + val opts = UpOptions.from(options*) + + val sharedArgs = opts.debugLogOpts.asArgs + ++ opts.message.map(s"--message=" + _) + ++ Option.when(opts.expectNoChanges)("--expect-no-changes") + ++ Option.when(opts.diff)("--diff") + ++ opts.replace.map("--replace=" + _) + ++ opts.target.map("--target=" + _) + ++ opts.policyPacks.map("--policy-pack=" + _) + ++ opts.policyPackConfigs.map("--policy-pack-config=" + _) + ++ Option.when(opts.targetDependents)("--target-dependents") + ++ opts.parallel.filter(_ > 0).map(s"--parallel=" + _) + ++ opts.userAgent.map(s"--exec-agent=" + _) + ++ opts.color.map(s"--color=" + _) + ++ opts.plan.map(s"--plan=" + _) + ++ remoteArgs // Apply the remote args, if needed + + val kindArgs: Seq[String] = + if workspace.program.isDefined then + val address = startLanguageRuntimeServer() + Seq(s"--exec-kind=${ExecKind.AutoInline}", s"--client=$address") + else Seq(s"--exec-kind=${ExecKind.AutoLocal}") + + val watchArgs: Seq[String] = Seq.empty // TODO: implement watchArgs + + val args: Seq[String] = Seq("up", "--yes", "--skip-preview") ++ sharedArgs ++ kindArgs ++ watchArgs + + pulumi(args)( +// FIXME: implement progressStreams and errorProgressStreams +// shell.Option.Stdout(opts.progressStreams), +// shell.Option.Stderr(opts.errorProgressStreams) + ) match + case Left(e) => Left(AutoError("Up failed", e)) + case Right(r) => + for + outputs <- outputs + history <- history( + pageSize = 1, + page = 1, + /* If it's a remote workspace, don't set ShowSecrets to prevent attempting to load the project file. */ + Option.when(opts.showSecrets && !isRemote)(HistoryOption.ShowSecrets).toSeq* + ).flatMap(_.headOption.toRight(AutoError("Failed to get history, result was empty"))) + yield UpResult( + stdout = r.out, + stderr = r.err, + outputs = outputs, + summary = history + ) + end up + + /** Refresh compares the current stack’s resource state with the state known to exist in the actual cloud provider. Any such changes are + * adopted into the current stack. + * + * @see + * [[https://www.pulumi.com/docs/reference/cli/pulumi_refresh/]] + * @param options + * the options for the refresh operation + * @return + * the refresh result or an error if any + */ + def refresh(options: RefreshOption*): Either[Exception, RefreshResult] = + val opts = RefreshOptions.from(options*) + + val sharedArgs = opts.debugLogOpts.asArgs + ++ opts.message.map(s"--message=" + _) + ++ Option.when(opts.expectNoChanges)("--expect-no-changes") + ++ opts.target.map("--target=" + _) + ++ opts.parallel.filter(_ > 0).map(s"--parallel=" + _) + ++ opts.userAgent.map(s"--exec-agent=" + _) + ++ opts.color.map(s"--color=" + _) + ++ (if workspace.program.isDefined then Seq(s"--exec-kind=${ExecKind.AutoInline}") else Seq(s"--exec-kind=${ExecKind.AutoLocal}")) + ++ remoteArgs // Apply the remote args, if needed + + val args: Seq[String] = Seq("refresh", "--yes", "--skip-preview") ++ sharedArgs + pulumi(args)() match + case Left(e) => Left(AutoError("Refresh failed", e)) + case Right(r) => + for history <- history( + pageSize = 1, + page = 1, + /* If it's a remote workspace, don't set ShowSecrets to prevent attempting to load the project file. */ + Option.when(opts.showSecrets && !isRemote)(HistoryOption.ShowSecrets).toSeq* + ).flatMap(_.headOption.toRight(AutoError("Failed to get history, result was empty"))) + yield RefreshResult( + stdout = r.out, + stderr = r.err, + summary = history + ) + end refresh + + /** Destroy deletes all resources in a stack, leaving all history and configuration intact. + * + * @see + * [[https://www.pulumi.com/docs/reference/cli/pulumi_destroy/]] + * @param options + * the options for the destroy operation + * @return + * the destroy result or an error if any + */ + def destroy(options: DestroyOption*): Either[Exception, DestroyResult] = + val opts = DestroyOptions.from(options*) + + val sharedArgs = opts.debugLogOpts.asArgs + ++ opts.message.map(s"--message=" + _) + ++ opts.target.map("--target=" + _) + ++ Option.when(opts.targetDependents)("--target-dependents") + ++ opts.parallel.filter(_ > 0).map(s"--parallel=" + _) + ++ opts.userAgent.map(s"--exec-agent=" + _) + ++ opts.color.map(s"--color=" + _) + ++ (if workspace.program.isDefined then Seq(s"--exec-kind=${ExecKind.AutoInline}") else Seq(s"--exec-kind=${ExecKind.AutoLocal}")) + ++ remoteArgs // Apply the remote args, if needed + + val args: Seq[String] = Seq("destroy", "--yes", "--skip-preview") ++ sharedArgs + pulumi(args)() match + case Left(e) => Left(AutoError("Destroy failed", e)) + case Right(r) => + for history <- history( + pageSize = 1, + page = 1, + /* If it's a remote workspace, don't set ShowSecrets to prevent attempting to load the project file. */ + Option.when(opts.showSecrets && !isRemote)(HistoryOption.ShowSecrets).toSeq* + ).flatMap(_.headOption.toRight(AutoError("Failed to get history, result was empty"))) + yield DestroyResult( + stdout = r.out, + stderr = r.err, + summary = history + ) + + end destroy + + /** Get the current set of [[Stack]] outputs from the last [[Stack.up]] + */ + def outputs: Either[Exception, OutputMap] = workspace.stackOutputs(name) + + /** History returns a list summarizing all previous and current results from [[Stack]] lifecycle operations (up/preview/refresh/destroy). + * + * @param pageSize + * used with 'page' to control number of results returned (e.g. 10) + * @param page + * used with 'page-size' to paginate results (e.g. 1) + * @param options + * the options for the history operation + * @return + * the history result or an error if any + */ + def history(pageSize: Int, page: Int, options: HistoryOption*): Either[Exception, List[UpdateSummary]] = + val opts = HistoryOptions.from(options*) + val args = Seq.empty[String] + ++ Option.when(opts.showSecrets)("--show-secrets") + ++ Option + .when(pageSize > 0) { + Seq(s"--page-size=$pageSize", s"--page=${if page < 1 then 1 else page}") + } + .toSeq + .flatten + + pulumi("stack", "history", "--json", args)().fold( + e => Left(AutoError("History failed", e)), + r => UpdateSummary.fromJsonList(r.out).left.map(e => AutoError("Failed to parse history JSON", e)) + ) + end history + + /** Adds environments to the end of a stack's import list. Imported environments are merged in order per the ESC merge rules. The list of + * environments behaves as if it were the import list in an anonymous environment. + * + * @param envs + * the environments to add + * @return + * returns nothing if successful, or an error if any + */ + def addEnvironments(envs: String*): Either[Exception, Unit] = + workspace.addEnvironments(name, envs*) + + /** ListEnvironments returns the list of environments from the stack's configuration. + * + * @return + * the list of environments or an error if any + */ + def listEnvironments: Either[Exception, List[String]] = + workspace.listEnvironments(name) + + /** Removes an environment from a stack's configuration. + * + * @param env + * the environment to remove + * @return + * nothing if successful, or an error if any + */ + def removeEnvironment(env: String): Either[Exception, Unit] = + workspace.removeEnvironment(name, env) + + /** Gets the config value associated with the specified key and the optional [[ConfigOption]]s. + * + * @param key + * the key of the config + * @param opts + * the optional [[ConfigOption]]s + * @return + * the [[ConfigValue]] or an error if any + */ + def getConfig(key: String, opts: ConfigOption*): Either[Exception, ConfigValue] = + workspace.getConfig(name, key, opts*) + + /** Gets the full config map. + * + * @return + * the ConfigMap or an error if any + */ + def getAllConfig: Either[Exception, ConfigMap] = + workspace.getAllConfig(name) + + /** Sets the specified config key-value pair using the optional [[ConfigOption]]s. + * + * @param key + * the key of the config + * @param value + * the value to set + * @return + * nothing if successful, or an error if any + */ + def setConfig(key: String, value: ConfigValue, options: ConfigOption*): Either[Exception, Unit] = + workspace.setConfig(name, key, value, options*) + + /** Sets all values in the provided config map using the optional [[ConfigOption]]s. + * + * @param config + * the config map to set. + * @param opts + * the optional [[ConfigOption]]s. + * @return + * nothing if successful, or an error if any + */ + def setAllConfig(config: ConfigMap, opts: ConfigOption*): Either[Exception, Unit] = + workspace.setAllConfig(name, config, opts*) + + /** Removes the specified config key-value pair using the optional [[ConfigOption]]s. + * + * @param key + * the key of the config to remove + * @param opts + * the optional ConfigOptions + * @return + * nothing if successful, or an error if any + */ + def removeConfig(key: String, opts: ConfigOption*): Either[Exception, Unit] = + workspace.removeConfig(name, key, opts*) + + /** Gets and sets the config map used with the last Update. + * @return + * the ConfigMap or an error if any + */ + def refreshConfig(): Either[Exception, ConfigMap] = + workspace.refreshConfig(name) + + /** Gets the tag value associated with specified key. + * + * @param key + * whe key of the tag + * @return + * the tag value or an error if any + */ + def getTag(key: String): Either[Exception, String] = + workspace.getTag(name, key) + + /** Sets a tag key-value pair on the stack. + * + * @param key + * the key of the tag + * @param value + * the value of the tag + * @return + * nothing if successful, or an error if any + */ + def setTag(key: String, value: String): Either[Exception, Unit] = + workspace.setTag(name, key, value) + + /** Removes the specified tag key-value pair from the stack. + * + * @param key + * the key of the tag to remove + * @return + * nothing if successful, or an error if any + */ + def removeTag(key: String): Either[Exception, Unit] = + workspace.removeTag(name, key) + + /** Returns the full key-value tag map associated with the stack. + * + * @return + * the tag map or an error if any + */ + def listTags: Either[Exception, Map[String, String]] = + workspace.listTags(name) + + /** @return + * a summary of the Stack including its URL + */ + def info: Either[Exception, Option[StackSummary]] = + for + _ <- workspace.selectStack(name) + s <- workspace.stack + yield s + end info + + /** Cancels a stack's currently running update. It returns an error if no update is currently running. Note that this operation is _very + * dangerous_, and may leave the stack in an inconsistent state if a resource operation was pending when the update was canceled. This + * command is not supported for local backends. + * + * @return + * nothing if successful, or an error if any + */ + def cancel(): Either[Exception, Unit] = + pulumi("cancel", "--yes")().fold( + e => Left(AutoError("Failed to cancel update", e)), + _ => Right(()) + ) + end cancel + + /** Exports the deployment state of the stack. This can be combined with [[Stack.importState]] to edit a stack's state (such as recovery + * from failed deployments). + * + * @return + * the deployment state of the stack or an error if any + */ + def exportState(): Either[Exception, UntypedDeployment] = + workspace.exportStack(name) + + /** Imports the specified deployment state into the stack. This can be combined with [[Stack.exportState]] to edit a stack's state (such + * as recovery from failed deployments). + * + * @param state + * The deployment state to import into the stack. + * @return + * nothing if successful, or an error if any + */ + def importState(state: UntypedDeployment): Either[Exception, Unit] = + workspace.importStack(name, state) + + /** @return + * returns true if the stack is remote + */ + def isRemote: Boolean = workspace.remote + + private def remoteArgs: Seq[String] = + def args( + repo: Option[GitRepo], + preRunCommands: List[String] = List.empty, + remoteEnvVars: Map[String, EnvVarValue] = Map.empty, + skipInstallDependencies: Boolean = false + ): Seq[String] = + repo.map(_.url).toSeq + ++ repo.flatMap(_.branch.map("--remote-git-branch=" + _)) + ++ repo.flatMap(_.commitHash.map("--remote-git-commit=" + _)) + ++ repo.flatMap(_.projectPath.map("--remote-git-repo-dir=" + _)) + ++ repo.toSeq.flatMap( + _.auth.asSeq.flatMap { + case GitAuth.PersonalAccessToken(token) => + Seq(s"--remote-git-auth-access-token=$token") + case GitAuth.SSHPrivateKey(key, passphrase) => + Seq(s"--remote-git-auth-ssh-private-key=$key") ++ passphrase.map("-remote-git-auth-password=" + _) + case GitAuth.SSHPrivateKeyPath(path, passphrase) => + Seq(s"--remote-git-auth-ssh-private-key-path=$path") ++ passphrase.map("-remote-git-auth-password=" + _) + case GitAuth.UsernameAndPassword(username, password) => + Seq(s"--remote-git-auth-username=$username", s"--remote-git-auth-password=$password") + } + ) + ++ preRunCommands.map("--remote-pre-run-command=" + _) + ++ remoteEnvVars.map { case (k, v) => s"--remote-env${if v.secret then "-secret" else ""}=$k=${v.value}" } + ++ Option.when(skipInstallDependencies)("--remote-skip-install-dependencies") + + workspace match + case ws: LocalWorkspace => + if !ws.remote then Seq.empty + else + args( + repo = ws.repo, + preRunCommands = ws.preRunCommands, + remoteEnvVars = ws.remoteEnvVars, + skipInstallDependencies = ws.remoteSkipInstallDependencies + ) + // TODO: implement RemoteWorkspace + case null => throw AutoError("Workspace is null") + case _ => throw AutoError(s"Unknown workspace type: ${workspace.getClass.getTypeName}") + end remoteArgs + + private def tailLogsPath(command: String): Either[Exception, os.Path] = + Try { + val logsDir = os.temp.dir(prefix = s"automation-logs-$command-") + val path = logsDir / "eventlog.txt" + os.write(path, "") + os.exists(path) match + case true => println(os.proc("ls", "-la", path).call().out.text()) + case false => throw AutoError(s"Failed to create event log file: $path") + path + }.toEither.left.map(e => AutoError("Failed to create temporary directory for event logs", e)) + end tailLogsPath + + private def startLanguageRuntimeServer(): String = + import concurrent.ExecutionContext.Implicits.global // FIXME: use a custom execution context + LanguageRuntimeServer(LanguageRuntimeService).start().toString + end startLanguageRuntimeServer + +end Stack + +object Stack: + /** A flag used to identify the origin of a command. */ + enum ExecKind(val value: String) extends Enum[ExecKind]: + override def toString: String = value + + /** Command originating from automation API using a traditional Pulumi project. */ + case AutoLocal extends ExecKind("auto.local") + + /** Command originating from automation API using an inline Pulumi project. + */ + case AutoInline extends ExecKind("auto.inline") + + /** Command originating from the CLI using a traditional Pulumi project. + */ + case CLI extends ExecKind("cli") + + def apply(name: String, workspace: Workspace): Stack = new Stack(name, workspace) + + /** Creates a new [[Stack]] using the given [[Workspace]] and stack name. It fails if a stack with that name already exists. + * + * @param stackName + * the name of the stack + * @param workspace + * the [[Workspace]] to use + * @return + * the [[Stack]] or an error if any + */ + def create(stackName: String, workspace: Workspace): Either[Exception, Stack] = + workspace.createStack(stackName) + + /** Selects a [[Stack]] using the given [[Workspace]] and stack name. It returns an error if the given [[Stack]] does not exist. + * @param stackName + * the name of the stack + * @param workspace + * the [[Workspace]] to use + * @return + * the [[Stack]] or an error if any + */ + def select(stackName: String, workspace: Workspace): Either[Exception, Stack] = + workspace.selectStack(stackName) + + /** Tries to select a [[Stack]] using the given [[Workspace]] and stack name, or falls back to trying to create the stack if it does not + * exist. + * + * @param stackName + * the name of the stack + * @param workspace + * the workspace to use + * @return + * the [[Stack]] or an error if any + */ + def upsert(stackName: String, workspace: Workspace): Either[Exception, Stack] = { + select(stackName, workspace).fold( + { + // If the stack is not found, attempt to create it. + case e: ShellAutoError if e.isSelectStack404Error => create(stackName, workspace) + case err => Left(err) + }, + Right(_) // If the stack was found, return it. + ) + } + +end Stack + +/** [[Stack.preview]] options + * @see + * [[PreviewOptions]] + */ +sealed trait PreviewOption +object PreviewOption: + + /** The number of resource operations to run in parallel at once during the update (1 for no parallelism). Defaults to unbounded. (default + * 2147483647) + */ + case class Parallel(n: Int) extends PreviewOption + + /** A message to associate with the preview operation + */ + case class Message(message: String) extends PreviewOption + + /** Will cause the preview to return an error if any changes occur + */ + case object ExpectNoChanges extends PreviewOption + + /** Displays operation as a rich diff showing the overall change + */ + case object Diff extends PreviewOption + + /** Specifies an array of resource URNs to explicitly replace during the preview + */ + case class Replace(urns: String*) extends PreviewOption + + /** Specifies an exclusive list of resource URNs to update + */ + case class Target(urns: String*) extends PreviewOption + + /** Allows updating of dependent targets discovered but not specified in the [[Target]] list + */ + case object TargetDependents extends PreviewOption + + /** Provides options for verbose logging to standard error, and enabling plugin logs. + */ + case class DebugLogging(debugOpts: LoggingOptions) extends PreviewOption + + /** Allows specifying one or more Writers to redirect incremental preview stdout + */ +// case class ProgressStreams(writers: os.ProcessOutput*) extends PreviewOption + + /** Allows specifying one or more Writers to redirect incremental preview stderr + */ +// case class ErrorProgressStreams(writers: os.ProcessOutput*) extends PreviewOption + + /** Allows specifying one or more channels to receive the Pulumi event stream + */ +// case class EventStreams(channels: EngineEvent*) extends PreviewOption + + /** Specifies the agent responsible for the update, stored in backends as "environment.exec.agent" + */ + case class UserAgent(agent: String) extends PreviewOption + + /** Colorize output. Choices are: [[besom.auto.Color.Always]], [[besom.auto.Color.Never]], [[besom.auto.Color.Raw]], + * [[besom.auto.Color.Auto]] (default "Auto") + */ + case class Color(color: besom.auto.Color) extends PreviewOption + + /** Saves an update plan to the given path. + */ + case class Plan(path: os.Path) extends PreviewOption + + /** Runs one or more policy packs as part of this update + */ + case class PolicyPacks(packs: String*) extends PreviewOption + + /** Path to a JSON file containing the config for the policy pack of the corresponding `--policy-pack` flag + */ + case class PolicyPackConfigs(path: os.Path*) extends PreviewOption +end PreviewOption + +/** [[Stack.preview]] options + * + * @see + * [[PreviewOption]] + * + * @param parallel + * the number of resource operations to run in parallel at once (1 for no parallelism). Defaults to unbounded. (default 2147483647) + * @param message + * message (optional) to associate with the preview operation + * @param expectNoChanges + * return an error if any changes occur during this preview + * @param diff + * diff displays operation as a rich diff showing the overall change + * @param replace + * Specify resources to replace + * @param target + * specify an exclusive list of resource URNs to update + * @param targetDependents + * allows updating of dependent targets discovered but not specified in the [[target]] list + * @param debugLogOpts + * specifies additional settings for debug logging + * @param progressStreams + * allows specifying one or more io.Writers to redirect incremental preview stdout + * @param errorProgressStreams + * allows specifying one or more io.Writers to redirect incremental preview stderr + * @param eventStreams + * allows specifying one or more channels to receive the Pulumi event stream + * @param userAgent + * the agent responsible for the update, stored in backends as "environment.exec.agent" + * @param color + * colorize output, choices are: always, never, raw, auto (default "auto") + * @param plan + * save an update plan to the given path + * @param policyPacks + * run one or more policy packs as part of this update + * @param policyPackConfigs + * path to JSON file containing the config for the policy pack of the corresponding "--policy-pack" flag + */ +private[auto] case class PreviewOptions( + parallel: NotProvidedOr[Int] = NotProvided, + message: NotProvidedOr[String] = NotProvided, + expectNoChanges: Boolean = false, + diff: Boolean = false, + replace: List[String] = List.empty, + target: List[String] = List.empty, + targetDependents: Boolean = false, + debugLogOpts: LoggingOptions = LoggingOptions(), +// progressStreams: List[os.ProcessOutput] = List.empty, // TODO: implement multiple writers +// errorProgressStreams: List[os.ProcessOutput] = List.empty, // TODO: implement multiple writers +// eventStreams: List[EngineEvent] = List.empty, // TODO: implement EngineEvent + userAgent: NotProvidedOr[String] = NotProvided, + color: NotProvidedOr[Color] = NotProvided, + plan: NotProvidedOr[os.Path] = NotProvided, + policyPacks: List[String] = List.empty, + policyPackConfigs: List[os.Path] = List.empty +) +object PreviewOptions: + /** Merge options, last specified value wins + * + * @return + * a new [[PreviewOptions]] + */ + def from(options: PreviewOption*): PreviewOptions = from(options.toList) + def from(options: List[PreviewOption]): PreviewOptions = + options match + case PreviewOption.Parallel(n) :: tail => from(tail*).copy(parallel = n) + case PreviewOption.Message(m) :: tail => from(tail*).copy(message = m) + case PreviewOption.ExpectNoChanges :: tail => from(tail*).copy(expectNoChanges = true) + case PreviewOption.Diff :: tail => from(tail*).copy(diff = true) + case PreviewOption.Replace(urns*) :: tail => from(tail*).copy(replace = urns.toList) + case PreviewOption.Target(urns*) :: tail => from(tail*).copy(target = urns.toList) + case PreviewOption.TargetDependents :: tail => from(tail*).copy(targetDependents = true) + case PreviewOption.DebugLogging(debugOpts) :: tail => from(tail*).copy(debugLogOpts = debugOpts) +// case PreviewOption.ProgressStreams(writers) :: tail => from(tail*).copy(progressStreams = writers) +// case PreviewOption.ErrorProgressStreams(writers) :: tail => from(tail*).copy(errorProgressStreams = writers) +// case PreviewOption.EventStreams(channels) :: tail => from(tail*).copy(eventStreams = channels) + case PreviewOption.UserAgent(agent) :: tail => from(tail*).copy(userAgent = agent) + case PreviewOption.Color(color) :: tail => from(tail*).copy(color = color) + case PreviewOption.Plan(path) :: tail => from(tail*).copy(plan = path) + case PreviewOption.PolicyPacks(packs*) :: tail => from(tail*).copy(policyPacks = packs.toList) + case PreviewOption.PolicyPackConfigs(paths*) :: tail => from(tail*).copy(policyPackConfigs = paths.toList) + case Nil => PreviewOptions() + case o => throw AutoError(s"Unknown preview option: $o") + +end PreviewOptions + +/** [[Stack.up]] options + * + * @see + * [[UpOption]] + */ +sealed trait UpOption +object UpOption: + /** The number of resource operations to run in parallel at once during the update (1 for no parallelism). Defaults to unbounded. (default + * 2147483647) + */ + case class Parallel(n: Int) extends UpOption + + /** Message (optional) to associate with the update operation + */ + case class Message(message: String) extends UpOption + + /** Will cause the update to return an error if any changes occur + */ + case object ExpectNoChanges extends UpOption + + /** Displays operation as a rich diff showing the overall change + */ + case object Diff extends UpOption + + /** Specifies an array of resource URNs to explicitly replace during the update + */ + case class Replace(urns: String*) extends UpOption + + /** Specifies an exclusive list of resource URNs to update + */ + case class Target(urns: String*) extends UpOption + + /** Allows updating of dependent targets discovered but not specified in the [[Target]] list + */ + case object TargetDependents extends UpOption + + /** Specifies additional settings for debug logging + */ + case class DebugLogging(debugOpts: LoggingOptions) extends UpOption + + /** Allows specifying one or more io.Writers to redirect incremental update stdout + */ + // case class ProgressStreams(writers: os.ProcessOutput*) extends UpOption + /** Allows specifying one or more io.Writers to redirect incremental update stderr + */ +// case class ErrorProgressStreams(writers: os.ProcessOutput*) extends UpOption + /** Allows specifying one or more channels to receive the Pulumi event stream + */ +// case class EventStreams(channels: EngineEvent*) extends UpOption + + /** Specifies the agent responsible for the update, stored in backends as "environment.exec.agent" + */ + case class UserAgent(agent: String) extends UpOption + + /** Colorize output. Choices are: [[besom.auto.Color.Always]], [[besom.auto.Color.Never]], [[besom.auto.Color.Raw]], + */ + case class Color(color: besom.auto.Color) extends UpOption + + /** Use the update plan at the given path. + */ + case class Plan(path: os.Path) extends UpOption + + /** Run one or more policy packs as part of this update + */ + case class PolicyPacks(packs: String*) extends UpOption + + /** Path to a JSON file containing the config for the policy pack of the corresponding `--policy-pack` flag + */ + case class PolicyPackConfigs(path: os.Path*) extends UpOption + + /** Show config secrets when they appear. + */ + case object ShowSecrets extends UpOption +end UpOption + +/** [[Stack.up]] options + * + * @see + * [[UpOption]] + * + * @param parallel + * the number of resource operations to run in parallel at once (1 for no parallelism). Defaults to unbounded. (default 2147483647) + * @param message + * message (optional) to associate with the preview operation + * @param expectNoChanges + * return an error if any changes occur during this preview + * @param diff + * diff displays operation as a rich diff showing the overall change + * @param replace + * specify resources to replace + * @param target + * specify an exclusive list of resource URNs to update + * @param targetDependents + * allows updating of dependent targets discovered but not specified in the Target list + * @param debugLogOpts + * specifies additional settings for debug logging + * @param progressStreams + * allows specifying one or more io.Writers to redirect incremental preview stdout + * @param errorProgressStreams + * allows specifying one or more io.Writers to redirect incremental preview stderr + * @param eventStreams + * allows specifying one or more channels to receive the Pulumi event stream + * @param userAgent + * specifies the agent responsible for the update, stored in backends as "environment.exec.agent" + * @param color + * colorize output, choices are: always, never, raw, auto (default "auto") + * @param plan + * save an update plan to the given path + * @param policyPacks + * run one or more policy packs as part of this update + * @param policyPackConfigs + * path to JSON file containing the config for the policy pack of the corresponding "--policy-pack" flag + * @param showSecrets + * show config secrets when they appear + */ +case class UpOptions( + parallel: NotProvidedOr[Int] = NotProvided, + message: NotProvidedOr[String] = NotProvided, + expectNoChanges: Boolean = false, + diff: Boolean = false, + replace: List[String] = List.empty, + target: List[String] = List.empty, + targetDependents: Boolean = false, + debugLogOpts: LoggingOptions = LoggingOptions(), +// progressStreams: List[os.ProcessOutput] = List.empty, // TODO: implement multiple writers +// errorProgressStreams: List[os.ProcessOutput] = List.empty, // TODO: implement multiple writers +// eventStreams: List[EngineEvent] = List.empty, // TODO: implement EngineEvent + userAgent: NotProvidedOr[String] = NotProvided, + color: NotProvidedOr[Color] = NotProvided, + plan: NotProvidedOr[os.Path] = NotProvided, + policyPacks: List[String] = List.empty, + policyPackConfigs: List[os.Path] = List.empty, + showSecrets: Boolean = false +) +object UpOptions: + def from(options: UpOption*): UpOptions = from(options.toList) + def from(options: List[UpOption]): UpOptions = + options match + case UpOption.Parallel(n) :: tail => from(tail*).copy(parallel = n) + case UpOption.Message(m) :: tail => from(tail*).copy(message = m) + case UpOption.ExpectNoChanges :: tail => from(tail*).copy(expectNoChanges = true) + case UpOption.Diff :: tail => from(tail*).copy(diff = true) + case UpOption.Replace(urns*) :: tail => from(tail*).copy(replace = urns.toList) + case UpOption.Target(urns*) :: tail => from(tail*).copy(target = urns.toList) + case UpOption.TargetDependents :: tail => from(tail*).copy(targetDependents = true) + case UpOption.DebugLogging(debugOpts) :: tail => from(tail*).copy(debugLogOpts = debugOpts) +// case UpOption.ProgressStreams(writers) :: tail => from(tail*).copy(progressStreams = writers) +// case UpOption.ErrorProgressStreams(writers) :: tail => from(tail*).copy(errorProgressStreams = writers) +// case UpOption.EventStreams(channels) :: tail => from(tail*).copy(eventStreams = channels) + case UpOption.UserAgent(agent) :: tail => from(tail*).copy(userAgent = agent) + case UpOption.Color(color) :: tail => from(tail*).copy(color = color) + case UpOption.Plan(path) :: tail => from(tail*).copy(plan = path) + case UpOption.PolicyPacks(packs*) :: tail => from(tail*).copy(policyPacks = packs.toList) + case UpOption.PolicyPackConfigs(paths*) :: tail => from(tail*).copy(policyPackConfigs = paths.toList) + case UpOption.ShowSecrets :: tail => from(tail*).copy(showSecrets = true) + case Nil => UpOptions() + case o => throw AutoError(s"Unknown up option: $o") + +end UpOptions + +/** [[Stack.refresh]] options + * + * @see + * [[RefreshOption]] + */ +sealed trait RefreshOption +object RefreshOption: + + /** the number of resource operations to run in parallel at once (1 for no parallelism). Defaults to unbounded. (default 2147483647) + */ + case class Parallel(n: Int) extends RefreshOption + + /** Message (optional) to associate with the refresh operation + */ + case class Message(message: String) extends RefreshOption + + /** Will cause the refresh to return an error if any changes occur + */ + case object ExpectNoChanges extends RefreshOption + + /** Specifies an array of resource URNs to explicitly refresh + */ + case class Target(urns: String*) extends RefreshOption + + /** Allows specifying one or more io.Writers to redirect incremental refresh stdout + */ +// case class ProgressStreams(writers: os.ProcessOutput*) extends RefreshOption + /** Allows specifying one or more io.Writers to redirect incremental refresh stderr + */ +// case class ErrorProgressStreams(writers: os.ProcessOutput*) extends RefreshOption + /** Allows specifying one or more channels to receive the Pulumi event stream + */ +// case class EventStreams(channels: EngineEvent*) extends RefreshOption + + /** Specifies additional settings for debug logging + */ + case class DebugLogging(debugOpts: LoggingOptions) extends RefreshOption + + /** Specifies the agent responsible for the refresh, stored in backends as "environment.exec.agent" + */ + case class UserAgent(agent: String) extends RefreshOption + + /** Colorize output. Choices are: [[besom.auto.Color.Always]], [[besom.auto.Color.Never]], [[besom.auto.Color.Raw]], + */ + case class Color(color: besom.auto.Color) extends RefreshOption + + /** Show config secrets when they appear. + */ + case object ShowSecrets extends RefreshOption + +end RefreshOption + +/** [[Stack.refresh]] options + * + * @see + * [[RefreshOption]] + * + * @param parallel + * the number of resource operations to run in parallel at once (1 for no parallelism). Defaults to unbounded. (default 2147483647) + * @param message + * message (optional) to associate with the refresh operation + * @param expectNoChanges + * return an error if any changes occur during this refresh + * @param target + * specify an exclusive list of resource URNs to update + * @param debugLogOpts + * specifies additional settings for debug logging + * @param progressStreams + * allows specifying one or more io.Writers to redirect incremental refresh stdout + * @param errorProgressStreams + * allows specifying one or more io.Writers to redirect incremental refresh stderr + * @param eventStreams + * allows specifying one or more channels to receive the Pulumi event stream + * @param userAgent + * specifies the agent responsible for the refresh, stored in backends as "environment.exec.agent" + * @param color + * colorize output, choices are: always, never, raw, auto (default "auto") + * @param showSecrets + * show config secrets when they appear + */ +case class RefreshOptions( + parallel: NotProvidedOr[Int] = NotProvided, + message: NotProvidedOr[String] = NotProvided, + expectNoChanges: Boolean = false, + target: List[String] = List.empty, + debugLogOpts: LoggingOptions = LoggingOptions(), +// progressStreams: List[os.ProcessOutput] = List.empty, // TODO: implement multiple writers +// errorProgressStreams: List[os.ProcessOutput] = List.empty, // TODO: implement multiple writers +// eventStreams: List[EngineEvent] = List.empty, // TODO: implement EngineEvent + userAgent: NotProvidedOr[String] = NotProvided, + color: NotProvidedOr[Color] = NotProvided, + showSecrets: Boolean = false +) +object RefreshOptions: + def from(options: RefreshOption*): RefreshOptions = from(options.toList) + def from(options: List[RefreshOption]): RefreshOptions = + options match + case RefreshOption.Parallel(n) :: tail => from(tail*).copy(parallel = n) + case RefreshOption.Message(m) :: tail => from(tail*).copy(message = m) + case RefreshOption.ExpectNoChanges :: tail => from(tail*).copy(expectNoChanges = true) + case RefreshOption.Target(urns*) :: tail => from(tail*).copy(target = urns.toList) + case RefreshOption.DebugLogging(debugOpts) :: tail => from(tail*).copy(debugLogOpts = debugOpts) +// case RefreshOption.ProgressStreams(writers) :: tail => from(tail*).copy(progressStreams = writers) +// case RefreshOption.ErrorProgressStreams(writers) :: tail => from(tail*).copy(errorProgressStreams = writers) +// case RefreshOption.EventStreams(channels) :: tail => from(tail*).copy(eventStreams = channels) + case RefreshOption.UserAgent(agent) :: tail => from(tail*).copy(userAgent = agent) + case RefreshOption.Color(color) :: tail => from(tail*).copy(color = color) + case RefreshOption.ShowSecrets :: tail => from(tail*).copy(showSecrets = true) + case Nil => RefreshOptions() + case o => throw AutoError(s"Unknown refresh option: $o") + +end RefreshOptions + +/** [[Stack.destroy]] options + * + * @see + * [[DestroyOption]] + */ +sealed trait DestroyOption +object DestroyOption: + + /** the number of resource operations to run in parallel at once (1 for no parallelism). Defaults to unbounded. (default 2147483647) + */ + case class Parallel(n: Int) extends DestroyOption + + /** Message (optional) to associate with the destroy operation + */ + case class Message(message: String) extends DestroyOption + + /** Specify exclusive list of resource URNs to destroy + */ + case class Target(urns: String*) extends DestroyOption + + /** Allows deleting of dependent targets discovered but not specified in the [[Target]] list + */ + case object TargetDependents extends DestroyOption + + /** Allows specifying one or more io.Writers to redirect incremental destroy stdout + */ +// case class ProgressStreams(writers: os.ProcessOutput*) extends DestroyOption + /** Allows specifying one or more io.Writers to redirect incremental destroy stderr + */ +// case class ErrorProgressStreams(writers: os.ProcessOutput*) extends DestroyOption + /** Allows specifying one or more channels to receive the Pulumi event stream + */ +// case class EventStreams(channels: EngineEvent*) extends DestroyOption + + /** Specifies additional settings for debug logging + */ + case class DebugLogging(debugOpts: LoggingOptions) extends DestroyOption + + /** Specifies the agent responsible for the destroy, stored in backends as "environment.exec.agent" + */ + case class UserAgent(agent: String) extends DestroyOption + + /** Colorize output. Choices are: [[besom.auto.Color.Always]], [[besom.auto.Color.Never]], [[besom.auto.Color.Raw]], + */ + case class Color(color: besom.auto.Color) extends DestroyOption + + /** Show config secrets when they appear. + */ + case object ShowSecrets extends DestroyOption + +end DestroyOption + +/** [[Stack.destroy]] options + * + * @see + * [[DestroyOption]] + * + * @param parallel + * the number of resource operations to run in parallel at once (1 for no parallelism). Defaults to unbounded. (default 2147483647) + * @param message + * message (optional) to associate with the destroy operation + * @param target + * specify an exclusive list of resource URNs to update + * @param targetDependents + * allows deleting of dependent targets discovered but not specified in the [[target]] list + * @param debugLogOpts + * specifies additional settings for debug logging + * @param progressStreams + * allows specifying one or more io.Writers to redirect incremental destroy stdout + * @param errorProgressStreams + * allows specifying one or more io.Writers to redirect incremental destroy stderr + * @param eventStreams + * allows specifying one or more channels to receive the Pulumi event stream + * @param userAgent + * specifies the agent responsible for the destroy, stored in backends as "environment.exec.agent" + * @param color + * colorize output, choices are: always, never, raw, auto (default "auto") + * @param showSecrets + * show config secrets when they appear + */ +case class DestroyOptions( + parallel: NotProvidedOr[Int] = NotProvided, + message: NotProvidedOr[String] = NotProvided, + target: List[String] = List.empty, + targetDependents: Boolean = false, + debugLogOpts: LoggingOptions = LoggingOptions(), +// progressStreams: List[os.ProcessOutput] = List.empty, // TODO: implement multiple writers +// errorProgressStreams: List[os.ProcessOutput] = List.empty, // TODO: implement multiple writers +// eventStreams: List[EngineEvent] = List.empty, // TODO: implement EngineEvent + userAgent: NotProvidedOr[String] = NotProvided, + color: NotProvidedOr[Color] = NotProvided, + showSecrets: Boolean = false +) +object DestroyOptions: + def from(options: DestroyOption*): DestroyOptions = from(options.toList) + def from(options: List[DestroyOption]): DestroyOptions = + options match + case DestroyOption.Parallel(n) :: tail => from(tail*).copy(parallel = n) + case DestroyOption.Message(m) :: tail => from(tail*).copy(message = m) + case DestroyOption.Target(urns*) :: tail => from(tail*).copy(target = urns.toList) + case DestroyOption.TargetDependents :: tail => from(tail*).copy(targetDependents = true) + case DestroyOption.DebugLogging(debugOpts) :: tail => from(tail*).copy(debugLogOpts = debugOpts) +// case DestroyOption.ProgressStreams(writers) :: tail => from(tail*).copy(progressStreams = writers) +// case DestroyOption.ErrorProgressStreams(writers) :: tail => from(tail*).copy(errorProgressStreams = writers) +// case DestroyOption.EventStreams(channels) :: tail => from(tail*).copy(eventStreams = channels) + case DestroyOption.UserAgent(agent) :: tail => from(tail*).copy(userAgent = agent) + case DestroyOption.Color(color) :: tail => from(tail*).copy(color = color) + case DestroyOption.ShowSecrets :: tail => from(tail*).copy(showSecrets = true) + case Nil => DestroyOptions() + case o => throw AutoError(s"Unknown destroy option: $o") + +end DestroyOptions + +/** [[Stack.history]] options + * + * @see + * [[HistoryOption]] + */ +sealed trait HistoryOption +object HistoryOption: + + /** Show config secrets when they appear. + */ + case object ShowSecrets extends HistoryOption + +end HistoryOption + +/** [[Stack.history]] options + * + * @see + * [[HistoryOption]] + * + * @param showSecrets + * show config secrets when they appear + */ +case class HistoryOptions( + showSecrets: Boolean = false +) +object HistoryOptions: + def from(options: HistoryOption*): HistoryOptions = from(options.toList) + def from(options: List[HistoryOption]): HistoryOptions = + options match + case HistoryOption.ShowSecrets :: tail => from(tail*).copy(showSecrets = true) + case Nil => HistoryOptions() + case null => throw AutoError(s"Unexpected null history option") + +end HistoryOptions + +/** Options for verbose logging to standard error, and enabling plugin logs. + * + * Note - These logs may include sensitive information that is provided from your execution environment to your cloud provider (and which + * Pulumi may not even itself be aware of). These options should be used with care. + * + * @param logLevel + * choose verbosity level of at least 1 (least verbose), if not specified, reverts to default log level + * @param logToStdErr + * specifies that all logs should be sent directly to stderr - making it more accessible and avoiding OS level buffering + * @param flowToPlugins + * reflects the logging settings to plugins as well as the CLI. This is useful when debugging a plugin + * @param tracing + * emit tracing to the specified endpoint. Use the `file:`` schema to write tracing data to a local file + * @param debug + * print detailed debugging output during resource operations + */ +case class LoggingOptions( + logLevel: NotProvidedOr[Int] = NotProvided, + logToStdErr: Boolean = false, + flowToPlugins: Boolean = false, + tracing: NotProvidedOr[String] = NotProvided, + debug: Boolean = false +): + private[auto] def asArgs: Seq[String] = + Seq( + logLevel.map(lvl => if lvl < 0 then 1 else lvl).map(lvl => s"-v=$lvl"), + Option.when(logToStdErr)("--logtostderr"), + Option.when(flowToPlugins)("--logflow"), + tracing.map(t => s"--tracing=$t"), + Option.when(debug)("--debug") + ).flatten + +/** Colorize output. Choices are: [[besom.auto.Color.Always]], [[besom.auto.Color.Never]], [[besom.auto.Color.Raw]], + * [[besom.auto.Color.Auto]] (default "Auto") + */ +enum Color(val value: String): + override def toString: String = value + + /** Always colorize output */ + case Always extends Color("always") + + /** Never colorize output. + */ + case Never extends Color("never") + + /** Raw colorize output. + */ + case Raw extends Color("raw") + + /** Automatically colorize output (default). + */ + case Auto extends Color("auto") +end Color + +/** PreviewResult is the output of [[Stack.preview]] describing the expected set of changes from the next [[Stack.up]] operation. + * @param stdout + * standard output + * @param stderr + * standard error + * @param summary + * the expected changes + */ +case class PreviewResult( + stdout: String, + stderr: String, + summary: Map[OpType, Int] +): + def permalink: Either[Exception, String] = ??? // TODO: implement GetPermalink +end PreviewResult + +/** UpResult contains information about a [[Stack.up]] operation, including [[outputs]], and a [[summary]] of the deployed changes. + * + * @param stdout + * standard output + * @param stderr + * standard error + * @param outputs + * the stack outputs + * @param summary + * the deployed changes + */ +case class UpResult( + stdout: String, + stderr: String, + outputs: OutputMap, + summary: UpdateSummary +): + def permalink: Either[Exception, String] = ??? // TODO: implement GetPermalink +end UpResult + +/** RefreshResult contains information about a [[Stack.refresh]] operation, including a [[summary]] of the deployed changes. + * + * @param stdout + * standard output + * @param stderr + * standard error + * @param summary + * the deployed changes + */ +case class RefreshResult( + stdout: String, + stderr: String, + summary: UpdateSummary +): + def permalink: Either[Exception, String] = ??? // TODO: implement GetPermalink +end RefreshResult + +/** DestroyResult contains information about a [[Stack.destroy]] operation, including a [[summary]] of the deployed changes. + * + * @param stdout + * standard output + * @param stderr + * standard error + * @param summary + * the deployed changes + */ +case class DestroyResult( + stdout: String, + stderr: String, + summary: UpdateSummary +): + def permalink: Either[Exception, String] = ??? // TODO: implement GetPermalink +end DestroyResult + +/** Provides a summary of a Stack lifecycle operation (up/preview/refresh/destroy). + * + * @param version + * The version of the update. + * @param kind + * The kind of operation being performed. + * @param startTime + * The start time of the operation. + * @param message + * The message associated with the operation. + * @param environment + * The environment variables during the operation. + * @param config + * The configuration used for the operation. + * @param result + * The result of the operation. + * @param endTime + * The end time of the operation. This is only present once the update finishes. + * @param resourceChanges + * The changes in resources during the operation. This is only present once the update finishes. + */ +case class UpdateSummary( + version: Int, + kind: String, + startTime: String, + message: String, + environment: Map[String, String], + config: ConfigMap, + result: Option[String], + endTime: Option[String], + resourceChanges: Option[Map[String, Int]] +) derives JsonFormat +object UpdateSummary: + def fromJsonList(json: String): Either[Exception, List[UpdateSummary]] = json.parseJson +end UpdateSummary + +/** Describes a Pulumi engine event, such as a change to a resource or diagnostic message. [[EngineEvent]] is a discriminated union of all + * possible event types, and exactly one field will be non-nil. + * + * @param sequence + * is a unique, and monotonically increasing number for each engine event sent to the Pulumi Service. Since events may be sent + * concurrently, and/or delayed via network routing, the sequence number is to ensure events can be placed into a total ordering. + * @param timestamp + * is a Unix timestamp (seconds) of when the event was emitted. + * @param summaryEvent + * represents a [[SummaryEvent]] + */ +case class EngineEvent( + sequence: Int, + timestamp: Int, + summaryEvent: Option[SummaryEvent] + // Ignore there rest for now +) +object EngineEvent: + implicit object EngineEventFormat extends RootJsonFormat[EngineEvent] { + def write(e: EngineEvent): JsObject = JsObject( + "sequence" -> JsNumber(e.sequence), + "timestamp" -> JsNumber(e.timestamp), + "summaryEvent" -> e.summaryEvent.toJson + ) + + def read(value: JsValue): EngineEvent = { + value.asJsObject.getFields("sequence", "timestamp", "summaryEvent") match { + case Seq(JsNumber(sequence), JsNumber(timestamp), summaryEvent) => + new EngineEvent( + sequence.toInt, + timestamp.toInt, + summaryEvent.convertTo[Option[SummaryEvent]] + ) + case Seq(JsNumber(sequence), JsNumber(timestamp), _*) => // Ignore events we don't care about + new EngineEvent( + sequence.toInt, + timestamp.toInt, + None + ) + } + } + } + + def fromJson(json: String): Either[Exception, EngineEvent] = json.parseJson +end EngineEvent + +/** SummaryEvent is emitted at the end of an update, with a summary of the changes made. + * + * @param maybeCorrupt + * is set if one or more of the resources is in an invalid state. + * @param durationSeconds + * is the number of seconds the update was executing. + * @param resourceChanges + * contains the count for resource change by type. + * @param policyPacks + * run during update. Maps PolicyPackName -> version. + */ +case class SummaryEvent( + maybeCorrupt: Boolean, + durationSeconds: Int, + resourceChanges: Map[OpType, Int], + policyPacks: Map[String, String] +) +object SummaryEvent: + implicit object SummaryEventFormat extends RootJsonFormat[SummaryEvent] { + def write(e: SummaryEvent): JsObject = JsObject( + "maybeCorrupt" -> JsBoolean(e.maybeCorrupt), + "durationSeconds" -> JsNumber(e.durationSeconds), + "resourceChanges" -> e.resourceChanges.toJson, + "PolicyPacks" -> e.policyPacks.toJson + ) + + def read(value: JsValue): SummaryEvent = { + value.asJsObject.getFields("maybeCorrupt", "durationSeconds", "resourceChanges", "PolicyPacks") match { + case Seq(JsBoolean(maybeCorrupt), JsNumber(durationSeconds), resourceChanges, policyPacks) => + new SummaryEvent( + maybeCorrupt, + durationSeconds.toInt, + resourceChanges.convertTo[Map[OpType, Int]], + policyPacks.convertTo[Map[String, String]] + ) + case _ => throw DeserializationException("SummaryEvent expected") + } + } + } +end SummaryEvent + +/** OpType describes the type of operation performed to a resource managed by Pulumi. Should generally mirror `deploy.StepOp` in the engine. + */ +enum OpType(value: String): + override def toString: String = value + + /** Indicates no change was made. */ + case Same extends OpType("same") + + /** Indicates a new resource was created. */ + case Create extends OpType("create") + + /** Indicates an existing resource was updated. */ + case Update extends OpType("update") + + /** Indicates an existing resource was deleted. */ + case Delete extends OpType("delete") + + /** Indicates an existing resource was replaced with a new one. */ + case Replace extends OpType("replace") + + /** Indicates a new resource was created for a replacement. */ + case CreateReplacement extends OpType("create-replacement") + + /** Indicates an existing resource was deleted after replacement. */ + case DeleteReplaced extends OpType("delete-replaced") + + /** Indicates reading an existing resource. */ + case Read extends OpType("read") + + /** Indicates reading an existing resource for a replacement. */ + case ReadReplacement extends OpType("read-replacement") + + /** Indicates refreshing an existing resource. */ + case Refresh extends OpType("refresh") + + /** Indicates removing a resource that was read. */ + case ReadDiscard extends OpType("discard") + + /** Indicates discarding a read resource that was replaced. */ + case DiscardReplaced extends OpType("discard-replaced") + + /** Indicates removing a pending replace resource. */ + case RemovePendingReplace extends OpType("remove-pending-replace") + + /** Indicates importing an existing resource. */ + case Import extends OpType("import") + + /** Indicates replacement of an existing resource with an imported resource. */ + case ImportReplacement extends OpType("import-replacement") +end OpType +object OpType: + implicit object OpTypeFormat extends RootJsonFormat[OpType] { + def write(e: OpType): JsObject = JsObject( + "value" -> JsString(e.toString) + ) + + def read(value: JsValue): OpType = { + value match { + case JsString(value) => + OpType.from(value).left.map(DeserializationException("OpType expected", _)).fold(throw _, identity) + case n => throw DeserializationException(s"OpType expected, got: $n") + } + } + } + + def from(value: String): Either[Exception, OpType] = + value match + case "same" => Right(Same) + case "create" => Right(Create) + case "update" => Right(Update) + case "delete" => Right(Delete) + case "replace" => Right(Replace) + case "create-replacement" => Right(CreateReplacement) + case "delete-replaced" => Right(DeleteReplaced) + case "read" => Right(Read) + case "read-replacement" => Right(ReadReplacement) + case "refresh" => Right(Refresh) + case "discard" => Right(ReadDiscard) + case "discard-replaced" => Right(DiscardReplaced) + case "remove-pending-replace" => Right(RemovePendingReplace) + case "import" => Right(Import) + case "import-replacement" => Right(ImportReplacement) + case _ => Left(Exception(s"Unknown OpType: $value")) + end from +end OpType diff --git a/auto/src/main/scala/besom/auto/Workspace.scala b/auto/src/main/scala/besom/auto/Workspace.scala new file mode 100644 index 00000000..6c0ed333 --- /dev/null +++ b/auto/src/main/scala/besom/auto/Workspace.scala @@ -0,0 +1,859 @@ +package besom.auto + +import besom.json.* +import besom.json.DefaultJsonProtocol.* +import besom.model +import besom.util.* +import org.virtuslab.yaml.* + +import scala.annotation.tailrec +import scala.language.implicitConversions +import scala.util.Try + +// FIXME: this is a hack to make the compiler happy + +object yamlHack: + import org.virtuslab.yaml.internal.dump.present.PresenterImpl + import besom.auto.internal.HackedSerializerImpl + + def asYaml(node: Node): String = + val events = HackedSerializerImpl.toEvents(node) + PresenterImpl.asString(events) +end yamlHack + +given JsonProtocol = DefaultJsonProtocol + +given JsonFormat[Any] = new JsonFormat[Any]: + override def write(obj: Any): JsValue = + obj match + case s: String => JsString(s) + case i: Int => JsNumber(i) + case b: Boolean => JsBoolean(b) + case a: List[Any] => JsArray(a.map(write).toVector) +// case m: Map[String, Any] => JsObject(m.map((k, v) => (k, write(v)))) + override def read(json: JsValue): Any = + json match + case JsNull => None + case JsTrue => true + case JsFalse => false + case JsBoolean(b) => b + case JsString(s) => s + case JsNumber(i) => i + case JsArray(a) => a.map(read) + case JsObject(fs) => fs.map((k, v) => (k, read(v))) + +implicit def forOption[T](implicit encoder: YamlEncoder[T]): YamlEncoder[Option[T]] = { + case Some(value) => encoder.asNode(value) + case None => Node.ScalarNode(null) +} + +implicit def forAny: YamlEncoder[Any] = { + case value: String => YamlEncoder.forString.asNode(value) + case value: Int => YamlEncoder.forInt.asNode(value) + case value: Boolean => YamlEncoder.forBoolean.asNode(value) + case value: List[Any] => YamlEncoder.forList[Any].asNode(value) +// case value: Map[String, Any] => YamlEncoder.forMap[String, Any].asNode(value) +} + +given JsonFormat[model.QName] = new JsonFormat[model.QName]: + override def write(obj: model.QName): JsValue = JsString(obj) + override def read(json: JsValue): model.QName = json match + case JsString(s) => model.QName.parse(s) + case _ => throw new RuntimeException("QName must be a string") +given YamlCodec[model.QName] = new YamlCodec[model.QName]: + def asNode(obj: model.QName): Node = summon[YamlEncoder[String]].asNode(obj) + def construct(node: Node)(implicit settings: LoadSettings = LoadSettings.empty): Either[ConstructError, model.QName] = + summon[YamlDecoder[String]].construct(node).map(model.QName.parse(_)) + +given JsonFormat[String | ProjectRuntimeInfo] = new JsonFormat[String | ProjectRuntimeInfo]: + override def write(obj: String | ProjectRuntimeInfo): JsValue = obj match + case s: String => JsString(s) + case ProjectRuntimeInfo(n, _) => JsString(n) + override def read(json: JsValue): String | ProjectRuntimeInfo = json match + case JsString(s) => s + case _ => throw new RuntimeException("ProjectRuntimeInfo must be a string") + +given YamlCodec[String | ProjectRuntimeInfo] = new YamlCodec[String | ProjectRuntimeInfo]: + def asNode(obj: String | ProjectRuntimeInfo): Node = obj match + case s: String => summon[YamlEncoder[String]].asNode(s) + case p: ProjectRuntimeInfo => summon[YamlEncoder[ProjectRuntimeInfo]].asNode(p) + def construct(node: Node)(implicit settings: LoadSettings = LoadSettings.empty): Either[ConstructError, String | ProjectRuntimeInfo] = + summon[YamlDecoder[String]].construct(node).map(s => ProjectRuntimeInfo(s, Map.empty)) + +given JsonFormat[java.time.Instant] = new JsonFormat[java.time.Instant]: + override def write(obj: java.time.Instant): JsValue = JsString(obj.toString) + override def read(json: JsValue): java.time.Instant = json match + case JsString(s) => java.time.Instant.parse(s) + case _ => throw new RuntimeException("Instant must be a string") + +// FIXME: end of hack + +/** Workspace is the execution context containing a single Pulumi project, a program, and multiple stacks. + * + * Workspaces are used to manage the execution environment, providing various utilities such as plugin installation, environment + * configuration `$PULUMI_HOME`, and creation, deletion, and listing of Stacks. + */ +trait Workspace: + + protected[auto] def pulumi(additional: os.Shellable*)(opts: shell.ShellOption*): Either[ShellAutoError, shell.Result] = + val allArgs = additional + val allOpts = opts ++ List( + shell.ShellOption.Cwd(workDir) + ) ++ List( + shell.ShellOption.Env(getEnvVars), + shell.ShellOption.Env(shell.pulumi.env.PulumiDebugCommandsEnv -> "true") + ) ++ pulumiHome.map(path => shell.ShellOption.Env(shell.pulumi.env.PulumiHomeEnv, path.toString)) + ++ Option.when(remote)(shell.ShellOption.Env(shell.pulumi.env.PulumiExperimentalEnv -> "true")) + shell.pulumi(allArgs)(allOpts*) + end pulumi + + /** Returns the settings object for the current project if any. */ + def projectSettings: Either[Exception, Project] + + /** Overwrites the settings object in the current project. There can only be a single project per workspace. Fails is new project name + * does not match old. + */ + def saveProjectSettings(project: Project): Either[Exception, Unit] + + /** Returns the settings object for the stack matching the specified stack name if any. */ + def stackSettings(stackName: String): Either[Exception, ProjectStack] + + /** Overwrites the settings object for the stack matching the specified stack name. */ + def saveStackSettings(stackName: String, projectStack: ProjectStack): Either[Exception, Unit] + + /** This is hook to provide additional args to every CLI commands before they are executed. Provided with stack name, returns a list of + * args to append to an invoked command `["--config=...", ]`. + */ + def serializeArgsForOp(stackName: String): Either[Exception, List[String]] + + /** This is a hook executed after every command. Called with the stack name. An extensibility point to perform workspace cleanup (CLI + * operations may create/modify a `Pulumi.[stack].yaml`). + */ + def postCommandCallback(stackName: String): Either[Exception, Unit] + + /** Adds the specified environments to the provided stack's configuration. */ + def addEnvironments(stackName: String, envs: String*): Either[Exception, Unit] + + /** ListEnvironments returns the list of environments from the provided stack's configuration */ + def listEnvironments(stackName: String): Either[Exception, List[String]] + + /** Removes the specified environment from the provided stack's configuration. */ + def removeEnvironment(stackName: String, env: String): Either[Exception, Unit] + + /** Returns the value associated with the specified stack name and key using the optional [[ConfigOption]], scoped to the current + * workspace. + */ + def getConfig(stackName: String, key: String, options: ConfigOption*): Either[Exception, ConfigValue] + + /** Returns the config map for the specified stack name, scoped to the current workspace. */ + def getAllConfig(stackName: String): Either[Exception, ConfigMap] + + /** Sets the specified key-value pair on the provided stack name using the optional ConfigOptions. + */ + def setConfig( + stackName: String, + key: String, + value: ConfigValue, + options: ConfigOption* + ): Either[Exception, Unit] + + /** Sets all values in the provided config map for the specified stack name using the optional ConfigOptions. + */ + def setAllConfig( + stackName: String, + config: ConfigMap, + options: ConfigOption* + ): Either[Exception, Unit] + + /** Removes the specified key-value pair on the provided stack name using the optional ConfigOptions. + */ + def removeConfig(stackName: String, key: String, options: ConfigOption*): Either[Exception, Unit] + + /** Removes all values in the provided key list for the specified stack name using the optional ConfigOptions. + */ + def removeAllConfig( + stackName: String, + keys: List[String], + options: ConfigOption* + ): Either[Exception, Unit] + + /** Gets and sets the config map used with the last Update for Stack matching stack name. */ + def refreshConfig(stackName: String): Either[Exception, ConfigMap] + + /** Returns the value associated with the specified stack name and key. */ + def getTag(stackName: String, key: String): Either[Exception, String] + + /** Sets the specified key-value pair on the provided stack name. */ + def setTag(stackName: String, key: String, value: String): Either[Exception, Unit] + + /** Removes the specified key-value pair on the provided stack name. */ + def removeTag(stackName: String, key: String): Either[Exception, Unit] + + /** Returns the tag map for the specified stack name. */ + def listTags(stackName: String): Either[Exception, Map[String, String]] + + /** Returns the environment values scoped to the current workspace. */ + def getEnvVars: Map[String, String] + + /** Sets the specified map of environment values scoped to the current workspace. These values will be passed to all Workspace and Stack + * level commands. + */ + def setEnvVars(envVars: Map[String, String]): Unit + + /** Sets the specified environment value scoped to the current workspace. This value will be passed to all Workspace and Stack level + * commands. + */ + def setEnvVar(key: String, value: String): Unit + + /** Unsets the specified environment value scoped to the current workspace. This value will be removed from all Workspace and Stack level + * commands. + */ + def unsetEnvVar(key: String): Unit + + /** Returns the working directory to run Pulumi CLI commands. */ + def workDir: os.Path + + /** Returns the directory override for CLI metadata if set. This customizes the location of $PULUMI_HOME where metadata is stored and + * plugins are installed. + */ + def pulumiHome: Option[os.Path] + + /** The secrets provider to use for encryption and decryption of stack secrets. See: + * https://www.pulumi.com/docs/intro/concepts/secrets/#available-encryption-providers + */ + def secretsProvider: Option[String] + + /** Returns the version of the underlying Pulumi CLI/Engine. */ + def pulumiVersion: model.SemanticVersion + + /** Returns detailed information about the currently logged-in Pulumi identity. + */ + def whoAmI: Either[Exception, WhoAmIResult] + + /** Edits the secrets provider for the given stack. */ + def changeStackSecretsProvider( + stackName: String, + newSecretsProvider: String | SecretsProviderType, + options: ChangeSecretsProviderOption* + ): Either[Exception, Unit] + + /** Returns a summary of the currently selected stack, if any. */ + def stack: Either[Exception, Option[StackSummary]] + + /** Creates and sets a new stack with the stack name, failing if one already exists. */ + def createStack(stackName: String): Either[Exception, Stack] + + /** Selects and sets an existing stack matching the stack name, failing if none exists. */ + def selectStack(stackName: String): Either[Exception, Stack] + + /** Deletes the stack and all associated configuration and history. */ + def removeStack(stackName: String, options: RemoveOption*): Either[Exception, Unit] + + /** Returns all Stacks created under the current Project. This queries underlying backend and may return stacks not present in the + * Workspace. + */ + def listStacks: Either[Exception, List[StackSummary]] + + /** Acquires the plugin matching the specified name and version. */ + def installPlugin( + name: String, + version: String, + kind: String = "resource", + server: NotProvidedOr[String] = NotProvided + ): Either[Exception, Unit] + + /** Deletes the plugin matching the specified name and version. */ + def removePlugin( + name: NotProvidedOr[String] = NotProvided, + versionRange: NotProvidedOr[String] = NotProvided, + kind: String = "resource" + ): Either[Exception, Unit] + + /** Lists all installed plugins. */ + def listPlugins: Either[Exception, List[PluginInfo]] + + /** Program returns the program `pulumi.RunFunc` to be used for Preview/Update if any. If none is specified, the stack will refer to + * ProjectSettings for this information. + */ + def program: Option[RunFunc] + + /** Exports the deployment state of the stack matching the given name. This can be combined with ImportStack to edit a stack's state (such + * as recovery from failed deployments). + */ + def exportStack(stackName: String): Either[Exception, UntypedDeployment] + + /** Imports the specified deployment state into a pre-existing stack. This can be combined with ExportStack to edit a stack's state (such + * as recovery from failed deployments). + */ + def importStack(stackName: String, deployment: UntypedDeployment): Either[Exception, Unit] + + /** Gets the current set of Stack outputs from the last Stack.Up(). + */ + def stackOutputs(stackName: String): Either[Exception, OutputMap] + + protected[auto] def remote: Boolean + +end Workspace + +/** ConfigValue is a configuration value used by a Pulumi program. Allows differentiating between secret and plaintext values by setting the + * `Secret` property. + */ +case class ConfigValue(value: String, secret: Boolean = false) derives JsonFormat +object ConfigValue: + def fromJson(json: String): Either[Exception, ConfigValue] = json.parseJson[ConfigValue] + +/** ConfigOptions is a configuration option used by a Pulumi program. */ +enum ConfigOption: + /** Indicates that the key contains a path to a property in a map or list to get/set + */ + case Path + +/** ConfigMap is a map of ConfigValue used by Pulumi programs. Allows differentiating between secret and plaintext values. + */ +type ConfigMap = Map[String, ConfigValue] +object ConfigMap: + def fromJson(json: String): Either[Exception, ConfigMap] = json.parseJson[ConfigMap] + +/** TagMap is a key-value map of tag metadata associated with a stack. + */ +type TagMap = Map[String, String] +object TagMap: + def fromJson(json: String): Either[Exception, TagMap] = json.parseJson[TagMap] + +/** StackSummary is a description of a stack and its current status. + */ +case class StackSummary( + name: String, + current: Boolean, + lastUpdate: Option[String], + updateInProgress: Boolean, + resourceCount: Option[Int], + url: Option[String] +) derives JsonFormat +object StackSummary: + def fromJsonList(json: String): Either[Exception, List[StackSummary]] = + json.parseJson[List[StackSummary]] + +/** WhoAmIResult contains detailed information about the currently logged-in Pulumi identity. + */ +case class WhoAmIResult(user: String, organizations: List[String], url: String) derives JsonFormat +object WhoAmIResult: + def fromJson(json: String): Either[Exception, WhoAmIResult] = json.parseJson[WhoAmIResult] + +/** Basic secret provider types */ +enum SecretsProviderType(val value: String): + override def toString: String = value + case Default extends SecretsProviderType("default") + case Passphrase extends SecretsProviderType("passphrase") + case AwsKms extends SecretsProviderType("awskms") + case AzureKeyVault extends SecretsProviderType("azurekeyvault") + case GcpKms extends SecretsProviderType("gcpkms") + case HashiVault extends SecretsProviderType("hashivault") +object SecretsProviderType: + implicit inline def spt2Str(inline spt: String | SecretsProviderType): String = spt.toString + +/** Options for changing the secrets provider. + */ +sealed trait ChangeSecretsProviderOption + +/** Represents the new passphrase when changing to a `passphrase` provider. + * + * @param newPassphrase + * The new passphrase. + */ +case class NewPassphraseOption(newPassphrase: String) extends ChangeSecretsProviderOption + +/** Project is a Pulumi project manifest. + * + * JSON Schema is available at https://github.com/pulumi/pulumi/blob/v3.98.0/sdk/go/common/workspace/project.json + * + * @param name + * is a required fully qualified name of the project containing alphanumeric characters, hyphens, underscores, and periods. + * @param runtime + * is a required runtime that executes code, e.g.: scala, nodejs, python, go, dotnet, java or yaml. + * @param main + * is an optional override for the program's main entry-point location + * @param description + * is an optional informational description + * @param author + * is an optional author that created this project + * @param website + * is an optional website for additional info about this project + * @param license + * is the optional license governing this project's usage + * @param config + * config is a map of config property keys to either values or structured declarations. Non-object values are allowed to be set directly. + * Anything more complex must be defined using the structured schema declaration, or the nested value declaration both shown below. + * @param stackConfigDir + * indicates where to store the `Pulumi.[stack-name].yaml` files, combined with the folder `Pulumi.yaml` is in + * @param template + * is an optional template manifest, if this project is a template + * @param backend + * is an optional backend configuration + * @param options + * is an optional set of project options + * @param plugins + * contains available plugins + */ +case class Project( + name: model.PackageName, + runtime: String | ProjectRuntimeInfo, + main: Option[String] = None, + description: Option[String] = None, + author: Option[String] = None, + website: Option[String] = None, + license: Option[String] = None, + config: Map[String, ProjectConfigValue] = Map.empty, + stackConfigDir: Option[String] = None, + template: Option[ProjectTemplate] = None, + backend: Option[ProjectBackend] = None, + options: Option[ProjectOptions] = None, + plugins: Option[Plugins] = None +) derives JsonFormat, + YamlCodec: + def save(path: os.Path): Either[Exception, Unit] = + val content = path match + case p if p.ext == "json" => summon[JsonWriter[Project]].write(this).prettyPrint + case p if p.ext == "yaml" || p.ext == "yml" => yamlHack.asYaml(summon[YamlEncoder[Project]].asNode(this)) + end content + Try { + os.write.over(path, content, createFolders = true) + }.toEither.left.map(e => AutoError(s"Failed to write project to '$path'", e)) + end save + +end Project +object Project: + def load(path: os.Path): Either[Exception, Project] = + path match + case p if p.ext == "json" => + Try { + os.read(p) + }.toEither.left + .map(e => AutoError(s"Failed to read project from '$path'", e)) + .flatMap(_.parseJson[Project].left.map(e => AutoError(s"Failed to parse project from '$path'", e))) + case p if p.ext == "yaml" || p.ext == "yml" => + Try { + os.read(p) + }.toEither.left + .map(e => AutoError(s"Failed to read project from '$path'", e)) + .flatMap(_.as[Project].left.map(e => AutoError(s"Failed to read project from '$path': ${e.msg}"))) + +/** ProjectRuntimeInfo is a configuration for the runtime used by the project + * @param name + * required language runtime of the project, e.g: scala, nodejs, python, go, dotnet, java or yaml. + * @param options + * The runtime attribute has an additional property called options where you can further specify runtime configuration. + */ +case class ProjectRuntimeInfo( + name: String, + options: Map[String, String] = Map.empty +) derives JsonFormat, + YamlCodec + +/** A config value included in the project manifest. + * + * @param type + * The type of this config property, either string, boolean, integer, or array. + * @param description + * A description for this config property. + * @param items + * A nested structured declaration of the type of the items in the array. Required if type is array + * @param default + * The default value for this config property, must match the given type. + * @param value + * The value of this configuration property. + */ +sealed trait ProjectConfigValue +object ProjectConfigValue: + case class StringValue( + description: Option[String] = None, + default: Option[String] = None, + value: Option[String] = None, + secret: Boolean = false + ) extends ProjectConfigValue + derives JsonFormat, + YamlCodec + case class BooleanValue( + description: Option[String] = None, + default: Option[Boolean] = None, + value: Option[Boolean] = None, + secret: Boolean = false + ) extends ProjectConfigValue + derives JsonFormat, + YamlCodec + case class IntegerValue( + description: Option[String] = None, + default: Option[Int] = None, + value: Option[Int] = None, + secret: Boolean = false + ) extends ProjectConfigValue + derives JsonFormat, + YamlCodec + case class ArrayValue( + items: ProjectConfigItemsType, + description: Option[String] = None, + default: List[ProjectConfigValue] = List.empty, + value: List[ProjectConfigValue] = List.empty, + secret: Boolean = false + ) extends ProjectConfigValue + derives JsonFormat, + YamlCodec + + given JsonFormat[ProjectConfigValue] = new JsonFormat[ProjectConfigValue]: + override def write(obj: ProjectConfigValue): JsValue = obj match + case StringValue(desc, default, value, secret) => + JsObject( + "type" -> JsString("string"), + "description" -> desc.toJson, + "default" -> default.toJson, + "value" -> value.toJson, + "secret" -> secret.toJson + ) + case BooleanValue(desc, default, value, secret) => + JsObject( + "type" -> JsString("boolean"), + "description" -> desc.toJson, + "default" -> default.toJson, + "value" -> value.toJson, + "secret" -> secret.toJson + ) + case IntegerValue(desc, default, value, secret) => + JsObject( + "type" -> JsString("integer"), + "description" -> desc.toJson, + "default" -> default.toJson, + "value" -> value.toJson, + "secret" -> secret.toJson + ) + case ArrayValue(items, desc, default, value, secret) => + JsObject( + "type" -> JsString("array"), + "items" -> items.toJson, + "description" -> desc.toJson, + "default" -> default.toJson, + "value" -> value.toJson, + "secret" -> secret.toJson + ) + override def read(json: JsValue): ProjectConfigValue = json match + case JsObject(fs) => + fs.get("type") match + case Some(JsString("string")) => summon[JsonReader[StringValue]].read(json) + case Some(JsString("boolean")) => summon[JsonReader[BooleanValue]].read(json) + case Some(JsString("integer")) => summon[JsonReader[IntegerValue]].read(json) + case Some(JsString("array")) => summon[JsonReader[ArrayValue]].read(json) + case t => throw new Exception(s"ProjectConfigValue is invalid $t") + case _ => throw new Exception(s"ProjectConfigValue is invalid, expected object") + + given YamlCodec[ProjectConfigValue] = new YamlCodec[ProjectConfigValue]: + def asNode(obj: ProjectConfigValue): Node = obj match + case s: StringValue => summon[YamlEncoder[StringValue]].asNode(s) + case b: BooleanValue => summon[YamlEncoder[BooleanValue]].asNode(b) + case i: IntegerValue => summon[YamlEncoder[IntegerValue]].asNode(i) + case a: ArrayValue => summon[YamlEncoder[ArrayValue]].asNode(a) + def construct(node: Node)(implicit settings: LoadSettings = LoadSettings.empty): Either[ConstructError, ProjectConfigValue] = + node match + case Node.MappingNode(m, _) => + m.get(Node.ScalarNode("type")) match + case Some(Node.ScalarNode("string", _)) => summon[YamlDecoder[StringValue]].construct(node) + case Some(Node.ScalarNode("boolean", _)) => summon[YamlDecoder[BooleanValue]].construct(node) + case Some(Node.ScalarNode("integer", _)) => summon[YamlDecoder[IntegerValue]].construct(node) + case Some(Node.ScalarNode("array", _)) => summon[YamlDecoder[ArrayValue]].construct(node) + case Some(t) => Left(ConstructError(s"ProjectConfigValue is invalid: $t")) + case None => Left(ConstructError(s"ProjectConfigValue is invalid, field 'type' is missing")) + case _ => throw new Exception(s"ProjectConfigValue is invalid, expected object") +end ProjectConfigValue + +/** ProjectConfigItemsType is a config item type included in the project manifest. */ +sealed trait ProjectConfigItemsType +object ProjectConfigItemsType: + object StringType extends ProjectConfigItemsType + object BooleanType extends ProjectConfigItemsType + object IntegerType extends ProjectConfigItemsType + case class ArrayType(items: ProjectConfigItemsType) extends ProjectConfigItemsType + + given JsonFormat[ProjectConfigItemsType] = new JsonFormat[ProjectConfigItemsType]: + override def write(obj: ProjectConfigItemsType): JsValue = obj match + case StringType => JsObject("type" -> JsString("string")) + case BooleanType => JsObject("type" -> JsString("boolean")) + case IntegerType => JsObject("type" -> JsString("integer")) + case ArrayType(it) => JsObject("type" -> JsString("array"), "items" -> write(it)) + override def read(json: JsValue): ProjectConfigItemsType = json match + case JsObject(fs) => + fs.get("type") match + case Some(JsString("string")) => StringType + case Some(JsString("boolean")) => BooleanType + case Some(JsString("integer")) => IntegerType + case Some(JsString("array")) => ArrayType(read(fs("items"))) + case t => throw new Exception(s"ProjectConfigItemsType is invalid $t") + case _ => throw new Exception(s"ProjectConfigItemsType is invalid, field 'type' is missing") + + given YamlCodec[ProjectConfigItemsType] = new YamlCodec[ProjectConfigItemsType]: + def asNode(obj: ProjectConfigItemsType): Node = obj match + case StringType => Node.MappingNode((Node.ScalarNode("type"), Node.ScalarNode("string"))) + case BooleanType => Node.MappingNode((Node.ScalarNode("type"), Node.ScalarNode("boolean"))) + case IntegerType => Node.MappingNode((Node.ScalarNode("type"), Node.ScalarNode("integer"))) + case ArrayType(it) => + Node.MappingNode( + (Node.ScalarNode("type"), Node.ScalarNode("array")), + (Node.ScalarNode("items"), asNode(it)) + ) + @tailrec + def construct(node: Node)(implicit settings: LoadSettings = LoadSettings.empty): Either[ConstructError, ProjectConfigItemsType] = + node match + case n @ Node.MappingNode(m, _) => + m.get(Node.ScalarNode("type")) match + case Some(Node.ScalarNode("string", _)) => Right(StringType) + case Some(Node.ScalarNode("boolean", _)) => Right(BooleanType) + case Some(Node.ScalarNode("integer", _)) => Right(IntegerType) + case Some(Node.ScalarNode("array", _)) => + m.get(Node.ScalarNode("items")) match + case Some(it) => construct(it) + case None => Left(ConstructError(s"ProjectConfigItemsType is invalid, field 'items' is missing")) + case Some(t) => Left(ConstructError(s"ProjectConfigItemsType is invalid: $t")) + case None => Left(ConstructError(s"ProjectConfigItemsType is invalid, field 'type' is missing")) + case _ => throw new Exception(s"ProjectConfigItemsType is invalid, field 'type' is missing") +end ProjectConfigItemsType + +/** ProjectTemplate is a Pulumi project template manifest. + * + * @param description + * an optional description of the template + * @param quickstart + * contains optional text to be displayed after template creation + * @param config + * an optional template config + * @param important + * indicates the template is important and should be listed by default + */ +case class ProjectTemplate( + description: Option[String] = None, + quickstart: Option[String] = None, + config: Map[String, ProjectTemplateConfigValue] = Map.empty, + important: Boolean = false +) derives JsonFormat, + YamlCodec + +/** ProjectTemplateConfigValue is a config value included in the project template manifest. + * + * @param description + * an optional description for the config value + * @param default + * an optional default value for the config value + * @param secret + * may be set to true to indicate that the config value should be encrypted + */ +case class ProjectTemplateConfigValue( + description: Option[String] = None, + default: Option[String] = None, + secret: Boolean = false +) derives JsonFormat, + YamlCodec + +/** ProjectBackend is a configuration for backend used by project + * + * @param url + * is optional field to explicitly set backend url + */ +case class ProjectBackend(url: Option[String] = None) derives JsonFormat, YamlCodec + +/** ProjectOptions + * + * @param refresh + * is the ability to always run a refresh as part of a pulumi update / preview / destroy + */ +case class ProjectOptions(refresh: Option[String] = None) derives JsonFormat, YamlCodec + +/** PluginOptions + * + * @param name + * is the name of the plugin + * @param path + * is the path of the plugin + * @param version + * is the version of the plugin + */ +case class PluginOptions(name: String, path: String, version: Option[String] = None) derives JsonFormat, YamlCodec + +/** Plugins + * + * @param providers + * is the list of provider plugins + * @param languages + * is the list of language plugins + * @param analyzers + * is the list of analyzer plugins + */ +case class Plugins( + providers: List[PluginOptions] = List.empty, + languages: List[PluginOptions] = List.empty, + analyzers: List[PluginOptions] = List.empty +) derives JsonFormat, + YamlCodec + +/** ProjectStack holds stack specific information about a project. + * + * @param secretsProvider + * this stack's secrets provider + * @param encryptedKey + * the KMS-encrypted ciphertext for the data key used for secrets encryption. Only used for cloud-based secrets providers + * @param encryptionSalt + * this stack's base64 encoded encryption salt. Only used for passphrase-based secrets providers + * @param config + * an optional config bag + * @param environment + * an optional environment definition or list of environments + */ +case class ProjectStack( + secretsProvider: Option[String] = None, + encryptedKey: Option[String] = None, + encryptionSalt: Option[String] = None, + config: Map[String, Any] = Map.empty, + environment: Option[Environment] = None +) derives JsonFormat, + YamlCodec: + def asYaml: String = summon[YamlEncoder[ProjectStack]].asNode(this).asYaml + def save(path: os.Path): Unit = os.write.over(path, asYaml, createFolders = true) +object ProjectStack: + def load(path: os.Path): Either[Exception, ProjectStack] = + path match + case p if p.ext == "json" => + os.read(p).parseJson[ProjectStack].left.map(e => AutoError(s"Failed to read project stack from '$path'", e)) + case p if p.ext == "yaml" || p.ext == "yml" => + os.read(p).as[ProjectStack].left.map(e => AutoError(s"Failed to read project stack from '$path': ${e.msg}")) + +/** Environment is an optional environment definition or list of environments. + * + * @param envs + * a list of environments + */ +case class Environment(envs: List[String] = List.empty) derives JsonFormat, YamlCodec + +/** Settings defines workspace settings shared amongst many related projects. + * + * @param stack + * an optional default stack to use + */ +case class Settings(stack: Option[String] = None) derives JsonFormat, YamlCodec + +/** A parameter to be applied to a stack remove operation + */ +enum RemoveOption: + /** Force causes the remove operation to occur even if there are resources existing in the stack + */ + case Force + +/** UntypedDeployment contains an inner, untyped deployment structure. + * + * @param version + * indicates the schema of the encoded deployment + * @param deployment + * the opaque Pulumi deployment. This is conceptually of type `Deployment`, but we use `JsonNode` to permit round-tripping of stack + * contents when an older client is talking to a newer server. If we un-marshaled the contents, and then re-marshaled them, we could end + * up losing important information. + */ +case class UntypedDeployment( + version: Option[Int] = None, + deployment: Option[JsValue] = None +) derives JsonFormat: + def toJson: String = summon[JsonWriter[UntypedDeployment]].write(this).prettyPrint +object UntypedDeployment: + def fromJson(json: String): Either[Exception, UntypedDeployment] = json.parseJson[UntypedDeployment] + +/** PluginInfo provides basic information about a plugin. Each plugin gets installed into a system-wide location, by default + * `~/.pulumi/plugins/[kind]-[name]-[version]/`. A plugin may contain multiple files, however the primary loadable executable must be named + * `pulumi-[kind]-[name]`. + * + * @param name + * the simple name of the plugin + * @param path + * the path that a plugin was loaded from (this will always be a directory) + * @param kind + * the kind of the plugin (language, resource, etc) + * @param version + * the plugin's semantic version, if present + * @param size + * the size of the plugin, in bytes + * @param installTime + * the time the plugin was installed + * @param lastUsedTime + * the last time the plugin was used + * @param schemaPath + * if set, used as the path for loading and caching the schema + * @param schemaTime + * if set and newer than the file at SchemaPath, used to invalidate a cached schema + */ +// TODO: can be moved to model module and used in core and codegen +case class PluginInfo( + name: String, + path: String, + kind: PluginKind, + version: Option[String] = None, + size: Long, + installTime: java.time.Instant, + lastUsedTime: java.time.Instant, + schemaPath: Option[String] = None, + schemaTime: Option[java.time.Instant] = None +) derives JsonFormat: + override def toString: String = name + version.map("-" + _).getOrElse("") +object PluginInfo: + def fromJsonList(json: String): Either[Exception, List[PluginInfo]] = + json.parseJson[List[PluginInfo]] + +/** PluginKind represents a kind of a plugin that may be dynamically loaded and used by Pulumi. */ +enum PluginKind(val value: String): + /** Analyzer is a plugin that can be used as a resource analyzer. + */ + case Analyzer extends PluginKind("analyzer") + + /** Language is a plugin that can be used as a language host. + */ + case Language extends PluginKind("language") + + /** Resource is a plugin that can be used as a resource provider for custom CRUD operations. + */ + case Resource extends PluginKind("resource") + + /** Converter is a plugin that can be used to convert from other ecosystems to Pulumi. + */ + case Converter extends PluginKind("converter") +object PluginKind: + given JsonFormat[PluginKind] = new JsonFormat[PluginKind]: + override def write(obj: PluginKind): JsValue = JsString(obj.value) + override def read(json: JsValue): PluginKind = json match + case JsString(s) => PluginKind.from(s) + case _ => throw new RuntimeException("PluginKind must be a string") + + def from(value: String): PluginKind = value match + case "analyzer" => Analyzer + case "language" => Language + case "resource" => Resource + case "converter" => Converter + case _ => throw new RuntimeException(s"Unknown plugin kind: $value") + +type RunFunc = besom.Context => besom.Output[besom.internal.Exports] + +/** OutputValue models a Pulumi Stack output, providing the plaintext value and a boolean indicating secretness. + * + * @param value + * the plaintext value of the output + * @param secret + * a boolean indicating if the output is a secret + */ +case class OutputValue(value: Any, secret: Boolean = false) + +/** OutputMap is the output result of running a Pulumi program. It is represented as a map from string to OutputValue. + */ +type OutputMap = Map[String, OutputValue] +object OutputMap: + // represents the CLI response for an output marked as "secret" + private val SecretSentinel = "[secret]" + + private[auto] def fromJson( + masked: String, + plaintext: String + ): Either[Exception, OutputMap] = + for + m <- masked.parseJson[Map[String, String]].left.map(e => AutoError(s"Failed to parse masked output map", e)) + p <- plaintext.parseJson[Map[String, String]].left.map(e => AutoError(s"Failed to parse plaintext output map", e)) + yield for (k, v) <- p yield k -> OutputValue(v, m.get(k).contains(SecretSentinel)) +end OutputMap diff --git a/auto/src/main/scala/besom/auto/auto.scala b/auto/src/main/scala/besom/auto/auto.scala new file mode 100644 index 00000000..55f27925 --- /dev/null +++ b/auto/src/main/scala/besom/auto/auto.scala @@ -0,0 +1,484 @@ +package besom.auto + +import LocalWorkspaceOption.* +import LocalWorkspace.* +import besom.util.* + +/** Log in to a local Pulumi backend. + * + * Will store your state information on your computer underneath the provided directory `file://[pulumiHome]`. It is then up to you to + * manage this state, including backing it up, using it in a team environment, and so on. Will set PULUMI_HOME to the provided path. + * + * Equivalent to `pulumi login file://[pulumiHome]/..` or `pulumi login file://~` or `pulumi login --local` + * + * @param pulumiHome + * the path to use for the local backend + * @return + * a [[Unit]] or an error if any + */ +def loginLocal(pulumiHome: NotProvidedOr[os.Path] = NotProvided): Either[Exception, Unit] = + pulumiHome match + case NotProvided => login(LoginOption.Local()) + case path: os.Path => login(LoginOption.Local(path / os.up), LoginOption.PulumiHome(path)) +end loginLocal + +/** Pulumi log in initialized the Pulumi state storage using the provided options. + * + * @param options + * the options to configure the login behavior + * @return + * a [[Unit]] or an error if any + */ +def login(options: LoginOption*): Either[Exception, Unit] = + val opts = LoginOptions.from(options.toList) + val args: Seq[String] = Seq.empty[String] + ++ opts.cloud.map("--cloud-url=" + _) + ++ opts.local.bimap("--local")("file://" + _) + ++ opts.defaultOrg.map("--default-org=" + _) + ++ Option.when(opts.allowInsecure)("--insecure") + val sOpts = Seq.empty[shell.ShellOption.Env] + ++ opts.pulumiHome.map(p => shell.ShellOption.Env(shell.pulumi.env.PulumiHomeEnv -> p.toString)) + ++ opts.pulumiAccessToken.map(t => shell.ShellOption.Env(shell.pulumi.env.PulumiAccessTokenEnv -> t)) + shell + .pulumi("login", args)(sOpts*) + .fold( + err => Left(AutoError(s"Failed to login: ${err.getMessage}", err)), + _ => Right(()) + ) +end login + +/** Log in to a Pulumi backend. + * + * Available backends are: + * - the managed Pulumi Cloud backend, e.g. `PulumiAccessToken("...")` + * - a self-hosted Pulumi Cloud backend, e.g. `Cloud("https://api.pulumi.acmecorp.com)` + * - an object storage backends, e.g. `Cloud("s3://my-bucket")` + * - a local computer backend, e.g. `Local(os.home)` + */ +sealed trait LoginOption +object LoginOption: + /** The URL of the Pulumi service to log in to. + * + * Equivalent to `pulumi login --cloud-url=[url]` + */ + case class Cloud(url: String) extends LoginOption + + /** The path to the Pulumi home directory. + * + * Overrides the metadata directory for `pulumi login`. This customizes the location of `$PULUMI_HOME` where metadata is stored. If not + * provided, will be read from the environment variable `PULUMI_HOME` or default to `~/.pulumi` + */ + case class PulumiHome(path: os.Path) extends LoginOption + + /** The Pulumi access token to use for logging in. + * + * If not provided, will be read from the environment variable `PULUMI_ACCESS_TOKEN`. + */ + case class PulumiAccessToken(token: String) extends LoginOption + + /** Use local log in to initialize the Pulumi state storage using the provided path. + * + * Will store your state information on your computer underneath the provided directory `file://[path]/.pulumi` It is then up to you to + * manage this state, including backing it up, using it in a team environment, and so on. + * + * Equivalent to `pulumi login file://[path]` or `pulumi login file://~` or `pulumi login --local` + * + * @param path + * the path to use for the local backend + */ + case class Local(path: NotProvidedOr[os.Path] = NotProvided) extends LoginOption + + /** A default org to associate with the login. Please note, currently, only the managed and self-hosted backends support organizations. + * + * Equivalent to `pulumi login --default-org=[org]` + * + * @param org + * the org to associate with the login + */ + case class DefaultOrg(org: String) extends LoginOption + + /** Allow insecure server connections when using SSL/TLS. + * + * Equivalent to `pulumi login --insecure` + */ + case object AllowInsecure extends LoginOption +end LoginOption + +/** Log in to a Pulumi backend. + * + * Available backends are: + * - the managed Pulumi Cloud backend, e.g. `PulumiAccessToken("...")` + * - a self-hosted Pulumi Cloud backend, e.g. `Cloud("https://api.pulumi.acmecorp.com)` + * - an object storage backends, e.g. `Cloud("s3://my-bucket")` + * - a local computer backend, e.g. `Local(os.home)` + * + * @param cloud + * the URL of the Pulumi service to log in to + * @param local + * the path to use for the local backend + * @param pulumiHome + * the path to the Pulumi home directory + * @param pulumiAccessToken + * the Pulumi access token to use for logging in + * @param defaultOrg + * a default org to associate with the login + * @param allowInsecure + * allow insecure server connections when using SSL/TLS + */ +case class LoginOptions( + cloud: NotProvidedOr[String] = NotProvided, + local: NotProvidedOr[os.Path] = NotProvided, + pulumiHome: NotProvidedOr[os.Path] = NotProvided, + pulumiAccessToken: NotProvidedOr[String] = NotProvided, + defaultOrg: NotProvidedOr[String] = NotProvided, + allowInsecure: Boolean = false +) +object LoginOptions: + def from(options: LoginOption*): LoginOptions = from(options.toList) + def from(options: List[LoginOption]): LoginOptions = + options match + case LoginOption.Cloud(url) :: tail => from(tail*).copy(cloud = url) + case LoginOption.Local(path) :: tail => from(tail*).copy(local = path) + case LoginOption.PulumiHome(path) :: tail => from(tail*).copy(pulumiHome = path) + case LoginOption.PulumiAccessToken(token) :: tail => from(tail*).copy(pulumiAccessToken = token) + case LoginOption.DefaultOrg(org) :: tail => from(tail*).copy(defaultOrg = org) + case LoginOption.AllowInsecure :: tail => from(tail*).copy(allowInsecure = true) + case Nil => LoginOptions() + case o => throw AutoError(s"Unknown login option: $o") + end from + +/** Log out of the Pulumi backend. + * @param options + * the options to configure the logout behavior + * @return + * a [[Unit]] or an error if any + */ +def logout(options: LogoutOption*): Either[Exception, Unit] = + val opts = LogoutOptions.from(options.toList) + val args = Seq.empty[String] + ++ opts.local.bimap("--local")(_.toString) + ++ opts.cloud.map("--cloud-url=" + _) + ++ Option.when(opts.all)("--all") + val sOpts = Seq.empty[shell.ShellOption.Env] + ++ opts.pulumiHome.map(p => shell.ShellOption.Env(shell.pulumi.env.PulumiHomeEnv -> p.toString)) + shell + .pulumi("logout", args)(sOpts*) + .fold( + err => Left(AutoError(s"Failed to logout: ${err.getMessage}", err)), + _ => Right(()) + ) +end logout + +/** Can be used to configure the [[logout]] behavior. + */ +sealed trait LogoutOption +object LogoutOption: + /** Logout of all backends. + */ + case object All extends LogoutOption + + /** A cloud URL to log out of (defaults to current cloud). + */ + case class Cloud(url: String) extends LogoutOption + + /** Log out of using local mode + */ + case class Local(path: NotProvidedOr[os.Path] = NotProvided) extends LogoutOption + + /** The path to the Pulumi home directory. + * + * Overrides the metadata directory for `pulumi logout`. This customizes the location of `$PULUMI_HOME` where metadata is stored. If not + * provided, will be read from the environment variable `PULUMI_HOME` or default to `~/.pulumi` + */ + case class PulumiHome(path: os.Path) extends LogoutOption + +/** Can be used to configure the [[logout]] behavior. + * @param all + * if true, log out of all backends + * @param local + * log out of using local mode with the provided path (defaults to `~`) + * @param cloud + * a cloud URL to log out of (defaults to current cloud) + * @param pulumiHome + * the path to the Pulumi home directory, if not provided, will be read from the environment variable `PULUMI_HOME` or default to + * `~/.pulumi` + */ +case class LogoutOptions( + all: Boolean = false, + local: NotProvidedOr[os.Path] = NotProvided, + cloud: NotProvidedOr[String] = NotProvided, + pulumiHome: NotProvidedOr[os.Path] = NotProvided +) +object LogoutOptions: + /** Creates a [[LogoutOptions]] from a list of [[LogoutOption]]s. + * @param options + * the list of [[LogoutOption]]s + * @return + * a [[LogoutOptions]] + */ + def from(options: LogoutOption*): LogoutOptions = from(options.toList) + + /** Creates a [[LogoutOptions]] from a list of [[LogoutOption]]s. + * @param options + * the list of [[LogoutOption]]s + * @return + * a [[LogoutOptions]] + */ + def from(options: List[LogoutOption]): LogoutOptions = + options match + case LogoutOption.All :: tail => from(tail*).copy(all = true) + case LogoutOption.Local(path) :: tail => from(tail*).copy(local = path) + case LogoutOption.Cloud(url) :: tail => from(tail*).copy(cloud = url) + case LogoutOption.PulumiHome(path) :: tail => from(tail*).copy(pulumiHome = path) + case Nil => LogoutOptions() + case o => throw AutoError(s"Unknown logout option: $o") + end from +end LogoutOptions + +/** Creates and configures a [[LocalWorkspace]]. + * + * [[LocalWorkspaceOption]]s can be used to configure things like e.g.: + * - [[WorkDir]] - the working directory + * - [[Program]] - the program to execute + * - [[Repo]] - the git repository to clone + * + * @param options + * options to pass to the [[LocalWorkspace]] + * @return + * a [[LocalWorkspace]] or an error if any + */ +def localWorkspace(options: LocalWorkspaceOption*): Either[Exception, LocalWorkspace] = LocalWorkspace(options*) + +/** Creates a [[Stack]] backed by a [[LocalWorkspace]] created on behalf of the user, from the specified [[WorkDir]]. + * + * This Workspace will pick up any available Settings files (`Pulumi.yaml`, `Pulumi.[stack].yaml`). + * @param stackName + * the name of the stack to create + * @param options + * options to pass to the [[LocalWorkspace]] + * @return + * a [[Stack]] backed by a [[LocalWorkspace]] or an error if any + */ +def createStackLocalSource( + stackName: String, + workDir: os.Path, + options: LocalWorkspaceOption* +): Either[Exception, Stack] = + for + ws <- localWorkspace(WorkDir(workDir) +: options*) + s <- Stack.create(stackName, ws) + yield s + +/** Creates or selects a [[Stack]] backed by a [[LocalWorkspace]] created on behalf of the user, from the specified [[WorkDir]]. If the + * [[Stack]] already exists, it will not throw an error and proceed to selecting the [[Stack]]. This [[Workspace]] will pick up any + * available Settings files (`Pulumi.yaml`, `Pulumi.[stack].yaml`). + * + * @param stackName + * the name of the stack to upsert + * @param workDir + * the working directory containing the project + * @param opts + * the options for the local workspace + * @return + * a [[Stack]] backed by a [[LocalWorkspace]] or an error if any + */ +def upsertStackLocalSource( + stackName: String, + workDir: os.Path, + opts: LocalWorkspaceOption* +): Either[Exception, Stack] = + for + ws <- localWorkspace(WorkDir(workDir) +: opts*) + s <- Stack.upsert(stackName, ws) + yield s + +/** Selects an existing [[Stack]] backed by a [[LocalWorkspace]] created on behalf of the user, from the specified [[WorkDir]]. This + * [[Workspace]] will pick up any available Settings files (`Pulumi.yaml`, `Pulumi.[stack].yaml`). + * + * @param stackName + * the name of the stack to select + * @param workDir + * the working directory containing the project + * @param opts + * the options for the local workspace + * @return + * a [[Stack]] backed by a [[LocalWorkspace]] or an error if any + */ +def selectStackLocalSource( + stackName: String, + workDir: os.Path, + opts: LocalWorkspaceOption* +): Either[Exception, Stack] = + for + ws <- localWorkspace(WorkDir(workDir) +: opts*) + s <- Stack.select(stackName, ws) + yield s + +/** Creates a [[Stack]] backed by a [[LocalWorkspace]] created on behalf of the user, with source code cloned from the specified + * [[GitRepo]]. This [[Workspace]] will pick up any available Settings files (`Pulumi.yaml`, `Pulumi.[stack].yaml`) that are cloned into + * the Workspace. Unless a [[WorkDir]] option is specified, the [[GitRepo]] will be clone into a new temporary directory provided by the + * OS. + * + * @param stackName + * the name of the stack to create + * @param repo + * the Git repository to clone + * @param opts + * the options for the local workspace + * @return + * a [[Stack]] backed by a [[LocalWorkspace]] or an error if any + */ +def createStackRemoteSource( + stackName: String, + repo: GitRepo, + opts: LocalWorkspaceOption* +): Either[Exception, Stack] = + for + ws <- localWorkspace(Repo(repo) +: opts*) + s <- Stack.create(stackName, ws) + yield s + +/** Creates a [[Stack]] backed by a [[LocalWorkspace]] created on behalf of the user, with source code cloned from the specified + * [[GitRepo]]. If the [[Stack]] already exists, it will not error and proceed to selecting the [[Stack]]. This [[Workspace]] will pick up + * any available Settings files (`Pulumi.yaml`, `Pulumi.[stack].yaml`) that are cloned into the [[Workspace]]. Unless a [[WorkDir]] option + * is specified, the [[GitRepo]] will be clone into a new temporary directory provided by the OS. + * @param stackName + * the name of the stack to upsert + * @param repo + * the Git repository to clone + * @param opts + * the options for the local workspace + * @return + * a [[Stack]] backed by a [[LocalWorkspace]] or an error if any + */ +def upsertStackRemoteSource( + stackName: String, + repo: GitRepo, + opts: LocalWorkspaceOption* +): Either[Exception, Stack] = + for + ws <- localWorkspace(Repo(repo) +: opts*) + s <- Stack.upsert(stackName, ws) + yield s + +/** Selects an existing [[Stack]] backed by a [[LocalWorkspace]] created on behalf of the user, with source code cloned from the specified + * [[GitRepo]]. This [[Workspace]] will pick up any available Settings files (`Pulumi.yaml`, `Pulumi.[stack].yaml`) that are cloned into + * the [[Workspace]]. Unless a [[WorkDir]] option is specified, the [[GitRepo]] will be clone into a new temporary directory provided by + * the OS. + * @param stackName + * the name of the stack to select + * @param repo + * the Git repository to clone + * @param opts + * the options for the local workspace + * @return + * a [[Stack]] backed by a [[LocalWorkspace]] or an error if any + */ +def selectStackRemoteSource( + stackName: String, + repo: GitRepo, + opts: LocalWorkspaceOption* +): Either[Exception, Stack] = + for + ws <- localWorkspace(Repo(repo) +: opts*) + s <- Stack.select(stackName, ws) + yield s + +/** Creates a [[Stack]] backed by a [[LocalWorkspace]] created on behalf of the user, with the specified program. If no [[Project]] option + * is specified, default project settings will be created on behalf of the user. Similarly, unless a [[WorkDir]] option is specified, the + * working directory will default to a new temporary directory provided by the OS. + * + * @param stackName + * the name of the stack to create + * @param projectName + * the name of the project + * @param program + * the Pulumi program to execute + * @param opts + * the options for the local workspace + * @return + * a [[Stack]] backed by a [[LocalWorkspace]] or an error if any + */ +def createStackInlineSource( + stackName: String, + projectName: String, + program: RunFunc, + opts: LocalWorkspaceOption* +): Either[Exception, Stack] = + val optsWithProgram = Program(program) +: opts + val allOpts: Either[AutoError, Seq[LocalWorkspaceOption]] = + getProjectSettings(projectName, optsWithProgram) match + case Left(e) => Left(AutoError(s"Failed to create stack '$stackName': ${e.getMessage}", e)) + case Right(proj) => Right(Project(proj) +: opts) + for + allOpts <- allOpts + ws <- localWorkspace(allOpts*) + s <- Stack.create(stackName, ws) + yield s +end createStackInlineSource + +/** Creates a [[Stack]] backed by a [[LocalWorkspace]] created on behalf of the user, with the specified program. If the [[Stack]] already + * exists, it will not error and proceed to selecting the [[Stack]]. If no [[Project]] option is specified, default project settings will + * be created on behalf of the user. Similarly, unless a [[WorkDir]] option is specified, the working directory will default to a new + * temporary directory provided by the OS. + * + * @param stackName + * the name of the stack to upsert + * @param projectName + * the name of the project + * @param program + * the Pulumi program to execute + * @param opts + * the options for the local workspace + * @return + * a [[Stack]] backed by a [[LocalWorkspace]] or an error if any + */ +def upsertStackInlineSource( + stackName: String, + projectName: String, + program: RunFunc, + opts: LocalWorkspaceOption* +): Either[Exception, Stack] = + val optsWithProgram = Program(program) +: opts + val allOpts: Either[AutoError, Seq[LocalWorkspaceOption]] = + getProjectSettings(projectName, optsWithProgram) match + case Left(e) => Left(AutoError(s"Failed to upsert stack '$stackName': ${e.getMessage}", e)) + case Right(proj) => Right(Project(proj) +: opts) + for + allOpts <- allOpts + ws <- localWorkspace(allOpts*) + s <- Stack.upsert(stackName, ws) + yield s +end upsertStackInlineSource + +/** Selects an existing [[Stack]] backed by a [[LocalWorkspace]] created on behalf of the user, with the specified program. If no + * [[Project]] option is specified, default project settings will be created on behalf of the user. Similarly, unless a [[WorkDir]] option + * is specified, the working directory will default to a new temporary directory provided by the OS. + * @param stackName + * the name of the stack to select + * @param projectName + * the name of the project + * @param program + * the Pulumi program to execute + * @param opts + * the options for the local workspace + * @return + * a [[Stack]] backed by a [[LocalWorkspace]] or an error if any + */ +def selectStackInlineSource( + stackName: String, + projectName: String, + program: RunFunc, + opts: LocalWorkspaceOption* +): Either[Exception, Stack] = + val optsWithProgram = Program(program) +: opts + val allOpts: Either[AutoError, Seq[LocalWorkspaceOption]] = + getProjectSettings(projectName, optsWithProgram) match + case Left(e) => Left(AutoError(s"Failed to select stack '$stackName': ${e.getMessage}", e)) + case Right(proj) => Right(Project(proj) +: opts) + for + allOpts <- allOpts + ws <- localWorkspace(allOpts*) + s <- Stack.select(stackName, ws) + yield s +end selectStackInlineSource diff --git a/auto/src/main/scala/besom/auto/shell.scala b/auto/src/main/scala/besom/auto/shell.scala new file mode 100644 index 00000000..7c210fe5 --- /dev/null +++ b/auto/src/main/scala/besom/auto/shell.scala @@ -0,0 +1,254 @@ +package besom.auto + +import besom.util.* +import os.CommandResult + +import java.nio.channels.Channels +import java.util.concurrent.atomic.AtomicLong +import scala.io.Source +import scala.util.Using + +object shell: + case class Result private ( + command: Seq[String], + exitCode: Int, + out: String, + err: String, + envVars: Map[String, String] + ): + def asError: ShellAutoError = ShellAutoError( + exitCode = exitCode, + stdout = out, + stderr = err, + command = command, + envVars = envVars + ) + + object Result: + def from(result: os.CommandResult, envVars: Map[String, String]): Either[ShellAutoError, Result] = + val res = Result(result.command, result.exitCode, result.out.text(), result.err.text(), envVars) + if res.exitCode == 0 then Right(res) else Left(res.asError) + end Result + + def apply(command: os.Shellable*)(opts: ShellOption*): Either[ShellAutoError, Result] = + val options = ShellOptions.from(opts*) + val result = os + .proc(command*) + .call( + cwd = options.cwd.asOption.orNull, + env = options.env, + stdin = options.stdin, + stdout = options.stdout, + stderr = options.stderr, + mergeErrIntoOut = options.mergeErrIntoOut, + timeout = options.timeout, + check = options.check, + propagateEnv = options.propagateEnv + ) + Result.from(result, options.env) + end apply + + sealed trait ShellOption + object ShellOption: + /** the working directory of the subprocess */ + case class Cwd(path: os.Path) extends ShellOption + + /** any additional environment variables you wish to set in the subprocess */ + case class Env(env: Map[String, String]) extends ShellOption + object Env: + def apply(env: (String, String)*): Env = new Env(env.toMap) + def apply(key: String, value: String): Env = Env(Map(key -> value)) + + /** Any data you wish to pass to the subprocess standard input. */ + case class Stdin(input: os.ProcessInput) extends ShellOption + + /** How the subprocess output stream is configured. */ + case class Stdout(output: os.ProcessOutput) extends ShellOption + + /** How the subprocess error stream is configured. */ + case class Stderr(output: os.ProcessOutput) extends ShellOption + + /** Whether to merge the subprocess error stream into its output stream. */ + case object MergeErrIntoOut extends ShellOption + + /** How long to wait for the subprocess to complete, in milliseconds. */ + case class Timeout(timeout: Long) extends ShellOption + + /** Whether to check the subprocess exit code and throw an exception if it is non-zero. Disable this to avoid throwing an exception if + * the subprocess. + */ + case object Check extends ShellOption + + /** Whether to propagate the current environment variables to the subprocess. Disable this to avoid passing in this parent process's + * environment variables to the subprocess. + */ + case object DontPropagateEnv extends ShellOption + + /** Options for the subprocess execution. + * @param cwd + * the working directory of the subprocess + * @param env + * any additional environment variables you wish to set in the subprocess + * @param stdin + * any data you wish to pass to the subprocess standard input + * @param stdout + * how the subprocess output stream is configured + * @param stderr + * how the subprocess error stream is configured + * @param mergeErrIntoOut + * whether to merge the subprocess error stream into its output stream + * @param timeout + * how long to wait for the subprocess to complete, in milliseconds + * @param check + * whether to check the subprocess exit code and throw an exception if it is non-zero + * @param propagateEnv + * whether to propagate the current environment variables to the subprocess + */ + case class ShellOptions( + cwd: NotProvidedOr[os.Path] = NotProvided, + env: Map[String, String] = Map.empty, + stdin: os.ProcessInput = os.Pipe, + stdout: os.ProcessOutput = os.Pipe, + stderr: os.ProcessOutput = os.Pipe, // in contrast to os lib we default to Pipe, because we use our own error handling + mergeErrIntoOut: Boolean = false, + timeout: Long = -1, + check: Boolean = false, // in contrast to os lib we default to false, because we use our own error handling + propagateEnv: Boolean = true + ) + + object ShellOptions: + def from(opts: ShellOption*): ShellOptions = from(opts.toList) + def from(opts: List[ShellOption]): ShellOptions = + opts match + case ShellOption.Cwd(path) :: tail => from(tail).copy(cwd = path) + case ShellOption.Stdin(input) :: tail => from(tail).copy(stdin = input) + case ShellOption.Stdout(output) :: tail => from(tail).copy(stdout = output) + case ShellOption.Stderr(output) :: tail => from(tail).copy(stderr = output) + case ShellOption.MergeErrIntoOut :: tail => from(tail).copy(mergeErrIntoOut = true) + case ShellOption.Timeout(timeout) :: tail => from(tail).copy(timeout = timeout) + case ShellOption.Check :: tail => from(tail).copy(check = true) + case ShellOption.DontPropagateEnv :: tail => from(tail).copy(propagateEnv = false) + case ShellOption.Env(env) :: tail => { + val old = from(tail*) + old.copy(env = old.env ++ env) + } + case Nil => ShellOptions() + case o => throw AutoError(s"Unknown shell option: $o") + + def env(name: String): Either[Exception, String] = + sys.env.get(name) match + case Some(v) => + Option(v).filter(_.trim.nonEmpty) match + case Some(value) => Right(value) + case None => Left(Exception(s"Environment variable $name is empty")) + case None => Left(Exception(s"Environment variable $name is not set")) + + object pulumi: + def ProjectFileName(ext: String = "yaml") = s"Pulumi.$ext" + def StackFileName(stackName: String, ext: String = "yaml") = s"Pulumi.$stackName.$ext" + + object env: + val PulumiHomeEnv = "PULUMI_HOME" + val PulumiAutomationApiSkipVersionCheckEnv = "PULUMI_AUTOMATION_API_SKIP_VERSION_CHECK" + val PulumiDebugCommandsEnv = "PULUMI_DEBUG_COMMANDS" + val PulumiExperimentalEnv = "PULUMI_EXPERIMENTAL" + val PulumiSkipUpdateCheckEnv = "PULUMI_SKIP_UPDATE_CHECK" + val PulumiAccessTokenEnv = "PULUMI_ACCESS_TOKEN" + val PulumiConfigPassphraseEnv = "PULUMI_CONFIG_PASSPHRASE" + val PulumiConfigPassphraseFileEnv = "PULUMI_CONFIG_PASSPHRASE_FILE" + + lazy val pulumiHome: Either[Exception, os.Path] = + shell.env(PulumiHomeEnv).map(os.Path(_)) + lazy val pulumiAutomationApiSkipVersionCheck: Boolean = + shell.env(PulumiAutomationApiSkipVersionCheckEnv).map(isTruthy).getOrElse(false) + lazy val pulumiAccessToken: Either[Exception, String] = + shell.env(PulumiAccessTokenEnv) + + end env + + // all commands should be run in non - interactive mode + // this causes commands to fail rather than prompting for input (and thus hanging indefinitely) + private val commonArgs: List[os.Shellable] = List("--non-interactive", "--logtostderr") + private val commonOpts: List[ShellOption] = List(ShellOption.Env(env.PulumiSkipUpdateCheckEnv -> "true")) + + def apply(additional: os.Shellable*)(opts: ShellOption*): Either[ShellAutoError, shell.Result] = + shell("pulumi", commonArgs ++ additional)(commonOpts ++ opts*) + + end pulumi + + object Tailer: + import org.apache.commons.io as cio + + import java.nio.charset.StandardCharsets + + private val DefaultBufSize = 4096 + private val DefaultDelay = 100 + + trait Listener extends cio.input.TailerListenerAdapter: + def path: os.Path + def handle(event: Listener.Event): Unit + override def fileNotFound(): Unit = handle(Listener.Event.FileNotFound(path)) + override def fileRotated(): Unit = handle(Listener.Event.FileRotated(path)) + override def handle(ex: Exception): Unit = handle(Listener.Event.Error(AutoError(s"Failed to tail a file", ex))) + override def handle(line: String): Unit = handle(Listener.Event.Line(line)) + object Listener: + sealed trait Event + object Event: + case class FileNotFound(path: os.Path) extends Event + case class FileRotated(path: os.Path) extends Event + case class Error(ex: Exception) extends Event + case class Line(line: String) extends Event + + def apply[A, L <: Listener]( + path: os.Path, + listener: os.Path => L, + delayMillis: Long = DefaultDelay, + end: Boolean = false, + reOpen: Boolean = false, + bufSize: Int = DefaultBufSize + )(block: L => A): Either[Exception, A] = + val ls = listener(path) + val tailer = cio.input.Tailer + .builder() + .setStartThread(true) + .setPath(path.toNIO) + .setTailerListener(ls) + .setCharset(StandardCharsets.UTF_8) + .setDelayDuration(java.time.Duration.ofMillis(delayMillis)) + .setTailFromEnd(end) + .setReOpen(reOpen) + .setBufferSize(bufSize) + .get() + Using(tailer)(_ => block(ls)).toEither.left.map(AutoError("Failed to tail a file", _)) + end Tailer + + def watch(path: os.Path, onEvent: os.Path => Unit)(block: => Unit): Either[Exception, Unit] = + Using( + os.watch.watch( + roots = Seq(path), + onEvent = (ps: Set[os.Path]) => ps.filter(_ == path).foreach(onEvent), + logger = (_, _) => () /* TODO: pass a logger adapter here */ + ) + )(_ => block).toEither.left.map(AutoError("Failed to watch a path", _)) + + case class Tailer2(path: os.Path, onLine: String => Unit): + private val lastPosition: AtomicLong = AtomicLong(0L) + + def tail(block: => Unit): Either[Exception, Unit] = + watch( + path, + onEvent = p => { + val _ = lastPosition.getAndUpdate(pos => { + val channel = os.read.channel(p).position(pos) + val inputStream = Channels.newInputStream(channel) + Using(Source.fromInputStream(inputStream)) { + _.getLines().foreach(onLine) + } + channel.position() + }) + } + )(block) + + end Tailer2 + +end shell diff --git a/auto/src/main/scala/besom/internal/HackedSerializer.scala b/auto/src/main/scala/besom/internal/HackedSerializer.scala new file mode 100644 index 00000000..9caeace3 --- /dev/null +++ b/auto/src/main/scala/besom/internal/HackedSerializer.scala @@ -0,0 +1,35 @@ +package besom.auto.internal + +import org.virtuslab.yaml.Node +import org.virtuslab.yaml.internal.load.parse.EventKind +import org.virtuslab.yaml.internal.load.parse.EventKind._ +import org.virtuslab.yaml.internal.dump.serialize.Serializer + +object HackedSerializerImpl extends Serializer { + override def toEvents(node: Node): Seq[EventKind] = + Seq(DocumentStart()) ++ convertNode(node) ++ Seq(DocumentEnd()) + + private def convertNode(node: Node) = node match { + case scalar: Node.ScalarNode => convertScalarNode(scalar) + case mapping: Node.MappingNode => convertMappingNode(mapping) + case sequence: Node.SequenceNode => convertSequenceNode(sequence) + } + + private def convertMappingNode(node: Node.MappingNode): Seq[EventKind] = { + val events = node.mappings.toSeq.flatMap { + case (_, Node.ScalarNode(null, _)) => Seq.empty + case (_, Node.SequenceNode(s, _)) if s.isEmpty => Seq.empty + case (_, Node.MappingNode(m, _)) if m.isEmpty => Seq.empty + case (k, v) => Seq(convertNode(k), convertNode(v)) + }.flatten + Seq(MappingStart()) ++ events ++ Seq(MappingEnd) + } + + private def convertSequenceNode(node: Node.SequenceNode): Seq[EventKind] = { + val events = node.nodes.flatMap(convertNode(_)) + Seq(SequenceStart()) ++ events ++ Seq(SequenceEnd) + } + + private def convertScalarNode(node: Node.ScalarNode): Seq[EventKind] = + Seq(Scalar(node.value)) +} diff --git a/auto/src/main/scala/besom/model/Names.scala b/auto/src/main/scala/besom/model/Names.scala new file mode 100644 index 00000000..21960de5 --- /dev/null +++ b/auto/src/main/scala/besom/model/Names.scala @@ -0,0 +1,124 @@ +package besom.model + +import scala.compiletime.* +import scala.compiletime.ops.string.* +import scala.language.implicitConversions + +/** Name is an identifier. */ +opaque type Name <: String = String +object Name: + private val NameFirstCharRegexpPattern = "[A-Za-z0-9_.-]" + private val NameRestCharRegexpPattern = "[A-Za-z0-9_.-]*" + private[model] val NameRegexpPattern = NameFirstCharRegexpPattern + NameRestCharRegexpPattern + + private val NameRegexp = NameRegexpPattern.r + private[model] val NameFirstCharRegexp = ("^" + NameFirstCharRegexpPattern + "$").r + private[model] val NameRestCharRegexp = ("^" + NameRestCharRegexpPattern + "$").r + + /** IsName checks whether a string is a legal Name. */ + def isName(s: String): Boolean = s.nonEmpty && NameRegexp.findFirstIn(s).isDefined + + /** Parse a string into a [[Name]]. + * @param s + * is a string to parse + * @return + * a [[Name]] if the string is valid, otherwise a compile time error occurs + */ + inline def apply(s: String): Name = + requireConst(s) + inline if !constValue[Matches[s.type, "[A-Za-z0-9_.-][A-Za-z0-9_.-]*"]] then + error("Invalid Name string. Must match '[A-Za-z0-9_.-][A-Za-z0-9_.-]*'.") + else s + + implicit inline def str2Name(inline s: String): Name = Name(s) + + private[besom] def unsafeOf(s: String): Name = s + + extension (name: Name) + /** Turns a [[Name]] into a qualified name, this is legal, since Name's is a proper subset of QName's grammar. + * @return + * the [[Name]] as a [[QName]] + */ + def asQName: QName = QName.unsafeOf(name) + +end Name + +/** QName is a qualified identifier. The "/" character optionally delimits different pieces of the name. Each element conforms to Name + * regexp pattern. For example, "pulumi/pulumi/stack". + */ + +opaque type QName <: String = String +object QName: + /** Parse a string into a [[QName]]. + * @param s + * is a string to parse + * @return + * a [[QName]] if the string is valid, otherwise a compile time error occurs + */ + inline def apply(s: String): QName = + requireConst(s) + inline if !constValue[Matches[s.type, "([A-Za-z0-9_.-][A-Za-z0-9_.-]*/)*[A-Za-z0-9_.-][A-Za-z0-9_.-]*"]] then + error("Invalid QName string. Must match '([A-Za-z0-9_.-][A-Za-z0-9_.-]*/)*[A-Za-z0-9_.-][A-Za-z0-9_.-]*'.") + else s + + implicit inline def str2QName(inline s: String): QName = QName(s) + + private[besom] def unsafeOf(s: String): QName = s + + /** QNameDelimiter is what delimits Namespace and Name parts. */ + private val QNameDelimiter = "/" + private val QNameRegexpPattern = "(" + Name.NameRegexpPattern + "\\" + QNameDelimiter + ")*" + Name.NameRegexpPattern + private val QNameRegexp = QNameRegexpPattern.r + + /** IsQName checks whether a string is a legal QName. */ + def isQName(s: String): Boolean = s.nonEmpty && QNameRegexp.findFirstIn(s).isDefined + + /** Converts an arbitrary string into a [[QName]], converting the string to a valid [[QName]] if necessary. The conversion is + * deterministic, but also lossy. + */ + def parse(s: String): QName = + val output = s.split(QNameDelimiter).filter(_.nonEmpty).map { segment => + val chars = segment.toCharArray + if (!Name.NameFirstCharRegexp.matches(chars.head.toString)) chars.update(0, '_') + for (i <- 1 until chars.length) { + if (!Name.NameRestCharRegexp.matches(chars(i).toString)) chars.update(i, '_') + } + new String(chars) + } + val result = output.mkString(QNameDelimiter) + if (result.isEmpty) QName.unsafeOf("_") else QName.unsafeOf(result) + end parse + + extension (qname: QName) + /** Extracts the [[Name]] portion of a [[QName]] (dropping any namespace). */ + def name: Name = + val ix = qname.lastIndexOf(QNameDelimiter) + val nmn = if ix == -1 then qname else qname.substring(ix + 1) + assert(Name.isName(nmn), s"QName $qname has invalid name $nmn") + nmn + + /** Extracts the namespace portion of a [[QName]] (dropping the name), this may be empty. */ + def namespace: QName = + val ix = qname.lastIndexOf(QNameDelimiter) + val qn = if ix == -1 then "" else qname.substring(0, ix) + assert(isQName(qn), s"QName $qname has invalid namespace $qn") + QName.unsafeOf(qn) + +end QName + +/** PackageName is a qualified name referring to an imported package. */ +type PackageName = QName +object PackageName: + def parse(s: String): PackageName = QName.parse(s) + +/** ModuleName is a qualified name referring to an imported module from a package. */ +type ModuleName = QName + +/** ModuleMemberName is a simple name representing the module member's identifier. */ +type ModuleMemberName = Name + +/** ClassMemberName is a simple name representing the class member's identifier. */ +type ClassMemberName = Name + +/** TypeName is a simple name representing the type's name, without any package/module qualifiers. */ +type TypeName = Name diff --git a/auto/src/main/scala/besom/model/Versions.scala b/auto/src/main/scala/besom/model/Versions.scala new file mode 100644 index 00000000..0905b779 --- /dev/null +++ b/auto/src/main/scala/besom/model/Versions.scala @@ -0,0 +1,70 @@ +package besom.model + +//noinspection ScalaFileName +case class SemanticVersion( + major: Int, + minor: Int, + patch: Int, + preRelease: Option[String], + buildMetadata: Option[String] +) extends Ordered[SemanticVersion]: + + override def compare(that: SemanticVersion): Int = + import math.Ordered.orderingToOrdered + + val mainCompared = (major, minor, patch).compare((that.major, that.minor, that.patch)) + + // for pre release compare each dot separated identifier from left to right + val thisPreRelease = preRelease.map(_.split('.')).getOrElse(Array.empty[String]) + val thatPreRelease = that.preRelease.map(_.split('.')).getOrElse(Array.empty[String]) + val preCompared = thisPreRelease + .zip(thatPreRelease) + .map { case (thisId, thatId) => + if thisId.forall(_.isDigit) && thatId.forall(_.isDigit) + then thisId.toInt.compare(thatId.toInt) + else thisId.compare(thatId) + } + .find(_ != 0) + .getOrElse(thisPreRelease.length.compare(thatPreRelease.length)) + // ignore build metadata when comparing versions per semver spec https://semver.org/#spec-item-10 + + if mainCompared != 0 + then mainCompared + else preCompared + + override def toString: String = + val preReleaseString = preRelease.map("-" + _).getOrElse("") + val buildMetadataString = buildMetadata.map("+" + _).getOrElse("") + s"$major.$minor.$patch$preReleaseString$buildMetadataString" + +//noinspection ScalaFileName +object SemanticVersion { + private val versionRegex = """(\d+)\.(\d+)\.(\d+)(?:-(.+))?(?:\+(.+))?""".r + + def apply(major: Int, minor: Int, patch: Int): SemanticVersion = + SemanticVersion(major, minor, patch, None, None) + + def parse(version: String): Either[Exception, SemanticVersion] = { + version match { + case versionRegex(major, minor, patch, preRelease, buildMetadata) => + Right(SemanticVersion(major.toInt, minor.toInt, patch.toInt, Option(preRelease), Option(buildMetadata))) + case _ => Left(Exception(s"Cannot parse as semantic version: '$version'")) + } + } + + /** ParseTolerant allows for certain version specifications that do not strictly adhere to semver specs to be parsed by this library. It + * does so by normalizing versions before passing them to [[parse]]. It currently trims spaces, removes a "v" prefix, and adds a 0 patch + * number to versions with only major and minor components specified. + */ + def parseTolerant(version: String): Either[Exception, SemanticVersion] = { + val str = version.trim.stripPrefix("v") + + // Split into major.minor.(patch+pr+meta) + val parts = str.split("\\.", 3) + if parts.length < 3 then + if parts.last.contains("+") || parts.last.contains("-") then + Left(Exception("Short version cannot contain PreRelease/Build meta data")) + else parse((parts.toList ::: List.fill(3 - parts.length)("0")).mkString(".")) + else parse(str) + } +} diff --git a/auto/src/test/scala/besom/auto/LocalWorkspaceTest.scala b/auto/src/test/scala/besom/auto/LocalWorkspaceTest.scala new file mode 100644 index 00000000..8ac44938 --- /dev/null +++ b/auto/src/test/scala/besom/auto/LocalWorkspaceTest.scala @@ -0,0 +1,57 @@ +package besom.auto + +import besom.FullyQualifiedStackName +import besom.test.* +import besom.util.eitherOps + +class LocalWorkspaceTest extends munit.FunSuite: + + FunFixture[FullyQualifiedStackName]( + setup = t => fqsn(this.getClass, t), + teardown = _ => () + ).test("new stack remote source with setup") { generatedStackName => + val stackName = FullyQualifiedStackName("goproj", generatedStackName.stack) + val pulumiHomeDir = os.temp.dir() / ".pulumi" + loginLocal(pulumiHomeDir) + + val binName = "examplesBinary" + val bin = if System.getProperty("os.name").startsWith("Windows") then binName + ".exe" else binName + val binaryBuilder = (ws: Workspace) => { + shell("go", "build", "-o", bin, "main.go")(shell.ShellOption.Cwd(ws.workDir)).bimap( + e => e.withMessage("go build failed"), + _ => () + ) + } + + val res = for + stack <- createStackRemoteSource( + stackName, + GitRepo( + url = "https://github.com/pulumi/test-repo.git", + projectPath = "goproj", + setup = binaryBuilder + ), + LocalWorkspaceOption.Project( + Project( + name = "goproj", + runtime = ProjectRuntimeInfo( + name = "go", + options = Map("binary" -> binName) + ) + ) + ), + LocalWorkspaceOption.PulumiHome(pulumiHomeDir), + LocalWorkspaceOption.EnvVars(shell.pulumi.env.PulumiConfigPassphraseEnv -> "test") + ) + prevRes <- stack.preview() + upRes <- stack.up() + yield (prevRes, upRes) + res.fold( + e => fail(e.getMessage, e), + (prevRes, upRes) => { + println(prevRes) + println(upRes) + } + ) + } +end LocalWorkspaceTest diff --git a/auto/src/test/scala/besom/auto/ShellTest.scala b/auto/src/test/scala/besom/auto/ShellTest.scala new file mode 100644 index 00000000..311bc904 --- /dev/null +++ b/auto/src/test/scala/besom/auto/ShellTest.scala @@ -0,0 +1,29 @@ +package besom.auto + +import besom.auto.shell.* + +class ShellTest extends munit.FunSuite: + test("ShellOptions.from") { + val options = ShellOptions.from( + ShellOption.Cwd(os.pwd / "test"), + ShellOption.Env("FOO" -> "BAR"), + ShellOption.Env("FOO2" -> "BAR2"), + ShellOption.Stdin("input"), + ShellOption.Stdout(os.ProcessOutput.Readlines(_ => ())), + ShellOption.Stderr(os.ProcessOutput.Readlines(_ => ())), + ShellOption.Timeout(1000), + ShellOption.MergeErrIntoOut, + ShellOption.Check, + ShellOption.DontPropagateEnv + ) + + assertEquals(options.cwd, os.pwd / "test") + assertEquals(options.env, Map("FOO" -> "BAR", "FOO2" -> "BAR2")) + assertEquals(options.stdin.getClass.getTypeName, "os.ProcessInput$SourceInput") + assertEquals(options.stdout.getClass.getTypeName, "os.ProcessOutput$Readlines") + assertEquals(options.stderr.getClass.getTypeName, "os.ProcessOutput$Readlines") + assertEquals(options.timeout, 1000L) + assertEquals(options.mergeErrIntoOut, true) + assertEquals(options.check, true) + assertEquals(options.propagateEnv, false) + } diff --git a/auto/src/test/scala/besom/auto/StackTest.scala b/auto/src/test/scala/besom/auto/StackTest.scala new file mode 100644 index 00000000..03837ea5 --- /dev/null +++ b/auto/src/test/scala/besom/auto/StackTest.scala @@ -0,0 +1,23 @@ +package besom.auto + +import besom.util.eitherOps + +//noinspection ScalaFileName +class EngineEventJSONTest extends munit.FunSuite { + + test("EngineEvent should deserialize from JSON") { + val json = + """{"sequence":4,"timestamp":1704893590,"summaryEvent":{"maybeCorrupt":false,"durationSeconds":0,"resourceChanges":{"create":1},"PolicyPacks":{}}}""" + + val event: EngineEvent = EngineEvent.fromJson(json).get + + assertEquals(event.sequence, 4) + assertEquals(event.timestamp, 1704893590) + assert(event.summaryEvent.isDefined) + val summary: SummaryEvent = event.summaryEvent.get + assertEquals(summary.maybeCorrupt, false) + assertEquals(summary.durationSeconds, 0) + assertEquals(summary.resourceChanges(OpType.Create), 1) + assertEquals(summary.policyPacks, Map.empty) + } +} diff --git a/auto/src/test/scala/besom/model/NamesTest.scala b/auto/src/test/scala/besom/model/NamesTest.scala new file mode 100644 index 00000000..8432c37b --- /dev/null +++ b/auto/src/test/scala/besom/model/NamesTest.scala @@ -0,0 +1,146 @@ +package besom.model + +import besom.test.CompileAssertions + +class NamesTest extends munit.FunSuite with CompileAssertions: + + import QName.* // force use of QName extensions instead of TestOptionsConversions.name + + test("validation - all alpha") { + compiles("""import besom.model._ + val n = Name("simple") + """) + } + + test("validation - mixed-case alpha") { + compiles("""import besom.model._ + val n = Name("SiMplE") + """) + } + + test("validation - alphanumeric") { + compiles("""import besom.model._ + val n = Name("simple0") + """) + } + + test("validation - mixed-case alphanumeric") { + compiles("""import besom.model._ + val n = Name("SiMpLe0") + """) + } + + test("validation - permit underscore") { + compiles("""import besom.model._ + val n = Name("_") + """) + } + + test("validation - mixed-case alphanumeric/underscore") { + compiles("""import besom.model._ + val n = Name("s1MPl3_") + """) + compiles("""import besom.model._ + val n = Name("_s1MPl3") + """) + } + + test("validation - permit hyphens") { + compiles("""import besom.model._ + val n = Name("hy-phy") + """) + } + + test("validation - start with .") { + compiles("""import besom.model._ + val n = Name(".dotstart") + """) + } + + test("validation - start with -") { + compiles("""import besom.model._ + val n = Name("-hyphenstart") + """) + } + + test("validation - start with numbers") { + compiles("""import besom.model._ + val n = Name("0num") + """) + } + + test("validation - start with numbers") { + compiles("""import besom.model._ + val n = Name("9num") + """) + } + + test("validation - multi-part name") { + compiles("""import besom.model._ + val n = QName("namespace/complex") + """) + failsToCompile("""import besom.model._ + val n = Name("namespace/complex") + """) + } + + test("validation - multi-part, alphanumeric, etc. name") { + compiles("""import besom.model._ + val n = QName("_naMeSpace0/coMpl3x32") + """) + failsToCompile("""import besom.model._ + val n = Name("_naMeSpace0/coMpl3x32") + """) + } + + test("validation - even more complex parts") { + compiles("""import besom.model._ + val n = QName("n_ameSpace3/moRenam3sp4ce/_Complex5") + """) + failsToCompile("""import besom.model._ + val n = Name("n_ameSpace3/moRenam3sp4ce/_Complex5") + """) + } + + test("validation - bad characters") { + failsToCompile("""import besom.model._ + val n = QName("s!mple") + """) + failsToCompile("""import besom.model._ + val n = Name("s!mple") + """) + failsToCompile("""import besom.model._ + val n = QName("namesp@ce/complex") + """) + failsToCompile("""import besom.model._ + val n = Name("namesp@ce/complex") + """) + failsToCompile("""import besom.model._ + val n = QName("namespace/morenamespace/compl#x") + """) + failsToCompile("""import besom.model._ + val n = Name("namespace/morenamespace/compl#x") + """) + } + + test("parsing - simple name") { + assertEquals(Name("simple"), "simple") + assertEquals(QName("namespace/complex").name, "complex") + assertEquals(QName("ns1/ns2/ns3/ns4/complex").name, "complex") + assertEquals(QName("_/_/_/_/a0/c0Mpl3x_").name, "c0Mpl3x_") + } + + test("parsing - simple namespace") { + assertEquals(QName("namespace/complex").namespace, "namespace") + assertEquals(QName("ns1/ns2/ns3/ns4/complex").namespace, "ns1/ns2/ns3/ns4") + assertEquals(QName("_/_/_/_/a0/c0Mpl3x_").namespace, "_/_/_/_/a0") + } + + test("convert to QName") { + assertEquals(QName.parse("foo/bar"), "foo/bar") + assertEquals(QName.parse("https:"), "https_") + assertEquals(QName.parse("https://"), "https_") + assertEquals(QName.parse(""), "_") + assertEquals(QName.parse("///"), "_") + } +end NamesTest diff --git a/auto/src/test/scala/besom/test/CompileAssertions.scala b/auto/src/test/scala/besom/test/CompileAssertions.scala new file mode 100644 index 00000000..316f51c0 --- /dev/null +++ b/auto/src/test/scala/besom/test/CompileAssertions.scala @@ -0,0 +1,13 @@ +package besom.test + +trait CompileAssertions: + self: munit.FunSuite => + + inline def failsToCompile(inline code: String): Unit = + assert( + !scala.compiletime.testing.typeChecks(code), + s"Code compiled correctly when expecting type errors:${System.lineSeparator()}$code" + ) + + inline def compiles(inline code: String): Unit = + assert(scala.compiletime.testing.typeChecks(code), s"Code failed to compile:${System.lineSeparator()}$code") diff --git a/auto/src/test/scala/besom/test/Naming.scala b/auto/src/test/scala/besom/test/Naming.scala new file mode 100644 index 00000000..efad8bf3 --- /dev/null +++ b/auto/src/test/scala/besom/test/Naming.scala @@ -0,0 +1,22 @@ +package besom.test + +import besom.FullyQualifiedStackName + +/** SHA1 hash of a string + * + * @param s + * string to hash + * @return + * 40 character hex string of the hash for the given string + */ +def sha1(s: String): String = { + import java.security.MessageDigest + val bytes = MessageDigest.getInstance("SHA-1").digest(s.getBytes("UTF-8")) + String.format("%x", new java.math.BigInteger(1, bytes)) +} + +def sanitizeName(name: String, replacement: String = "-", limit: Int = 40): String = + name.replaceAll("[^a-zA-Z0-9]+", replacement).toLowerCase().take(limit).stripSuffix(replacement) +def stackName(name: String): String = "tests-" + sanitizeName(name) +def fqsn(`class`: Class[_], test: munit.TestOptions): FullyQualifiedStackName = + FullyQualifiedStackName(sanitizeName(`class`.getSimpleName, limit = 20), stackName(test.name)) From 0ccacd755b57fd6a1a194fc91d4ad56b62c13d39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Pra=C5=BCak?= Date: Wed, 15 May 2024 14:40:50 +0200 Subject: [PATCH 03/15] Add Pulumi gRPC language service --- .../pulumirpc/codegen/hcl/Diagnostic.scala | 261 +++++++ .../codegen/hcl/DiagnosticSeverity.scala | 65 ++ .../rpc/pulumirpc/codegen/hcl/HclProto.scala | 41 ++ .../besom/rpc/pulumirpc/codegen/hcl/Pos.scala | 196 +++++ .../rpc/pulumirpc/codegen/hcl/Range.scala | 185 +++++ .../pulumirpc/language/AboutResponse.scala | 338 +++++++++ .../pulumirpc/language/DependencyInfo.scala | 152 ++++ .../language/GeneratePackageRequest.scala | 546 ++++++++++++++ .../language/GeneratePackageResponse.scala | 123 ++++ .../language/GenerateProgramRequest.scala | 304 ++++++++ .../language/GenerateProgramResponse.scala | 302 ++++++++ .../language/GenerateProjectRequest.scala | 433 +++++++++++ .../language/GenerateProjectResponse.scala | 123 ++++ .../GetProgramDependenciesRequest.scala | 251 +++++++ .../GetProgramDependenciesResponse.scala | 123 ++++ .../language/GetRequiredPluginsRequest.scala | 219 ++++++ .../language/GetRequiredPluginsResponse.scala | 123 ++++ .../language/InstallDependenciesRequest.scala | 187 +++++ .../InstallDependenciesResponse.scala | 152 ++++ .../pulumirpc/language/LanguageProto.scala | 138 ++++ .../language/LanguageRuntimeGrpc.scala | 443 ++++++++++++ .../rpc/pulumirpc/language/PackRequest.scala | 152 ++++ .../rpc/pulumirpc/language/PackResponse.scala | 120 ++++ .../rpc/pulumirpc/language/ProgramInfo.scala | 226 ++++++ .../pulumirpc/language/RunPluginRequest.scala | 241 +++++++ .../language/RunPluginResponse.scala | 190 +++++ .../rpc/pulumirpc/language/RunRequest.scala | 676 ++++++++++++++++++ .../rpc/pulumirpc/language/RunResponse.scala | 156 ++++ proto/pulumi/codegen/hcl.proto | 89 +++ proto/pulumi/language.proto | 233 ++++++ scripts/Proto.scala | 2 + 31 files changed, 6790 insertions(+) create mode 100644 core/src/main/scala/besom/rpc/pulumirpc/codegen/hcl/Diagnostic.scala create mode 100644 core/src/main/scala/besom/rpc/pulumirpc/codegen/hcl/DiagnosticSeverity.scala create mode 100644 core/src/main/scala/besom/rpc/pulumirpc/codegen/hcl/HclProto.scala create mode 100644 core/src/main/scala/besom/rpc/pulumirpc/codegen/hcl/Pos.scala create mode 100644 core/src/main/scala/besom/rpc/pulumirpc/codegen/hcl/Range.scala create mode 100644 core/src/main/scala/besom/rpc/pulumirpc/language/AboutResponse.scala create mode 100644 core/src/main/scala/besom/rpc/pulumirpc/language/DependencyInfo.scala create mode 100644 core/src/main/scala/besom/rpc/pulumirpc/language/GeneratePackageRequest.scala create mode 100644 core/src/main/scala/besom/rpc/pulumirpc/language/GeneratePackageResponse.scala create mode 100644 core/src/main/scala/besom/rpc/pulumirpc/language/GenerateProgramRequest.scala create mode 100644 core/src/main/scala/besom/rpc/pulumirpc/language/GenerateProgramResponse.scala create mode 100644 core/src/main/scala/besom/rpc/pulumirpc/language/GenerateProjectRequest.scala create mode 100644 core/src/main/scala/besom/rpc/pulumirpc/language/GenerateProjectResponse.scala create mode 100644 core/src/main/scala/besom/rpc/pulumirpc/language/GetProgramDependenciesRequest.scala create mode 100644 core/src/main/scala/besom/rpc/pulumirpc/language/GetProgramDependenciesResponse.scala create mode 100644 core/src/main/scala/besom/rpc/pulumirpc/language/GetRequiredPluginsRequest.scala create mode 100644 core/src/main/scala/besom/rpc/pulumirpc/language/GetRequiredPluginsResponse.scala create mode 100644 core/src/main/scala/besom/rpc/pulumirpc/language/InstallDependenciesRequest.scala create mode 100644 core/src/main/scala/besom/rpc/pulumirpc/language/InstallDependenciesResponse.scala create mode 100644 core/src/main/scala/besom/rpc/pulumirpc/language/LanguageProto.scala create mode 100644 core/src/main/scala/besom/rpc/pulumirpc/language/LanguageRuntimeGrpc.scala create mode 100644 core/src/main/scala/besom/rpc/pulumirpc/language/PackRequest.scala create mode 100644 core/src/main/scala/besom/rpc/pulumirpc/language/PackResponse.scala create mode 100644 core/src/main/scala/besom/rpc/pulumirpc/language/ProgramInfo.scala create mode 100644 core/src/main/scala/besom/rpc/pulumirpc/language/RunPluginRequest.scala create mode 100644 core/src/main/scala/besom/rpc/pulumirpc/language/RunPluginResponse.scala create mode 100644 core/src/main/scala/besom/rpc/pulumirpc/language/RunRequest.scala create mode 100644 core/src/main/scala/besom/rpc/pulumirpc/language/RunResponse.scala create mode 100644 proto/pulumi/codegen/hcl.proto create mode 100644 proto/pulumi/language.proto diff --git a/core/src/main/scala/besom/rpc/pulumirpc/codegen/hcl/Diagnostic.scala b/core/src/main/scala/besom/rpc/pulumirpc/codegen/hcl/Diagnostic.scala new file mode 100644 index 00000000..1b263fc8 --- /dev/null +++ b/core/src/main/scala/besom/rpc/pulumirpc/codegen/hcl/Diagnostic.scala @@ -0,0 +1,261 @@ +// Generated by the Scala Plugin for the Protocol Buffer Compiler. +// Do not edit! +// +// Protofile syntax: PROTO3 + +package pulumirpc.codegen.hcl + +/** Diagnostic represents information to be presented to a user about an error or anomaly in parsing or evaluating configuration. + * + * @param summary + * Summary and Detail contain the English-language description of the + * problem. Summary is a terse description of the general problem and + * detail is a more elaborate, often-multi-sentence description of + * the problem and what might be done to solve it. + * @param subject + * Subject and Context are both source ranges relating to the diagnostic. + * + * Subject is a tight range referring to exactly the construct that + * is problematic, while Context is an optional broader range (which should + * fully contain Subject) that ought to be shown around Subject when + * generating isolated source-code snippets in diagnostic messages. + * If Context is nil, the Subject is also the Context. + * + * Some diagnostics have no source ranges at all. If Context is set then + * Subject should always also be set. + */ +@SerialVersionUID(0L) +final case class Diagnostic( + severity: pulumirpc.codegen.hcl.DiagnosticSeverity = pulumirpc.codegen.hcl.DiagnosticSeverity.DIAG_INVALID, + summary: _root_.scala.Predef.String = "", + detail: _root_.scala.Predef.String = "", + subject: _root_.scala.Option[pulumirpc.codegen.hcl.Range] = _root_.scala.None, + context: _root_.scala.Option[pulumirpc.codegen.hcl.Range] = _root_.scala.None, + unknownFields: _root_.scalapb.UnknownFieldSet = _root_.scalapb.UnknownFieldSet.empty + ) extends scalapb.GeneratedMessage with scalapb.lenses.Updatable[Diagnostic] { + @transient + private[this] var __serializedSizeMemoized: _root_.scala.Int = 0 + private[this] def __computeSerializedSize(): _root_.scala.Int = { + var __size = 0 + + { + val __value = severity.value + if (__value != 0) { + __size += _root_.com.google.protobuf.CodedOutputStream.computeEnumSize(1, __value) + } + }; + + { + val __value = summary + if (!__value.isEmpty) { + __size += _root_.com.google.protobuf.CodedOutputStream.computeStringSize(2, __value) + } + }; + + { + val __value = detail + if (!__value.isEmpty) { + __size += _root_.com.google.protobuf.CodedOutputStream.computeStringSize(3, __value) + } + }; + if (subject.isDefined) { + val __value = subject.get + __size += 1 + _root_.com.google.protobuf.CodedOutputStream.computeUInt32SizeNoTag(__value.serializedSize) + __value.serializedSize + }; + if (context.isDefined) { + val __value = context.get + __size += 1 + _root_.com.google.protobuf.CodedOutputStream.computeUInt32SizeNoTag(__value.serializedSize) + __value.serializedSize + }; + __size += unknownFields.serializedSize + __size + } + override def serializedSize: _root_.scala.Int = { + var __size = __serializedSizeMemoized + if (__size == 0) { + __size = __computeSerializedSize() + 1 + __serializedSizeMemoized = __size + } + __size - 1 + + } + def writeTo(`_output__`: _root_.com.google.protobuf.CodedOutputStream): _root_.scala.Unit = { + { + val __v = severity.value + if (__v != 0) { + _output__.writeEnum(1, __v) + } + }; + { + val __v = summary + if (!__v.isEmpty) { + _output__.writeString(2, __v) + } + }; + { + val __v = detail + if (!__v.isEmpty) { + _output__.writeString(3, __v) + } + }; + subject.foreach { __v => + val __m = __v + _output__.writeTag(4, 2) + _output__.writeUInt32NoTag(__m.serializedSize) + __m.writeTo(_output__) + }; + context.foreach { __v => + val __m = __v + _output__.writeTag(5, 2) + _output__.writeUInt32NoTag(__m.serializedSize) + __m.writeTo(_output__) + }; + unknownFields.writeTo(_output__) + } + def withSeverity(__v: pulumirpc.codegen.hcl.DiagnosticSeverity): Diagnostic = copy(severity = __v) + def withSummary(__v: _root_.scala.Predef.String): Diagnostic = copy(summary = __v) + def withDetail(__v: _root_.scala.Predef.String): Diagnostic = copy(detail = __v) + def getSubject: pulumirpc.codegen.hcl.Range = subject.getOrElse(pulumirpc.codegen.hcl.Range.defaultInstance) + def clearSubject: Diagnostic = copy(subject = _root_.scala.None) + def withSubject(__v: pulumirpc.codegen.hcl.Range): Diagnostic = copy(subject = Option(__v)) + def getContext: pulumirpc.codegen.hcl.Range = context.getOrElse(pulumirpc.codegen.hcl.Range.defaultInstance) + def clearContext: Diagnostic = copy(context = _root_.scala.None) + def withContext(__v: pulumirpc.codegen.hcl.Range): Diagnostic = copy(context = Option(__v)) + def withUnknownFields(__v: _root_.scalapb.UnknownFieldSet) = copy(unknownFields = __v) + def discardUnknownFields = copy(unknownFields = _root_.scalapb.UnknownFieldSet.empty) + def getFieldByNumber(__fieldNumber: _root_.scala.Int): _root_.scala.Any = { + (__fieldNumber: @_root_.scala.unchecked) match { + case 1 => { + val __t = severity.javaValueDescriptor + if (__t.getNumber() != 0) __t else null + } + case 2 => { + val __t = summary + if (__t != "") __t else null + } + case 3 => { + val __t = detail + if (__t != "") __t else null + } + case 4 => subject.orNull + case 5 => context.orNull + } + } + def getField(__field: _root_.scalapb.descriptors.FieldDescriptor): _root_.scalapb.descriptors.PValue = { + _root_.scala.Predef.require(__field.containingMessage eq companion.scalaDescriptor) + (__field.number: @_root_.scala.unchecked) match { + case 1 => _root_.scalapb.descriptors.PEnum(severity.scalaValueDescriptor) + case 2 => _root_.scalapb.descriptors.PString(summary) + case 3 => _root_.scalapb.descriptors.PString(detail) + case 4 => subject.map(_.toPMessage).getOrElse(_root_.scalapb.descriptors.PEmpty) + case 5 => context.map(_.toPMessage).getOrElse(_root_.scalapb.descriptors.PEmpty) + } + } + def toProtoString: _root_.scala.Predef.String = _root_.scalapb.TextFormat.printToUnicodeString(this) + def companion: pulumirpc.codegen.hcl.Diagnostic.type = pulumirpc.codegen.hcl.Diagnostic + // @@protoc_insertion_point(GeneratedMessage[pulumirpc.codegen.Diagnostic]) +} + +object Diagnostic extends scalapb.GeneratedMessageCompanion[pulumirpc.codegen.hcl.Diagnostic] { + implicit def messageCompanion: scalapb.GeneratedMessageCompanion[pulumirpc.codegen.hcl.Diagnostic] = this + def parseFrom(`_input__`: _root_.com.google.protobuf.CodedInputStream): pulumirpc.codegen.hcl.Diagnostic = { + var __severity: pulumirpc.codegen.hcl.DiagnosticSeverity = pulumirpc.codegen.hcl.DiagnosticSeverity.DIAG_INVALID + var __summary: _root_.scala.Predef.String = "" + var __detail: _root_.scala.Predef.String = "" + var __subject: _root_.scala.Option[pulumirpc.codegen.hcl.Range] = _root_.scala.None + var __context: _root_.scala.Option[pulumirpc.codegen.hcl.Range] = _root_.scala.None + var `_unknownFields__`: _root_.scalapb.UnknownFieldSet.Builder = null + var _done__ = false + while (!_done__) { + val _tag__ = _input__.readTag() + _tag__ match { + case 0 => _done__ = true + case 8 => + __severity = pulumirpc.codegen.hcl.DiagnosticSeverity.fromValue(_input__.readEnum()) + case 18 => + __summary = _input__.readStringRequireUtf8() + case 26 => + __detail = _input__.readStringRequireUtf8() + case 34 => + __subject = _root_.scala.Option(__subject.fold(_root_.scalapb.LiteParser.readMessage[pulumirpc.codegen.hcl.Range](_input__))(_root_.scalapb.LiteParser.readMessage(_input__, _))) + case 42 => + __context = _root_.scala.Option(__context.fold(_root_.scalapb.LiteParser.readMessage[pulumirpc.codegen.hcl.Range](_input__))(_root_.scalapb.LiteParser.readMessage(_input__, _))) + case tag => + if (_unknownFields__ == null) { + _unknownFields__ = new _root_.scalapb.UnknownFieldSet.Builder() + } + _unknownFields__.parseField(tag, _input__) + } + } + pulumirpc.codegen.hcl.Diagnostic( + severity = __severity, + summary = __summary, + detail = __detail, + subject = __subject, + context = __context, + unknownFields = if (_unknownFields__ == null) _root_.scalapb.UnknownFieldSet.empty else _unknownFields__.result() + ) + } + implicit def messageReads: _root_.scalapb.descriptors.Reads[pulumirpc.codegen.hcl.Diagnostic] = _root_.scalapb.descriptors.Reads{ + case _root_.scalapb.descriptors.PMessage(__fieldsMap) => + _root_.scala.Predef.require(__fieldsMap.keys.forall(_.containingMessage eq scalaDescriptor), "FieldDescriptor does not match message type.") + pulumirpc.codegen.hcl.Diagnostic( + severity = pulumirpc.codegen.hcl.DiagnosticSeverity.fromValue(__fieldsMap.get(scalaDescriptor.findFieldByNumber(1).get).map(_.as[_root_.scalapb.descriptors.EnumValueDescriptor]).getOrElse(pulumirpc.codegen.hcl.DiagnosticSeverity.DIAG_INVALID.scalaValueDescriptor).number), + summary = __fieldsMap.get(scalaDescriptor.findFieldByNumber(2).get).map(_.as[_root_.scala.Predef.String]).getOrElse(""), + detail = __fieldsMap.get(scalaDescriptor.findFieldByNumber(3).get).map(_.as[_root_.scala.Predef.String]).getOrElse(""), + subject = __fieldsMap.get(scalaDescriptor.findFieldByNumber(4).get).flatMap(_.as[_root_.scala.Option[pulumirpc.codegen.hcl.Range]]), + context = __fieldsMap.get(scalaDescriptor.findFieldByNumber(5).get).flatMap(_.as[_root_.scala.Option[pulumirpc.codegen.hcl.Range]]) + ) + case _ => throw new RuntimeException("Expected PMessage") + } + def javaDescriptor: _root_.com.google.protobuf.Descriptors.Descriptor = HclProto.javaDescriptor.getMessageTypes().get(2) + def scalaDescriptor: _root_.scalapb.descriptors.Descriptor = HclProto.scalaDescriptor.messages(2) + def messageCompanionForFieldNumber(__number: _root_.scala.Int): _root_.scalapb.GeneratedMessageCompanion[_] = { + var __out: _root_.scalapb.GeneratedMessageCompanion[_] = null + (__number: @_root_.scala.unchecked) match { + case 4 => __out = pulumirpc.codegen.hcl.Range + case 5 => __out = pulumirpc.codegen.hcl.Range + } + __out + } + lazy val nestedMessagesCompanions: Seq[_root_.scalapb.GeneratedMessageCompanion[_ <: _root_.scalapb.GeneratedMessage]] = Seq.empty + def enumCompanionForFieldNumber(__fieldNumber: _root_.scala.Int): _root_.scalapb.GeneratedEnumCompanion[_] = { + (__fieldNumber: @_root_.scala.unchecked) match { + case 1 => pulumirpc.codegen.hcl.DiagnosticSeverity + } + } + lazy val defaultInstance = pulumirpc.codegen.hcl.Diagnostic( + severity = pulumirpc.codegen.hcl.DiagnosticSeverity.DIAG_INVALID, + summary = "", + detail = "", + subject = _root_.scala.None, + context = _root_.scala.None + ) + implicit class DiagnosticLens[UpperPB](_l: _root_.scalapb.lenses.Lens[UpperPB, pulumirpc.codegen.hcl.Diagnostic]) extends _root_.scalapb.lenses.ObjectLens[UpperPB, pulumirpc.codegen.hcl.Diagnostic](_l) { + def severity: _root_.scalapb.lenses.Lens[UpperPB, pulumirpc.codegen.hcl.DiagnosticSeverity] = field(_.severity)((c_, f_) => c_.copy(severity = f_)) + def summary: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Predef.String] = field(_.summary)((c_, f_) => c_.copy(summary = f_)) + def detail: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Predef.String] = field(_.detail)((c_, f_) => c_.copy(detail = f_)) + def subject: _root_.scalapb.lenses.Lens[UpperPB, pulumirpc.codegen.hcl.Range] = field(_.getSubject)((c_, f_) => c_.copy(subject = _root_.scala.Option(f_))) + def optionalSubject: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Option[pulumirpc.codegen.hcl.Range]] = field(_.subject)((c_, f_) => c_.copy(subject = f_)) + def context: _root_.scalapb.lenses.Lens[UpperPB, pulumirpc.codegen.hcl.Range] = field(_.getContext)((c_, f_) => c_.copy(context = _root_.scala.Option(f_))) + def optionalContext: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Option[pulumirpc.codegen.hcl.Range]] = field(_.context)((c_, f_) => c_.copy(context = f_)) + } + final val SEVERITY_FIELD_NUMBER = 1 + final val SUMMARY_FIELD_NUMBER = 2 + final val DETAIL_FIELD_NUMBER = 3 + final val SUBJECT_FIELD_NUMBER = 4 + final val CONTEXT_FIELD_NUMBER = 5 + def of( + severity: pulumirpc.codegen.hcl.DiagnosticSeverity, + summary: _root_.scala.Predef.String, + detail: _root_.scala.Predef.String, + subject: _root_.scala.Option[pulumirpc.codegen.hcl.Range], + context: _root_.scala.Option[pulumirpc.codegen.hcl.Range] + ): _root_.pulumirpc.codegen.hcl.Diagnostic = _root_.pulumirpc.codegen.hcl.Diagnostic( + severity, + summary, + detail, + subject, + context + ) + // @@protoc_insertion_point(GeneratedMessageCompanion[pulumirpc.codegen.Diagnostic]) +} diff --git a/core/src/main/scala/besom/rpc/pulumirpc/codegen/hcl/DiagnosticSeverity.scala b/core/src/main/scala/besom/rpc/pulumirpc/codegen/hcl/DiagnosticSeverity.scala new file mode 100644 index 00000000..e993be77 --- /dev/null +++ b/core/src/main/scala/besom/rpc/pulumirpc/codegen/hcl/DiagnosticSeverity.scala @@ -0,0 +1,65 @@ +// Generated by the Scala Plugin for the Protocol Buffer Compiler. +// Do not edit! +// +// Protofile syntax: PROTO3 + +package pulumirpc.codegen.hcl + +/** DiagnosticSeverity is the severity level of a diagnostic message. + */ +sealed abstract class DiagnosticSeverity(val value: _root_.scala.Int) extends _root_.scalapb.GeneratedEnum { + type EnumType = pulumirpc.codegen.hcl.DiagnosticSeverity + type RecognizedType = pulumirpc.codegen.hcl.DiagnosticSeverity.Recognized + def isDiagInvalid: _root_.scala.Boolean = false + def isDiagError: _root_.scala.Boolean = false + def isDiagWarning: _root_.scala.Boolean = false + def companion: _root_.scalapb.GeneratedEnumCompanion[DiagnosticSeverity] = pulumirpc.codegen.hcl.DiagnosticSeverity + final def asRecognized: _root_.scala.Option[pulumirpc.codegen.hcl.DiagnosticSeverity.Recognized] = if (isUnrecognized) _root_.scala.None else _root_.scala.Some(this.asInstanceOf[pulumirpc.codegen.hcl.DiagnosticSeverity.Recognized]) +} + +object DiagnosticSeverity extends _root_.scalapb.GeneratedEnumCompanion[DiagnosticSeverity] { + sealed trait Recognized extends DiagnosticSeverity + implicit def enumCompanion: _root_.scalapb.GeneratedEnumCompanion[DiagnosticSeverity] = this + + /** DIAG_INVALID is the invalid zero value of DiagnosticSeverity + */ + @SerialVersionUID(0L) + case object DIAG_INVALID extends DiagnosticSeverity(0) with DiagnosticSeverity.Recognized { + val index = 0 + val name = "DIAG_INVALID" + override def isDiagInvalid: _root_.scala.Boolean = true + } + + /** DIAG_ERROR indicates that the problem reported by a diagnostic prevents + * further progress in parsing and/or evaluating the subject. + */ + @SerialVersionUID(0L) + case object DIAG_ERROR extends DiagnosticSeverity(1) with DiagnosticSeverity.Recognized { + val index = 1 + val name = "DIAG_ERROR" + override def isDiagError: _root_.scala.Boolean = true + } + + /** DIAG_WARNING indicates that the problem reported by a diagnostic warrants + * user attention but does not prevent further progress. It is most + * commonly used for showing deprecation notices. + */ + @SerialVersionUID(0L) + case object DIAG_WARNING extends DiagnosticSeverity(2) with DiagnosticSeverity.Recognized { + val index = 2 + val name = "DIAG_WARNING" + override def isDiagWarning: _root_.scala.Boolean = true + } + + @SerialVersionUID(0L) + final case class Unrecognized(unrecognizedValue: _root_.scala.Int) extends DiagnosticSeverity(unrecognizedValue) with _root_.scalapb.UnrecognizedEnum + lazy val values: scala.collection.immutable.Seq[ValueType] = scala.collection.immutable.Seq(DIAG_INVALID, DIAG_ERROR, DIAG_WARNING) + def fromValue(__value: _root_.scala.Int): DiagnosticSeverity = __value match { + case 0 => DIAG_INVALID + case 1 => DIAG_ERROR + case 2 => DIAG_WARNING + case __other => Unrecognized(__other) + } + def javaDescriptor: _root_.com.google.protobuf.Descriptors.EnumDescriptor = HclProto.javaDescriptor.getEnumTypes().get(0) + def scalaDescriptor: _root_.scalapb.descriptors.EnumDescriptor = HclProto.scalaDescriptor.enums(0) +} \ No newline at end of file diff --git a/core/src/main/scala/besom/rpc/pulumirpc/codegen/hcl/HclProto.scala b/core/src/main/scala/besom/rpc/pulumirpc/codegen/hcl/HclProto.scala new file mode 100644 index 00000000..3fee8491 --- /dev/null +++ b/core/src/main/scala/besom/rpc/pulumirpc/codegen/hcl/HclProto.scala @@ -0,0 +1,41 @@ +// Generated by the Scala Plugin for the Protocol Buffer Compiler. +// Do not edit! +// +// Protofile syntax: PROTO3 + +package pulumirpc.codegen.hcl + +object HclProto extends _root_.scalapb.GeneratedFileObject { + lazy val dependencies: Seq[_root_.scalapb.GeneratedFileObject] = Seq.empty + lazy val messagesCompanions: Seq[_root_.scalapb.GeneratedMessageCompanion[_ <: _root_.scalapb.GeneratedMessage]] = + Seq[_root_.scalapb.GeneratedMessageCompanion[_ <: _root_.scalapb.GeneratedMessage]]( + pulumirpc.codegen.hcl.Pos, + pulumirpc.codegen.hcl.Range, + pulumirpc.codegen.hcl.Diagnostic + ) + private lazy val ProtoBytes: _root_.scala.Array[Byte] = + scalapb.Encoding.fromBase64(scala.collection.immutable.Seq( + """ChhwdWx1bWkvY29kZWdlbi9oY2wucHJvdG8SEXB1bHVtaXJwYy5jb2RlZ2VuImgKA1BvcxIdCgRsaW5lGAEgASgDQgniPwYSB + GxpbmVSBGxpbmUSIwoGY29sdW1uGAIgASgDQgviPwgSBmNvbHVtblIGY29sdW1uEh0KBGJ5dGUYAyABKANCCeI/BhIEYnl0ZVIEY + nl0ZSKgAQoFUmFuZ2USKQoIZmlsZW5hbWUYASABKAlCDeI/ChIIZmlsZW5hbWVSCGZpbGVuYW1lEjgKBXN0YXJ0GAIgASgLMhYuc + HVsdW1pcnBjLmNvZGVnZW4uUG9zQgriPwcSBXN0YXJ0UgVzdGFydBIyCgNlbmQYAyABKAsyFi5wdWx1bWlycGMuY29kZWdlbi5Qb + 3NCCOI/BRIDZW5kUgNlbmQirwIKCkRpYWdub3N0aWMSUAoIc2V2ZXJpdHkYASABKA4yJS5wdWx1bWlycGMuY29kZWdlbi5EaWFnb + m9zdGljU2V2ZXJpdHlCDeI/ChIIc2V2ZXJpdHlSCHNldmVyaXR5EiYKB3N1bW1hcnkYAiABKAlCDOI/CRIHc3VtbWFyeVIHc3Vtb + WFyeRIjCgZkZXRhaWwYAyABKAlCC+I/CBIGZGV0YWlsUgZkZXRhaWwSQAoHc3ViamVjdBgEIAEoCzIYLnB1bHVtaXJwYy5jb2RlZ + 2VuLlJhbmdlQgziPwkSB3N1YmplY3RSB3N1YmplY3QSQAoHY29udGV4dBgFIAEoCzIYLnB1bHVtaXJwYy5jb2RlZ2VuLlJhbmdlQ + gziPwkSB2NvbnRleHRSB2NvbnRleHQqfwoSRGlhZ25vc3RpY1NldmVyaXR5EiMKDERJQUdfSU5WQUxJRBAAGhHiPw4SDERJQUdfS + U5WQUxJRBIfCgpESUFHX0VSUk9SEAEaD+I/DBIKRElBR19FUlJPUhIjCgxESUFHX1dBUk5JTkcQAhoR4j8OEgxESUFHX1dBUk5JT + kdCMlowZ2l0aHViLmNvbS9wdWx1bWkvcHVsdW1pL3Nkay92My9wcm90by9nby9jb2RlZ2VuYgZwcm90bzM=""" + ).mkString) + lazy val scalaDescriptor: _root_.scalapb.descriptors.FileDescriptor = { + val scalaProto = com.google.protobuf.descriptor.FileDescriptorProto.parseFrom(ProtoBytes) + _root_.scalapb.descriptors.FileDescriptor.buildFrom(scalaProto, dependencies.map(_.scalaDescriptor)) + } + lazy val javaDescriptor: com.google.protobuf.Descriptors.FileDescriptor = { + val javaProto = com.google.protobuf.DescriptorProtos.FileDescriptorProto.parseFrom(ProtoBytes) + com.google.protobuf.Descriptors.FileDescriptor.buildFrom(javaProto, _root_.scala.Array( + )) + } + @deprecated("Use javaDescriptor instead. In a future version this will refer to scalaDescriptor.", "ScalaPB 0.5.47") + def descriptor: com.google.protobuf.Descriptors.FileDescriptor = javaDescriptor +} \ No newline at end of file diff --git a/core/src/main/scala/besom/rpc/pulumirpc/codegen/hcl/Pos.scala b/core/src/main/scala/besom/rpc/pulumirpc/codegen/hcl/Pos.scala new file mode 100644 index 00000000..2a6fcc0e --- /dev/null +++ b/core/src/main/scala/besom/rpc/pulumirpc/codegen/hcl/Pos.scala @@ -0,0 +1,196 @@ +// Generated by the Scala Plugin for the Protocol Buffer Compiler. +// Do not edit! +// +// Protofile syntax: PROTO3 + +package pulumirpc.codegen.hcl + +/** Pos represents a single position in a source file, by addressing the start byte of a unicode character + * encoded in UTF-8. + * + * @param line + * Line is the source code line where this position points. Lines are counted starting at 1 and + * incremented for each newline character encountered. + * @param column + * Column is the source code column where this position points, in unicode characters, with counting + * starting at 1. + * + * Column counts characters as they appear visually, so for example a latin letter with a combining + * diacritic mark counts as one character. This is intended for rendering visual markers against source + * code in contexts where these diacritics would be rendered in a single character cell. Technically + * speaking, Column is counting grapheme clusters as used in unicode normalization. + * @param byte + * Byte is the byte offset into the file where the indicated character begins. This is a zero-based offset + * to the first byte of the first UTF-8 codepoint sequence in the character, and thus gives a position + * that can be resolved _without_ awareness of Unicode characters. + */ +@SerialVersionUID(0L) +final case class Pos( + line: _root_.scala.Long = 0L, + column: _root_.scala.Long = 0L, + byte: _root_.scala.Long = 0L, + unknownFields: _root_.scalapb.UnknownFieldSet = _root_.scalapb.UnknownFieldSet.empty + ) extends scalapb.GeneratedMessage with scalapb.lenses.Updatable[Pos] { + @transient + private[this] var __serializedSizeMemoized: _root_.scala.Int = 0 + private[this] def __computeSerializedSize(): _root_.scala.Int = { + var __size = 0 + + { + val __value = line + if (__value != 0L) { + __size += _root_.com.google.protobuf.CodedOutputStream.computeInt64Size(1, __value) + } + }; + + { + val __value = column + if (__value != 0L) { + __size += _root_.com.google.protobuf.CodedOutputStream.computeInt64Size(2, __value) + } + }; + + { + val __value = byte + if (__value != 0L) { + __size += _root_.com.google.protobuf.CodedOutputStream.computeInt64Size(3, __value) + } + }; + __size += unknownFields.serializedSize + __size + } + override def serializedSize: _root_.scala.Int = { + var __size = __serializedSizeMemoized + if (__size == 0) { + __size = __computeSerializedSize() + 1 + __serializedSizeMemoized = __size + } + __size - 1 + + } + def writeTo(`_output__`: _root_.com.google.protobuf.CodedOutputStream): _root_.scala.Unit = { + { + val __v = line + if (__v != 0L) { + _output__.writeInt64(1, __v) + } + }; + { + val __v = column + if (__v != 0L) { + _output__.writeInt64(2, __v) + } + }; + { + val __v = byte + if (__v != 0L) { + _output__.writeInt64(3, __v) + } + }; + unknownFields.writeTo(_output__) + } + def withLine(__v: _root_.scala.Long): Pos = copy(line = __v) + def withColumn(__v: _root_.scala.Long): Pos = copy(column = __v) + def withByte(__v: _root_.scala.Long): Pos = copy(byte = __v) + def withUnknownFields(__v: _root_.scalapb.UnknownFieldSet) = copy(unknownFields = __v) + def discardUnknownFields = copy(unknownFields = _root_.scalapb.UnknownFieldSet.empty) + def getFieldByNumber(__fieldNumber: _root_.scala.Int): _root_.scala.Any = { + (__fieldNumber: @_root_.scala.unchecked) match { + case 1 => { + val __t = line + if (__t != 0L) __t else null + } + case 2 => { + val __t = column + if (__t != 0L) __t else null + } + case 3 => { + val __t = byte + if (__t != 0L) __t else null + } + } + } + def getField(__field: _root_.scalapb.descriptors.FieldDescriptor): _root_.scalapb.descriptors.PValue = { + _root_.scala.Predef.require(__field.containingMessage eq companion.scalaDescriptor) + (__field.number: @_root_.scala.unchecked) match { + case 1 => _root_.scalapb.descriptors.PLong(line) + case 2 => _root_.scalapb.descriptors.PLong(column) + case 3 => _root_.scalapb.descriptors.PLong(byte) + } + } + def toProtoString: _root_.scala.Predef.String = _root_.scalapb.TextFormat.printToUnicodeString(this) + def companion: pulumirpc.codegen.hcl.Pos.type = pulumirpc.codegen.hcl.Pos + // @@protoc_insertion_point(GeneratedMessage[pulumirpc.codegen.Pos]) +} + +object Pos extends scalapb.GeneratedMessageCompanion[pulumirpc.codegen.hcl.Pos] { + implicit def messageCompanion: scalapb.GeneratedMessageCompanion[pulumirpc.codegen.hcl.Pos] = this + def parseFrom(`_input__`: _root_.com.google.protobuf.CodedInputStream): pulumirpc.codegen.hcl.Pos = { + var __line: _root_.scala.Long = 0L + var __column: _root_.scala.Long = 0L + var __byte: _root_.scala.Long = 0L + var `_unknownFields__`: _root_.scalapb.UnknownFieldSet.Builder = null + var _done__ = false + while (!_done__) { + val _tag__ = _input__.readTag() + _tag__ match { + case 0 => _done__ = true + case 8 => + __line = _input__.readInt64() + case 16 => + __column = _input__.readInt64() + case 24 => + __byte = _input__.readInt64() + case tag => + if (_unknownFields__ == null) { + _unknownFields__ = new _root_.scalapb.UnknownFieldSet.Builder() + } + _unknownFields__.parseField(tag, _input__) + } + } + pulumirpc.codegen.hcl.Pos( + line = __line, + column = __column, + byte = __byte, + unknownFields = if (_unknownFields__ == null) _root_.scalapb.UnknownFieldSet.empty else _unknownFields__.result() + ) + } + implicit def messageReads: _root_.scalapb.descriptors.Reads[pulumirpc.codegen.hcl.Pos] = _root_.scalapb.descriptors.Reads{ + case _root_.scalapb.descriptors.PMessage(__fieldsMap) => + _root_.scala.Predef.require(__fieldsMap.keys.forall(_.containingMessage eq scalaDescriptor), "FieldDescriptor does not match message type.") + pulumirpc.codegen.hcl.Pos( + line = __fieldsMap.get(scalaDescriptor.findFieldByNumber(1).get).map(_.as[_root_.scala.Long]).getOrElse(0L), + column = __fieldsMap.get(scalaDescriptor.findFieldByNumber(2).get).map(_.as[_root_.scala.Long]).getOrElse(0L), + byte = __fieldsMap.get(scalaDescriptor.findFieldByNumber(3).get).map(_.as[_root_.scala.Long]).getOrElse(0L) + ) + case _ => throw new RuntimeException("Expected PMessage") + } + def javaDescriptor: _root_.com.google.protobuf.Descriptors.Descriptor = HclProto.javaDescriptor.getMessageTypes().get(0) + def scalaDescriptor: _root_.scalapb.descriptors.Descriptor = HclProto.scalaDescriptor.messages(0) + def messageCompanionForFieldNumber(__number: _root_.scala.Int): _root_.scalapb.GeneratedMessageCompanion[_] = throw new MatchError(__number) + lazy val nestedMessagesCompanions: Seq[_root_.scalapb.GeneratedMessageCompanion[_ <: _root_.scalapb.GeneratedMessage]] = Seq.empty + def enumCompanionForFieldNumber(__fieldNumber: _root_.scala.Int): _root_.scalapb.GeneratedEnumCompanion[_] = throw new MatchError(__fieldNumber) + lazy val defaultInstance = pulumirpc.codegen.hcl.Pos( + line = 0L, + column = 0L, + byte = 0L + ) + implicit class PosLens[UpperPB](_l: _root_.scalapb.lenses.Lens[UpperPB, pulumirpc.codegen.hcl.Pos]) extends _root_.scalapb.lenses.ObjectLens[UpperPB, pulumirpc.codegen.hcl.Pos](_l) { + def line: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Long] = field(_.line)((c_, f_) => c_.copy(line = f_)) + def column: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Long] = field(_.column)((c_, f_) => c_.copy(column = f_)) + def byte: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Long] = field(_.byte)((c_, f_) => c_.copy(byte = f_)) + } + final val LINE_FIELD_NUMBER = 1 + final val COLUMN_FIELD_NUMBER = 2 + final val BYTE_FIELD_NUMBER = 3 + def of( + line: _root_.scala.Long, + column: _root_.scala.Long, + byte: _root_.scala.Long + ): _root_.pulumirpc.codegen.hcl.Pos = _root_.pulumirpc.codegen.hcl.Pos( + line, + column, + byte + ) + // @@protoc_insertion_point(GeneratedMessageCompanion[pulumirpc.codegen.Pos]) +} diff --git a/core/src/main/scala/besom/rpc/pulumirpc/codegen/hcl/Range.scala b/core/src/main/scala/besom/rpc/pulumirpc/codegen/hcl/Range.scala new file mode 100644 index 00000000..0e8be286 --- /dev/null +++ b/core/src/main/scala/besom/rpc/pulumirpc/codegen/hcl/Range.scala @@ -0,0 +1,185 @@ +// Generated by the Scala Plugin for the Protocol Buffer Compiler. +// Do not edit! +// +// Protofile syntax: PROTO3 + +package pulumirpc.codegen.hcl + +/** Range represents a span of characters between two positions in a source file. + * + * @param filename + * Filename is the name of the file into which this range's positions point. + * @param start + * Start and End represent the bounds of this range. Start is inclusive and End is exclusive. + */ +@SerialVersionUID(0L) +final case class Range( + filename: _root_.scala.Predef.String = "", + start: _root_.scala.Option[pulumirpc.codegen.hcl.Pos] = _root_.scala.None, + end: _root_.scala.Option[pulumirpc.codegen.hcl.Pos] = _root_.scala.None, + unknownFields: _root_.scalapb.UnknownFieldSet = _root_.scalapb.UnknownFieldSet.empty + ) extends scalapb.GeneratedMessage with scalapb.lenses.Updatable[Range] { + @transient + private[this] var __serializedSizeMemoized: _root_.scala.Int = 0 + private[this] def __computeSerializedSize(): _root_.scala.Int = { + var __size = 0 + + { + val __value = filename + if (!__value.isEmpty) { + __size += _root_.com.google.protobuf.CodedOutputStream.computeStringSize(1, __value) + } + }; + if (start.isDefined) { + val __value = start.get + __size += 1 + _root_.com.google.protobuf.CodedOutputStream.computeUInt32SizeNoTag(__value.serializedSize) + __value.serializedSize + }; + if (end.isDefined) { + val __value = end.get + __size += 1 + _root_.com.google.protobuf.CodedOutputStream.computeUInt32SizeNoTag(__value.serializedSize) + __value.serializedSize + }; + __size += unknownFields.serializedSize + __size + } + override def serializedSize: _root_.scala.Int = { + var __size = __serializedSizeMemoized + if (__size == 0) { + __size = __computeSerializedSize() + 1 + __serializedSizeMemoized = __size + } + __size - 1 + + } + def writeTo(`_output__`: _root_.com.google.protobuf.CodedOutputStream): _root_.scala.Unit = { + { + val __v = filename + if (!__v.isEmpty) { + _output__.writeString(1, __v) + } + }; + start.foreach { __v => + val __m = __v + _output__.writeTag(2, 2) + _output__.writeUInt32NoTag(__m.serializedSize) + __m.writeTo(_output__) + }; + end.foreach { __v => + val __m = __v + _output__.writeTag(3, 2) + _output__.writeUInt32NoTag(__m.serializedSize) + __m.writeTo(_output__) + }; + unknownFields.writeTo(_output__) + } + def withFilename(__v: _root_.scala.Predef.String): Range = copy(filename = __v) + def getStart: pulumirpc.codegen.hcl.Pos = start.getOrElse(pulumirpc.codegen.hcl.Pos.defaultInstance) + def clearStart: Range = copy(start = _root_.scala.None) + def withStart(__v: pulumirpc.codegen.hcl.Pos): Range = copy(start = Option(__v)) + def getEnd: pulumirpc.codegen.hcl.Pos = end.getOrElse(pulumirpc.codegen.hcl.Pos.defaultInstance) + def clearEnd: Range = copy(end = _root_.scala.None) + def withEnd(__v: pulumirpc.codegen.hcl.Pos): Range = copy(end = Option(__v)) + def withUnknownFields(__v: _root_.scalapb.UnknownFieldSet) = copy(unknownFields = __v) + def discardUnknownFields = copy(unknownFields = _root_.scalapb.UnknownFieldSet.empty) + def getFieldByNumber(__fieldNumber: _root_.scala.Int): _root_.scala.Any = { + (__fieldNumber: @_root_.scala.unchecked) match { + case 1 => { + val __t = filename + if (__t != "") __t else null + } + case 2 => start.orNull + case 3 => end.orNull + } + } + def getField(__field: _root_.scalapb.descriptors.FieldDescriptor): _root_.scalapb.descriptors.PValue = { + _root_.scala.Predef.require(__field.containingMessage eq companion.scalaDescriptor) + (__field.number: @_root_.scala.unchecked) match { + case 1 => _root_.scalapb.descriptors.PString(filename) + case 2 => start.map(_.toPMessage).getOrElse(_root_.scalapb.descriptors.PEmpty) + case 3 => end.map(_.toPMessage).getOrElse(_root_.scalapb.descriptors.PEmpty) + } + } + def toProtoString: _root_.scala.Predef.String = _root_.scalapb.TextFormat.printToUnicodeString(this) + def companion: pulumirpc.codegen.hcl.Range.type = pulumirpc.codegen.hcl.Range + // @@protoc_insertion_point(GeneratedMessage[pulumirpc.codegen.Range]) +} + +object Range extends scalapb.GeneratedMessageCompanion[pulumirpc.codegen.hcl.Range] { + implicit def messageCompanion: scalapb.GeneratedMessageCompanion[pulumirpc.codegen.hcl.Range] = this + def parseFrom(`_input__`: _root_.com.google.protobuf.CodedInputStream): pulumirpc.codegen.hcl.Range = { + var __filename: _root_.scala.Predef.String = "" + var __start: _root_.scala.Option[pulumirpc.codegen.hcl.Pos] = _root_.scala.None + var __end: _root_.scala.Option[pulumirpc.codegen.hcl.Pos] = _root_.scala.None + var `_unknownFields__`: _root_.scalapb.UnknownFieldSet.Builder = null + var _done__ = false + while (!_done__) { + val _tag__ = _input__.readTag() + _tag__ match { + case 0 => _done__ = true + case 10 => + __filename = _input__.readStringRequireUtf8() + case 18 => + __start = _root_.scala.Option(__start.fold(_root_.scalapb.LiteParser.readMessage[pulumirpc.codegen.hcl.Pos](_input__))(_root_.scalapb.LiteParser.readMessage(_input__, _))) + case 26 => + __end = _root_.scala.Option(__end.fold(_root_.scalapb.LiteParser.readMessage[pulumirpc.codegen.hcl.Pos](_input__))(_root_.scalapb.LiteParser.readMessage(_input__, _))) + case tag => + if (_unknownFields__ == null) { + _unknownFields__ = new _root_.scalapb.UnknownFieldSet.Builder() + } + _unknownFields__.parseField(tag, _input__) + } + } + pulumirpc.codegen.hcl.Range( + filename = __filename, + start = __start, + end = __end, + unknownFields = if (_unknownFields__ == null) _root_.scalapb.UnknownFieldSet.empty else _unknownFields__.result() + ) + } + implicit def messageReads: _root_.scalapb.descriptors.Reads[pulumirpc.codegen.hcl.Range] = _root_.scalapb.descriptors.Reads{ + case _root_.scalapb.descriptors.PMessage(__fieldsMap) => + _root_.scala.Predef.require(__fieldsMap.keys.forall(_.containingMessage eq scalaDescriptor), "FieldDescriptor does not match message type.") + pulumirpc.codegen.hcl.Range( + filename = __fieldsMap.get(scalaDescriptor.findFieldByNumber(1).get).map(_.as[_root_.scala.Predef.String]).getOrElse(""), + start = __fieldsMap.get(scalaDescriptor.findFieldByNumber(2).get).flatMap(_.as[_root_.scala.Option[pulumirpc.codegen.hcl.Pos]]), + end = __fieldsMap.get(scalaDescriptor.findFieldByNumber(3).get).flatMap(_.as[_root_.scala.Option[pulumirpc.codegen.hcl.Pos]]) + ) + case _ => throw new RuntimeException("Expected PMessage") + } + def javaDescriptor: _root_.com.google.protobuf.Descriptors.Descriptor = HclProto.javaDescriptor.getMessageTypes().get(1) + def scalaDescriptor: _root_.scalapb.descriptors.Descriptor = HclProto.scalaDescriptor.messages(1) + def messageCompanionForFieldNumber(__number: _root_.scala.Int): _root_.scalapb.GeneratedMessageCompanion[_] = { + var __out: _root_.scalapb.GeneratedMessageCompanion[_] = null + (__number: @_root_.scala.unchecked) match { + case 2 => __out = pulumirpc.codegen.hcl.Pos + case 3 => __out = pulumirpc.codegen.hcl.Pos + } + __out + } + lazy val nestedMessagesCompanions: Seq[_root_.scalapb.GeneratedMessageCompanion[_ <: _root_.scalapb.GeneratedMessage]] = Seq.empty + def enumCompanionForFieldNumber(__fieldNumber: _root_.scala.Int): _root_.scalapb.GeneratedEnumCompanion[_] = throw new MatchError(__fieldNumber) + lazy val defaultInstance = pulumirpc.codegen.hcl.Range( + filename = "", + start = _root_.scala.None, + end = _root_.scala.None + ) + implicit class RangeLens[UpperPB](_l: _root_.scalapb.lenses.Lens[UpperPB, pulumirpc.codegen.hcl.Range]) extends _root_.scalapb.lenses.ObjectLens[UpperPB, pulumirpc.codegen.hcl.Range](_l) { + def filename: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Predef.String] = field(_.filename)((c_, f_) => c_.copy(filename = f_)) + def start: _root_.scalapb.lenses.Lens[UpperPB, pulumirpc.codegen.hcl.Pos] = field(_.getStart)((c_, f_) => c_.copy(start = _root_.scala.Option(f_))) + def optionalStart: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Option[pulumirpc.codegen.hcl.Pos]] = field(_.start)((c_, f_) => c_.copy(start = f_)) + def end: _root_.scalapb.lenses.Lens[UpperPB, pulumirpc.codegen.hcl.Pos] = field(_.getEnd)((c_, f_) => c_.copy(end = _root_.scala.Option(f_))) + def optionalEnd: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Option[pulumirpc.codegen.hcl.Pos]] = field(_.end)((c_, f_) => c_.copy(end = f_)) + } + final val FILENAME_FIELD_NUMBER = 1 + final val START_FIELD_NUMBER = 2 + final val END_FIELD_NUMBER = 3 + def of( + filename: _root_.scala.Predef.String, + start: _root_.scala.Option[pulumirpc.codegen.hcl.Pos], + end: _root_.scala.Option[pulumirpc.codegen.hcl.Pos] + ): _root_.pulumirpc.codegen.hcl.Range = _root_.pulumirpc.codegen.hcl.Range( + filename, + start, + end + ) + // @@protoc_insertion_point(GeneratedMessageCompanion[pulumirpc.codegen.Range]) +} diff --git a/core/src/main/scala/besom/rpc/pulumirpc/language/AboutResponse.scala b/core/src/main/scala/besom/rpc/pulumirpc/language/AboutResponse.scala new file mode 100644 index 00000000..7f521561 --- /dev/null +++ b/core/src/main/scala/besom/rpc/pulumirpc/language/AboutResponse.scala @@ -0,0 +1,338 @@ +// Generated by the Scala Plugin for the Protocol Buffer Compiler. +// Do not edit! +// +// Protofile syntax: PROTO3 + +package pulumirpc.language + +/** AboutResponse returns runtime information about the language. + * + * @param executable + * the primary executable for the runtime of this language. + * @param version + * the version of the runtime for this language. + * @param metadata + * other information about this language. + */ +@SerialVersionUID(0L) +final case class AboutResponse( + executable: _root_.scala.Predef.String = "", + version: _root_.scala.Predef.String = "", + metadata: _root_.scala.collection.immutable.Map[_root_.scala.Predef.String, _root_.scala.Predef.String] = _root_.scala.collection.immutable.Map.empty, + unknownFields: _root_.scalapb.UnknownFieldSet = _root_.scalapb.UnknownFieldSet.empty + ) extends scalapb.GeneratedMessage with scalapb.lenses.Updatable[AboutResponse] { + @transient + private[this] var __serializedSizeMemoized: _root_.scala.Int = 0 + private[this] def __computeSerializedSize(): _root_.scala.Int = { + var __size = 0 + + { + val __value = executable + if (!__value.isEmpty) { + __size += _root_.com.google.protobuf.CodedOutputStream.computeStringSize(1, __value) + } + }; + + { + val __value = version + if (!__value.isEmpty) { + __size += _root_.com.google.protobuf.CodedOutputStream.computeStringSize(2, __value) + } + }; + metadata.foreach { __item => + val __value = pulumirpc.language.AboutResponse._typemapper_metadata.toBase(__item) + __size += 1 + _root_.com.google.protobuf.CodedOutputStream.computeUInt32SizeNoTag(__value.serializedSize) + __value.serializedSize + } + __size += unknownFields.serializedSize + __size + } + override def serializedSize: _root_.scala.Int = { + var __size = __serializedSizeMemoized + if (__size == 0) { + __size = __computeSerializedSize() + 1 + __serializedSizeMemoized = __size + } + __size - 1 + + } + def writeTo(`_output__`: _root_.com.google.protobuf.CodedOutputStream): _root_.scala.Unit = { + { + val __v = executable + if (!__v.isEmpty) { + _output__.writeString(1, __v) + } + }; + { + val __v = version + if (!__v.isEmpty) { + _output__.writeString(2, __v) + } + }; + metadata.foreach { __v => + val __m = pulumirpc.language.AboutResponse._typemapper_metadata.toBase(__v) + _output__.writeTag(3, 2) + _output__.writeUInt32NoTag(__m.serializedSize) + __m.writeTo(_output__) + }; + unknownFields.writeTo(_output__) + } + def withExecutable(__v: _root_.scala.Predef.String): AboutResponse = copy(executable = __v) + def withVersion(__v: _root_.scala.Predef.String): AboutResponse = copy(version = __v) + def clearMetadata = copy(metadata = _root_.scala.collection.immutable.Map.empty) + def addMetadata(__vs: (_root_.scala.Predef.String, _root_.scala.Predef.String) *): AboutResponse = addAllMetadata(__vs) + def addAllMetadata(__vs: Iterable[(_root_.scala.Predef.String, _root_.scala.Predef.String)]): AboutResponse = copy(metadata = metadata ++ __vs) + def withMetadata(__v: _root_.scala.collection.immutable.Map[_root_.scala.Predef.String, _root_.scala.Predef.String]): AboutResponse = copy(metadata = __v) + def withUnknownFields(__v: _root_.scalapb.UnknownFieldSet) = copy(unknownFields = __v) + def discardUnknownFields = copy(unknownFields = _root_.scalapb.UnknownFieldSet.empty) + def getFieldByNumber(__fieldNumber: _root_.scala.Int): _root_.scala.Any = { + (__fieldNumber: @_root_.scala.unchecked) match { + case 1 => { + val __t = executable + if (__t != "") __t else null + } + case 2 => { + val __t = version + if (__t != "") __t else null + } + case 3 => metadata.iterator.map(pulumirpc.language.AboutResponse._typemapper_metadata.toBase(_)).toSeq + } + } + def getField(__field: _root_.scalapb.descriptors.FieldDescriptor): _root_.scalapb.descriptors.PValue = { + _root_.scala.Predef.require(__field.containingMessage eq companion.scalaDescriptor) + (__field.number: @_root_.scala.unchecked) match { + case 1 => _root_.scalapb.descriptors.PString(executable) + case 2 => _root_.scalapb.descriptors.PString(version) + case 3 => _root_.scalapb.descriptors.PRepeated(metadata.iterator.map(pulumirpc.language.AboutResponse._typemapper_metadata.toBase(_).toPMessage).toVector) + } + } + def toProtoString: _root_.scala.Predef.String = _root_.scalapb.TextFormat.printToUnicodeString(this) + def companion: pulumirpc.language.AboutResponse.type = pulumirpc.language.AboutResponse + // @@protoc_insertion_point(GeneratedMessage[pulumirpc.AboutResponse]) +} + +object AboutResponse extends scalapb.GeneratedMessageCompanion[pulumirpc.language.AboutResponse] { + implicit def messageCompanion: scalapb.GeneratedMessageCompanion[pulumirpc.language.AboutResponse] = this + def parseFrom(`_input__`: _root_.com.google.protobuf.CodedInputStream): pulumirpc.language.AboutResponse = { + var __executable: _root_.scala.Predef.String = "" + var __version: _root_.scala.Predef.String = "" + val __metadata: _root_.scala.collection.mutable.Builder[(_root_.scala.Predef.String, _root_.scala.Predef.String), _root_.scala.collection.immutable.Map[_root_.scala.Predef.String, _root_.scala.Predef.String]] = _root_.scala.collection.immutable.Map.newBuilder[_root_.scala.Predef.String, _root_.scala.Predef.String] + var `_unknownFields__`: _root_.scalapb.UnknownFieldSet.Builder = null + var _done__ = false + while (!_done__) { + val _tag__ = _input__.readTag() + _tag__ match { + case 0 => _done__ = true + case 10 => + __executable = _input__.readStringRequireUtf8() + case 18 => + __version = _input__.readStringRequireUtf8() + case 26 => + __metadata += pulumirpc.language.AboutResponse._typemapper_metadata.toCustom(_root_.scalapb.LiteParser.readMessage[pulumirpc.language.AboutResponse.MetadataEntry](_input__)) + case tag => + if (_unknownFields__ == null) { + _unknownFields__ = new _root_.scalapb.UnknownFieldSet.Builder() + } + _unknownFields__.parseField(tag, _input__) + } + } + pulumirpc.language.AboutResponse( + executable = __executable, + version = __version, + metadata = __metadata.result(), + unknownFields = if (_unknownFields__ == null) _root_.scalapb.UnknownFieldSet.empty else _unknownFields__.result() + ) + } + implicit def messageReads: _root_.scalapb.descriptors.Reads[pulumirpc.language.AboutResponse] = _root_.scalapb.descriptors.Reads{ + case _root_.scalapb.descriptors.PMessage(__fieldsMap) => + _root_.scala.Predef.require(__fieldsMap.keys.forall(_.containingMessage eq scalaDescriptor), "FieldDescriptor does not match message type.") + pulumirpc.language.AboutResponse( + executable = __fieldsMap.get(scalaDescriptor.findFieldByNumber(1).get).map(_.as[_root_.scala.Predef.String]).getOrElse(""), + version = __fieldsMap.get(scalaDescriptor.findFieldByNumber(2).get).map(_.as[_root_.scala.Predef.String]).getOrElse(""), + metadata = __fieldsMap.get(scalaDescriptor.findFieldByNumber(3).get).map(_.as[_root_.scala.Seq[pulumirpc.language.AboutResponse.MetadataEntry]]).getOrElse(_root_.scala.Seq.empty).iterator.map(pulumirpc.language.AboutResponse._typemapper_metadata.toCustom(_)).toMap + ) + case _ => throw new RuntimeException("Expected PMessage") + } + def javaDescriptor: _root_.com.google.protobuf.Descriptors.Descriptor = LanguageProto.javaDescriptor.getMessageTypes().get(1) + def scalaDescriptor: _root_.scalapb.descriptors.Descriptor = LanguageProto.scalaDescriptor.messages(1) + def messageCompanionForFieldNumber(__number: _root_.scala.Int): _root_.scalapb.GeneratedMessageCompanion[_] = { + var __out: _root_.scalapb.GeneratedMessageCompanion[_] = null + (__number: @_root_.scala.unchecked) match { + case 3 => __out = pulumirpc.language.AboutResponse.MetadataEntry + } + __out + } + lazy val nestedMessagesCompanions: Seq[_root_.scalapb.GeneratedMessageCompanion[_ <: _root_.scalapb.GeneratedMessage]] = + Seq[_root_.scalapb.GeneratedMessageCompanion[_ <: _root_.scalapb.GeneratedMessage]]( + _root_.pulumirpc.language.AboutResponse.MetadataEntry + ) + def enumCompanionForFieldNumber(__fieldNumber: _root_.scala.Int): _root_.scalapb.GeneratedEnumCompanion[_] = throw new MatchError(__fieldNumber) + lazy val defaultInstance = pulumirpc.language.AboutResponse( + executable = "", + version = "", + metadata = _root_.scala.collection.immutable.Map.empty + ) + @SerialVersionUID(0L) + final case class MetadataEntry( + key: _root_.scala.Predef.String = "", + value: _root_.scala.Predef.String = "", + unknownFields: _root_.scalapb.UnknownFieldSet = _root_.scalapb.UnknownFieldSet.empty + ) extends scalapb.GeneratedMessage with scalapb.lenses.Updatable[MetadataEntry] { + @transient + private[this] var __serializedSizeMemoized: _root_.scala.Int = 0 + private[this] def __computeSerializedSize(): _root_.scala.Int = { + var __size = 0 + + { + val __value = key + if (!__value.isEmpty) { + __size += _root_.com.google.protobuf.CodedOutputStream.computeStringSize(1, __value) + } + }; + + { + val __value = value + if (!__value.isEmpty) { + __size += _root_.com.google.protobuf.CodedOutputStream.computeStringSize(2, __value) + } + }; + __size += unknownFields.serializedSize + __size + } + override def serializedSize: _root_.scala.Int = { + var __size = __serializedSizeMemoized + if (__size == 0) { + __size = __computeSerializedSize() + 1 + __serializedSizeMemoized = __size + } + __size - 1 + + } + def writeTo(`_output__`: _root_.com.google.protobuf.CodedOutputStream): _root_.scala.Unit = { + { + val __v = key + if (!__v.isEmpty) { + _output__.writeString(1, __v) + } + }; + { + val __v = value + if (!__v.isEmpty) { + _output__.writeString(2, __v) + } + }; + unknownFields.writeTo(_output__) + } + def withKey(__v: _root_.scala.Predef.String): MetadataEntry = copy(key = __v) + def withValue(__v: _root_.scala.Predef.String): MetadataEntry = copy(value = __v) + def withUnknownFields(__v: _root_.scalapb.UnknownFieldSet) = copy(unknownFields = __v) + def discardUnknownFields = copy(unknownFields = _root_.scalapb.UnknownFieldSet.empty) + def getFieldByNumber(__fieldNumber: _root_.scala.Int): _root_.scala.Any = { + (__fieldNumber: @_root_.scala.unchecked) match { + case 1 => { + val __t = key + if (__t != "") __t else null + } + case 2 => { + val __t = value + if (__t != "") __t else null + } + } + } + def getField(__field: _root_.scalapb.descriptors.FieldDescriptor): _root_.scalapb.descriptors.PValue = { + _root_.scala.Predef.require(__field.containingMessage eq companion.scalaDescriptor) + (__field.number: @_root_.scala.unchecked) match { + case 1 => _root_.scalapb.descriptors.PString(key) + case 2 => _root_.scalapb.descriptors.PString(value) + } + } + def toProtoString: _root_.scala.Predef.String = _root_.scalapb.TextFormat.printToUnicodeString(this) + def companion: pulumirpc.language.AboutResponse.MetadataEntry.type = pulumirpc.language.AboutResponse.MetadataEntry + // @@protoc_insertion_point(GeneratedMessage[pulumirpc.AboutResponse.MetadataEntry]) + } + + object MetadataEntry extends scalapb.GeneratedMessageCompanion[pulumirpc.language.AboutResponse.MetadataEntry] { + implicit def messageCompanion: scalapb.GeneratedMessageCompanion[pulumirpc.language.AboutResponse.MetadataEntry] = this + def parseFrom(`_input__`: _root_.com.google.protobuf.CodedInputStream): pulumirpc.language.AboutResponse.MetadataEntry = { + var __key: _root_.scala.Predef.String = "" + var __value: _root_.scala.Predef.String = "" + var `_unknownFields__`: _root_.scalapb.UnknownFieldSet.Builder = null + var _done__ = false + while (!_done__) { + val _tag__ = _input__.readTag() + _tag__ match { + case 0 => _done__ = true + case 10 => + __key = _input__.readStringRequireUtf8() + case 18 => + __value = _input__.readStringRequireUtf8() + case tag => + if (_unknownFields__ == null) { + _unknownFields__ = new _root_.scalapb.UnknownFieldSet.Builder() + } + _unknownFields__.parseField(tag, _input__) + } + } + pulumirpc.language.AboutResponse.MetadataEntry( + key = __key, + value = __value, + unknownFields = if (_unknownFields__ == null) _root_.scalapb.UnknownFieldSet.empty else _unknownFields__.result() + ) + } + implicit def messageReads: _root_.scalapb.descriptors.Reads[pulumirpc.language.AboutResponse.MetadataEntry] = _root_.scalapb.descriptors.Reads{ + case _root_.scalapb.descriptors.PMessage(__fieldsMap) => + _root_.scala.Predef.require(__fieldsMap.keys.forall(_.containingMessage eq scalaDescriptor), "FieldDescriptor does not match message type.") + pulumirpc.language.AboutResponse.MetadataEntry( + key = __fieldsMap.get(scalaDescriptor.findFieldByNumber(1).get).map(_.as[_root_.scala.Predef.String]).getOrElse(""), + value = __fieldsMap.get(scalaDescriptor.findFieldByNumber(2).get).map(_.as[_root_.scala.Predef.String]).getOrElse("") + ) + case _ => throw new RuntimeException("Expected PMessage") + } + def javaDescriptor: _root_.com.google.protobuf.Descriptors.Descriptor = pulumirpc.language.AboutResponse.javaDescriptor.getNestedTypes().get(0) + def scalaDescriptor: _root_.scalapb.descriptors.Descriptor = pulumirpc.language.AboutResponse.scalaDescriptor.nestedMessages(0) + def messageCompanionForFieldNumber(__number: _root_.scala.Int): _root_.scalapb.GeneratedMessageCompanion[_] = throw new MatchError(__number) + lazy val nestedMessagesCompanions: Seq[_root_.scalapb.GeneratedMessageCompanion[_ <: _root_.scalapb.GeneratedMessage]] = Seq.empty + def enumCompanionForFieldNumber(__fieldNumber: _root_.scala.Int): _root_.scalapb.GeneratedEnumCompanion[_] = throw new MatchError(__fieldNumber) + lazy val defaultInstance = pulumirpc.language.AboutResponse.MetadataEntry( + key = "", + value = "" + ) + implicit class MetadataEntryLens[UpperPB](_l: _root_.scalapb.lenses.Lens[UpperPB, pulumirpc.language.AboutResponse.MetadataEntry]) extends _root_.scalapb.lenses.ObjectLens[UpperPB, pulumirpc.language.AboutResponse.MetadataEntry](_l) { + def key: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Predef.String] = field(_.key)((c_, f_) => c_.copy(key = f_)) + def value: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Predef.String] = field(_.value)((c_, f_) => c_.copy(value = f_)) + } + final val KEY_FIELD_NUMBER = 1 + final val VALUE_FIELD_NUMBER = 2 + @transient + implicit val keyValueMapper: _root_.scalapb.TypeMapper[pulumirpc.language.AboutResponse.MetadataEntry, (_root_.scala.Predef.String, _root_.scala.Predef.String)] = + _root_.scalapb.TypeMapper[pulumirpc.language.AboutResponse.MetadataEntry, (_root_.scala.Predef.String, _root_.scala.Predef.String)](__m => (__m.key, __m.value))(__p => pulumirpc.language.AboutResponse.MetadataEntry(__p._1, __p._2)) + def of( + key: _root_.scala.Predef.String, + value: _root_.scala.Predef.String + ): _root_.pulumirpc.language.AboutResponse.MetadataEntry = _root_.pulumirpc.language.AboutResponse.MetadataEntry( + key, + value + ) + // @@protoc_insertion_point(GeneratedMessageCompanion[pulumirpc.AboutResponse.MetadataEntry]) + } + + implicit class AboutResponseLens[UpperPB](_l: _root_.scalapb.lenses.Lens[UpperPB, pulumirpc.language.AboutResponse]) extends _root_.scalapb.lenses.ObjectLens[UpperPB, pulumirpc.language.AboutResponse](_l) { + def executable: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Predef.String] = field(_.executable)((c_, f_) => c_.copy(executable = f_)) + def version: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Predef.String] = field(_.version)((c_, f_) => c_.copy(version = f_)) + def metadata: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.collection.immutable.Map[_root_.scala.Predef.String, _root_.scala.Predef.String]] = field(_.metadata)((c_, f_) => c_.copy(metadata = f_)) + } + final val EXECUTABLE_FIELD_NUMBER = 1 + final val VERSION_FIELD_NUMBER = 2 + final val METADATA_FIELD_NUMBER = 3 + @transient + private[language] val _typemapper_metadata: _root_.scalapb.TypeMapper[pulumirpc.language.AboutResponse.MetadataEntry, (_root_.scala.Predef.String, _root_.scala.Predef.String)] = implicitly[_root_.scalapb.TypeMapper[pulumirpc.language.AboutResponse.MetadataEntry, (_root_.scala.Predef.String, _root_.scala.Predef.String)]] + def of( + executable: _root_.scala.Predef.String, + version: _root_.scala.Predef.String, + metadata: _root_.scala.collection.immutable.Map[_root_.scala.Predef.String, _root_.scala.Predef.String] + ): _root_.pulumirpc.language.AboutResponse = _root_.pulumirpc.language.AboutResponse( + executable, + version, + metadata + ) + // @@protoc_insertion_point(GeneratedMessageCompanion[pulumirpc.AboutResponse]) +} diff --git a/core/src/main/scala/besom/rpc/pulumirpc/language/DependencyInfo.scala b/core/src/main/scala/besom/rpc/pulumirpc/language/DependencyInfo.scala new file mode 100644 index 00000000..76f554d0 --- /dev/null +++ b/core/src/main/scala/besom/rpc/pulumirpc/language/DependencyInfo.scala @@ -0,0 +1,152 @@ +// Generated by the Scala Plugin for the Protocol Buffer Compiler. +// Do not edit! +// +// Protofile syntax: PROTO3 + +package pulumirpc.language + +/** @param name + * The name of the dependency. + * @param version + * The version of the dependency. + */ +@SerialVersionUID(0L) +final case class DependencyInfo( + name: _root_.scala.Predef.String = "", + version: _root_.scala.Predef.String = "", + unknownFields: _root_.scalapb.UnknownFieldSet = _root_.scalapb.UnknownFieldSet.empty + ) extends scalapb.GeneratedMessage with scalapb.lenses.Updatable[DependencyInfo] { + @transient + private[this] var __serializedSizeMemoized: _root_.scala.Int = 0 + private[this] def __computeSerializedSize(): _root_.scala.Int = { + var __size = 0 + + { + val __value = name + if (!__value.isEmpty) { + __size += _root_.com.google.protobuf.CodedOutputStream.computeStringSize(1, __value) + } + }; + + { + val __value = version + if (!__value.isEmpty) { + __size += _root_.com.google.protobuf.CodedOutputStream.computeStringSize(2, __value) + } + }; + __size += unknownFields.serializedSize + __size + } + override def serializedSize: _root_.scala.Int = { + var __size = __serializedSizeMemoized + if (__size == 0) { + __size = __computeSerializedSize() + 1 + __serializedSizeMemoized = __size + } + __size - 1 + + } + def writeTo(`_output__`: _root_.com.google.protobuf.CodedOutputStream): _root_.scala.Unit = { + { + val __v = name + if (!__v.isEmpty) { + _output__.writeString(1, __v) + } + }; + { + val __v = version + if (!__v.isEmpty) { + _output__.writeString(2, __v) + } + }; + unknownFields.writeTo(_output__) + } + def withName(__v: _root_.scala.Predef.String): DependencyInfo = copy(name = __v) + def withVersion(__v: _root_.scala.Predef.String): DependencyInfo = copy(version = __v) + def withUnknownFields(__v: _root_.scalapb.UnknownFieldSet) = copy(unknownFields = __v) + def discardUnknownFields = copy(unknownFields = _root_.scalapb.UnknownFieldSet.empty) + def getFieldByNumber(__fieldNumber: _root_.scala.Int): _root_.scala.Any = { + (__fieldNumber: @_root_.scala.unchecked) match { + case 1 => { + val __t = name + if (__t != "") __t else null + } + case 2 => { + val __t = version + if (__t != "") __t else null + } + } + } + def getField(__field: _root_.scalapb.descriptors.FieldDescriptor): _root_.scalapb.descriptors.PValue = { + _root_.scala.Predef.require(__field.containingMessage eq companion.scalaDescriptor) + (__field.number: @_root_.scala.unchecked) match { + case 1 => _root_.scalapb.descriptors.PString(name) + case 2 => _root_.scalapb.descriptors.PString(version) + } + } + def toProtoString: _root_.scala.Predef.String = _root_.scalapb.TextFormat.printToUnicodeString(this) + def companion: pulumirpc.language.DependencyInfo.type = pulumirpc.language.DependencyInfo + // @@protoc_insertion_point(GeneratedMessage[pulumirpc.DependencyInfo]) +} + +object DependencyInfo extends scalapb.GeneratedMessageCompanion[pulumirpc.language.DependencyInfo] { + implicit def messageCompanion: scalapb.GeneratedMessageCompanion[pulumirpc.language.DependencyInfo] = this + def parseFrom(`_input__`: _root_.com.google.protobuf.CodedInputStream): pulumirpc.language.DependencyInfo = { + var __name: _root_.scala.Predef.String = "" + var __version: _root_.scala.Predef.String = "" + var `_unknownFields__`: _root_.scalapb.UnknownFieldSet.Builder = null + var _done__ = false + while (!_done__) { + val _tag__ = _input__.readTag() + _tag__ match { + case 0 => _done__ = true + case 10 => + __name = _input__.readStringRequireUtf8() + case 18 => + __version = _input__.readStringRequireUtf8() + case tag => + if (_unknownFields__ == null) { + _unknownFields__ = new _root_.scalapb.UnknownFieldSet.Builder() + } + _unknownFields__.parseField(tag, _input__) + } + } + pulumirpc.language.DependencyInfo( + name = __name, + version = __version, + unknownFields = if (_unknownFields__ == null) _root_.scalapb.UnknownFieldSet.empty else _unknownFields__.result() + ) + } + implicit def messageReads: _root_.scalapb.descriptors.Reads[pulumirpc.language.DependencyInfo] = _root_.scalapb.descriptors.Reads{ + case _root_.scalapb.descriptors.PMessage(__fieldsMap) => + _root_.scala.Predef.require(__fieldsMap.keys.forall(_.containingMessage eq scalaDescriptor), "FieldDescriptor does not match message type.") + pulumirpc.language.DependencyInfo( + name = __fieldsMap.get(scalaDescriptor.findFieldByNumber(1).get).map(_.as[_root_.scala.Predef.String]).getOrElse(""), + version = __fieldsMap.get(scalaDescriptor.findFieldByNumber(2).get).map(_.as[_root_.scala.Predef.String]).getOrElse("") + ) + case _ => throw new RuntimeException("Expected PMessage") + } + def javaDescriptor: _root_.com.google.protobuf.Descriptors.Descriptor = LanguageProto.javaDescriptor.getMessageTypes().get(3) + def scalaDescriptor: _root_.scalapb.descriptors.Descriptor = LanguageProto.scalaDescriptor.messages(3) + def messageCompanionForFieldNumber(__number: _root_.scala.Int): _root_.scalapb.GeneratedMessageCompanion[_] = throw new MatchError(__number) + lazy val nestedMessagesCompanions: Seq[_root_.scalapb.GeneratedMessageCompanion[_ <: _root_.scalapb.GeneratedMessage]] = Seq.empty + def enumCompanionForFieldNumber(__fieldNumber: _root_.scala.Int): _root_.scalapb.GeneratedEnumCompanion[_] = throw new MatchError(__fieldNumber) + lazy val defaultInstance = pulumirpc.language.DependencyInfo( + name = "", + version = "" + ) + implicit class DependencyInfoLens[UpperPB](_l: _root_.scalapb.lenses.Lens[UpperPB, pulumirpc.language.DependencyInfo]) extends _root_.scalapb.lenses.ObjectLens[UpperPB, pulumirpc.language.DependencyInfo](_l) { + def name: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Predef.String] = field(_.name)((c_, f_) => c_.copy(name = f_)) + def version: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Predef.String] = field(_.version)((c_, f_) => c_.copy(version = f_)) + } + final val NAME_FIELD_NUMBER = 1 + final val VERSION_FIELD_NUMBER = 2 + def of( + name: _root_.scala.Predef.String, + version: _root_.scala.Predef.String + ): _root_.pulumirpc.language.DependencyInfo = _root_.pulumirpc.language.DependencyInfo( + name, + version + ) + // @@protoc_insertion_point(GeneratedMessageCompanion[pulumirpc.DependencyInfo]) +} diff --git a/core/src/main/scala/besom/rpc/pulumirpc/language/GeneratePackageRequest.scala b/core/src/main/scala/besom/rpc/pulumirpc/language/GeneratePackageRequest.scala new file mode 100644 index 00000000..ec509821 --- /dev/null +++ b/core/src/main/scala/besom/rpc/pulumirpc/language/GeneratePackageRequest.scala @@ -0,0 +1,546 @@ +// Generated by the Scala Plugin for the Protocol Buffer Compiler. +// Do not edit! +// +// Protofile syntax: PROTO3 + +package pulumirpc.language + +/** @param directory + * the directory to generate the package in. + * @param schema + * the JSON-encoded schema. + * @param extraFiles + * extra files to copy to the package output. + * @param loaderTarget + * The target of a codegen.LoaderServer to use for loading schemas. + * @param localDependencies + * local dependencies to use instead of using the package system. This is a map of package name to a local + * path of a language specific artifact to use for the SDK for that package. + */ +@SerialVersionUID(0L) +final case class GeneratePackageRequest( + directory: _root_.scala.Predef.String = "", + schema: _root_.scala.Predef.String = "", + extraFiles: _root_.scala.collection.immutable.Map[_root_.scala.Predef.String, _root_.com.google.protobuf.ByteString] = _root_.scala.collection.immutable.Map.empty, + loaderTarget: _root_.scala.Predef.String = "", + localDependencies: _root_.scala.collection.immutable.Map[_root_.scala.Predef.String, _root_.scala.Predef.String] = _root_.scala.collection.immutable.Map.empty, + unknownFields: _root_.scalapb.UnknownFieldSet = _root_.scalapb.UnknownFieldSet.empty + ) extends scalapb.GeneratedMessage with scalapb.lenses.Updatable[GeneratePackageRequest] { + @transient + private[this] var __serializedSizeMemoized: _root_.scala.Int = 0 + private[this] def __computeSerializedSize(): _root_.scala.Int = { + var __size = 0 + + { + val __value = directory + if (!__value.isEmpty) { + __size += _root_.com.google.protobuf.CodedOutputStream.computeStringSize(1, __value) + } + }; + + { + val __value = schema + if (!__value.isEmpty) { + __size += _root_.com.google.protobuf.CodedOutputStream.computeStringSize(2, __value) + } + }; + extraFiles.foreach { __item => + val __value = pulumirpc.language.GeneratePackageRequest._typemapper_extraFiles.toBase(__item) + __size += 1 + _root_.com.google.protobuf.CodedOutputStream.computeUInt32SizeNoTag(__value.serializedSize) + __value.serializedSize + } + + { + val __value = loaderTarget + if (!__value.isEmpty) { + __size += _root_.com.google.protobuf.CodedOutputStream.computeStringSize(4, __value) + } + }; + localDependencies.foreach { __item => + val __value = pulumirpc.language.GeneratePackageRequest._typemapper_localDependencies.toBase(__item) + __size += 1 + _root_.com.google.protobuf.CodedOutputStream.computeUInt32SizeNoTag(__value.serializedSize) + __value.serializedSize + } + __size += unknownFields.serializedSize + __size + } + override def serializedSize: _root_.scala.Int = { + var __size = __serializedSizeMemoized + if (__size == 0) { + __size = __computeSerializedSize() + 1 + __serializedSizeMemoized = __size + } + __size - 1 + + } + def writeTo(`_output__`: _root_.com.google.protobuf.CodedOutputStream): _root_.scala.Unit = { + { + val __v = directory + if (!__v.isEmpty) { + _output__.writeString(1, __v) + } + }; + { + val __v = schema + if (!__v.isEmpty) { + _output__.writeString(2, __v) + } + }; + extraFiles.foreach { __v => + val __m = pulumirpc.language.GeneratePackageRequest._typemapper_extraFiles.toBase(__v) + _output__.writeTag(3, 2) + _output__.writeUInt32NoTag(__m.serializedSize) + __m.writeTo(_output__) + }; + { + val __v = loaderTarget + if (!__v.isEmpty) { + _output__.writeString(4, __v) + } + }; + localDependencies.foreach { __v => + val __m = pulumirpc.language.GeneratePackageRequest._typemapper_localDependencies.toBase(__v) + _output__.writeTag(5, 2) + _output__.writeUInt32NoTag(__m.serializedSize) + __m.writeTo(_output__) + }; + unknownFields.writeTo(_output__) + } + def withDirectory(__v: _root_.scala.Predef.String): GeneratePackageRequest = copy(directory = __v) + def withSchema(__v: _root_.scala.Predef.String): GeneratePackageRequest = copy(schema = __v) + def clearExtraFiles = copy(extraFiles = _root_.scala.collection.immutable.Map.empty) + def addExtraFiles(__vs: (_root_.scala.Predef.String, _root_.com.google.protobuf.ByteString) *): GeneratePackageRequest = addAllExtraFiles(__vs) + def addAllExtraFiles(__vs: Iterable[(_root_.scala.Predef.String, _root_.com.google.protobuf.ByteString)]): GeneratePackageRequest = copy(extraFiles = extraFiles ++ __vs) + def withExtraFiles(__v: _root_.scala.collection.immutable.Map[_root_.scala.Predef.String, _root_.com.google.protobuf.ByteString]): GeneratePackageRequest = copy(extraFiles = __v) + def withLoaderTarget(__v: _root_.scala.Predef.String): GeneratePackageRequest = copy(loaderTarget = __v) + def clearLocalDependencies = copy(localDependencies = _root_.scala.collection.immutable.Map.empty) + def addLocalDependencies(__vs: (_root_.scala.Predef.String, _root_.scala.Predef.String) *): GeneratePackageRequest = addAllLocalDependencies(__vs) + def addAllLocalDependencies(__vs: Iterable[(_root_.scala.Predef.String, _root_.scala.Predef.String)]): GeneratePackageRequest = copy(localDependencies = localDependencies ++ __vs) + def withLocalDependencies(__v: _root_.scala.collection.immutable.Map[_root_.scala.Predef.String, _root_.scala.Predef.String]): GeneratePackageRequest = copy(localDependencies = __v) + def withUnknownFields(__v: _root_.scalapb.UnknownFieldSet) = copy(unknownFields = __v) + def discardUnknownFields = copy(unknownFields = _root_.scalapb.UnknownFieldSet.empty) + def getFieldByNumber(__fieldNumber: _root_.scala.Int): _root_.scala.Any = { + (__fieldNumber: @_root_.scala.unchecked) match { + case 1 => { + val __t = directory + if (__t != "") __t else null + } + case 2 => { + val __t = schema + if (__t != "") __t else null + } + case 3 => extraFiles.iterator.map(pulumirpc.language.GeneratePackageRequest._typemapper_extraFiles.toBase(_)).toSeq + case 4 => { + val __t = loaderTarget + if (__t != "") __t else null + } + case 5 => localDependencies.iterator.map(pulumirpc.language.GeneratePackageRequest._typemapper_localDependencies.toBase(_)).toSeq + } + } + def getField(__field: _root_.scalapb.descriptors.FieldDescriptor): _root_.scalapb.descriptors.PValue = { + _root_.scala.Predef.require(__field.containingMessage eq companion.scalaDescriptor) + (__field.number: @_root_.scala.unchecked) match { + case 1 => _root_.scalapb.descriptors.PString(directory) + case 2 => _root_.scalapb.descriptors.PString(schema) + case 3 => _root_.scalapb.descriptors.PRepeated(extraFiles.iterator.map(pulumirpc.language.GeneratePackageRequest._typemapper_extraFiles.toBase(_).toPMessage).toVector) + case 4 => _root_.scalapb.descriptors.PString(loaderTarget) + case 5 => _root_.scalapb.descriptors.PRepeated(localDependencies.iterator.map(pulumirpc.language.GeneratePackageRequest._typemapper_localDependencies.toBase(_).toPMessage).toVector) + } + } + def toProtoString: _root_.scala.Predef.String = _root_.scalapb.TextFormat.printToUnicodeString(this) + def companion: pulumirpc.language.GeneratePackageRequest.type = pulumirpc.language.GeneratePackageRequest + // @@protoc_insertion_point(GeneratedMessage[pulumirpc.GeneratePackageRequest]) +} + +object GeneratePackageRequest extends scalapb.GeneratedMessageCompanion[pulumirpc.language.GeneratePackageRequest] { + implicit def messageCompanion: scalapb.GeneratedMessageCompanion[pulumirpc.language.GeneratePackageRequest] = this + def parseFrom(`_input__`: _root_.com.google.protobuf.CodedInputStream): pulumirpc.language.GeneratePackageRequest = { + var __directory: _root_.scala.Predef.String = "" + var __schema: _root_.scala.Predef.String = "" + val __extraFiles: _root_.scala.collection.mutable.Builder[(_root_.scala.Predef.String, _root_.com.google.protobuf.ByteString), _root_.scala.collection.immutable.Map[_root_.scala.Predef.String, _root_.com.google.protobuf.ByteString]] = _root_.scala.collection.immutable.Map.newBuilder[_root_.scala.Predef.String, _root_.com.google.protobuf.ByteString] + var __loaderTarget: _root_.scala.Predef.String = "" + val __localDependencies: _root_.scala.collection.mutable.Builder[(_root_.scala.Predef.String, _root_.scala.Predef.String), _root_.scala.collection.immutable.Map[_root_.scala.Predef.String, _root_.scala.Predef.String]] = _root_.scala.collection.immutable.Map.newBuilder[_root_.scala.Predef.String, _root_.scala.Predef.String] + var `_unknownFields__`: _root_.scalapb.UnknownFieldSet.Builder = null + var _done__ = false + while (!_done__) { + val _tag__ = _input__.readTag() + _tag__ match { + case 0 => _done__ = true + case 10 => + __directory = _input__.readStringRequireUtf8() + case 18 => + __schema = _input__.readStringRequireUtf8() + case 26 => + __extraFiles += pulumirpc.language.GeneratePackageRequest._typemapper_extraFiles.toCustom(_root_.scalapb.LiteParser.readMessage[pulumirpc.language.GeneratePackageRequest.ExtraFilesEntry](_input__)) + case 34 => + __loaderTarget = _input__.readStringRequireUtf8() + case 42 => + __localDependencies += pulumirpc.language.GeneratePackageRequest._typemapper_localDependencies.toCustom(_root_.scalapb.LiteParser.readMessage[pulumirpc.language.GeneratePackageRequest.LocalDependenciesEntry](_input__)) + case tag => + if (_unknownFields__ == null) { + _unknownFields__ = new _root_.scalapb.UnknownFieldSet.Builder() + } + _unknownFields__.parseField(tag, _input__) + } + } + pulumirpc.language.GeneratePackageRequest( + directory = __directory, + schema = __schema, + extraFiles = __extraFiles.result(), + loaderTarget = __loaderTarget, + localDependencies = __localDependencies.result(), + unknownFields = if (_unknownFields__ == null) _root_.scalapb.UnknownFieldSet.empty else _unknownFields__.result() + ) + } + implicit def messageReads: _root_.scalapb.descriptors.Reads[pulumirpc.language.GeneratePackageRequest] = _root_.scalapb.descriptors.Reads{ + case _root_.scalapb.descriptors.PMessage(__fieldsMap) => + _root_.scala.Predef.require(__fieldsMap.keys.forall(_.containingMessage eq scalaDescriptor), "FieldDescriptor does not match message type.") + pulumirpc.language.GeneratePackageRequest( + directory = __fieldsMap.get(scalaDescriptor.findFieldByNumber(1).get).map(_.as[_root_.scala.Predef.String]).getOrElse(""), + schema = __fieldsMap.get(scalaDescriptor.findFieldByNumber(2).get).map(_.as[_root_.scala.Predef.String]).getOrElse(""), + extraFiles = __fieldsMap.get(scalaDescriptor.findFieldByNumber(3).get).map(_.as[_root_.scala.Seq[pulumirpc.language.GeneratePackageRequest.ExtraFilesEntry]]).getOrElse(_root_.scala.Seq.empty).iterator.map(pulumirpc.language.GeneratePackageRequest._typemapper_extraFiles.toCustom(_)).toMap, + loaderTarget = __fieldsMap.get(scalaDescriptor.findFieldByNumber(4).get).map(_.as[_root_.scala.Predef.String]).getOrElse(""), + localDependencies = __fieldsMap.get(scalaDescriptor.findFieldByNumber(5).get).map(_.as[_root_.scala.Seq[pulumirpc.language.GeneratePackageRequest.LocalDependenciesEntry]]).getOrElse(_root_.scala.Seq.empty).iterator.map(pulumirpc.language.GeneratePackageRequest._typemapper_localDependencies.toCustom(_)).toMap + ) + case _ => throw new RuntimeException("Expected PMessage") + } + def javaDescriptor: _root_.com.google.protobuf.Descriptors.Descriptor = LanguageProto.javaDescriptor.getMessageTypes().get(17) + def scalaDescriptor: _root_.scalapb.descriptors.Descriptor = LanguageProto.scalaDescriptor.messages(17) + def messageCompanionForFieldNumber(__number: _root_.scala.Int): _root_.scalapb.GeneratedMessageCompanion[_] = { + var __out: _root_.scalapb.GeneratedMessageCompanion[_] = null + (__number: @_root_.scala.unchecked) match { + case 3 => __out = pulumirpc.language.GeneratePackageRequest.ExtraFilesEntry + case 5 => __out = pulumirpc.language.GeneratePackageRequest.LocalDependenciesEntry + } + __out + } + lazy val nestedMessagesCompanions: Seq[_root_.scalapb.GeneratedMessageCompanion[_ <: _root_.scalapb.GeneratedMessage]] = + Seq[_root_.scalapb.GeneratedMessageCompanion[_ <: _root_.scalapb.GeneratedMessage]]( + _root_.pulumirpc.language.GeneratePackageRequest.ExtraFilesEntry, + _root_.pulumirpc.language.GeneratePackageRequest.LocalDependenciesEntry + ) + def enumCompanionForFieldNumber(__fieldNumber: _root_.scala.Int): _root_.scalapb.GeneratedEnumCompanion[_] = throw new MatchError(__fieldNumber) + lazy val defaultInstance = pulumirpc.language.GeneratePackageRequest( + directory = "", + schema = "", + extraFiles = _root_.scala.collection.immutable.Map.empty, + loaderTarget = "", + localDependencies = _root_.scala.collection.immutable.Map.empty + ) + @SerialVersionUID(0L) + final case class ExtraFilesEntry( + key: _root_.scala.Predef.String = "", + value: _root_.com.google.protobuf.ByteString = _root_.com.google.protobuf.ByteString.EMPTY, + unknownFields: _root_.scalapb.UnknownFieldSet = _root_.scalapb.UnknownFieldSet.empty + ) extends scalapb.GeneratedMessage with scalapb.lenses.Updatable[ExtraFilesEntry] { + @transient + private[this] var __serializedSizeMemoized: _root_.scala.Int = 0 + private[this] def __computeSerializedSize(): _root_.scala.Int = { + var __size = 0 + + { + val __value = key + if (!__value.isEmpty) { + __size += _root_.com.google.protobuf.CodedOutputStream.computeStringSize(1, __value) + } + }; + + { + val __value = value + if (!__value.isEmpty) { + __size += _root_.com.google.protobuf.CodedOutputStream.computeBytesSize(2, __value) + } + }; + __size += unknownFields.serializedSize + __size + } + override def serializedSize: _root_.scala.Int = { + var __size = __serializedSizeMemoized + if (__size == 0) { + __size = __computeSerializedSize() + 1 + __serializedSizeMemoized = __size + } + __size - 1 + + } + def writeTo(`_output__`: _root_.com.google.protobuf.CodedOutputStream): _root_.scala.Unit = { + { + val __v = key + if (!__v.isEmpty) { + _output__.writeString(1, __v) + } + }; + { + val __v = value + if (!__v.isEmpty) { + _output__.writeBytes(2, __v) + } + }; + unknownFields.writeTo(_output__) + } + def withKey(__v: _root_.scala.Predef.String): ExtraFilesEntry = copy(key = __v) + def withValue(__v: _root_.com.google.protobuf.ByteString): ExtraFilesEntry = copy(value = __v) + def withUnknownFields(__v: _root_.scalapb.UnknownFieldSet) = copy(unknownFields = __v) + def discardUnknownFields = copy(unknownFields = _root_.scalapb.UnknownFieldSet.empty) + def getFieldByNumber(__fieldNumber: _root_.scala.Int): _root_.scala.Any = { + (__fieldNumber: @_root_.scala.unchecked) match { + case 1 => { + val __t = key + if (__t != "") __t else null + } + case 2 => { + val __t = value + if (__t != _root_.com.google.protobuf.ByteString.EMPTY) __t else null + } + } + } + def getField(__field: _root_.scalapb.descriptors.FieldDescriptor): _root_.scalapb.descriptors.PValue = { + _root_.scala.Predef.require(__field.containingMessage eq companion.scalaDescriptor) + (__field.number: @_root_.scala.unchecked) match { + case 1 => _root_.scalapb.descriptors.PString(key) + case 2 => _root_.scalapb.descriptors.PByteString(value) + } + } + def toProtoString: _root_.scala.Predef.String = _root_.scalapb.TextFormat.printToUnicodeString(this) + def companion: pulumirpc.language.GeneratePackageRequest.ExtraFilesEntry.type = pulumirpc.language.GeneratePackageRequest.ExtraFilesEntry + // @@protoc_insertion_point(GeneratedMessage[pulumirpc.GeneratePackageRequest.ExtraFilesEntry]) + } + + object ExtraFilesEntry extends scalapb.GeneratedMessageCompanion[pulumirpc.language.GeneratePackageRequest.ExtraFilesEntry] { + implicit def messageCompanion: scalapb.GeneratedMessageCompanion[pulumirpc.language.GeneratePackageRequest.ExtraFilesEntry] = this + def parseFrom(`_input__`: _root_.com.google.protobuf.CodedInputStream): pulumirpc.language.GeneratePackageRequest.ExtraFilesEntry = { + var __key: _root_.scala.Predef.String = "" + var __value: _root_.com.google.protobuf.ByteString = _root_.com.google.protobuf.ByteString.EMPTY + var `_unknownFields__`: _root_.scalapb.UnknownFieldSet.Builder = null + var _done__ = false + while (!_done__) { + val _tag__ = _input__.readTag() + _tag__ match { + case 0 => _done__ = true + case 10 => + __key = _input__.readStringRequireUtf8() + case 18 => + __value = _input__.readBytes() + case tag => + if (_unknownFields__ == null) { + _unknownFields__ = new _root_.scalapb.UnknownFieldSet.Builder() + } + _unknownFields__.parseField(tag, _input__) + } + } + pulumirpc.language.GeneratePackageRequest.ExtraFilesEntry( + key = __key, + value = __value, + unknownFields = if (_unknownFields__ == null) _root_.scalapb.UnknownFieldSet.empty else _unknownFields__.result() + ) + } + implicit def messageReads: _root_.scalapb.descriptors.Reads[pulumirpc.language.GeneratePackageRequest.ExtraFilesEntry] = _root_.scalapb.descriptors.Reads{ + case _root_.scalapb.descriptors.PMessage(__fieldsMap) => + _root_.scala.Predef.require(__fieldsMap.keys.forall(_.containingMessage eq scalaDescriptor), "FieldDescriptor does not match message type.") + pulumirpc.language.GeneratePackageRequest.ExtraFilesEntry( + key = __fieldsMap.get(scalaDescriptor.findFieldByNumber(1).get).map(_.as[_root_.scala.Predef.String]).getOrElse(""), + value = __fieldsMap.get(scalaDescriptor.findFieldByNumber(2).get).map(_.as[_root_.com.google.protobuf.ByteString]).getOrElse(_root_.com.google.protobuf.ByteString.EMPTY) + ) + case _ => throw new RuntimeException("Expected PMessage") + } + def javaDescriptor: _root_.com.google.protobuf.Descriptors.Descriptor = pulumirpc.language.GeneratePackageRequest.javaDescriptor.getNestedTypes().get(0) + def scalaDescriptor: _root_.scalapb.descriptors.Descriptor = pulumirpc.language.GeneratePackageRequest.scalaDescriptor.nestedMessages(0) + def messageCompanionForFieldNumber(__number: _root_.scala.Int): _root_.scalapb.GeneratedMessageCompanion[_] = throw new MatchError(__number) + lazy val nestedMessagesCompanions: Seq[_root_.scalapb.GeneratedMessageCompanion[_ <: _root_.scalapb.GeneratedMessage]] = Seq.empty + def enumCompanionForFieldNumber(__fieldNumber: _root_.scala.Int): _root_.scalapb.GeneratedEnumCompanion[_] = throw new MatchError(__fieldNumber) + lazy val defaultInstance = pulumirpc.language.GeneratePackageRequest.ExtraFilesEntry( + key = "", + value = _root_.com.google.protobuf.ByteString.EMPTY + ) + implicit class ExtraFilesEntryLens[UpperPB](_l: _root_.scalapb.lenses.Lens[UpperPB, pulumirpc.language.GeneratePackageRequest.ExtraFilesEntry]) extends _root_.scalapb.lenses.ObjectLens[UpperPB, pulumirpc.language.GeneratePackageRequest.ExtraFilesEntry](_l) { + def key: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Predef.String] = field(_.key)((c_, f_) => c_.copy(key = f_)) + def value: _root_.scalapb.lenses.Lens[UpperPB, _root_.com.google.protobuf.ByteString] = field(_.value)((c_, f_) => c_.copy(value = f_)) + } + final val KEY_FIELD_NUMBER = 1 + final val VALUE_FIELD_NUMBER = 2 + @transient + implicit val keyValueMapper: _root_.scalapb.TypeMapper[pulumirpc.language.GeneratePackageRequest.ExtraFilesEntry, (_root_.scala.Predef.String, _root_.com.google.protobuf.ByteString)] = + _root_.scalapb.TypeMapper[pulumirpc.language.GeneratePackageRequest.ExtraFilesEntry, (_root_.scala.Predef.String, _root_.com.google.protobuf.ByteString)](__m => (__m.key, __m.value))(__p => pulumirpc.language.GeneratePackageRequest.ExtraFilesEntry(__p._1, __p._2)) + def of( + key: _root_.scala.Predef.String, + value: _root_.com.google.protobuf.ByteString + ): _root_.pulumirpc.language.GeneratePackageRequest.ExtraFilesEntry = _root_.pulumirpc.language.GeneratePackageRequest.ExtraFilesEntry( + key, + value + ) + // @@protoc_insertion_point(GeneratedMessageCompanion[pulumirpc.GeneratePackageRequest.ExtraFilesEntry]) + } + + @SerialVersionUID(0L) + final case class LocalDependenciesEntry( + key: _root_.scala.Predef.String = "", + value: _root_.scala.Predef.String = "", + unknownFields: _root_.scalapb.UnknownFieldSet = _root_.scalapb.UnknownFieldSet.empty + ) extends scalapb.GeneratedMessage with scalapb.lenses.Updatable[LocalDependenciesEntry] { + @transient + private[this] var __serializedSizeMemoized: _root_.scala.Int = 0 + private[this] def __computeSerializedSize(): _root_.scala.Int = { + var __size = 0 + + { + val __value = key + if (!__value.isEmpty) { + __size += _root_.com.google.protobuf.CodedOutputStream.computeStringSize(1, __value) + } + }; + + { + val __value = value + if (!__value.isEmpty) { + __size += _root_.com.google.protobuf.CodedOutputStream.computeStringSize(2, __value) + } + }; + __size += unknownFields.serializedSize + __size + } + override def serializedSize: _root_.scala.Int = { + var __size = __serializedSizeMemoized + if (__size == 0) { + __size = __computeSerializedSize() + 1 + __serializedSizeMemoized = __size + } + __size - 1 + + } + def writeTo(`_output__`: _root_.com.google.protobuf.CodedOutputStream): _root_.scala.Unit = { + { + val __v = key + if (!__v.isEmpty) { + _output__.writeString(1, __v) + } + }; + { + val __v = value + if (!__v.isEmpty) { + _output__.writeString(2, __v) + } + }; + unknownFields.writeTo(_output__) + } + def withKey(__v: _root_.scala.Predef.String): LocalDependenciesEntry = copy(key = __v) + def withValue(__v: _root_.scala.Predef.String): LocalDependenciesEntry = copy(value = __v) + def withUnknownFields(__v: _root_.scalapb.UnknownFieldSet) = copy(unknownFields = __v) + def discardUnknownFields = copy(unknownFields = _root_.scalapb.UnknownFieldSet.empty) + def getFieldByNumber(__fieldNumber: _root_.scala.Int): _root_.scala.Any = { + (__fieldNumber: @_root_.scala.unchecked) match { + case 1 => { + val __t = key + if (__t != "") __t else null + } + case 2 => { + val __t = value + if (__t != "") __t else null + } + } + } + def getField(__field: _root_.scalapb.descriptors.FieldDescriptor): _root_.scalapb.descriptors.PValue = { + _root_.scala.Predef.require(__field.containingMessage eq companion.scalaDescriptor) + (__field.number: @_root_.scala.unchecked) match { + case 1 => _root_.scalapb.descriptors.PString(key) + case 2 => _root_.scalapb.descriptors.PString(value) + } + } + def toProtoString: _root_.scala.Predef.String = _root_.scalapb.TextFormat.printToUnicodeString(this) + def companion: pulumirpc.language.GeneratePackageRequest.LocalDependenciesEntry.type = pulumirpc.language.GeneratePackageRequest.LocalDependenciesEntry + // @@protoc_insertion_point(GeneratedMessage[pulumirpc.GeneratePackageRequest.LocalDependenciesEntry]) + } + + object LocalDependenciesEntry extends scalapb.GeneratedMessageCompanion[pulumirpc.language.GeneratePackageRequest.LocalDependenciesEntry] { + implicit def messageCompanion: scalapb.GeneratedMessageCompanion[pulumirpc.language.GeneratePackageRequest.LocalDependenciesEntry] = this + def parseFrom(`_input__`: _root_.com.google.protobuf.CodedInputStream): pulumirpc.language.GeneratePackageRequest.LocalDependenciesEntry = { + var __key: _root_.scala.Predef.String = "" + var __value: _root_.scala.Predef.String = "" + var `_unknownFields__`: _root_.scalapb.UnknownFieldSet.Builder = null + var _done__ = false + while (!_done__) { + val _tag__ = _input__.readTag() + _tag__ match { + case 0 => _done__ = true + case 10 => + __key = _input__.readStringRequireUtf8() + case 18 => + __value = _input__.readStringRequireUtf8() + case tag => + if (_unknownFields__ == null) { + _unknownFields__ = new _root_.scalapb.UnknownFieldSet.Builder() + } + _unknownFields__.parseField(tag, _input__) + } + } + pulumirpc.language.GeneratePackageRequest.LocalDependenciesEntry( + key = __key, + value = __value, + unknownFields = if (_unknownFields__ == null) _root_.scalapb.UnknownFieldSet.empty else _unknownFields__.result() + ) + } + implicit def messageReads: _root_.scalapb.descriptors.Reads[pulumirpc.language.GeneratePackageRequest.LocalDependenciesEntry] = _root_.scalapb.descriptors.Reads{ + case _root_.scalapb.descriptors.PMessage(__fieldsMap) => + _root_.scala.Predef.require(__fieldsMap.keys.forall(_.containingMessage eq scalaDescriptor), "FieldDescriptor does not match message type.") + pulumirpc.language.GeneratePackageRequest.LocalDependenciesEntry( + key = __fieldsMap.get(scalaDescriptor.findFieldByNumber(1).get).map(_.as[_root_.scala.Predef.String]).getOrElse(""), + value = __fieldsMap.get(scalaDescriptor.findFieldByNumber(2).get).map(_.as[_root_.scala.Predef.String]).getOrElse("") + ) + case _ => throw new RuntimeException("Expected PMessage") + } + def javaDescriptor: _root_.com.google.protobuf.Descriptors.Descriptor = pulumirpc.language.GeneratePackageRequest.javaDescriptor.getNestedTypes().get(1) + def scalaDescriptor: _root_.scalapb.descriptors.Descriptor = pulumirpc.language.GeneratePackageRequest.scalaDescriptor.nestedMessages(1) + def messageCompanionForFieldNumber(__number: _root_.scala.Int): _root_.scalapb.GeneratedMessageCompanion[_] = throw new MatchError(__number) + lazy val nestedMessagesCompanions: Seq[_root_.scalapb.GeneratedMessageCompanion[_ <: _root_.scalapb.GeneratedMessage]] = Seq.empty + def enumCompanionForFieldNumber(__fieldNumber: _root_.scala.Int): _root_.scalapb.GeneratedEnumCompanion[_] = throw new MatchError(__fieldNumber) + lazy val defaultInstance = pulumirpc.language.GeneratePackageRequest.LocalDependenciesEntry( + key = "", + value = "" + ) + implicit class LocalDependenciesEntryLens[UpperPB](_l: _root_.scalapb.lenses.Lens[UpperPB, pulumirpc.language.GeneratePackageRequest.LocalDependenciesEntry]) extends _root_.scalapb.lenses.ObjectLens[UpperPB, pulumirpc.language.GeneratePackageRequest.LocalDependenciesEntry](_l) { + def key: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Predef.String] = field(_.key)((c_, f_) => c_.copy(key = f_)) + def value: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Predef.String] = field(_.value)((c_, f_) => c_.copy(value = f_)) + } + final val KEY_FIELD_NUMBER = 1 + final val VALUE_FIELD_NUMBER = 2 + @transient + implicit val keyValueMapper: _root_.scalapb.TypeMapper[pulumirpc.language.GeneratePackageRequest.LocalDependenciesEntry, (_root_.scala.Predef.String, _root_.scala.Predef.String)] = + _root_.scalapb.TypeMapper[pulumirpc.language.GeneratePackageRequest.LocalDependenciesEntry, (_root_.scala.Predef.String, _root_.scala.Predef.String)](__m => (__m.key, __m.value))(__p => pulumirpc.language.GeneratePackageRequest.LocalDependenciesEntry(__p._1, __p._2)) + def of( + key: _root_.scala.Predef.String, + value: _root_.scala.Predef.String + ): _root_.pulumirpc.language.GeneratePackageRequest.LocalDependenciesEntry = _root_.pulumirpc.language.GeneratePackageRequest.LocalDependenciesEntry( + key, + value + ) + // @@protoc_insertion_point(GeneratedMessageCompanion[pulumirpc.GeneratePackageRequest.LocalDependenciesEntry]) + } + + implicit class GeneratePackageRequestLens[UpperPB](_l: _root_.scalapb.lenses.Lens[UpperPB, pulumirpc.language.GeneratePackageRequest]) extends _root_.scalapb.lenses.ObjectLens[UpperPB, pulumirpc.language.GeneratePackageRequest](_l) { + def directory: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Predef.String] = field(_.directory)((c_, f_) => c_.copy(directory = f_)) + def schema: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Predef.String] = field(_.schema)((c_, f_) => c_.copy(schema = f_)) + def extraFiles: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.collection.immutable.Map[_root_.scala.Predef.String, _root_.com.google.protobuf.ByteString]] = field(_.extraFiles)((c_, f_) => c_.copy(extraFiles = f_)) + def loaderTarget: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Predef.String] = field(_.loaderTarget)((c_, f_) => c_.copy(loaderTarget = f_)) + def localDependencies: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.collection.immutable.Map[_root_.scala.Predef.String, _root_.scala.Predef.String]] = field(_.localDependencies)((c_, f_) => c_.copy(localDependencies = f_)) + } + final val DIRECTORY_FIELD_NUMBER = 1 + final val SCHEMA_FIELD_NUMBER = 2 + final val EXTRA_FILES_FIELD_NUMBER = 3 + final val LOADER_TARGET_FIELD_NUMBER = 4 + final val LOCAL_DEPENDENCIES_FIELD_NUMBER = 5 + @transient + private[language] val _typemapper_extraFiles: _root_.scalapb.TypeMapper[pulumirpc.language.GeneratePackageRequest.ExtraFilesEntry, (_root_.scala.Predef.String, _root_.com.google.protobuf.ByteString)] = implicitly[_root_.scalapb.TypeMapper[pulumirpc.language.GeneratePackageRequest.ExtraFilesEntry, (_root_.scala.Predef.String, _root_.com.google.protobuf.ByteString)]] + @transient + private[language] val _typemapper_localDependencies: _root_.scalapb.TypeMapper[pulumirpc.language.GeneratePackageRequest.LocalDependenciesEntry, (_root_.scala.Predef.String, _root_.scala.Predef.String)] = implicitly[_root_.scalapb.TypeMapper[pulumirpc.language.GeneratePackageRequest.LocalDependenciesEntry, (_root_.scala.Predef.String, _root_.scala.Predef.String)]] + def of( + directory: _root_.scala.Predef.String, + schema: _root_.scala.Predef.String, + extraFiles: _root_.scala.collection.immutable.Map[_root_.scala.Predef.String, _root_.com.google.protobuf.ByteString], + loaderTarget: _root_.scala.Predef.String, + localDependencies: _root_.scala.collection.immutable.Map[_root_.scala.Predef.String, _root_.scala.Predef.String] + ): _root_.pulumirpc.language.GeneratePackageRequest = _root_.pulumirpc.language.GeneratePackageRequest( + directory, + schema, + extraFiles, + loaderTarget, + localDependencies + ) + // @@protoc_insertion_point(GeneratedMessageCompanion[pulumirpc.GeneratePackageRequest]) +} diff --git a/core/src/main/scala/besom/rpc/pulumirpc/language/GeneratePackageResponse.scala b/core/src/main/scala/besom/rpc/pulumirpc/language/GeneratePackageResponse.scala new file mode 100644 index 00000000..edf5ce9c --- /dev/null +++ b/core/src/main/scala/besom/rpc/pulumirpc/language/GeneratePackageResponse.scala @@ -0,0 +1,123 @@ +// Generated by the Scala Plugin for the Protocol Buffer Compiler. +// Do not edit! +// +// Protofile syntax: PROTO3 + +package pulumirpc.language + +/** @param diagnostics + * any diagnostics from code generation. + */ +@SerialVersionUID(0L) +final case class GeneratePackageResponse( + diagnostics: _root_.scala.Seq[pulumirpc.codegen.hcl.Diagnostic] = _root_.scala.Seq.empty, + unknownFields: _root_.scalapb.UnknownFieldSet = _root_.scalapb.UnknownFieldSet.empty + ) extends scalapb.GeneratedMessage with scalapb.lenses.Updatable[GeneratePackageResponse] { + @transient + private[this] var __serializedSizeMemoized: _root_.scala.Int = 0 + private[this] def __computeSerializedSize(): _root_.scala.Int = { + var __size = 0 + diagnostics.foreach { __item => + val __value = __item + __size += 1 + _root_.com.google.protobuf.CodedOutputStream.computeUInt32SizeNoTag(__value.serializedSize) + __value.serializedSize + } + __size += unknownFields.serializedSize + __size + } + override def serializedSize: _root_.scala.Int = { + var __size = __serializedSizeMemoized + if (__size == 0) { + __size = __computeSerializedSize() + 1 + __serializedSizeMemoized = __size + } + __size - 1 + + } + def writeTo(`_output__`: _root_.com.google.protobuf.CodedOutputStream): _root_.scala.Unit = { + diagnostics.foreach { __v => + val __m = __v + _output__.writeTag(1, 2) + _output__.writeUInt32NoTag(__m.serializedSize) + __m.writeTo(_output__) + }; + unknownFields.writeTo(_output__) + } + def clearDiagnostics = copy(diagnostics = _root_.scala.Seq.empty) + def addDiagnostics(__vs: pulumirpc.codegen.hcl.Diagnostic *): GeneratePackageResponse = addAllDiagnostics(__vs) + def addAllDiagnostics(__vs: Iterable[pulumirpc.codegen.hcl.Diagnostic]): GeneratePackageResponse = copy(diagnostics = diagnostics ++ __vs) + def withDiagnostics(__v: _root_.scala.Seq[pulumirpc.codegen.hcl.Diagnostic]): GeneratePackageResponse = copy(diagnostics = __v) + def withUnknownFields(__v: _root_.scalapb.UnknownFieldSet) = copy(unknownFields = __v) + def discardUnknownFields = copy(unknownFields = _root_.scalapb.UnknownFieldSet.empty) + def getFieldByNumber(__fieldNumber: _root_.scala.Int): _root_.scala.Any = { + (__fieldNumber: @_root_.scala.unchecked) match { + case 1 => diagnostics + } + } + def getField(__field: _root_.scalapb.descriptors.FieldDescriptor): _root_.scalapb.descriptors.PValue = { + _root_.scala.Predef.require(__field.containingMessage eq companion.scalaDescriptor) + (__field.number: @_root_.scala.unchecked) match { + case 1 => _root_.scalapb.descriptors.PRepeated(diagnostics.iterator.map(_.toPMessage).toVector) + } + } + def toProtoString: _root_.scala.Predef.String = _root_.scalapb.TextFormat.printToUnicodeString(this) + def companion: pulumirpc.language.GeneratePackageResponse.type = pulumirpc.language.GeneratePackageResponse + // @@protoc_insertion_point(GeneratedMessage[pulumirpc.GeneratePackageResponse]) +} + +object GeneratePackageResponse extends scalapb.GeneratedMessageCompanion[pulumirpc.language.GeneratePackageResponse] { + implicit def messageCompanion: scalapb.GeneratedMessageCompanion[pulumirpc.language.GeneratePackageResponse] = this + def parseFrom(`_input__`: _root_.com.google.protobuf.CodedInputStream): pulumirpc.language.GeneratePackageResponse = { + val __diagnostics: _root_.scala.collection.immutable.VectorBuilder[pulumirpc.codegen.hcl.Diagnostic] = new _root_.scala.collection.immutable.VectorBuilder[pulumirpc.codegen.hcl.Diagnostic] + var `_unknownFields__`: _root_.scalapb.UnknownFieldSet.Builder = null + var _done__ = false + while (!_done__) { + val _tag__ = _input__.readTag() + _tag__ match { + case 0 => _done__ = true + case 10 => + __diagnostics += _root_.scalapb.LiteParser.readMessage[pulumirpc.codegen.hcl.Diagnostic](_input__) + case tag => + if (_unknownFields__ == null) { + _unknownFields__ = new _root_.scalapb.UnknownFieldSet.Builder() + } + _unknownFields__.parseField(tag, _input__) + } + } + pulumirpc.language.GeneratePackageResponse( + diagnostics = __diagnostics.result(), + unknownFields = if (_unknownFields__ == null) _root_.scalapb.UnknownFieldSet.empty else _unknownFields__.result() + ) + } + implicit def messageReads: _root_.scalapb.descriptors.Reads[pulumirpc.language.GeneratePackageResponse] = _root_.scalapb.descriptors.Reads{ + case _root_.scalapb.descriptors.PMessage(__fieldsMap) => + _root_.scala.Predef.require(__fieldsMap.keys.forall(_.containingMessage eq scalaDescriptor), "FieldDescriptor does not match message type.") + pulumirpc.language.GeneratePackageResponse( + diagnostics = __fieldsMap.get(scalaDescriptor.findFieldByNumber(1).get).map(_.as[_root_.scala.Seq[pulumirpc.codegen.hcl.Diagnostic]]).getOrElse(_root_.scala.Seq.empty) + ) + case _ => throw new RuntimeException("Expected PMessage") + } + def javaDescriptor: _root_.com.google.protobuf.Descriptors.Descriptor = LanguageProto.javaDescriptor.getMessageTypes().get(18) + def scalaDescriptor: _root_.scalapb.descriptors.Descriptor = LanguageProto.scalaDescriptor.messages(18) + def messageCompanionForFieldNumber(__number: _root_.scala.Int): _root_.scalapb.GeneratedMessageCompanion[_] = { + var __out: _root_.scalapb.GeneratedMessageCompanion[_] = null + (__number: @_root_.scala.unchecked) match { + case 1 => __out = pulumirpc.codegen.hcl.Diagnostic + } + __out + } + lazy val nestedMessagesCompanions: Seq[_root_.scalapb.GeneratedMessageCompanion[_ <: _root_.scalapb.GeneratedMessage]] = Seq.empty + def enumCompanionForFieldNumber(__fieldNumber: _root_.scala.Int): _root_.scalapb.GeneratedEnumCompanion[_] = throw new MatchError(__fieldNumber) + lazy val defaultInstance = pulumirpc.language.GeneratePackageResponse( + diagnostics = _root_.scala.Seq.empty + ) + implicit class GeneratePackageResponseLens[UpperPB](_l: _root_.scalapb.lenses.Lens[UpperPB, pulumirpc.language.GeneratePackageResponse]) extends _root_.scalapb.lenses.ObjectLens[UpperPB, pulumirpc.language.GeneratePackageResponse](_l) { + def diagnostics: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Seq[pulumirpc.codegen.hcl.Diagnostic]] = field(_.diagnostics)((c_, f_) => c_.copy(diagnostics = f_)) + } + final val DIAGNOSTICS_FIELD_NUMBER = 1 + def of( + diagnostics: _root_.scala.Seq[pulumirpc.codegen.hcl.Diagnostic] + ): _root_.pulumirpc.language.GeneratePackageResponse = _root_.pulumirpc.language.GeneratePackageResponse( + diagnostics + ) + // @@protoc_insertion_point(GeneratedMessageCompanion[pulumirpc.GeneratePackageResponse]) +} diff --git a/core/src/main/scala/besom/rpc/pulumirpc/language/GenerateProgramRequest.scala b/core/src/main/scala/besom/rpc/pulumirpc/language/GenerateProgramRequest.scala new file mode 100644 index 00000000..f7f5ee8c --- /dev/null +++ b/core/src/main/scala/besom/rpc/pulumirpc/language/GenerateProgramRequest.scala @@ -0,0 +1,304 @@ +// Generated by the Scala Plugin for the Protocol Buffer Compiler. +// Do not edit! +// +// Protofile syntax: PROTO3 + +package pulumirpc.language + +/** @param source + * the PCL source of the project. + * @param loaderTarget + * The target of a codegen.LoaderServer to use for loading schemas. + */ +@SerialVersionUID(0L) +final case class GenerateProgramRequest( + source: _root_.scala.collection.immutable.Map[_root_.scala.Predef.String, _root_.scala.Predef.String] = _root_.scala.collection.immutable.Map.empty, + loaderTarget: _root_.scala.Predef.String = "", + unknownFields: _root_.scalapb.UnknownFieldSet = _root_.scalapb.UnknownFieldSet.empty + ) extends scalapb.GeneratedMessage with scalapb.lenses.Updatable[GenerateProgramRequest] { + @transient + private[this] var __serializedSizeMemoized: _root_.scala.Int = 0 + private[this] def __computeSerializedSize(): _root_.scala.Int = { + var __size = 0 + source.foreach { __item => + val __value = pulumirpc.language.GenerateProgramRequest._typemapper_source.toBase(__item) + __size += 1 + _root_.com.google.protobuf.CodedOutputStream.computeUInt32SizeNoTag(__value.serializedSize) + __value.serializedSize + } + + { + val __value = loaderTarget + if (!__value.isEmpty) { + __size += _root_.com.google.protobuf.CodedOutputStream.computeStringSize(2, __value) + } + }; + __size += unknownFields.serializedSize + __size + } + override def serializedSize: _root_.scala.Int = { + var __size = __serializedSizeMemoized + if (__size == 0) { + __size = __computeSerializedSize() + 1 + __serializedSizeMemoized = __size + } + __size - 1 + + } + def writeTo(`_output__`: _root_.com.google.protobuf.CodedOutputStream): _root_.scala.Unit = { + source.foreach { __v => + val __m = pulumirpc.language.GenerateProgramRequest._typemapper_source.toBase(__v) + _output__.writeTag(1, 2) + _output__.writeUInt32NoTag(__m.serializedSize) + __m.writeTo(_output__) + }; + { + val __v = loaderTarget + if (!__v.isEmpty) { + _output__.writeString(2, __v) + } + }; + unknownFields.writeTo(_output__) + } + def clearSource = copy(source = _root_.scala.collection.immutable.Map.empty) + def addSource(__vs: (_root_.scala.Predef.String, _root_.scala.Predef.String) *): GenerateProgramRequest = addAllSource(__vs) + def addAllSource(__vs: Iterable[(_root_.scala.Predef.String, _root_.scala.Predef.String)]): GenerateProgramRequest = copy(source = source ++ __vs) + def withSource(__v: _root_.scala.collection.immutable.Map[_root_.scala.Predef.String, _root_.scala.Predef.String]): GenerateProgramRequest = copy(source = __v) + def withLoaderTarget(__v: _root_.scala.Predef.String): GenerateProgramRequest = copy(loaderTarget = __v) + def withUnknownFields(__v: _root_.scalapb.UnknownFieldSet) = copy(unknownFields = __v) + def discardUnknownFields = copy(unknownFields = _root_.scalapb.UnknownFieldSet.empty) + def getFieldByNumber(__fieldNumber: _root_.scala.Int): _root_.scala.Any = { + (__fieldNumber: @_root_.scala.unchecked) match { + case 1 => source.iterator.map(pulumirpc.language.GenerateProgramRequest._typemapper_source.toBase(_)).toSeq + case 2 => { + val __t = loaderTarget + if (__t != "") __t else null + } + } + } + def getField(__field: _root_.scalapb.descriptors.FieldDescriptor): _root_.scalapb.descriptors.PValue = { + _root_.scala.Predef.require(__field.containingMessage eq companion.scalaDescriptor) + (__field.number: @_root_.scala.unchecked) match { + case 1 => _root_.scalapb.descriptors.PRepeated(source.iterator.map(pulumirpc.language.GenerateProgramRequest._typemapper_source.toBase(_).toPMessage).toVector) + case 2 => _root_.scalapb.descriptors.PString(loaderTarget) + } + } + def toProtoString: _root_.scala.Predef.String = _root_.scalapb.TextFormat.printToUnicodeString(this) + def companion: pulumirpc.language.GenerateProgramRequest.type = pulumirpc.language.GenerateProgramRequest + // @@protoc_insertion_point(GeneratedMessage[pulumirpc.GenerateProgramRequest]) +} + +object GenerateProgramRequest extends scalapb.GeneratedMessageCompanion[pulumirpc.language.GenerateProgramRequest] { + implicit def messageCompanion: scalapb.GeneratedMessageCompanion[pulumirpc.language.GenerateProgramRequest] = this + def parseFrom(`_input__`: _root_.com.google.protobuf.CodedInputStream): pulumirpc.language.GenerateProgramRequest = { + val __source: _root_.scala.collection.mutable.Builder[(_root_.scala.Predef.String, _root_.scala.Predef.String), _root_.scala.collection.immutable.Map[_root_.scala.Predef.String, _root_.scala.Predef.String]] = _root_.scala.collection.immutable.Map.newBuilder[_root_.scala.Predef.String, _root_.scala.Predef.String] + var __loaderTarget: _root_.scala.Predef.String = "" + var `_unknownFields__`: _root_.scalapb.UnknownFieldSet.Builder = null + var _done__ = false + while (!_done__) { + val _tag__ = _input__.readTag() + _tag__ match { + case 0 => _done__ = true + case 10 => + __source += pulumirpc.language.GenerateProgramRequest._typemapper_source.toCustom(_root_.scalapb.LiteParser.readMessage[pulumirpc.language.GenerateProgramRequest.SourceEntry](_input__)) + case 18 => + __loaderTarget = _input__.readStringRequireUtf8() + case tag => + if (_unknownFields__ == null) { + _unknownFields__ = new _root_.scalapb.UnknownFieldSet.Builder() + } + _unknownFields__.parseField(tag, _input__) + } + } + pulumirpc.language.GenerateProgramRequest( + source = __source.result(), + loaderTarget = __loaderTarget, + unknownFields = if (_unknownFields__ == null) _root_.scalapb.UnknownFieldSet.empty else _unknownFields__.result() + ) + } + implicit def messageReads: _root_.scalapb.descriptors.Reads[pulumirpc.language.GenerateProgramRequest] = _root_.scalapb.descriptors.Reads{ + case _root_.scalapb.descriptors.PMessage(__fieldsMap) => + _root_.scala.Predef.require(__fieldsMap.keys.forall(_.containingMessage eq scalaDescriptor), "FieldDescriptor does not match message type.") + pulumirpc.language.GenerateProgramRequest( + source = __fieldsMap.get(scalaDescriptor.findFieldByNumber(1).get).map(_.as[_root_.scala.Seq[pulumirpc.language.GenerateProgramRequest.SourceEntry]]).getOrElse(_root_.scala.Seq.empty).iterator.map(pulumirpc.language.GenerateProgramRequest._typemapper_source.toCustom(_)).toMap, + loaderTarget = __fieldsMap.get(scalaDescriptor.findFieldByNumber(2).get).map(_.as[_root_.scala.Predef.String]).getOrElse("") + ) + case _ => throw new RuntimeException("Expected PMessage") + } + def javaDescriptor: _root_.com.google.protobuf.Descriptors.Descriptor = LanguageProto.javaDescriptor.getMessageTypes().get(13) + def scalaDescriptor: _root_.scalapb.descriptors.Descriptor = LanguageProto.scalaDescriptor.messages(13) + def messageCompanionForFieldNumber(__number: _root_.scala.Int): _root_.scalapb.GeneratedMessageCompanion[_] = { + var __out: _root_.scalapb.GeneratedMessageCompanion[_] = null + (__number: @_root_.scala.unchecked) match { + case 1 => __out = pulumirpc.language.GenerateProgramRequest.SourceEntry + } + __out + } + lazy val nestedMessagesCompanions: Seq[_root_.scalapb.GeneratedMessageCompanion[_ <: _root_.scalapb.GeneratedMessage]] = + Seq[_root_.scalapb.GeneratedMessageCompanion[_ <: _root_.scalapb.GeneratedMessage]]( + _root_.pulumirpc.language.GenerateProgramRequest.SourceEntry + ) + def enumCompanionForFieldNumber(__fieldNumber: _root_.scala.Int): _root_.scalapb.GeneratedEnumCompanion[_] = throw new MatchError(__fieldNumber) + lazy val defaultInstance = pulumirpc.language.GenerateProgramRequest( + source = _root_.scala.collection.immutable.Map.empty, + loaderTarget = "" + ) + @SerialVersionUID(0L) + final case class SourceEntry( + key: _root_.scala.Predef.String = "", + value: _root_.scala.Predef.String = "", + unknownFields: _root_.scalapb.UnknownFieldSet = _root_.scalapb.UnknownFieldSet.empty + ) extends scalapb.GeneratedMessage with scalapb.lenses.Updatable[SourceEntry] { + @transient + private[this] var __serializedSizeMemoized: _root_.scala.Int = 0 + private[this] def __computeSerializedSize(): _root_.scala.Int = { + var __size = 0 + + { + val __value = key + if (!__value.isEmpty) { + __size += _root_.com.google.protobuf.CodedOutputStream.computeStringSize(1, __value) + } + }; + + { + val __value = value + if (!__value.isEmpty) { + __size += _root_.com.google.protobuf.CodedOutputStream.computeStringSize(2, __value) + } + }; + __size += unknownFields.serializedSize + __size + } + override def serializedSize: _root_.scala.Int = { + var __size = __serializedSizeMemoized + if (__size == 0) { + __size = __computeSerializedSize() + 1 + __serializedSizeMemoized = __size + } + __size - 1 + + } + def writeTo(`_output__`: _root_.com.google.protobuf.CodedOutputStream): _root_.scala.Unit = { + { + val __v = key + if (!__v.isEmpty) { + _output__.writeString(1, __v) + } + }; + { + val __v = value + if (!__v.isEmpty) { + _output__.writeString(2, __v) + } + }; + unknownFields.writeTo(_output__) + } + def withKey(__v: _root_.scala.Predef.String): SourceEntry = copy(key = __v) + def withValue(__v: _root_.scala.Predef.String): SourceEntry = copy(value = __v) + def withUnknownFields(__v: _root_.scalapb.UnknownFieldSet) = copy(unknownFields = __v) + def discardUnknownFields = copy(unknownFields = _root_.scalapb.UnknownFieldSet.empty) + def getFieldByNumber(__fieldNumber: _root_.scala.Int): _root_.scala.Any = { + (__fieldNumber: @_root_.scala.unchecked) match { + case 1 => { + val __t = key + if (__t != "") __t else null + } + case 2 => { + val __t = value + if (__t != "") __t else null + } + } + } + def getField(__field: _root_.scalapb.descriptors.FieldDescriptor): _root_.scalapb.descriptors.PValue = { + _root_.scala.Predef.require(__field.containingMessage eq companion.scalaDescriptor) + (__field.number: @_root_.scala.unchecked) match { + case 1 => _root_.scalapb.descriptors.PString(key) + case 2 => _root_.scalapb.descriptors.PString(value) + } + } + def toProtoString: _root_.scala.Predef.String = _root_.scalapb.TextFormat.printToUnicodeString(this) + def companion: pulumirpc.language.GenerateProgramRequest.SourceEntry.type = pulumirpc.language.GenerateProgramRequest.SourceEntry + // @@protoc_insertion_point(GeneratedMessage[pulumirpc.GenerateProgramRequest.SourceEntry]) + } + + object SourceEntry extends scalapb.GeneratedMessageCompanion[pulumirpc.language.GenerateProgramRequest.SourceEntry] { + implicit def messageCompanion: scalapb.GeneratedMessageCompanion[pulumirpc.language.GenerateProgramRequest.SourceEntry] = this + def parseFrom(`_input__`: _root_.com.google.protobuf.CodedInputStream): pulumirpc.language.GenerateProgramRequest.SourceEntry = { + var __key: _root_.scala.Predef.String = "" + var __value: _root_.scala.Predef.String = "" + var `_unknownFields__`: _root_.scalapb.UnknownFieldSet.Builder = null + var _done__ = false + while (!_done__) { + val _tag__ = _input__.readTag() + _tag__ match { + case 0 => _done__ = true + case 10 => + __key = _input__.readStringRequireUtf8() + case 18 => + __value = _input__.readStringRequireUtf8() + case tag => + if (_unknownFields__ == null) { + _unknownFields__ = new _root_.scalapb.UnknownFieldSet.Builder() + } + _unknownFields__.parseField(tag, _input__) + } + } + pulumirpc.language.GenerateProgramRequest.SourceEntry( + key = __key, + value = __value, + unknownFields = if (_unknownFields__ == null) _root_.scalapb.UnknownFieldSet.empty else _unknownFields__.result() + ) + } + implicit def messageReads: _root_.scalapb.descriptors.Reads[pulumirpc.language.GenerateProgramRequest.SourceEntry] = _root_.scalapb.descriptors.Reads{ + case _root_.scalapb.descriptors.PMessage(__fieldsMap) => + _root_.scala.Predef.require(__fieldsMap.keys.forall(_.containingMessage eq scalaDescriptor), "FieldDescriptor does not match message type.") + pulumirpc.language.GenerateProgramRequest.SourceEntry( + key = __fieldsMap.get(scalaDescriptor.findFieldByNumber(1).get).map(_.as[_root_.scala.Predef.String]).getOrElse(""), + value = __fieldsMap.get(scalaDescriptor.findFieldByNumber(2).get).map(_.as[_root_.scala.Predef.String]).getOrElse("") + ) + case _ => throw new RuntimeException("Expected PMessage") + } + def javaDescriptor: _root_.com.google.protobuf.Descriptors.Descriptor = pulumirpc.language.GenerateProgramRequest.javaDescriptor.getNestedTypes().get(0) + def scalaDescriptor: _root_.scalapb.descriptors.Descriptor = pulumirpc.language.GenerateProgramRequest.scalaDescriptor.nestedMessages(0) + def messageCompanionForFieldNumber(__number: _root_.scala.Int): _root_.scalapb.GeneratedMessageCompanion[_] = throw new MatchError(__number) + lazy val nestedMessagesCompanions: Seq[_root_.scalapb.GeneratedMessageCompanion[_ <: _root_.scalapb.GeneratedMessage]] = Seq.empty + def enumCompanionForFieldNumber(__fieldNumber: _root_.scala.Int): _root_.scalapb.GeneratedEnumCompanion[_] = throw new MatchError(__fieldNumber) + lazy val defaultInstance = pulumirpc.language.GenerateProgramRequest.SourceEntry( + key = "", + value = "" + ) + implicit class SourceEntryLens[UpperPB](_l: _root_.scalapb.lenses.Lens[UpperPB, pulumirpc.language.GenerateProgramRequest.SourceEntry]) extends _root_.scalapb.lenses.ObjectLens[UpperPB, pulumirpc.language.GenerateProgramRequest.SourceEntry](_l) { + def key: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Predef.String] = field(_.key)((c_, f_) => c_.copy(key = f_)) + def value: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Predef.String] = field(_.value)((c_, f_) => c_.copy(value = f_)) + } + final val KEY_FIELD_NUMBER = 1 + final val VALUE_FIELD_NUMBER = 2 + @transient + implicit val keyValueMapper: _root_.scalapb.TypeMapper[pulumirpc.language.GenerateProgramRequest.SourceEntry, (_root_.scala.Predef.String, _root_.scala.Predef.String)] = + _root_.scalapb.TypeMapper[pulumirpc.language.GenerateProgramRequest.SourceEntry, (_root_.scala.Predef.String, _root_.scala.Predef.String)](__m => (__m.key, __m.value))(__p => pulumirpc.language.GenerateProgramRequest.SourceEntry(__p._1, __p._2)) + def of( + key: _root_.scala.Predef.String, + value: _root_.scala.Predef.String + ): _root_.pulumirpc.language.GenerateProgramRequest.SourceEntry = _root_.pulumirpc.language.GenerateProgramRequest.SourceEntry( + key, + value + ) + // @@protoc_insertion_point(GeneratedMessageCompanion[pulumirpc.GenerateProgramRequest.SourceEntry]) + } + + implicit class GenerateProgramRequestLens[UpperPB](_l: _root_.scalapb.lenses.Lens[UpperPB, pulumirpc.language.GenerateProgramRequest]) extends _root_.scalapb.lenses.ObjectLens[UpperPB, pulumirpc.language.GenerateProgramRequest](_l) { + def source: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.collection.immutable.Map[_root_.scala.Predef.String, _root_.scala.Predef.String]] = field(_.source)((c_, f_) => c_.copy(source = f_)) + def loaderTarget: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Predef.String] = field(_.loaderTarget)((c_, f_) => c_.copy(loaderTarget = f_)) + } + final val SOURCE_FIELD_NUMBER = 1 + final val LOADER_TARGET_FIELD_NUMBER = 2 + @transient + private[language] val _typemapper_source: _root_.scalapb.TypeMapper[pulumirpc.language.GenerateProgramRequest.SourceEntry, (_root_.scala.Predef.String, _root_.scala.Predef.String)] = implicitly[_root_.scalapb.TypeMapper[pulumirpc.language.GenerateProgramRequest.SourceEntry, (_root_.scala.Predef.String, _root_.scala.Predef.String)]] + def of( + source: _root_.scala.collection.immutable.Map[_root_.scala.Predef.String, _root_.scala.Predef.String], + loaderTarget: _root_.scala.Predef.String + ): _root_.pulumirpc.language.GenerateProgramRequest = _root_.pulumirpc.language.GenerateProgramRequest( + source, + loaderTarget + ) + // @@protoc_insertion_point(GeneratedMessageCompanion[pulumirpc.GenerateProgramRequest]) +} diff --git a/core/src/main/scala/besom/rpc/pulumirpc/language/GenerateProgramResponse.scala b/core/src/main/scala/besom/rpc/pulumirpc/language/GenerateProgramResponse.scala new file mode 100644 index 00000000..f32fa233 --- /dev/null +++ b/core/src/main/scala/besom/rpc/pulumirpc/language/GenerateProgramResponse.scala @@ -0,0 +1,302 @@ +// Generated by the Scala Plugin for the Protocol Buffer Compiler. +// Do not edit! +// +// Protofile syntax: PROTO3 + +package pulumirpc.language + +/** @param diagnostics + * any diagnostics from code generation. + * @param source + * the generated program source code. + */ +@SerialVersionUID(0L) +final case class GenerateProgramResponse( + diagnostics: _root_.scala.Seq[pulumirpc.codegen.hcl.Diagnostic] = _root_.scala.Seq.empty, + source: _root_.scala.collection.immutable.Map[_root_.scala.Predef.String, _root_.com.google.protobuf.ByteString] = _root_.scala.collection.immutable.Map.empty, + unknownFields: _root_.scalapb.UnknownFieldSet = _root_.scalapb.UnknownFieldSet.empty + ) extends scalapb.GeneratedMessage with scalapb.lenses.Updatable[GenerateProgramResponse] { + @transient + private[this] var __serializedSizeMemoized: _root_.scala.Int = 0 + private[this] def __computeSerializedSize(): _root_.scala.Int = { + var __size = 0 + diagnostics.foreach { __item => + val __value = __item + __size += 1 + _root_.com.google.protobuf.CodedOutputStream.computeUInt32SizeNoTag(__value.serializedSize) + __value.serializedSize + } + source.foreach { __item => + val __value = pulumirpc.language.GenerateProgramResponse._typemapper_source.toBase(__item) + __size += 1 + _root_.com.google.protobuf.CodedOutputStream.computeUInt32SizeNoTag(__value.serializedSize) + __value.serializedSize + } + __size += unknownFields.serializedSize + __size + } + override def serializedSize: _root_.scala.Int = { + var __size = __serializedSizeMemoized + if (__size == 0) { + __size = __computeSerializedSize() + 1 + __serializedSizeMemoized = __size + } + __size - 1 + + } + def writeTo(`_output__`: _root_.com.google.protobuf.CodedOutputStream): _root_.scala.Unit = { + diagnostics.foreach { __v => + val __m = __v + _output__.writeTag(1, 2) + _output__.writeUInt32NoTag(__m.serializedSize) + __m.writeTo(_output__) + }; + source.foreach { __v => + val __m = pulumirpc.language.GenerateProgramResponse._typemapper_source.toBase(__v) + _output__.writeTag(2, 2) + _output__.writeUInt32NoTag(__m.serializedSize) + __m.writeTo(_output__) + }; + unknownFields.writeTo(_output__) + } + def clearDiagnostics = copy(diagnostics = _root_.scala.Seq.empty) + def addDiagnostics(__vs: pulumirpc.codegen.hcl.Diagnostic *): GenerateProgramResponse = addAllDiagnostics(__vs) + def addAllDiagnostics(__vs: Iterable[pulumirpc.codegen.hcl.Diagnostic]): GenerateProgramResponse = copy(diagnostics = diagnostics ++ __vs) + def withDiagnostics(__v: _root_.scala.Seq[pulumirpc.codegen.hcl.Diagnostic]): GenerateProgramResponse = copy(diagnostics = __v) + def clearSource = copy(source = _root_.scala.collection.immutable.Map.empty) + def addSource(__vs: (_root_.scala.Predef.String, _root_.com.google.protobuf.ByteString) *): GenerateProgramResponse = addAllSource(__vs) + def addAllSource(__vs: Iterable[(_root_.scala.Predef.String, _root_.com.google.protobuf.ByteString)]): GenerateProgramResponse = copy(source = source ++ __vs) + def withSource(__v: _root_.scala.collection.immutable.Map[_root_.scala.Predef.String, _root_.com.google.protobuf.ByteString]): GenerateProgramResponse = copy(source = __v) + def withUnknownFields(__v: _root_.scalapb.UnknownFieldSet) = copy(unknownFields = __v) + def discardUnknownFields = copy(unknownFields = _root_.scalapb.UnknownFieldSet.empty) + def getFieldByNumber(__fieldNumber: _root_.scala.Int): _root_.scala.Any = { + (__fieldNumber: @_root_.scala.unchecked) match { + case 1 => diagnostics + case 2 => source.iterator.map(pulumirpc.language.GenerateProgramResponse._typemapper_source.toBase(_)).toSeq + } + } + def getField(__field: _root_.scalapb.descriptors.FieldDescriptor): _root_.scalapb.descriptors.PValue = { + _root_.scala.Predef.require(__field.containingMessage eq companion.scalaDescriptor) + (__field.number: @_root_.scala.unchecked) match { + case 1 => _root_.scalapb.descriptors.PRepeated(diagnostics.iterator.map(_.toPMessage).toVector) + case 2 => _root_.scalapb.descriptors.PRepeated(source.iterator.map(pulumirpc.language.GenerateProgramResponse._typemapper_source.toBase(_).toPMessage).toVector) + } + } + def toProtoString: _root_.scala.Predef.String = _root_.scalapb.TextFormat.printToUnicodeString(this) + def companion: pulumirpc.language.GenerateProgramResponse.type = pulumirpc.language.GenerateProgramResponse + // @@protoc_insertion_point(GeneratedMessage[pulumirpc.GenerateProgramResponse]) +} + +object GenerateProgramResponse extends scalapb.GeneratedMessageCompanion[pulumirpc.language.GenerateProgramResponse] { + implicit def messageCompanion: scalapb.GeneratedMessageCompanion[pulumirpc.language.GenerateProgramResponse] = this + def parseFrom(`_input__`: _root_.com.google.protobuf.CodedInputStream): pulumirpc.language.GenerateProgramResponse = { + val __diagnostics: _root_.scala.collection.immutable.VectorBuilder[pulumirpc.codegen.hcl.Diagnostic] = new _root_.scala.collection.immutable.VectorBuilder[pulumirpc.codegen.hcl.Diagnostic] + val __source: _root_.scala.collection.mutable.Builder[(_root_.scala.Predef.String, _root_.com.google.protobuf.ByteString), _root_.scala.collection.immutable.Map[_root_.scala.Predef.String, _root_.com.google.protobuf.ByteString]] = _root_.scala.collection.immutable.Map.newBuilder[_root_.scala.Predef.String, _root_.com.google.protobuf.ByteString] + var `_unknownFields__`: _root_.scalapb.UnknownFieldSet.Builder = null + var _done__ = false + while (!_done__) { + val _tag__ = _input__.readTag() + _tag__ match { + case 0 => _done__ = true + case 10 => + __diagnostics += _root_.scalapb.LiteParser.readMessage[pulumirpc.codegen.hcl.Diagnostic](_input__) + case 18 => + __source += pulumirpc.language.GenerateProgramResponse._typemapper_source.toCustom(_root_.scalapb.LiteParser.readMessage[pulumirpc.language.GenerateProgramResponse.SourceEntry](_input__)) + case tag => + if (_unknownFields__ == null) { + _unknownFields__ = new _root_.scalapb.UnknownFieldSet.Builder() + } + _unknownFields__.parseField(tag, _input__) + } + } + pulumirpc.language.GenerateProgramResponse( + diagnostics = __diagnostics.result(), + source = __source.result(), + unknownFields = if (_unknownFields__ == null) _root_.scalapb.UnknownFieldSet.empty else _unknownFields__.result() + ) + } + implicit def messageReads: _root_.scalapb.descriptors.Reads[pulumirpc.language.GenerateProgramResponse] = _root_.scalapb.descriptors.Reads{ + case _root_.scalapb.descriptors.PMessage(__fieldsMap) => + _root_.scala.Predef.require(__fieldsMap.keys.forall(_.containingMessage eq scalaDescriptor), "FieldDescriptor does not match message type.") + pulumirpc.language.GenerateProgramResponse( + diagnostics = __fieldsMap.get(scalaDescriptor.findFieldByNumber(1).get).map(_.as[_root_.scala.Seq[pulumirpc.codegen.hcl.Diagnostic]]).getOrElse(_root_.scala.Seq.empty), + source = __fieldsMap.get(scalaDescriptor.findFieldByNumber(2).get).map(_.as[_root_.scala.Seq[pulumirpc.language.GenerateProgramResponse.SourceEntry]]).getOrElse(_root_.scala.Seq.empty).iterator.map(pulumirpc.language.GenerateProgramResponse._typemapper_source.toCustom(_)).toMap + ) + case _ => throw new RuntimeException("Expected PMessage") + } + def javaDescriptor: _root_.com.google.protobuf.Descriptors.Descriptor = LanguageProto.javaDescriptor.getMessageTypes().get(14) + def scalaDescriptor: _root_.scalapb.descriptors.Descriptor = LanguageProto.scalaDescriptor.messages(14) + def messageCompanionForFieldNumber(__number: _root_.scala.Int): _root_.scalapb.GeneratedMessageCompanion[_] = { + var __out: _root_.scalapb.GeneratedMessageCompanion[_] = null + (__number: @_root_.scala.unchecked) match { + case 1 => __out = pulumirpc.codegen.hcl.Diagnostic + case 2 => __out = pulumirpc.language.GenerateProgramResponse.SourceEntry + } + __out + } + lazy val nestedMessagesCompanions: Seq[_root_.scalapb.GeneratedMessageCompanion[_ <: _root_.scalapb.GeneratedMessage]] = + Seq[_root_.scalapb.GeneratedMessageCompanion[_ <: _root_.scalapb.GeneratedMessage]]( + _root_.pulumirpc.language.GenerateProgramResponse.SourceEntry + ) + def enumCompanionForFieldNumber(__fieldNumber: _root_.scala.Int): _root_.scalapb.GeneratedEnumCompanion[_] = throw new MatchError(__fieldNumber) + lazy val defaultInstance = pulumirpc.language.GenerateProgramResponse( + diagnostics = _root_.scala.Seq.empty, + source = _root_.scala.collection.immutable.Map.empty + ) + @SerialVersionUID(0L) + final case class SourceEntry( + key: _root_.scala.Predef.String = "", + value: _root_.com.google.protobuf.ByteString = _root_.com.google.protobuf.ByteString.EMPTY, + unknownFields: _root_.scalapb.UnknownFieldSet = _root_.scalapb.UnknownFieldSet.empty + ) extends scalapb.GeneratedMessage with scalapb.lenses.Updatable[SourceEntry] { + @transient + private[this] var __serializedSizeMemoized: _root_.scala.Int = 0 + private[this] def __computeSerializedSize(): _root_.scala.Int = { + var __size = 0 + + { + val __value = key + if (!__value.isEmpty) { + __size += _root_.com.google.protobuf.CodedOutputStream.computeStringSize(1, __value) + } + }; + + { + val __value = value + if (!__value.isEmpty) { + __size += _root_.com.google.protobuf.CodedOutputStream.computeBytesSize(2, __value) + } + }; + __size += unknownFields.serializedSize + __size + } + override def serializedSize: _root_.scala.Int = { + var __size = __serializedSizeMemoized + if (__size == 0) { + __size = __computeSerializedSize() + 1 + __serializedSizeMemoized = __size + } + __size - 1 + + } + def writeTo(`_output__`: _root_.com.google.protobuf.CodedOutputStream): _root_.scala.Unit = { + { + val __v = key + if (!__v.isEmpty) { + _output__.writeString(1, __v) + } + }; + { + val __v = value + if (!__v.isEmpty) { + _output__.writeBytes(2, __v) + } + }; + unknownFields.writeTo(_output__) + } + def withKey(__v: _root_.scala.Predef.String): SourceEntry = copy(key = __v) + def withValue(__v: _root_.com.google.protobuf.ByteString): SourceEntry = copy(value = __v) + def withUnknownFields(__v: _root_.scalapb.UnknownFieldSet) = copy(unknownFields = __v) + def discardUnknownFields = copy(unknownFields = _root_.scalapb.UnknownFieldSet.empty) + def getFieldByNumber(__fieldNumber: _root_.scala.Int): _root_.scala.Any = { + (__fieldNumber: @_root_.scala.unchecked) match { + case 1 => { + val __t = key + if (__t != "") __t else null + } + case 2 => { + val __t = value + if (__t != _root_.com.google.protobuf.ByteString.EMPTY) __t else null + } + } + } + def getField(__field: _root_.scalapb.descriptors.FieldDescriptor): _root_.scalapb.descriptors.PValue = { + _root_.scala.Predef.require(__field.containingMessage eq companion.scalaDescriptor) + (__field.number: @_root_.scala.unchecked) match { + case 1 => _root_.scalapb.descriptors.PString(key) + case 2 => _root_.scalapb.descriptors.PByteString(value) + } + } + def toProtoString: _root_.scala.Predef.String = _root_.scalapb.TextFormat.printToUnicodeString(this) + def companion: pulumirpc.language.GenerateProgramResponse.SourceEntry.type = pulumirpc.language.GenerateProgramResponse.SourceEntry + // @@protoc_insertion_point(GeneratedMessage[pulumirpc.GenerateProgramResponse.SourceEntry]) + } + + object SourceEntry extends scalapb.GeneratedMessageCompanion[pulumirpc.language.GenerateProgramResponse.SourceEntry] { + implicit def messageCompanion: scalapb.GeneratedMessageCompanion[pulumirpc.language.GenerateProgramResponse.SourceEntry] = this + def parseFrom(`_input__`: _root_.com.google.protobuf.CodedInputStream): pulumirpc.language.GenerateProgramResponse.SourceEntry = { + var __key: _root_.scala.Predef.String = "" + var __value: _root_.com.google.protobuf.ByteString = _root_.com.google.protobuf.ByteString.EMPTY + var `_unknownFields__`: _root_.scalapb.UnknownFieldSet.Builder = null + var _done__ = false + while (!_done__) { + val _tag__ = _input__.readTag() + _tag__ match { + case 0 => _done__ = true + case 10 => + __key = _input__.readStringRequireUtf8() + case 18 => + __value = _input__.readBytes() + case tag => + if (_unknownFields__ == null) { + _unknownFields__ = new _root_.scalapb.UnknownFieldSet.Builder() + } + _unknownFields__.parseField(tag, _input__) + } + } + pulumirpc.language.GenerateProgramResponse.SourceEntry( + key = __key, + value = __value, + unknownFields = if (_unknownFields__ == null) _root_.scalapb.UnknownFieldSet.empty else _unknownFields__.result() + ) + } + implicit def messageReads: _root_.scalapb.descriptors.Reads[pulumirpc.language.GenerateProgramResponse.SourceEntry] = _root_.scalapb.descriptors.Reads{ + case _root_.scalapb.descriptors.PMessage(__fieldsMap) => + _root_.scala.Predef.require(__fieldsMap.keys.forall(_.containingMessage eq scalaDescriptor), "FieldDescriptor does not match message type.") + pulumirpc.language.GenerateProgramResponse.SourceEntry( + key = __fieldsMap.get(scalaDescriptor.findFieldByNumber(1).get).map(_.as[_root_.scala.Predef.String]).getOrElse(""), + value = __fieldsMap.get(scalaDescriptor.findFieldByNumber(2).get).map(_.as[_root_.com.google.protobuf.ByteString]).getOrElse(_root_.com.google.protobuf.ByteString.EMPTY) + ) + case _ => throw new RuntimeException("Expected PMessage") + } + def javaDescriptor: _root_.com.google.protobuf.Descriptors.Descriptor = pulumirpc.language.GenerateProgramResponse.javaDescriptor.getNestedTypes().get(0) + def scalaDescriptor: _root_.scalapb.descriptors.Descriptor = pulumirpc.language.GenerateProgramResponse.scalaDescriptor.nestedMessages(0) + def messageCompanionForFieldNumber(__number: _root_.scala.Int): _root_.scalapb.GeneratedMessageCompanion[_] = throw new MatchError(__number) + lazy val nestedMessagesCompanions: Seq[_root_.scalapb.GeneratedMessageCompanion[_ <: _root_.scalapb.GeneratedMessage]] = Seq.empty + def enumCompanionForFieldNumber(__fieldNumber: _root_.scala.Int): _root_.scalapb.GeneratedEnumCompanion[_] = throw new MatchError(__fieldNumber) + lazy val defaultInstance = pulumirpc.language.GenerateProgramResponse.SourceEntry( + key = "", + value = _root_.com.google.protobuf.ByteString.EMPTY + ) + implicit class SourceEntryLens[UpperPB](_l: _root_.scalapb.lenses.Lens[UpperPB, pulumirpc.language.GenerateProgramResponse.SourceEntry]) extends _root_.scalapb.lenses.ObjectLens[UpperPB, pulumirpc.language.GenerateProgramResponse.SourceEntry](_l) { + def key: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Predef.String] = field(_.key)((c_, f_) => c_.copy(key = f_)) + def value: _root_.scalapb.lenses.Lens[UpperPB, _root_.com.google.protobuf.ByteString] = field(_.value)((c_, f_) => c_.copy(value = f_)) + } + final val KEY_FIELD_NUMBER = 1 + final val VALUE_FIELD_NUMBER = 2 + @transient + implicit val keyValueMapper: _root_.scalapb.TypeMapper[pulumirpc.language.GenerateProgramResponse.SourceEntry, (_root_.scala.Predef.String, _root_.com.google.protobuf.ByteString)] = + _root_.scalapb.TypeMapper[pulumirpc.language.GenerateProgramResponse.SourceEntry, (_root_.scala.Predef.String, _root_.com.google.protobuf.ByteString)](__m => (__m.key, __m.value))(__p => pulumirpc.language.GenerateProgramResponse.SourceEntry(__p._1, __p._2)) + def of( + key: _root_.scala.Predef.String, + value: _root_.com.google.protobuf.ByteString + ): _root_.pulumirpc.language.GenerateProgramResponse.SourceEntry = _root_.pulumirpc.language.GenerateProgramResponse.SourceEntry( + key, + value + ) + // @@protoc_insertion_point(GeneratedMessageCompanion[pulumirpc.GenerateProgramResponse.SourceEntry]) + } + + implicit class GenerateProgramResponseLens[UpperPB](_l: _root_.scalapb.lenses.Lens[UpperPB, pulumirpc.language.GenerateProgramResponse]) extends _root_.scalapb.lenses.ObjectLens[UpperPB, pulumirpc.language.GenerateProgramResponse](_l) { + def diagnostics: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Seq[pulumirpc.codegen.hcl.Diagnostic]] = field(_.diagnostics)((c_, f_) => c_.copy(diagnostics = f_)) + def source: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.collection.immutable.Map[_root_.scala.Predef.String, _root_.com.google.protobuf.ByteString]] = field(_.source)((c_, f_) => c_.copy(source = f_)) + } + final val DIAGNOSTICS_FIELD_NUMBER = 1 + final val SOURCE_FIELD_NUMBER = 2 + @transient + private[language] val _typemapper_source: _root_.scalapb.TypeMapper[pulumirpc.language.GenerateProgramResponse.SourceEntry, (_root_.scala.Predef.String, _root_.com.google.protobuf.ByteString)] = implicitly[_root_.scalapb.TypeMapper[pulumirpc.language.GenerateProgramResponse.SourceEntry, (_root_.scala.Predef.String, _root_.com.google.protobuf.ByteString)]] + def of( + diagnostics: _root_.scala.Seq[pulumirpc.codegen.hcl.Diagnostic], + source: _root_.scala.collection.immutable.Map[_root_.scala.Predef.String, _root_.com.google.protobuf.ByteString] + ): _root_.pulumirpc.language.GenerateProgramResponse = _root_.pulumirpc.language.GenerateProgramResponse( + diagnostics, + source + ) + // @@protoc_insertion_point(GeneratedMessageCompanion[pulumirpc.GenerateProgramResponse]) +} diff --git a/core/src/main/scala/besom/rpc/pulumirpc/language/GenerateProjectRequest.scala b/core/src/main/scala/besom/rpc/pulumirpc/language/GenerateProjectRequest.scala new file mode 100644 index 00000000..f75bbb2e --- /dev/null +++ b/core/src/main/scala/besom/rpc/pulumirpc/language/GenerateProjectRequest.scala @@ -0,0 +1,433 @@ +// Generated by the Scala Plugin for the Protocol Buffer Compiler. +// Do not edit! +// +// Protofile syntax: PROTO3 + +package pulumirpc.language + +/** @param sourceDirectory + * the directory to generate the project from. + * @param targetDirectory + * the directory to generate the project in. + * @param project + * the JSON-encoded pulumi project file. + * @param strict + * if PCL binding should be strict or not. + * @param loaderTarget + * The target of a codegen.LoaderServer to use for loading schemas. + * @param localDependencies + * local dependencies to use instead of using the package system. This is a map of package name to a local + * path of a language specific artifact to use for the SDK for that package. + */ +@SerialVersionUID(0L) +final case class GenerateProjectRequest( + sourceDirectory: _root_.scala.Predef.String = "", + targetDirectory: _root_.scala.Predef.String = "", + project: _root_.scala.Predef.String = "", + strict: _root_.scala.Boolean = false, + loaderTarget: _root_.scala.Predef.String = "", + localDependencies: _root_.scala.collection.immutable.Map[_root_.scala.Predef.String, _root_.scala.Predef.String] = _root_.scala.collection.immutable.Map.empty, + unknownFields: _root_.scalapb.UnknownFieldSet = _root_.scalapb.UnknownFieldSet.empty + ) extends scalapb.GeneratedMessage with scalapb.lenses.Updatable[GenerateProjectRequest] { + @transient + private[this] var __serializedSizeMemoized: _root_.scala.Int = 0 + private[this] def __computeSerializedSize(): _root_.scala.Int = { + var __size = 0 + + { + val __value = sourceDirectory + if (!__value.isEmpty) { + __size += _root_.com.google.protobuf.CodedOutputStream.computeStringSize(1, __value) + } + }; + + { + val __value = targetDirectory + if (!__value.isEmpty) { + __size += _root_.com.google.protobuf.CodedOutputStream.computeStringSize(2, __value) + } + }; + + { + val __value = project + if (!__value.isEmpty) { + __size += _root_.com.google.protobuf.CodedOutputStream.computeStringSize(3, __value) + } + }; + + { + val __value = strict + if (__value != false) { + __size += _root_.com.google.protobuf.CodedOutputStream.computeBoolSize(4, __value) + } + }; + + { + val __value = loaderTarget + if (!__value.isEmpty) { + __size += _root_.com.google.protobuf.CodedOutputStream.computeStringSize(5, __value) + } + }; + localDependencies.foreach { __item => + val __value = pulumirpc.language.GenerateProjectRequest._typemapper_localDependencies.toBase(__item) + __size += 1 + _root_.com.google.protobuf.CodedOutputStream.computeUInt32SizeNoTag(__value.serializedSize) + __value.serializedSize + } + __size += unknownFields.serializedSize + __size + } + override def serializedSize: _root_.scala.Int = { + var __size = __serializedSizeMemoized + if (__size == 0) { + __size = __computeSerializedSize() + 1 + __serializedSizeMemoized = __size + } + __size - 1 + + } + def writeTo(`_output__`: _root_.com.google.protobuf.CodedOutputStream): _root_.scala.Unit = { + { + val __v = sourceDirectory + if (!__v.isEmpty) { + _output__.writeString(1, __v) + } + }; + { + val __v = targetDirectory + if (!__v.isEmpty) { + _output__.writeString(2, __v) + } + }; + { + val __v = project + if (!__v.isEmpty) { + _output__.writeString(3, __v) + } + }; + { + val __v = strict + if (__v != false) { + _output__.writeBool(4, __v) + } + }; + { + val __v = loaderTarget + if (!__v.isEmpty) { + _output__.writeString(5, __v) + } + }; + localDependencies.foreach { __v => + val __m = pulumirpc.language.GenerateProjectRequest._typemapper_localDependencies.toBase(__v) + _output__.writeTag(6, 2) + _output__.writeUInt32NoTag(__m.serializedSize) + __m.writeTo(_output__) + }; + unknownFields.writeTo(_output__) + } + def withSourceDirectory(__v: _root_.scala.Predef.String): GenerateProjectRequest = copy(sourceDirectory = __v) + def withTargetDirectory(__v: _root_.scala.Predef.String): GenerateProjectRequest = copy(targetDirectory = __v) + def withProject(__v: _root_.scala.Predef.String): GenerateProjectRequest = copy(project = __v) + def withStrict(__v: _root_.scala.Boolean): GenerateProjectRequest = copy(strict = __v) + def withLoaderTarget(__v: _root_.scala.Predef.String): GenerateProjectRequest = copy(loaderTarget = __v) + def clearLocalDependencies = copy(localDependencies = _root_.scala.collection.immutable.Map.empty) + def addLocalDependencies(__vs: (_root_.scala.Predef.String, _root_.scala.Predef.String) *): GenerateProjectRequest = addAllLocalDependencies(__vs) + def addAllLocalDependencies(__vs: Iterable[(_root_.scala.Predef.String, _root_.scala.Predef.String)]): GenerateProjectRequest = copy(localDependencies = localDependencies ++ __vs) + def withLocalDependencies(__v: _root_.scala.collection.immutable.Map[_root_.scala.Predef.String, _root_.scala.Predef.String]): GenerateProjectRequest = copy(localDependencies = __v) + def withUnknownFields(__v: _root_.scalapb.UnknownFieldSet) = copy(unknownFields = __v) + def discardUnknownFields = copy(unknownFields = _root_.scalapb.UnknownFieldSet.empty) + def getFieldByNumber(__fieldNumber: _root_.scala.Int): _root_.scala.Any = { + (__fieldNumber: @_root_.scala.unchecked) match { + case 1 => { + val __t = sourceDirectory + if (__t != "") __t else null + } + case 2 => { + val __t = targetDirectory + if (__t != "") __t else null + } + case 3 => { + val __t = project + if (__t != "") __t else null + } + case 4 => { + val __t = strict + if (__t != false) __t else null + } + case 5 => { + val __t = loaderTarget + if (__t != "") __t else null + } + case 6 => localDependencies.iterator.map(pulumirpc.language.GenerateProjectRequest._typemapper_localDependencies.toBase(_)).toSeq + } + } + def getField(__field: _root_.scalapb.descriptors.FieldDescriptor): _root_.scalapb.descriptors.PValue = { + _root_.scala.Predef.require(__field.containingMessage eq companion.scalaDescriptor) + (__field.number: @_root_.scala.unchecked) match { + case 1 => _root_.scalapb.descriptors.PString(sourceDirectory) + case 2 => _root_.scalapb.descriptors.PString(targetDirectory) + case 3 => _root_.scalapb.descriptors.PString(project) + case 4 => _root_.scalapb.descriptors.PBoolean(strict) + case 5 => _root_.scalapb.descriptors.PString(loaderTarget) + case 6 => _root_.scalapb.descriptors.PRepeated(localDependencies.iterator.map(pulumirpc.language.GenerateProjectRequest._typemapper_localDependencies.toBase(_).toPMessage).toVector) + } + } + def toProtoString: _root_.scala.Predef.String = _root_.scalapb.TextFormat.printToUnicodeString(this) + def companion: pulumirpc.language.GenerateProjectRequest.type = pulumirpc.language.GenerateProjectRequest + // @@protoc_insertion_point(GeneratedMessage[pulumirpc.GenerateProjectRequest]) +} + +object GenerateProjectRequest extends scalapb.GeneratedMessageCompanion[pulumirpc.language.GenerateProjectRequest] { + implicit def messageCompanion: scalapb.GeneratedMessageCompanion[pulumirpc.language.GenerateProjectRequest] = this + def parseFrom(`_input__`: _root_.com.google.protobuf.CodedInputStream): pulumirpc.language.GenerateProjectRequest = { + var __sourceDirectory: _root_.scala.Predef.String = "" + var __targetDirectory: _root_.scala.Predef.String = "" + var __project: _root_.scala.Predef.String = "" + var __strict: _root_.scala.Boolean = false + var __loaderTarget: _root_.scala.Predef.String = "" + val __localDependencies: _root_.scala.collection.mutable.Builder[(_root_.scala.Predef.String, _root_.scala.Predef.String), _root_.scala.collection.immutable.Map[_root_.scala.Predef.String, _root_.scala.Predef.String]] = _root_.scala.collection.immutable.Map.newBuilder[_root_.scala.Predef.String, _root_.scala.Predef.String] + var `_unknownFields__`: _root_.scalapb.UnknownFieldSet.Builder = null + var _done__ = false + while (!_done__) { + val _tag__ = _input__.readTag() + _tag__ match { + case 0 => _done__ = true + case 10 => + __sourceDirectory = _input__.readStringRequireUtf8() + case 18 => + __targetDirectory = _input__.readStringRequireUtf8() + case 26 => + __project = _input__.readStringRequireUtf8() + case 32 => + __strict = _input__.readBool() + case 42 => + __loaderTarget = _input__.readStringRequireUtf8() + case 50 => + __localDependencies += pulumirpc.language.GenerateProjectRequest._typemapper_localDependencies.toCustom(_root_.scalapb.LiteParser.readMessage[pulumirpc.language.GenerateProjectRequest.LocalDependenciesEntry](_input__)) + case tag => + if (_unknownFields__ == null) { + _unknownFields__ = new _root_.scalapb.UnknownFieldSet.Builder() + } + _unknownFields__.parseField(tag, _input__) + } + } + pulumirpc.language.GenerateProjectRequest( + sourceDirectory = __sourceDirectory, + targetDirectory = __targetDirectory, + project = __project, + strict = __strict, + loaderTarget = __loaderTarget, + localDependencies = __localDependencies.result(), + unknownFields = if (_unknownFields__ == null) _root_.scalapb.UnknownFieldSet.empty else _unknownFields__.result() + ) + } + implicit def messageReads: _root_.scalapb.descriptors.Reads[pulumirpc.language.GenerateProjectRequest] = _root_.scalapb.descriptors.Reads{ + case _root_.scalapb.descriptors.PMessage(__fieldsMap) => + _root_.scala.Predef.require(__fieldsMap.keys.forall(_.containingMessage eq scalaDescriptor), "FieldDescriptor does not match message type.") + pulumirpc.language.GenerateProjectRequest( + sourceDirectory = __fieldsMap.get(scalaDescriptor.findFieldByNumber(1).get).map(_.as[_root_.scala.Predef.String]).getOrElse(""), + targetDirectory = __fieldsMap.get(scalaDescriptor.findFieldByNumber(2).get).map(_.as[_root_.scala.Predef.String]).getOrElse(""), + project = __fieldsMap.get(scalaDescriptor.findFieldByNumber(3).get).map(_.as[_root_.scala.Predef.String]).getOrElse(""), + strict = __fieldsMap.get(scalaDescriptor.findFieldByNumber(4).get).map(_.as[_root_.scala.Boolean]).getOrElse(false), + loaderTarget = __fieldsMap.get(scalaDescriptor.findFieldByNumber(5).get).map(_.as[_root_.scala.Predef.String]).getOrElse(""), + localDependencies = __fieldsMap.get(scalaDescriptor.findFieldByNumber(6).get).map(_.as[_root_.scala.Seq[pulumirpc.language.GenerateProjectRequest.LocalDependenciesEntry]]).getOrElse(_root_.scala.Seq.empty).iterator.map(pulumirpc.language.GenerateProjectRequest._typemapper_localDependencies.toCustom(_)).toMap + ) + case _ => throw new RuntimeException("Expected PMessage") + } + def javaDescriptor: _root_.com.google.protobuf.Descriptors.Descriptor = LanguageProto.javaDescriptor.getMessageTypes().get(15) + def scalaDescriptor: _root_.scalapb.descriptors.Descriptor = LanguageProto.scalaDescriptor.messages(15) + def messageCompanionForFieldNumber(__number: _root_.scala.Int): _root_.scalapb.GeneratedMessageCompanion[_] = { + var __out: _root_.scalapb.GeneratedMessageCompanion[_] = null + (__number: @_root_.scala.unchecked) match { + case 6 => __out = pulumirpc.language.GenerateProjectRequest.LocalDependenciesEntry + } + __out + } + lazy val nestedMessagesCompanions: Seq[_root_.scalapb.GeneratedMessageCompanion[_ <: _root_.scalapb.GeneratedMessage]] = + Seq[_root_.scalapb.GeneratedMessageCompanion[_ <: _root_.scalapb.GeneratedMessage]]( + _root_.pulumirpc.language.GenerateProjectRequest.LocalDependenciesEntry + ) + def enumCompanionForFieldNumber(__fieldNumber: _root_.scala.Int): _root_.scalapb.GeneratedEnumCompanion[_] = throw new MatchError(__fieldNumber) + lazy val defaultInstance = pulumirpc.language.GenerateProjectRequest( + sourceDirectory = "", + targetDirectory = "", + project = "", + strict = false, + loaderTarget = "", + localDependencies = _root_.scala.collection.immutable.Map.empty + ) + @SerialVersionUID(0L) + final case class LocalDependenciesEntry( + key: _root_.scala.Predef.String = "", + value: _root_.scala.Predef.String = "", + unknownFields: _root_.scalapb.UnknownFieldSet = _root_.scalapb.UnknownFieldSet.empty + ) extends scalapb.GeneratedMessage with scalapb.lenses.Updatable[LocalDependenciesEntry] { + @transient + private[this] var __serializedSizeMemoized: _root_.scala.Int = 0 + private[this] def __computeSerializedSize(): _root_.scala.Int = { + var __size = 0 + + { + val __value = key + if (!__value.isEmpty) { + __size += _root_.com.google.protobuf.CodedOutputStream.computeStringSize(1, __value) + } + }; + + { + val __value = value + if (!__value.isEmpty) { + __size += _root_.com.google.protobuf.CodedOutputStream.computeStringSize(2, __value) + } + }; + __size += unknownFields.serializedSize + __size + } + override def serializedSize: _root_.scala.Int = { + var __size = __serializedSizeMemoized + if (__size == 0) { + __size = __computeSerializedSize() + 1 + __serializedSizeMemoized = __size + } + __size - 1 + + } + def writeTo(`_output__`: _root_.com.google.protobuf.CodedOutputStream): _root_.scala.Unit = { + { + val __v = key + if (!__v.isEmpty) { + _output__.writeString(1, __v) + } + }; + { + val __v = value + if (!__v.isEmpty) { + _output__.writeString(2, __v) + } + }; + unknownFields.writeTo(_output__) + } + def withKey(__v: _root_.scala.Predef.String): LocalDependenciesEntry = copy(key = __v) + def withValue(__v: _root_.scala.Predef.String): LocalDependenciesEntry = copy(value = __v) + def withUnknownFields(__v: _root_.scalapb.UnknownFieldSet) = copy(unknownFields = __v) + def discardUnknownFields = copy(unknownFields = _root_.scalapb.UnknownFieldSet.empty) + def getFieldByNumber(__fieldNumber: _root_.scala.Int): _root_.scala.Any = { + (__fieldNumber: @_root_.scala.unchecked) match { + case 1 => { + val __t = key + if (__t != "") __t else null + } + case 2 => { + val __t = value + if (__t != "") __t else null + } + } + } + def getField(__field: _root_.scalapb.descriptors.FieldDescriptor): _root_.scalapb.descriptors.PValue = { + _root_.scala.Predef.require(__field.containingMessage eq companion.scalaDescriptor) + (__field.number: @_root_.scala.unchecked) match { + case 1 => _root_.scalapb.descriptors.PString(key) + case 2 => _root_.scalapb.descriptors.PString(value) + } + } + def toProtoString: _root_.scala.Predef.String = _root_.scalapb.TextFormat.printToUnicodeString(this) + def companion: pulumirpc.language.GenerateProjectRequest.LocalDependenciesEntry.type = pulumirpc.language.GenerateProjectRequest.LocalDependenciesEntry + // @@protoc_insertion_point(GeneratedMessage[pulumirpc.GenerateProjectRequest.LocalDependenciesEntry]) + } + + object LocalDependenciesEntry extends scalapb.GeneratedMessageCompanion[pulumirpc.language.GenerateProjectRequest.LocalDependenciesEntry] { + implicit def messageCompanion: scalapb.GeneratedMessageCompanion[pulumirpc.language.GenerateProjectRequest.LocalDependenciesEntry] = this + def parseFrom(`_input__`: _root_.com.google.protobuf.CodedInputStream): pulumirpc.language.GenerateProjectRequest.LocalDependenciesEntry = { + var __key: _root_.scala.Predef.String = "" + var __value: _root_.scala.Predef.String = "" + var `_unknownFields__`: _root_.scalapb.UnknownFieldSet.Builder = null + var _done__ = false + while (!_done__) { + val _tag__ = _input__.readTag() + _tag__ match { + case 0 => _done__ = true + case 10 => + __key = _input__.readStringRequireUtf8() + case 18 => + __value = _input__.readStringRequireUtf8() + case tag => + if (_unknownFields__ == null) { + _unknownFields__ = new _root_.scalapb.UnknownFieldSet.Builder() + } + _unknownFields__.parseField(tag, _input__) + } + } + pulumirpc.language.GenerateProjectRequest.LocalDependenciesEntry( + key = __key, + value = __value, + unknownFields = if (_unknownFields__ == null) _root_.scalapb.UnknownFieldSet.empty else _unknownFields__.result() + ) + } + implicit def messageReads: _root_.scalapb.descriptors.Reads[pulumirpc.language.GenerateProjectRequest.LocalDependenciesEntry] = _root_.scalapb.descriptors.Reads{ + case _root_.scalapb.descriptors.PMessage(__fieldsMap) => + _root_.scala.Predef.require(__fieldsMap.keys.forall(_.containingMessage eq scalaDescriptor), "FieldDescriptor does not match message type.") + pulumirpc.language.GenerateProjectRequest.LocalDependenciesEntry( + key = __fieldsMap.get(scalaDescriptor.findFieldByNumber(1).get).map(_.as[_root_.scala.Predef.String]).getOrElse(""), + value = __fieldsMap.get(scalaDescriptor.findFieldByNumber(2).get).map(_.as[_root_.scala.Predef.String]).getOrElse("") + ) + case _ => throw new RuntimeException("Expected PMessage") + } + def javaDescriptor: _root_.com.google.protobuf.Descriptors.Descriptor = pulumirpc.language.GenerateProjectRequest.javaDescriptor.getNestedTypes().get(0) + def scalaDescriptor: _root_.scalapb.descriptors.Descriptor = pulumirpc.language.GenerateProjectRequest.scalaDescriptor.nestedMessages(0) + def messageCompanionForFieldNumber(__number: _root_.scala.Int): _root_.scalapb.GeneratedMessageCompanion[_] = throw new MatchError(__number) + lazy val nestedMessagesCompanions: Seq[_root_.scalapb.GeneratedMessageCompanion[_ <: _root_.scalapb.GeneratedMessage]] = Seq.empty + def enumCompanionForFieldNumber(__fieldNumber: _root_.scala.Int): _root_.scalapb.GeneratedEnumCompanion[_] = throw new MatchError(__fieldNumber) + lazy val defaultInstance = pulumirpc.language.GenerateProjectRequest.LocalDependenciesEntry( + key = "", + value = "" + ) + implicit class LocalDependenciesEntryLens[UpperPB](_l: _root_.scalapb.lenses.Lens[UpperPB, pulumirpc.language.GenerateProjectRequest.LocalDependenciesEntry]) extends _root_.scalapb.lenses.ObjectLens[UpperPB, pulumirpc.language.GenerateProjectRequest.LocalDependenciesEntry](_l) { + def key: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Predef.String] = field(_.key)((c_, f_) => c_.copy(key = f_)) + def value: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Predef.String] = field(_.value)((c_, f_) => c_.copy(value = f_)) + } + final val KEY_FIELD_NUMBER = 1 + final val VALUE_FIELD_NUMBER = 2 + @transient + implicit val keyValueMapper: _root_.scalapb.TypeMapper[pulumirpc.language.GenerateProjectRequest.LocalDependenciesEntry, (_root_.scala.Predef.String, _root_.scala.Predef.String)] = + _root_.scalapb.TypeMapper[pulumirpc.language.GenerateProjectRequest.LocalDependenciesEntry, (_root_.scala.Predef.String, _root_.scala.Predef.String)](__m => (__m.key, __m.value))(__p => pulumirpc.language.GenerateProjectRequest.LocalDependenciesEntry(__p._1, __p._2)) + def of( + key: _root_.scala.Predef.String, + value: _root_.scala.Predef.String + ): _root_.pulumirpc.language.GenerateProjectRequest.LocalDependenciesEntry = _root_.pulumirpc.language.GenerateProjectRequest.LocalDependenciesEntry( + key, + value + ) + // @@protoc_insertion_point(GeneratedMessageCompanion[pulumirpc.GenerateProjectRequest.LocalDependenciesEntry]) + } + + implicit class GenerateProjectRequestLens[UpperPB](_l: _root_.scalapb.lenses.Lens[UpperPB, pulumirpc.language.GenerateProjectRequest]) extends _root_.scalapb.lenses.ObjectLens[UpperPB, pulumirpc.language.GenerateProjectRequest](_l) { + def sourceDirectory: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Predef.String] = field(_.sourceDirectory)((c_, f_) => c_.copy(sourceDirectory = f_)) + def targetDirectory: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Predef.String] = field(_.targetDirectory)((c_, f_) => c_.copy(targetDirectory = f_)) + def project: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Predef.String] = field(_.project)((c_, f_) => c_.copy(project = f_)) + def strict: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Boolean] = field(_.strict)((c_, f_) => c_.copy(strict = f_)) + def loaderTarget: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Predef.String] = field(_.loaderTarget)((c_, f_) => c_.copy(loaderTarget = f_)) + def localDependencies: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.collection.immutable.Map[_root_.scala.Predef.String, _root_.scala.Predef.String]] = field(_.localDependencies)((c_, f_) => c_.copy(localDependencies = f_)) + } + final val SOURCE_DIRECTORY_FIELD_NUMBER = 1 + final val TARGET_DIRECTORY_FIELD_NUMBER = 2 + final val PROJECT_FIELD_NUMBER = 3 + final val STRICT_FIELD_NUMBER = 4 + final val LOADER_TARGET_FIELD_NUMBER = 5 + final val LOCAL_DEPENDENCIES_FIELD_NUMBER = 6 + @transient + private[language] val _typemapper_localDependencies: _root_.scalapb.TypeMapper[pulumirpc.language.GenerateProjectRequest.LocalDependenciesEntry, (_root_.scala.Predef.String, _root_.scala.Predef.String)] = implicitly[_root_.scalapb.TypeMapper[pulumirpc.language.GenerateProjectRequest.LocalDependenciesEntry, (_root_.scala.Predef.String, _root_.scala.Predef.String)]] + def of( + sourceDirectory: _root_.scala.Predef.String, + targetDirectory: _root_.scala.Predef.String, + project: _root_.scala.Predef.String, + strict: _root_.scala.Boolean, + loaderTarget: _root_.scala.Predef.String, + localDependencies: _root_.scala.collection.immutable.Map[_root_.scala.Predef.String, _root_.scala.Predef.String] + ): _root_.pulumirpc.language.GenerateProjectRequest = _root_.pulumirpc.language.GenerateProjectRequest( + sourceDirectory, + targetDirectory, + project, + strict, + loaderTarget, + localDependencies + ) + // @@protoc_insertion_point(GeneratedMessageCompanion[pulumirpc.GenerateProjectRequest]) +} diff --git a/core/src/main/scala/besom/rpc/pulumirpc/language/GenerateProjectResponse.scala b/core/src/main/scala/besom/rpc/pulumirpc/language/GenerateProjectResponse.scala new file mode 100644 index 00000000..18f3379a --- /dev/null +++ b/core/src/main/scala/besom/rpc/pulumirpc/language/GenerateProjectResponse.scala @@ -0,0 +1,123 @@ +// Generated by the Scala Plugin for the Protocol Buffer Compiler. +// Do not edit! +// +// Protofile syntax: PROTO3 + +package pulumirpc.language + +/** @param diagnostics + * any diagnostics from code generation. + */ +@SerialVersionUID(0L) +final case class GenerateProjectResponse( + diagnostics: _root_.scala.Seq[pulumirpc.codegen.hcl.Diagnostic] = _root_.scala.Seq.empty, + unknownFields: _root_.scalapb.UnknownFieldSet = _root_.scalapb.UnknownFieldSet.empty + ) extends scalapb.GeneratedMessage with scalapb.lenses.Updatable[GenerateProjectResponse] { + @transient + private[this] var __serializedSizeMemoized: _root_.scala.Int = 0 + private[this] def __computeSerializedSize(): _root_.scala.Int = { + var __size = 0 + diagnostics.foreach { __item => + val __value = __item + __size += 1 + _root_.com.google.protobuf.CodedOutputStream.computeUInt32SizeNoTag(__value.serializedSize) + __value.serializedSize + } + __size += unknownFields.serializedSize + __size + } + override def serializedSize: _root_.scala.Int = { + var __size = __serializedSizeMemoized + if (__size == 0) { + __size = __computeSerializedSize() + 1 + __serializedSizeMemoized = __size + } + __size - 1 + + } + def writeTo(`_output__`: _root_.com.google.protobuf.CodedOutputStream): _root_.scala.Unit = { + diagnostics.foreach { __v => + val __m = __v + _output__.writeTag(1, 2) + _output__.writeUInt32NoTag(__m.serializedSize) + __m.writeTo(_output__) + }; + unknownFields.writeTo(_output__) + } + def clearDiagnostics = copy(diagnostics = _root_.scala.Seq.empty) + def addDiagnostics(__vs: pulumirpc.codegen.hcl.Diagnostic *): GenerateProjectResponse = addAllDiagnostics(__vs) + def addAllDiagnostics(__vs: Iterable[pulumirpc.codegen.hcl.Diagnostic]): GenerateProjectResponse = copy(diagnostics = diagnostics ++ __vs) + def withDiagnostics(__v: _root_.scala.Seq[pulumirpc.codegen.hcl.Diagnostic]): GenerateProjectResponse = copy(diagnostics = __v) + def withUnknownFields(__v: _root_.scalapb.UnknownFieldSet) = copy(unknownFields = __v) + def discardUnknownFields = copy(unknownFields = _root_.scalapb.UnknownFieldSet.empty) + def getFieldByNumber(__fieldNumber: _root_.scala.Int): _root_.scala.Any = { + (__fieldNumber: @_root_.scala.unchecked) match { + case 1 => diagnostics + } + } + def getField(__field: _root_.scalapb.descriptors.FieldDescriptor): _root_.scalapb.descriptors.PValue = { + _root_.scala.Predef.require(__field.containingMessage eq companion.scalaDescriptor) + (__field.number: @_root_.scala.unchecked) match { + case 1 => _root_.scalapb.descriptors.PRepeated(diagnostics.iterator.map(_.toPMessage).toVector) + } + } + def toProtoString: _root_.scala.Predef.String = _root_.scalapb.TextFormat.printToUnicodeString(this) + def companion: pulumirpc.language.GenerateProjectResponse.type = pulumirpc.language.GenerateProjectResponse + // @@protoc_insertion_point(GeneratedMessage[pulumirpc.GenerateProjectResponse]) +} + +object GenerateProjectResponse extends scalapb.GeneratedMessageCompanion[pulumirpc.language.GenerateProjectResponse] { + implicit def messageCompanion: scalapb.GeneratedMessageCompanion[pulumirpc.language.GenerateProjectResponse] = this + def parseFrom(`_input__`: _root_.com.google.protobuf.CodedInputStream): pulumirpc.language.GenerateProjectResponse = { + val __diagnostics: _root_.scala.collection.immutable.VectorBuilder[pulumirpc.codegen.hcl.Diagnostic] = new _root_.scala.collection.immutable.VectorBuilder[pulumirpc.codegen.hcl.Diagnostic] + var `_unknownFields__`: _root_.scalapb.UnknownFieldSet.Builder = null + var _done__ = false + while (!_done__) { + val _tag__ = _input__.readTag() + _tag__ match { + case 0 => _done__ = true + case 10 => + __diagnostics += _root_.scalapb.LiteParser.readMessage[pulumirpc.codegen.hcl.Diagnostic](_input__) + case tag => + if (_unknownFields__ == null) { + _unknownFields__ = new _root_.scalapb.UnknownFieldSet.Builder() + } + _unknownFields__.parseField(tag, _input__) + } + } + pulumirpc.language.GenerateProjectResponse( + diagnostics = __diagnostics.result(), + unknownFields = if (_unknownFields__ == null) _root_.scalapb.UnknownFieldSet.empty else _unknownFields__.result() + ) + } + implicit def messageReads: _root_.scalapb.descriptors.Reads[pulumirpc.language.GenerateProjectResponse] = _root_.scalapb.descriptors.Reads{ + case _root_.scalapb.descriptors.PMessage(__fieldsMap) => + _root_.scala.Predef.require(__fieldsMap.keys.forall(_.containingMessage eq scalaDescriptor), "FieldDescriptor does not match message type.") + pulumirpc.language.GenerateProjectResponse( + diagnostics = __fieldsMap.get(scalaDescriptor.findFieldByNumber(1).get).map(_.as[_root_.scala.Seq[pulumirpc.codegen.hcl.Diagnostic]]).getOrElse(_root_.scala.Seq.empty) + ) + case _ => throw new RuntimeException("Expected PMessage") + } + def javaDescriptor: _root_.com.google.protobuf.Descriptors.Descriptor = LanguageProto.javaDescriptor.getMessageTypes().get(16) + def scalaDescriptor: _root_.scalapb.descriptors.Descriptor = LanguageProto.scalaDescriptor.messages(16) + def messageCompanionForFieldNumber(__number: _root_.scala.Int): _root_.scalapb.GeneratedMessageCompanion[_] = { + var __out: _root_.scalapb.GeneratedMessageCompanion[_] = null + (__number: @_root_.scala.unchecked) match { + case 1 => __out = pulumirpc.codegen.hcl.Diagnostic + } + __out + } + lazy val nestedMessagesCompanions: Seq[_root_.scalapb.GeneratedMessageCompanion[_ <: _root_.scalapb.GeneratedMessage]] = Seq.empty + def enumCompanionForFieldNumber(__fieldNumber: _root_.scala.Int): _root_.scalapb.GeneratedEnumCompanion[_] = throw new MatchError(__fieldNumber) + lazy val defaultInstance = pulumirpc.language.GenerateProjectResponse( + diagnostics = _root_.scala.Seq.empty + ) + implicit class GenerateProjectResponseLens[UpperPB](_l: _root_.scalapb.lenses.Lens[UpperPB, pulumirpc.language.GenerateProjectResponse]) extends _root_.scalapb.lenses.ObjectLens[UpperPB, pulumirpc.language.GenerateProjectResponse](_l) { + def diagnostics: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Seq[pulumirpc.codegen.hcl.Diagnostic]] = field(_.diagnostics)((c_, f_) => c_.copy(diagnostics = f_)) + } + final val DIAGNOSTICS_FIELD_NUMBER = 1 + def of( + diagnostics: _root_.scala.Seq[pulumirpc.codegen.hcl.Diagnostic] + ): _root_.pulumirpc.language.GenerateProjectResponse = _root_.pulumirpc.language.GenerateProjectResponse( + diagnostics + ) + // @@protoc_insertion_point(GeneratedMessageCompanion[pulumirpc.GenerateProjectResponse]) +} diff --git a/core/src/main/scala/besom/rpc/pulumirpc/language/GetProgramDependenciesRequest.scala b/core/src/main/scala/besom/rpc/pulumirpc/language/GetProgramDependenciesRequest.scala new file mode 100644 index 00000000..2b993bca --- /dev/null +++ b/core/src/main/scala/besom/rpc/pulumirpc/language/GetProgramDependenciesRequest.scala @@ -0,0 +1,251 @@ +// Generated by the Scala Plugin for the Protocol Buffer Compiler. +// Do not edit! +// +// Protofile syntax: PROTO3 + +package pulumirpc.language + +/** @param project + * the project name, the engine always sets this to "deprecated" now. + * @param pwd + * the program's working directory. + * @param program + * the path to the program. + * @param transitiveDependencies + * if transitive dependencies should be included in the result. + * @param info + * the program info to use to calculate dependencies. + */ +@SerialVersionUID(0L) +final case class GetProgramDependenciesRequest( + @scala.deprecated(message="Marked as deprecated in proto file", "") project: _root_.scala.Predef.String = "", + @scala.deprecated(message="Marked as deprecated in proto file", "") pwd: _root_.scala.Predef.String = "", + @scala.deprecated(message="Marked as deprecated in proto file", "") program: _root_.scala.Predef.String = "", + transitiveDependencies: _root_.scala.Boolean = false, + info: _root_.scala.Option[pulumirpc.language.ProgramInfo] = _root_.scala.None, + unknownFields: _root_.scalapb.UnknownFieldSet = _root_.scalapb.UnknownFieldSet.empty + ) extends scalapb.GeneratedMessage with scalapb.lenses.Updatable[GetProgramDependenciesRequest] { + @transient + private[this] var __serializedSizeMemoized: _root_.scala.Int = 0 + private[this] def __computeSerializedSize(): _root_.scala.Int = { + var __size = 0 + + { + val __value = project + if (!__value.isEmpty) { + __size += _root_.com.google.protobuf.CodedOutputStream.computeStringSize(1, __value) + } + }; + + { + val __value = pwd + if (!__value.isEmpty) { + __size += _root_.com.google.protobuf.CodedOutputStream.computeStringSize(2, __value) + } + }; + + { + val __value = program + if (!__value.isEmpty) { + __size += _root_.com.google.protobuf.CodedOutputStream.computeStringSize(3, __value) + } + }; + + { + val __value = transitiveDependencies + if (__value != false) { + __size += _root_.com.google.protobuf.CodedOutputStream.computeBoolSize(4, __value) + } + }; + if (info.isDefined) { + val __value = info.get + __size += 1 + _root_.com.google.protobuf.CodedOutputStream.computeUInt32SizeNoTag(__value.serializedSize) + __value.serializedSize + }; + __size += unknownFields.serializedSize + __size + } + override def serializedSize: _root_.scala.Int = { + var __size = __serializedSizeMemoized + if (__size == 0) { + __size = __computeSerializedSize() + 1 + __serializedSizeMemoized = __size + } + __size - 1 + + } + def writeTo(`_output__`: _root_.com.google.protobuf.CodedOutputStream): _root_.scala.Unit = { + { + val __v = project + if (!__v.isEmpty) { + _output__.writeString(1, __v) + } + }; + { + val __v = pwd + if (!__v.isEmpty) { + _output__.writeString(2, __v) + } + }; + { + val __v = program + if (!__v.isEmpty) { + _output__.writeString(3, __v) + } + }; + { + val __v = transitiveDependencies + if (__v != false) { + _output__.writeBool(4, __v) + } + }; + info.foreach { __v => + val __m = __v + _output__.writeTag(5, 2) + _output__.writeUInt32NoTag(__m.serializedSize) + __m.writeTo(_output__) + }; + unknownFields.writeTo(_output__) + } + def withProject(__v: _root_.scala.Predef.String): GetProgramDependenciesRequest = copy(project = __v) + def withPwd(__v: _root_.scala.Predef.String): GetProgramDependenciesRequest = copy(pwd = __v) + def withProgram(__v: _root_.scala.Predef.String): GetProgramDependenciesRequest = copy(program = __v) + def withTransitiveDependencies(__v: _root_.scala.Boolean): GetProgramDependenciesRequest = copy(transitiveDependencies = __v) + def getInfo: pulumirpc.language.ProgramInfo = info.getOrElse(pulumirpc.language.ProgramInfo.defaultInstance) + def clearInfo: GetProgramDependenciesRequest = copy(info = _root_.scala.None) + def withInfo(__v: pulumirpc.language.ProgramInfo): GetProgramDependenciesRequest = copy(info = Option(__v)) + def withUnknownFields(__v: _root_.scalapb.UnknownFieldSet) = copy(unknownFields = __v) + def discardUnknownFields = copy(unknownFields = _root_.scalapb.UnknownFieldSet.empty) + def getFieldByNumber(__fieldNumber: _root_.scala.Int): _root_.scala.Any = { + (__fieldNumber: @_root_.scala.unchecked) match { + case 1 => { + val __t = project + if (__t != "") __t else null + } + case 2 => { + val __t = pwd + if (__t != "") __t else null + } + case 3 => { + val __t = program + if (__t != "") __t else null + } + case 4 => { + val __t = transitiveDependencies + if (__t != false) __t else null + } + case 5 => info.orNull + } + } + def getField(__field: _root_.scalapb.descriptors.FieldDescriptor): _root_.scalapb.descriptors.PValue = { + _root_.scala.Predef.require(__field.containingMessage eq companion.scalaDescriptor) + (__field.number: @_root_.scala.unchecked) match { + case 1 => _root_.scalapb.descriptors.PString(project) + case 2 => _root_.scalapb.descriptors.PString(pwd) + case 3 => _root_.scalapb.descriptors.PString(program) + case 4 => _root_.scalapb.descriptors.PBoolean(transitiveDependencies) + case 5 => info.map(_.toPMessage).getOrElse(_root_.scalapb.descriptors.PEmpty) + } + } + def toProtoString: _root_.scala.Predef.String = _root_.scalapb.TextFormat.printToUnicodeString(this) + def companion: pulumirpc.language.GetProgramDependenciesRequest.type = pulumirpc.language.GetProgramDependenciesRequest + // @@protoc_insertion_point(GeneratedMessage[pulumirpc.GetProgramDependenciesRequest]) +} + +object GetProgramDependenciesRequest extends scalapb.GeneratedMessageCompanion[pulumirpc.language.GetProgramDependenciesRequest] { + implicit def messageCompanion: scalapb.GeneratedMessageCompanion[pulumirpc.language.GetProgramDependenciesRequest] = this + def parseFrom(`_input__`: _root_.com.google.protobuf.CodedInputStream): pulumirpc.language.GetProgramDependenciesRequest = { + var __project: _root_.scala.Predef.String = "" + var __pwd: _root_.scala.Predef.String = "" + var __program: _root_.scala.Predef.String = "" + var __transitiveDependencies: _root_.scala.Boolean = false + var __info: _root_.scala.Option[pulumirpc.language.ProgramInfo] = _root_.scala.None + var `_unknownFields__`: _root_.scalapb.UnknownFieldSet.Builder = null + var _done__ = false + while (!_done__) { + val _tag__ = _input__.readTag() + _tag__ match { + case 0 => _done__ = true + case 10 => + __project = _input__.readStringRequireUtf8() + case 18 => + __pwd = _input__.readStringRequireUtf8() + case 26 => + __program = _input__.readStringRequireUtf8() + case 32 => + __transitiveDependencies = _input__.readBool() + case 42 => + __info = _root_.scala.Option(__info.fold(_root_.scalapb.LiteParser.readMessage[pulumirpc.language.ProgramInfo](_input__))(_root_.scalapb.LiteParser.readMessage(_input__, _))) + case tag => + if (_unknownFields__ == null) { + _unknownFields__ = new _root_.scalapb.UnknownFieldSet.Builder() + } + _unknownFields__.parseField(tag, _input__) + } + } + pulumirpc.language.GetProgramDependenciesRequest( + project = __project, + pwd = __pwd, + program = __program, + transitiveDependencies = __transitiveDependencies, + info = __info, + unknownFields = if (_unknownFields__ == null) _root_.scalapb.UnknownFieldSet.empty else _unknownFields__.result() + ) + } + implicit def messageReads: _root_.scalapb.descriptors.Reads[pulumirpc.language.GetProgramDependenciesRequest] = _root_.scalapb.descriptors.Reads{ + case _root_.scalapb.descriptors.PMessage(__fieldsMap) => + _root_.scala.Predef.require(__fieldsMap.keys.forall(_.containingMessage eq scalaDescriptor), "FieldDescriptor does not match message type.") + pulumirpc.language.GetProgramDependenciesRequest( + project = __fieldsMap.get(scalaDescriptor.findFieldByNumber(1).get).map(_.as[_root_.scala.Predef.String]).getOrElse(""), + pwd = __fieldsMap.get(scalaDescriptor.findFieldByNumber(2).get).map(_.as[_root_.scala.Predef.String]).getOrElse(""), + program = __fieldsMap.get(scalaDescriptor.findFieldByNumber(3).get).map(_.as[_root_.scala.Predef.String]).getOrElse(""), + transitiveDependencies = __fieldsMap.get(scalaDescriptor.findFieldByNumber(4).get).map(_.as[_root_.scala.Boolean]).getOrElse(false), + info = __fieldsMap.get(scalaDescriptor.findFieldByNumber(5).get).flatMap(_.as[_root_.scala.Option[pulumirpc.language.ProgramInfo]]) + ) + case _ => throw new RuntimeException("Expected PMessage") + } + def javaDescriptor: _root_.com.google.protobuf.Descriptors.Descriptor = LanguageProto.javaDescriptor.getMessageTypes().get(2) + def scalaDescriptor: _root_.scalapb.descriptors.Descriptor = LanguageProto.scalaDescriptor.messages(2) + def messageCompanionForFieldNumber(__number: _root_.scala.Int): _root_.scalapb.GeneratedMessageCompanion[_] = { + var __out: _root_.scalapb.GeneratedMessageCompanion[_] = null + (__number: @_root_.scala.unchecked) match { + case 5 => __out = pulumirpc.language.ProgramInfo + } + __out + } + lazy val nestedMessagesCompanions: Seq[_root_.scalapb.GeneratedMessageCompanion[_ <: _root_.scalapb.GeneratedMessage]] = Seq.empty + def enumCompanionForFieldNumber(__fieldNumber: _root_.scala.Int): _root_.scalapb.GeneratedEnumCompanion[_] = throw new MatchError(__fieldNumber) + lazy val defaultInstance = pulumirpc.language.GetProgramDependenciesRequest( + project = "", + pwd = "", + program = "", + transitiveDependencies = false, + info = _root_.scala.None + ) + implicit class GetProgramDependenciesRequestLens[UpperPB](_l: _root_.scalapb.lenses.Lens[UpperPB, pulumirpc.language.GetProgramDependenciesRequest]) extends _root_.scalapb.lenses.ObjectLens[UpperPB, pulumirpc.language.GetProgramDependenciesRequest](_l) { + def project: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Predef.String] = field(_.project)((c_, f_) => c_.copy(project = f_)) + def pwd: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Predef.String] = field(_.pwd)((c_, f_) => c_.copy(pwd = f_)) + def program: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Predef.String] = field(_.program)((c_, f_) => c_.copy(program = f_)) + def transitiveDependencies: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Boolean] = field(_.transitiveDependencies)((c_, f_) => c_.copy(transitiveDependencies = f_)) + def info: _root_.scalapb.lenses.Lens[UpperPB, pulumirpc.language.ProgramInfo] = field(_.getInfo)((c_, f_) => c_.copy(info = _root_.scala.Option(f_))) + def optionalInfo: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Option[pulumirpc.language.ProgramInfo]] = field(_.info)((c_, f_) => c_.copy(info = f_)) + } + final val PROJECT_FIELD_NUMBER = 1 + final val PWD_FIELD_NUMBER = 2 + final val PROGRAM_FIELD_NUMBER = 3 + final val TRANSITIVEDEPENDENCIES_FIELD_NUMBER = 4 + final val INFO_FIELD_NUMBER = 5 + def of( + project: _root_.scala.Predef.String, + pwd: _root_.scala.Predef.String, + program: _root_.scala.Predef.String, + transitiveDependencies: _root_.scala.Boolean, + info: _root_.scala.Option[pulumirpc.language.ProgramInfo] + ): _root_.pulumirpc.language.GetProgramDependenciesRequest = _root_.pulumirpc.language.GetProgramDependenciesRequest( + project, + pwd, + program, + transitiveDependencies, + info + ) + // @@protoc_insertion_point(GeneratedMessageCompanion[pulumirpc.GetProgramDependenciesRequest]) +} diff --git a/core/src/main/scala/besom/rpc/pulumirpc/language/GetProgramDependenciesResponse.scala b/core/src/main/scala/besom/rpc/pulumirpc/language/GetProgramDependenciesResponse.scala new file mode 100644 index 00000000..bd64391e --- /dev/null +++ b/core/src/main/scala/besom/rpc/pulumirpc/language/GetProgramDependenciesResponse.scala @@ -0,0 +1,123 @@ +// Generated by the Scala Plugin for the Protocol Buffer Compiler. +// Do not edit! +// +// Protofile syntax: PROTO3 + +package pulumirpc.language + +/** @param dependencies + * the dependencies of this program + */ +@SerialVersionUID(0L) +final case class GetProgramDependenciesResponse( + dependencies: _root_.scala.Seq[pulumirpc.language.DependencyInfo] = _root_.scala.Seq.empty, + unknownFields: _root_.scalapb.UnknownFieldSet = _root_.scalapb.UnknownFieldSet.empty + ) extends scalapb.GeneratedMessage with scalapb.lenses.Updatable[GetProgramDependenciesResponse] { + @transient + private[this] var __serializedSizeMemoized: _root_.scala.Int = 0 + private[this] def __computeSerializedSize(): _root_.scala.Int = { + var __size = 0 + dependencies.foreach { __item => + val __value = __item + __size += 1 + _root_.com.google.protobuf.CodedOutputStream.computeUInt32SizeNoTag(__value.serializedSize) + __value.serializedSize + } + __size += unknownFields.serializedSize + __size + } + override def serializedSize: _root_.scala.Int = { + var __size = __serializedSizeMemoized + if (__size == 0) { + __size = __computeSerializedSize() + 1 + __serializedSizeMemoized = __size + } + __size - 1 + + } + def writeTo(`_output__`: _root_.com.google.protobuf.CodedOutputStream): _root_.scala.Unit = { + dependencies.foreach { __v => + val __m = __v + _output__.writeTag(1, 2) + _output__.writeUInt32NoTag(__m.serializedSize) + __m.writeTo(_output__) + }; + unknownFields.writeTo(_output__) + } + def clearDependencies = copy(dependencies = _root_.scala.Seq.empty) + def addDependencies(__vs: pulumirpc.language.DependencyInfo *): GetProgramDependenciesResponse = addAllDependencies(__vs) + def addAllDependencies(__vs: Iterable[pulumirpc.language.DependencyInfo]): GetProgramDependenciesResponse = copy(dependencies = dependencies ++ __vs) + def withDependencies(__v: _root_.scala.Seq[pulumirpc.language.DependencyInfo]): GetProgramDependenciesResponse = copy(dependencies = __v) + def withUnknownFields(__v: _root_.scalapb.UnknownFieldSet) = copy(unknownFields = __v) + def discardUnknownFields = copy(unknownFields = _root_.scalapb.UnknownFieldSet.empty) + def getFieldByNumber(__fieldNumber: _root_.scala.Int): _root_.scala.Any = { + (__fieldNumber: @_root_.scala.unchecked) match { + case 1 => dependencies + } + } + def getField(__field: _root_.scalapb.descriptors.FieldDescriptor): _root_.scalapb.descriptors.PValue = { + _root_.scala.Predef.require(__field.containingMessage eq companion.scalaDescriptor) + (__field.number: @_root_.scala.unchecked) match { + case 1 => _root_.scalapb.descriptors.PRepeated(dependencies.iterator.map(_.toPMessage).toVector) + } + } + def toProtoString: _root_.scala.Predef.String = _root_.scalapb.TextFormat.printToUnicodeString(this) + def companion: pulumirpc.language.GetProgramDependenciesResponse.type = pulumirpc.language.GetProgramDependenciesResponse + // @@protoc_insertion_point(GeneratedMessage[pulumirpc.GetProgramDependenciesResponse]) +} + +object GetProgramDependenciesResponse extends scalapb.GeneratedMessageCompanion[pulumirpc.language.GetProgramDependenciesResponse] { + implicit def messageCompanion: scalapb.GeneratedMessageCompanion[pulumirpc.language.GetProgramDependenciesResponse] = this + def parseFrom(`_input__`: _root_.com.google.protobuf.CodedInputStream): pulumirpc.language.GetProgramDependenciesResponse = { + val __dependencies: _root_.scala.collection.immutable.VectorBuilder[pulumirpc.language.DependencyInfo] = new _root_.scala.collection.immutable.VectorBuilder[pulumirpc.language.DependencyInfo] + var `_unknownFields__`: _root_.scalapb.UnknownFieldSet.Builder = null + var _done__ = false + while (!_done__) { + val _tag__ = _input__.readTag() + _tag__ match { + case 0 => _done__ = true + case 10 => + __dependencies += _root_.scalapb.LiteParser.readMessage[pulumirpc.language.DependencyInfo](_input__) + case tag => + if (_unknownFields__ == null) { + _unknownFields__ = new _root_.scalapb.UnknownFieldSet.Builder() + } + _unknownFields__.parseField(tag, _input__) + } + } + pulumirpc.language.GetProgramDependenciesResponse( + dependencies = __dependencies.result(), + unknownFields = if (_unknownFields__ == null) _root_.scalapb.UnknownFieldSet.empty else _unknownFields__.result() + ) + } + implicit def messageReads: _root_.scalapb.descriptors.Reads[pulumirpc.language.GetProgramDependenciesResponse] = _root_.scalapb.descriptors.Reads{ + case _root_.scalapb.descriptors.PMessage(__fieldsMap) => + _root_.scala.Predef.require(__fieldsMap.keys.forall(_.containingMessage eq scalaDescriptor), "FieldDescriptor does not match message type.") + pulumirpc.language.GetProgramDependenciesResponse( + dependencies = __fieldsMap.get(scalaDescriptor.findFieldByNumber(1).get).map(_.as[_root_.scala.Seq[pulumirpc.language.DependencyInfo]]).getOrElse(_root_.scala.Seq.empty) + ) + case _ => throw new RuntimeException("Expected PMessage") + } + def javaDescriptor: _root_.com.google.protobuf.Descriptors.Descriptor = LanguageProto.javaDescriptor.getMessageTypes().get(4) + def scalaDescriptor: _root_.scalapb.descriptors.Descriptor = LanguageProto.scalaDescriptor.messages(4) + def messageCompanionForFieldNumber(__number: _root_.scala.Int): _root_.scalapb.GeneratedMessageCompanion[_] = { + var __out: _root_.scalapb.GeneratedMessageCompanion[_] = null + (__number: @_root_.scala.unchecked) match { + case 1 => __out = pulumirpc.language.DependencyInfo + } + __out + } + lazy val nestedMessagesCompanions: Seq[_root_.scalapb.GeneratedMessageCompanion[_ <: _root_.scalapb.GeneratedMessage]] = Seq.empty + def enumCompanionForFieldNumber(__fieldNumber: _root_.scala.Int): _root_.scalapb.GeneratedEnumCompanion[_] = throw new MatchError(__fieldNumber) + lazy val defaultInstance = pulumirpc.language.GetProgramDependenciesResponse( + dependencies = _root_.scala.Seq.empty + ) + implicit class GetProgramDependenciesResponseLens[UpperPB](_l: _root_.scalapb.lenses.Lens[UpperPB, pulumirpc.language.GetProgramDependenciesResponse]) extends _root_.scalapb.lenses.ObjectLens[UpperPB, pulumirpc.language.GetProgramDependenciesResponse](_l) { + def dependencies: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Seq[pulumirpc.language.DependencyInfo]] = field(_.dependencies)((c_, f_) => c_.copy(dependencies = f_)) + } + final val DEPENDENCIES_FIELD_NUMBER = 1 + def of( + dependencies: _root_.scala.Seq[pulumirpc.language.DependencyInfo] + ): _root_.pulumirpc.language.GetProgramDependenciesResponse = _root_.pulumirpc.language.GetProgramDependenciesResponse( + dependencies + ) + // @@protoc_insertion_point(GeneratedMessageCompanion[pulumirpc.GetProgramDependenciesResponse]) +} diff --git a/core/src/main/scala/besom/rpc/pulumirpc/language/GetRequiredPluginsRequest.scala b/core/src/main/scala/besom/rpc/pulumirpc/language/GetRequiredPluginsRequest.scala new file mode 100644 index 00000000..da6aa4b0 --- /dev/null +++ b/core/src/main/scala/besom/rpc/pulumirpc/language/GetRequiredPluginsRequest.scala @@ -0,0 +1,219 @@ +// Generated by the Scala Plugin for the Protocol Buffer Compiler. +// Do not edit! +// +// Protofile syntax: PROTO3 + +package pulumirpc.language + +/** @param project + * the project name, the engine always sets this to "deprecated" now. + * @param pwd + * the program's working directory. + * @param program + * the path to the program. + * @param info + * the program info to use to calculate plugins. + */ +@SerialVersionUID(0L) +final case class GetRequiredPluginsRequest( + @scala.deprecated(message="Marked as deprecated in proto file", "") project: _root_.scala.Predef.String = "", + @scala.deprecated(message="Marked as deprecated in proto file", "") pwd: _root_.scala.Predef.String = "", + @scala.deprecated(message="Marked as deprecated in proto file", "") program: _root_.scala.Predef.String = "", + info: _root_.scala.Option[pulumirpc.language.ProgramInfo] = _root_.scala.None, + unknownFields: _root_.scalapb.UnknownFieldSet = _root_.scalapb.UnknownFieldSet.empty + ) extends scalapb.GeneratedMessage with scalapb.lenses.Updatable[GetRequiredPluginsRequest] { + @transient + private[this] var __serializedSizeMemoized: _root_.scala.Int = 0 + private[this] def __computeSerializedSize(): _root_.scala.Int = { + var __size = 0 + + { + val __value = project + if (!__value.isEmpty) { + __size += _root_.com.google.protobuf.CodedOutputStream.computeStringSize(1, __value) + } + }; + + { + val __value = pwd + if (!__value.isEmpty) { + __size += _root_.com.google.protobuf.CodedOutputStream.computeStringSize(2, __value) + } + }; + + { + val __value = program + if (!__value.isEmpty) { + __size += _root_.com.google.protobuf.CodedOutputStream.computeStringSize(3, __value) + } + }; + if (info.isDefined) { + val __value = info.get + __size += 1 + _root_.com.google.protobuf.CodedOutputStream.computeUInt32SizeNoTag(__value.serializedSize) + __value.serializedSize + }; + __size += unknownFields.serializedSize + __size + } + override def serializedSize: _root_.scala.Int = { + var __size = __serializedSizeMemoized + if (__size == 0) { + __size = __computeSerializedSize() + 1 + __serializedSizeMemoized = __size + } + __size - 1 + + } + def writeTo(`_output__`: _root_.com.google.protobuf.CodedOutputStream): _root_.scala.Unit = { + { + val __v = project + if (!__v.isEmpty) { + _output__.writeString(1, __v) + } + }; + { + val __v = pwd + if (!__v.isEmpty) { + _output__.writeString(2, __v) + } + }; + { + val __v = program + if (!__v.isEmpty) { + _output__.writeString(3, __v) + } + }; + info.foreach { __v => + val __m = __v + _output__.writeTag(4, 2) + _output__.writeUInt32NoTag(__m.serializedSize) + __m.writeTo(_output__) + }; + unknownFields.writeTo(_output__) + } + def withProject(__v: _root_.scala.Predef.String): GetRequiredPluginsRequest = copy(project = __v) + def withPwd(__v: _root_.scala.Predef.String): GetRequiredPluginsRequest = copy(pwd = __v) + def withProgram(__v: _root_.scala.Predef.String): GetRequiredPluginsRequest = copy(program = __v) + def getInfo: pulumirpc.language.ProgramInfo = info.getOrElse(pulumirpc.language.ProgramInfo.defaultInstance) + def clearInfo: GetRequiredPluginsRequest = copy(info = _root_.scala.None) + def withInfo(__v: pulumirpc.language.ProgramInfo): GetRequiredPluginsRequest = copy(info = Option(__v)) + def withUnknownFields(__v: _root_.scalapb.UnknownFieldSet) = copy(unknownFields = __v) + def discardUnknownFields = copy(unknownFields = _root_.scalapb.UnknownFieldSet.empty) + def getFieldByNumber(__fieldNumber: _root_.scala.Int): _root_.scala.Any = { + (__fieldNumber: @_root_.scala.unchecked) match { + case 1 => { + val __t = project + if (__t != "") __t else null + } + case 2 => { + val __t = pwd + if (__t != "") __t else null + } + case 3 => { + val __t = program + if (__t != "") __t else null + } + case 4 => info.orNull + } + } + def getField(__field: _root_.scalapb.descriptors.FieldDescriptor): _root_.scalapb.descriptors.PValue = { + _root_.scala.Predef.require(__field.containingMessage eq companion.scalaDescriptor) + (__field.number: @_root_.scala.unchecked) match { + case 1 => _root_.scalapb.descriptors.PString(project) + case 2 => _root_.scalapb.descriptors.PString(pwd) + case 3 => _root_.scalapb.descriptors.PString(program) + case 4 => info.map(_.toPMessage).getOrElse(_root_.scalapb.descriptors.PEmpty) + } + } + def toProtoString: _root_.scala.Predef.String = _root_.scalapb.TextFormat.printToUnicodeString(this) + def companion: pulumirpc.language.GetRequiredPluginsRequest.type = pulumirpc.language.GetRequiredPluginsRequest + // @@protoc_insertion_point(GeneratedMessage[pulumirpc.GetRequiredPluginsRequest]) +} + +object GetRequiredPluginsRequest extends scalapb.GeneratedMessageCompanion[pulumirpc.language.GetRequiredPluginsRequest] { + implicit def messageCompanion: scalapb.GeneratedMessageCompanion[pulumirpc.language.GetRequiredPluginsRequest] = this + def parseFrom(`_input__`: _root_.com.google.protobuf.CodedInputStream): pulumirpc.language.GetRequiredPluginsRequest = { + var __project: _root_.scala.Predef.String = "" + var __pwd: _root_.scala.Predef.String = "" + var __program: _root_.scala.Predef.String = "" + var __info: _root_.scala.Option[pulumirpc.language.ProgramInfo] = _root_.scala.None + var `_unknownFields__`: _root_.scalapb.UnknownFieldSet.Builder = null + var _done__ = false + while (!_done__) { + val _tag__ = _input__.readTag() + _tag__ match { + case 0 => _done__ = true + case 10 => + __project = _input__.readStringRequireUtf8() + case 18 => + __pwd = _input__.readStringRequireUtf8() + case 26 => + __program = _input__.readStringRequireUtf8() + case 34 => + __info = _root_.scala.Option(__info.fold(_root_.scalapb.LiteParser.readMessage[pulumirpc.language.ProgramInfo](_input__))(_root_.scalapb.LiteParser.readMessage(_input__, _))) + case tag => + if (_unknownFields__ == null) { + _unknownFields__ = new _root_.scalapb.UnknownFieldSet.Builder() + } + _unknownFields__.parseField(tag, _input__) + } + } + pulumirpc.language.GetRequiredPluginsRequest( + project = __project, + pwd = __pwd, + program = __program, + info = __info, + unknownFields = if (_unknownFields__ == null) _root_.scalapb.UnknownFieldSet.empty else _unknownFields__.result() + ) + } + implicit def messageReads: _root_.scalapb.descriptors.Reads[pulumirpc.language.GetRequiredPluginsRequest] = _root_.scalapb.descriptors.Reads{ + case _root_.scalapb.descriptors.PMessage(__fieldsMap) => + _root_.scala.Predef.require(__fieldsMap.keys.forall(_.containingMessage eq scalaDescriptor), "FieldDescriptor does not match message type.") + pulumirpc.language.GetRequiredPluginsRequest( + project = __fieldsMap.get(scalaDescriptor.findFieldByNumber(1).get).map(_.as[_root_.scala.Predef.String]).getOrElse(""), + pwd = __fieldsMap.get(scalaDescriptor.findFieldByNumber(2).get).map(_.as[_root_.scala.Predef.String]).getOrElse(""), + program = __fieldsMap.get(scalaDescriptor.findFieldByNumber(3).get).map(_.as[_root_.scala.Predef.String]).getOrElse(""), + info = __fieldsMap.get(scalaDescriptor.findFieldByNumber(4).get).flatMap(_.as[_root_.scala.Option[pulumirpc.language.ProgramInfo]]) + ) + case _ => throw new RuntimeException("Expected PMessage") + } + def javaDescriptor: _root_.com.google.protobuf.Descriptors.Descriptor = LanguageProto.javaDescriptor.getMessageTypes().get(5) + def scalaDescriptor: _root_.scalapb.descriptors.Descriptor = LanguageProto.scalaDescriptor.messages(5) + def messageCompanionForFieldNumber(__number: _root_.scala.Int): _root_.scalapb.GeneratedMessageCompanion[_] = { + var __out: _root_.scalapb.GeneratedMessageCompanion[_] = null + (__number: @_root_.scala.unchecked) match { + case 4 => __out = pulumirpc.language.ProgramInfo + } + __out + } + lazy val nestedMessagesCompanions: Seq[_root_.scalapb.GeneratedMessageCompanion[_ <: _root_.scalapb.GeneratedMessage]] = Seq.empty + def enumCompanionForFieldNumber(__fieldNumber: _root_.scala.Int): _root_.scalapb.GeneratedEnumCompanion[_] = throw new MatchError(__fieldNumber) + lazy val defaultInstance = pulumirpc.language.GetRequiredPluginsRequest( + project = "", + pwd = "", + program = "", + info = _root_.scala.None + ) + implicit class GetRequiredPluginsRequestLens[UpperPB](_l: _root_.scalapb.lenses.Lens[UpperPB, pulumirpc.language.GetRequiredPluginsRequest]) extends _root_.scalapb.lenses.ObjectLens[UpperPB, pulumirpc.language.GetRequiredPluginsRequest](_l) { + def project: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Predef.String] = field(_.project)((c_, f_) => c_.copy(project = f_)) + def pwd: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Predef.String] = field(_.pwd)((c_, f_) => c_.copy(pwd = f_)) + def program: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Predef.String] = field(_.program)((c_, f_) => c_.copy(program = f_)) + def info: _root_.scalapb.lenses.Lens[UpperPB, pulumirpc.language.ProgramInfo] = field(_.getInfo)((c_, f_) => c_.copy(info = _root_.scala.Option(f_))) + def optionalInfo: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Option[pulumirpc.language.ProgramInfo]] = field(_.info)((c_, f_) => c_.copy(info = f_)) + } + final val PROJECT_FIELD_NUMBER = 1 + final val PWD_FIELD_NUMBER = 2 + final val PROGRAM_FIELD_NUMBER = 3 + final val INFO_FIELD_NUMBER = 4 + def of( + project: _root_.scala.Predef.String, + pwd: _root_.scala.Predef.String, + program: _root_.scala.Predef.String, + info: _root_.scala.Option[pulumirpc.language.ProgramInfo] + ): _root_.pulumirpc.language.GetRequiredPluginsRequest = _root_.pulumirpc.language.GetRequiredPluginsRequest( + project, + pwd, + program, + info + ) + // @@protoc_insertion_point(GeneratedMessageCompanion[pulumirpc.GetRequiredPluginsRequest]) +} diff --git a/core/src/main/scala/besom/rpc/pulumirpc/language/GetRequiredPluginsResponse.scala b/core/src/main/scala/besom/rpc/pulumirpc/language/GetRequiredPluginsResponse.scala new file mode 100644 index 00000000..6b40506f --- /dev/null +++ b/core/src/main/scala/besom/rpc/pulumirpc/language/GetRequiredPluginsResponse.scala @@ -0,0 +1,123 @@ +// Generated by the Scala Plugin for the Protocol Buffer Compiler. +// Do not edit! +// +// Protofile syntax: PROTO3 + +package pulumirpc.language + +/** @param plugins + * a list of plugins required by this program. + */ +@SerialVersionUID(0L) +final case class GetRequiredPluginsResponse( + plugins: _root_.scala.Seq[pulumirpc.plugin.PluginDependency] = _root_.scala.Seq.empty, + unknownFields: _root_.scalapb.UnknownFieldSet = _root_.scalapb.UnknownFieldSet.empty + ) extends scalapb.GeneratedMessage with scalapb.lenses.Updatable[GetRequiredPluginsResponse] { + @transient + private[this] var __serializedSizeMemoized: _root_.scala.Int = 0 + private[this] def __computeSerializedSize(): _root_.scala.Int = { + var __size = 0 + plugins.foreach { __item => + val __value = __item + __size += 1 + _root_.com.google.protobuf.CodedOutputStream.computeUInt32SizeNoTag(__value.serializedSize) + __value.serializedSize + } + __size += unknownFields.serializedSize + __size + } + override def serializedSize: _root_.scala.Int = { + var __size = __serializedSizeMemoized + if (__size == 0) { + __size = __computeSerializedSize() + 1 + __serializedSizeMemoized = __size + } + __size - 1 + + } + def writeTo(`_output__`: _root_.com.google.protobuf.CodedOutputStream): _root_.scala.Unit = { + plugins.foreach { __v => + val __m = __v + _output__.writeTag(1, 2) + _output__.writeUInt32NoTag(__m.serializedSize) + __m.writeTo(_output__) + }; + unknownFields.writeTo(_output__) + } + def clearPlugins = copy(plugins = _root_.scala.Seq.empty) + def addPlugins(__vs: pulumirpc.plugin.PluginDependency *): GetRequiredPluginsResponse = addAllPlugins(__vs) + def addAllPlugins(__vs: Iterable[pulumirpc.plugin.PluginDependency]): GetRequiredPluginsResponse = copy(plugins = plugins ++ __vs) + def withPlugins(__v: _root_.scala.Seq[pulumirpc.plugin.PluginDependency]): GetRequiredPluginsResponse = copy(plugins = __v) + def withUnknownFields(__v: _root_.scalapb.UnknownFieldSet) = copy(unknownFields = __v) + def discardUnknownFields = copy(unknownFields = _root_.scalapb.UnknownFieldSet.empty) + def getFieldByNumber(__fieldNumber: _root_.scala.Int): _root_.scala.Any = { + (__fieldNumber: @_root_.scala.unchecked) match { + case 1 => plugins + } + } + def getField(__field: _root_.scalapb.descriptors.FieldDescriptor): _root_.scalapb.descriptors.PValue = { + _root_.scala.Predef.require(__field.containingMessage eq companion.scalaDescriptor) + (__field.number: @_root_.scala.unchecked) match { + case 1 => _root_.scalapb.descriptors.PRepeated(plugins.iterator.map(_.toPMessage).toVector) + } + } + def toProtoString: _root_.scala.Predef.String = _root_.scalapb.TextFormat.printToUnicodeString(this) + def companion: pulumirpc.language.GetRequiredPluginsResponse.type = pulumirpc.language.GetRequiredPluginsResponse + // @@protoc_insertion_point(GeneratedMessage[pulumirpc.GetRequiredPluginsResponse]) +} + +object GetRequiredPluginsResponse extends scalapb.GeneratedMessageCompanion[pulumirpc.language.GetRequiredPluginsResponse] { + implicit def messageCompanion: scalapb.GeneratedMessageCompanion[pulumirpc.language.GetRequiredPluginsResponse] = this + def parseFrom(`_input__`: _root_.com.google.protobuf.CodedInputStream): pulumirpc.language.GetRequiredPluginsResponse = { + val __plugins: _root_.scala.collection.immutable.VectorBuilder[pulumirpc.plugin.PluginDependency] = new _root_.scala.collection.immutable.VectorBuilder[pulumirpc.plugin.PluginDependency] + var `_unknownFields__`: _root_.scalapb.UnknownFieldSet.Builder = null + var _done__ = false + while (!_done__) { + val _tag__ = _input__.readTag() + _tag__ match { + case 0 => _done__ = true + case 10 => + __plugins += _root_.scalapb.LiteParser.readMessage[pulumirpc.plugin.PluginDependency](_input__) + case tag => + if (_unknownFields__ == null) { + _unknownFields__ = new _root_.scalapb.UnknownFieldSet.Builder() + } + _unknownFields__.parseField(tag, _input__) + } + } + pulumirpc.language.GetRequiredPluginsResponse( + plugins = __plugins.result(), + unknownFields = if (_unknownFields__ == null) _root_.scalapb.UnknownFieldSet.empty else _unknownFields__.result() + ) + } + implicit def messageReads: _root_.scalapb.descriptors.Reads[pulumirpc.language.GetRequiredPluginsResponse] = _root_.scalapb.descriptors.Reads{ + case _root_.scalapb.descriptors.PMessage(__fieldsMap) => + _root_.scala.Predef.require(__fieldsMap.keys.forall(_.containingMessage eq scalaDescriptor), "FieldDescriptor does not match message type.") + pulumirpc.language.GetRequiredPluginsResponse( + plugins = __fieldsMap.get(scalaDescriptor.findFieldByNumber(1).get).map(_.as[_root_.scala.Seq[pulumirpc.plugin.PluginDependency]]).getOrElse(_root_.scala.Seq.empty) + ) + case _ => throw new RuntimeException("Expected PMessage") + } + def javaDescriptor: _root_.com.google.protobuf.Descriptors.Descriptor = LanguageProto.javaDescriptor.getMessageTypes().get(6) + def scalaDescriptor: _root_.scalapb.descriptors.Descriptor = LanguageProto.scalaDescriptor.messages(6) + def messageCompanionForFieldNumber(__number: _root_.scala.Int): _root_.scalapb.GeneratedMessageCompanion[_] = { + var __out: _root_.scalapb.GeneratedMessageCompanion[_] = null + (__number: @_root_.scala.unchecked) match { + case 1 => __out = pulumirpc.plugin.PluginDependency + } + __out + } + lazy val nestedMessagesCompanions: Seq[_root_.scalapb.GeneratedMessageCompanion[_ <: _root_.scalapb.GeneratedMessage]] = Seq.empty + def enumCompanionForFieldNumber(__fieldNumber: _root_.scala.Int): _root_.scalapb.GeneratedEnumCompanion[_] = throw new MatchError(__fieldNumber) + lazy val defaultInstance = pulumirpc.language.GetRequiredPluginsResponse( + plugins = _root_.scala.Seq.empty + ) + implicit class GetRequiredPluginsResponseLens[UpperPB](_l: _root_.scalapb.lenses.Lens[UpperPB, pulumirpc.language.GetRequiredPluginsResponse]) extends _root_.scalapb.lenses.ObjectLens[UpperPB, pulumirpc.language.GetRequiredPluginsResponse](_l) { + def plugins: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Seq[pulumirpc.plugin.PluginDependency]] = field(_.plugins)((c_, f_) => c_.copy(plugins = f_)) + } + final val PLUGINS_FIELD_NUMBER = 1 + def of( + plugins: _root_.scala.Seq[pulumirpc.plugin.PluginDependency] + ): _root_.pulumirpc.language.GetRequiredPluginsResponse = _root_.pulumirpc.language.GetRequiredPluginsResponse( + plugins + ) + // @@protoc_insertion_point(GeneratedMessageCompanion[pulumirpc.GetRequiredPluginsResponse]) +} diff --git a/core/src/main/scala/besom/rpc/pulumirpc/language/InstallDependenciesRequest.scala b/core/src/main/scala/besom/rpc/pulumirpc/language/InstallDependenciesRequest.scala new file mode 100644 index 00000000..f3e064ee --- /dev/null +++ b/core/src/main/scala/besom/rpc/pulumirpc/language/InstallDependenciesRequest.scala @@ -0,0 +1,187 @@ +// Generated by the Scala Plugin for the Protocol Buffer Compiler. +// Do not edit! +// +// Protofile syntax: PROTO3 + +package pulumirpc.language + +/** @param directory + * the program's working directory. + * @param isTerminal + * if we are running in a terminal and should use ANSI codes + * @param info + * the program info to use to execute the plugin. + */ +@SerialVersionUID(0L) +final case class InstallDependenciesRequest( + @scala.deprecated(message="Marked as deprecated in proto file", "") directory: _root_.scala.Predef.String = "", + isTerminal: _root_.scala.Boolean = false, + info: _root_.scala.Option[pulumirpc.language.ProgramInfo] = _root_.scala.None, + unknownFields: _root_.scalapb.UnknownFieldSet = _root_.scalapb.UnknownFieldSet.empty + ) extends scalapb.GeneratedMessage with scalapb.lenses.Updatable[InstallDependenciesRequest] { + @transient + private[this] var __serializedSizeMemoized: _root_.scala.Int = 0 + private[this] def __computeSerializedSize(): _root_.scala.Int = { + var __size = 0 + + { + val __value = directory + if (!__value.isEmpty) { + __size += _root_.com.google.protobuf.CodedOutputStream.computeStringSize(1, __value) + } + }; + + { + val __value = isTerminal + if (__value != false) { + __size += _root_.com.google.protobuf.CodedOutputStream.computeBoolSize(2, __value) + } + }; + if (info.isDefined) { + val __value = info.get + __size += 1 + _root_.com.google.protobuf.CodedOutputStream.computeUInt32SizeNoTag(__value.serializedSize) + __value.serializedSize + }; + __size += unknownFields.serializedSize + __size + } + override def serializedSize: _root_.scala.Int = { + var __size = __serializedSizeMemoized + if (__size == 0) { + __size = __computeSerializedSize() + 1 + __serializedSizeMemoized = __size + } + __size - 1 + + } + def writeTo(`_output__`: _root_.com.google.protobuf.CodedOutputStream): _root_.scala.Unit = { + { + val __v = directory + if (!__v.isEmpty) { + _output__.writeString(1, __v) + } + }; + { + val __v = isTerminal + if (__v != false) { + _output__.writeBool(2, __v) + } + }; + info.foreach { __v => + val __m = __v + _output__.writeTag(3, 2) + _output__.writeUInt32NoTag(__m.serializedSize) + __m.writeTo(_output__) + }; + unknownFields.writeTo(_output__) + } + def withDirectory(__v: _root_.scala.Predef.String): InstallDependenciesRequest = copy(directory = __v) + def withIsTerminal(__v: _root_.scala.Boolean): InstallDependenciesRequest = copy(isTerminal = __v) + def getInfo: pulumirpc.language.ProgramInfo = info.getOrElse(pulumirpc.language.ProgramInfo.defaultInstance) + def clearInfo: InstallDependenciesRequest = copy(info = _root_.scala.None) + def withInfo(__v: pulumirpc.language.ProgramInfo): InstallDependenciesRequest = copy(info = Option(__v)) + def withUnknownFields(__v: _root_.scalapb.UnknownFieldSet) = copy(unknownFields = __v) + def discardUnknownFields = copy(unknownFields = _root_.scalapb.UnknownFieldSet.empty) + def getFieldByNumber(__fieldNumber: _root_.scala.Int): _root_.scala.Any = { + (__fieldNumber: @_root_.scala.unchecked) match { + case 1 => { + val __t = directory + if (__t != "") __t else null + } + case 2 => { + val __t = isTerminal + if (__t != false) __t else null + } + case 3 => info.orNull + } + } + def getField(__field: _root_.scalapb.descriptors.FieldDescriptor): _root_.scalapb.descriptors.PValue = { + _root_.scala.Predef.require(__field.containingMessage eq companion.scalaDescriptor) + (__field.number: @_root_.scala.unchecked) match { + case 1 => _root_.scalapb.descriptors.PString(directory) + case 2 => _root_.scalapb.descriptors.PBoolean(isTerminal) + case 3 => info.map(_.toPMessage).getOrElse(_root_.scalapb.descriptors.PEmpty) + } + } + def toProtoString: _root_.scala.Predef.String = _root_.scalapb.TextFormat.printToUnicodeString(this) + def companion: pulumirpc.language.InstallDependenciesRequest.type = pulumirpc.language.InstallDependenciesRequest + // @@protoc_insertion_point(GeneratedMessage[pulumirpc.InstallDependenciesRequest]) +} + +object InstallDependenciesRequest extends scalapb.GeneratedMessageCompanion[pulumirpc.language.InstallDependenciesRequest] { + implicit def messageCompanion: scalapb.GeneratedMessageCompanion[pulumirpc.language.InstallDependenciesRequest] = this + def parseFrom(`_input__`: _root_.com.google.protobuf.CodedInputStream): pulumirpc.language.InstallDependenciesRequest = { + var __directory: _root_.scala.Predef.String = "" + var __isTerminal: _root_.scala.Boolean = false + var __info: _root_.scala.Option[pulumirpc.language.ProgramInfo] = _root_.scala.None + var `_unknownFields__`: _root_.scalapb.UnknownFieldSet.Builder = null + var _done__ = false + while (!_done__) { + val _tag__ = _input__.readTag() + _tag__ match { + case 0 => _done__ = true + case 10 => + __directory = _input__.readStringRequireUtf8() + case 16 => + __isTerminal = _input__.readBool() + case 26 => + __info = _root_.scala.Option(__info.fold(_root_.scalapb.LiteParser.readMessage[pulumirpc.language.ProgramInfo](_input__))(_root_.scalapb.LiteParser.readMessage(_input__, _))) + case tag => + if (_unknownFields__ == null) { + _unknownFields__ = new _root_.scalapb.UnknownFieldSet.Builder() + } + _unknownFields__.parseField(tag, _input__) + } + } + pulumirpc.language.InstallDependenciesRequest( + directory = __directory, + isTerminal = __isTerminal, + info = __info, + unknownFields = if (_unknownFields__ == null) _root_.scalapb.UnknownFieldSet.empty else _unknownFields__.result() + ) + } + implicit def messageReads: _root_.scalapb.descriptors.Reads[pulumirpc.language.InstallDependenciesRequest] = _root_.scalapb.descriptors.Reads{ + case _root_.scalapb.descriptors.PMessage(__fieldsMap) => + _root_.scala.Predef.require(__fieldsMap.keys.forall(_.containingMessage eq scalaDescriptor), "FieldDescriptor does not match message type.") + pulumirpc.language.InstallDependenciesRequest( + directory = __fieldsMap.get(scalaDescriptor.findFieldByNumber(1).get).map(_.as[_root_.scala.Predef.String]).getOrElse(""), + isTerminal = __fieldsMap.get(scalaDescriptor.findFieldByNumber(2).get).map(_.as[_root_.scala.Boolean]).getOrElse(false), + info = __fieldsMap.get(scalaDescriptor.findFieldByNumber(3).get).flatMap(_.as[_root_.scala.Option[pulumirpc.language.ProgramInfo]]) + ) + case _ => throw new RuntimeException("Expected PMessage") + } + def javaDescriptor: _root_.com.google.protobuf.Descriptors.Descriptor = LanguageProto.javaDescriptor.getMessageTypes().get(9) + def scalaDescriptor: _root_.scalapb.descriptors.Descriptor = LanguageProto.scalaDescriptor.messages(9) + def messageCompanionForFieldNumber(__number: _root_.scala.Int): _root_.scalapb.GeneratedMessageCompanion[_] = { + var __out: _root_.scalapb.GeneratedMessageCompanion[_] = null + (__number: @_root_.scala.unchecked) match { + case 3 => __out = pulumirpc.language.ProgramInfo + } + __out + } + lazy val nestedMessagesCompanions: Seq[_root_.scalapb.GeneratedMessageCompanion[_ <: _root_.scalapb.GeneratedMessage]] = Seq.empty + def enumCompanionForFieldNumber(__fieldNumber: _root_.scala.Int): _root_.scalapb.GeneratedEnumCompanion[_] = throw new MatchError(__fieldNumber) + lazy val defaultInstance = pulumirpc.language.InstallDependenciesRequest( + directory = "", + isTerminal = false, + info = _root_.scala.None + ) + implicit class InstallDependenciesRequestLens[UpperPB](_l: _root_.scalapb.lenses.Lens[UpperPB, pulumirpc.language.InstallDependenciesRequest]) extends _root_.scalapb.lenses.ObjectLens[UpperPB, pulumirpc.language.InstallDependenciesRequest](_l) { + def directory: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Predef.String] = field(_.directory)((c_, f_) => c_.copy(directory = f_)) + def isTerminal: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Boolean] = field(_.isTerminal)((c_, f_) => c_.copy(isTerminal = f_)) + def info: _root_.scalapb.lenses.Lens[UpperPB, pulumirpc.language.ProgramInfo] = field(_.getInfo)((c_, f_) => c_.copy(info = _root_.scala.Option(f_))) + def optionalInfo: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Option[pulumirpc.language.ProgramInfo]] = field(_.info)((c_, f_) => c_.copy(info = f_)) + } + final val DIRECTORY_FIELD_NUMBER = 1 + final val IS_TERMINAL_FIELD_NUMBER = 2 + final val INFO_FIELD_NUMBER = 3 + def of( + directory: _root_.scala.Predef.String, + isTerminal: _root_.scala.Boolean, + info: _root_.scala.Option[pulumirpc.language.ProgramInfo] + ): _root_.pulumirpc.language.InstallDependenciesRequest = _root_.pulumirpc.language.InstallDependenciesRequest( + directory, + isTerminal, + info + ) + // @@protoc_insertion_point(GeneratedMessageCompanion[pulumirpc.InstallDependenciesRequest]) +} diff --git a/core/src/main/scala/besom/rpc/pulumirpc/language/InstallDependenciesResponse.scala b/core/src/main/scala/besom/rpc/pulumirpc/language/InstallDependenciesResponse.scala new file mode 100644 index 00000000..8e5fae91 --- /dev/null +++ b/core/src/main/scala/besom/rpc/pulumirpc/language/InstallDependenciesResponse.scala @@ -0,0 +1,152 @@ +// Generated by the Scala Plugin for the Protocol Buffer Compiler. +// Do not edit! +// +// Protofile syntax: PROTO3 + +package pulumirpc.language + +/** @param stdout + * a line of stdout text. + * @param stderr + * a line of stderr text. + */ +@SerialVersionUID(0L) +final case class InstallDependenciesResponse( + stdout: _root_.com.google.protobuf.ByteString = _root_.com.google.protobuf.ByteString.EMPTY, + stderr: _root_.com.google.protobuf.ByteString = _root_.com.google.protobuf.ByteString.EMPTY, + unknownFields: _root_.scalapb.UnknownFieldSet = _root_.scalapb.UnknownFieldSet.empty + ) extends scalapb.GeneratedMessage with scalapb.lenses.Updatable[InstallDependenciesResponse] { + @transient + private[this] var __serializedSizeMemoized: _root_.scala.Int = 0 + private[this] def __computeSerializedSize(): _root_.scala.Int = { + var __size = 0 + + { + val __value = stdout + if (!__value.isEmpty) { + __size += _root_.com.google.protobuf.CodedOutputStream.computeBytesSize(1, __value) + } + }; + + { + val __value = stderr + if (!__value.isEmpty) { + __size += _root_.com.google.protobuf.CodedOutputStream.computeBytesSize(2, __value) + } + }; + __size += unknownFields.serializedSize + __size + } + override def serializedSize: _root_.scala.Int = { + var __size = __serializedSizeMemoized + if (__size == 0) { + __size = __computeSerializedSize() + 1 + __serializedSizeMemoized = __size + } + __size - 1 + + } + def writeTo(`_output__`: _root_.com.google.protobuf.CodedOutputStream): _root_.scala.Unit = { + { + val __v = stdout + if (!__v.isEmpty) { + _output__.writeBytes(1, __v) + } + }; + { + val __v = stderr + if (!__v.isEmpty) { + _output__.writeBytes(2, __v) + } + }; + unknownFields.writeTo(_output__) + } + def withStdout(__v: _root_.com.google.protobuf.ByteString): InstallDependenciesResponse = copy(stdout = __v) + def withStderr(__v: _root_.com.google.protobuf.ByteString): InstallDependenciesResponse = copy(stderr = __v) + def withUnknownFields(__v: _root_.scalapb.UnknownFieldSet) = copy(unknownFields = __v) + def discardUnknownFields = copy(unknownFields = _root_.scalapb.UnknownFieldSet.empty) + def getFieldByNumber(__fieldNumber: _root_.scala.Int): _root_.scala.Any = { + (__fieldNumber: @_root_.scala.unchecked) match { + case 1 => { + val __t = stdout + if (__t != _root_.com.google.protobuf.ByteString.EMPTY) __t else null + } + case 2 => { + val __t = stderr + if (__t != _root_.com.google.protobuf.ByteString.EMPTY) __t else null + } + } + } + def getField(__field: _root_.scalapb.descriptors.FieldDescriptor): _root_.scalapb.descriptors.PValue = { + _root_.scala.Predef.require(__field.containingMessage eq companion.scalaDescriptor) + (__field.number: @_root_.scala.unchecked) match { + case 1 => _root_.scalapb.descriptors.PByteString(stdout) + case 2 => _root_.scalapb.descriptors.PByteString(stderr) + } + } + def toProtoString: _root_.scala.Predef.String = _root_.scalapb.TextFormat.printToUnicodeString(this) + def companion: pulumirpc.language.InstallDependenciesResponse.type = pulumirpc.language.InstallDependenciesResponse + // @@protoc_insertion_point(GeneratedMessage[pulumirpc.InstallDependenciesResponse]) +} + +object InstallDependenciesResponse extends scalapb.GeneratedMessageCompanion[pulumirpc.language.InstallDependenciesResponse] { + implicit def messageCompanion: scalapb.GeneratedMessageCompanion[pulumirpc.language.InstallDependenciesResponse] = this + def parseFrom(`_input__`: _root_.com.google.protobuf.CodedInputStream): pulumirpc.language.InstallDependenciesResponse = { + var __stdout: _root_.com.google.protobuf.ByteString = _root_.com.google.protobuf.ByteString.EMPTY + var __stderr: _root_.com.google.protobuf.ByteString = _root_.com.google.protobuf.ByteString.EMPTY + var `_unknownFields__`: _root_.scalapb.UnknownFieldSet.Builder = null + var _done__ = false + while (!_done__) { + val _tag__ = _input__.readTag() + _tag__ match { + case 0 => _done__ = true + case 10 => + __stdout = _input__.readBytes() + case 18 => + __stderr = _input__.readBytes() + case tag => + if (_unknownFields__ == null) { + _unknownFields__ = new _root_.scalapb.UnknownFieldSet.Builder() + } + _unknownFields__.parseField(tag, _input__) + } + } + pulumirpc.language.InstallDependenciesResponse( + stdout = __stdout, + stderr = __stderr, + unknownFields = if (_unknownFields__ == null) _root_.scalapb.UnknownFieldSet.empty else _unknownFields__.result() + ) + } + implicit def messageReads: _root_.scalapb.descriptors.Reads[pulumirpc.language.InstallDependenciesResponse] = _root_.scalapb.descriptors.Reads{ + case _root_.scalapb.descriptors.PMessage(__fieldsMap) => + _root_.scala.Predef.require(__fieldsMap.keys.forall(_.containingMessage eq scalaDescriptor), "FieldDescriptor does not match message type.") + pulumirpc.language.InstallDependenciesResponse( + stdout = __fieldsMap.get(scalaDescriptor.findFieldByNumber(1).get).map(_.as[_root_.com.google.protobuf.ByteString]).getOrElse(_root_.com.google.protobuf.ByteString.EMPTY), + stderr = __fieldsMap.get(scalaDescriptor.findFieldByNumber(2).get).map(_.as[_root_.com.google.protobuf.ByteString]).getOrElse(_root_.com.google.protobuf.ByteString.EMPTY) + ) + case _ => throw new RuntimeException("Expected PMessage") + } + def javaDescriptor: _root_.com.google.protobuf.Descriptors.Descriptor = LanguageProto.javaDescriptor.getMessageTypes().get(10) + def scalaDescriptor: _root_.scalapb.descriptors.Descriptor = LanguageProto.scalaDescriptor.messages(10) + def messageCompanionForFieldNumber(__number: _root_.scala.Int): _root_.scalapb.GeneratedMessageCompanion[_] = throw new MatchError(__number) + lazy val nestedMessagesCompanions: Seq[_root_.scalapb.GeneratedMessageCompanion[_ <: _root_.scalapb.GeneratedMessage]] = Seq.empty + def enumCompanionForFieldNumber(__fieldNumber: _root_.scala.Int): _root_.scalapb.GeneratedEnumCompanion[_] = throw new MatchError(__fieldNumber) + lazy val defaultInstance = pulumirpc.language.InstallDependenciesResponse( + stdout = _root_.com.google.protobuf.ByteString.EMPTY, + stderr = _root_.com.google.protobuf.ByteString.EMPTY + ) + implicit class InstallDependenciesResponseLens[UpperPB](_l: _root_.scalapb.lenses.Lens[UpperPB, pulumirpc.language.InstallDependenciesResponse]) extends _root_.scalapb.lenses.ObjectLens[UpperPB, pulumirpc.language.InstallDependenciesResponse](_l) { + def stdout: _root_.scalapb.lenses.Lens[UpperPB, _root_.com.google.protobuf.ByteString] = field(_.stdout)((c_, f_) => c_.copy(stdout = f_)) + def stderr: _root_.scalapb.lenses.Lens[UpperPB, _root_.com.google.protobuf.ByteString] = field(_.stderr)((c_, f_) => c_.copy(stderr = f_)) + } + final val STDOUT_FIELD_NUMBER = 1 + final val STDERR_FIELD_NUMBER = 2 + def of( + stdout: _root_.com.google.protobuf.ByteString, + stderr: _root_.com.google.protobuf.ByteString + ): _root_.pulumirpc.language.InstallDependenciesResponse = _root_.pulumirpc.language.InstallDependenciesResponse( + stdout, + stderr + ) + // @@protoc_insertion_point(GeneratedMessageCompanion[pulumirpc.InstallDependenciesResponse]) +} diff --git a/core/src/main/scala/besom/rpc/pulumirpc/language/LanguageProto.scala b/core/src/main/scala/besom/rpc/pulumirpc/language/LanguageProto.scala new file mode 100644 index 00000000..5d681798 --- /dev/null +++ b/core/src/main/scala/besom/rpc/pulumirpc/language/LanguageProto.scala @@ -0,0 +1,138 @@ +// Generated by the Scala Plugin for the Protocol Buffer Compiler. +// Do not edit! +// +// Protofile syntax: PROTO3 + +package pulumirpc.language + +object LanguageProto extends _root_.scalapb.GeneratedFileObject { + lazy val dependencies: Seq[_root_.scalapb.GeneratedFileObject] = Seq( + pulumirpc.codegen.hcl.HclProto, + pulumirpc.plugin.PluginProto, + com.google.protobuf.empty.EmptyProto, + com.google.protobuf.struct.StructProto + ) + lazy val messagesCompanions: Seq[_root_.scalapb.GeneratedMessageCompanion[_ <: _root_.scalapb.GeneratedMessage]] = + Seq[_root_.scalapb.GeneratedMessageCompanion[_ <: _root_.scalapb.GeneratedMessage]]( + pulumirpc.language.ProgramInfo, + pulumirpc.language.AboutResponse, + pulumirpc.language.GetProgramDependenciesRequest, + pulumirpc.language.DependencyInfo, + pulumirpc.language.GetProgramDependenciesResponse, + pulumirpc.language.GetRequiredPluginsRequest, + pulumirpc.language.GetRequiredPluginsResponse, + pulumirpc.language.RunRequest, + pulumirpc.language.RunResponse, + pulumirpc.language.InstallDependenciesRequest, + pulumirpc.language.InstallDependenciesResponse, + pulumirpc.language.RunPluginRequest, + pulumirpc.language.RunPluginResponse, + pulumirpc.language.GenerateProgramRequest, + pulumirpc.language.GenerateProgramResponse, + pulumirpc.language.GenerateProjectRequest, + pulumirpc.language.GenerateProjectResponse, + pulumirpc.language.GeneratePackageRequest, + pulumirpc.language.GeneratePackageResponse, + pulumirpc.language.PackRequest, + pulumirpc.language.PackResponse + ) + private lazy val ProtoBytes: _root_.scala.Array[Byte] = + scalapb.Encoding.fromBase64(scala.collection.immutable.Seq( + """ChVwdWx1bWkvbGFuZ3VhZ2UucHJvdG8SCXB1bHVtaXJwYxoYcHVsdW1pL2NvZGVnZW4vaGNsLnByb3RvGhNwdWx1bWkvcGx1Z + 2luLnByb3RvGhtnb29nbGUvcHJvdG9idWYvZW1wdHkucHJvdG8aHGdvb2dsZS9wcm90b2J1Zi9zdHJ1Y3QucHJvdG8i/wEKC1Byb + 2dyYW1JbmZvEjkKDnJvb3RfZGlyZWN0b3J5GAEgASgJQhLiPw8SDXJvb3REaXJlY3RvcnlSDXJvb3REaXJlY3RvcnkSQgoRcHJvZ + 3JhbV9kaXJlY3RvcnkYAiABKAlCFeI/EhIQcHJvZ3JhbURpcmVjdG9yeVIQcHJvZ3JhbURpcmVjdG9yeRIwCgtlbnRyeV9wb2lud + BgDIAEoCUIP4j8MEgplbnRyeVBvaW50UgplbnRyeVBvaW50Ej8KB29wdGlvbnMYBCABKAsyFy5nb29nbGUucHJvdG9idWYuU3Ryd + WN0QgziPwkSB29wdGlvbnNSB29wdGlvbnMijgIKDUFib3V0UmVzcG9uc2USLwoKZXhlY3V0YWJsZRgBIAEoCUIP4j8MEgpleGVjd + XRhYmxlUgpleGVjdXRhYmxlEiYKB3ZlcnNpb24YAiABKAlCDOI/CRIHdmVyc2lvblIHdmVyc2lvbhJRCghtZXRhZGF0YRgDIAMoC + zImLnB1bHVtaXJwYy5BYm91dFJlc3BvbnNlLk1ldGFkYXRhRW50cnlCDeI/ChIIbWV0YWRhdGFSCG1ldGFkYXRhGlEKDU1ldGFkY + XRhRW50cnkSGgoDa2V5GAEgASgJQgjiPwUSA2tleVIDa2V5EiAKBXZhbHVlGAIgASgJQgriPwcSBXZhbHVlUgV2YWx1ZToCOAEin + QIKHUdldFByb2dyYW1EZXBlbmRlbmNpZXNSZXF1ZXN0EigKB3Byb2plY3QYASABKAlCDhgB4j8JEgdwcm9qZWN0Ugdwcm9qZWN0E + hwKA3B3ZBgCIAEoCUIKGAHiPwUSA3B3ZFIDcHdkEigKB3Byb2dyYW0YAyABKAlCDhgB4j8JEgdwcm9ncmFtUgdwcm9ncmFtElMKF + nRyYW5zaXRpdmVEZXBlbmRlbmNpZXMYBCABKAhCG+I/GBIWdHJhbnNpdGl2ZURlcGVuZGVuY2llc1IWdHJhbnNpdGl2ZURlcGVuZ + GVuY2llcxI1CgRpbmZvGAUgASgLMhYucHVsdW1pcnBjLlByb2dyYW1JbmZvQgniPwYSBGluZm9SBGluZm8iVwoORGVwZW5kZW5je + UluZm8SHQoEbmFtZRgBIAEoCUIJ4j8GEgRuYW1lUgRuYW1lEiYKB3ZlcnNpb24YAiABKAlCDOI/CRIHdmVyc2lvblIHdmVyc2lvb + iJyCh5HZXRQcm9ncmFtRGVwZW5kZW5jaWVzUmVzcG9uc2USUAoMZGVwZW5kZW5jaWVzGAEgAygLMhkucHVsdW1pcnBjLkRlcGVuZ + GVuY3lJbmZvQhHiPw4SDGRlcGVuZGVuY2llc1IMZGVwZW5kZW5jaWVzIsQBChlHZXRSZXF1aXJlZFBsdWdpbnNSZXF1ZXN0EigKB + 3Byb2plY3QYASABKAlCDhgB4j8JEgdwcm9qZWN0Ugdwcm9qZWN0EhwKA3B3ZBgCIAEoCUIKGAHiPwUSA3B3ZFIDcHdkEigKB3Byb + 2dyYW0YAyABKAlCDhgB4j8JEgdwcm9ncmFtUgdwcm9ncmFtEjUKBGluZm8YBCABKAsyFi5wdWx1bWlycGMuUHJvZ3JhbUluZm9CC + eI/BhIEaW5mb1IEaW5mbyJhChpHZXRSZXF1aXJlZFBsdWdpbnNSZXNwb25zZRJDCgdwbHVnaW5zGAEgAygLMhsucHVsdW1pcnBjL + lBsdWdpbkRlcGVuZGVuY3lCDOI/CRIHcGx1Z2luc1IHcGx1Z2lucyKgBgoKUnVuUmVxdWVzdBImCgdwcm9qZWN0GAEgASgJQgziP + wkSB3Byb2plY3RSB3Byb2plY3QSIAoFc3RhY2sYAiABKAlCCuI/BxIFc3RhY2tSBXN0YWNrEhoKA3B3ZBgDIAEoCUII4j8FEgNwd + 2RSA3B3ZBIoCgdwcm9ncmFtGAQgASgJQg4YAeI/CRIHcHJvZ3JhbVIHcHJvZ3JhbRIdCgRhcmdzGAUgAygJQgniPwYSBGFyZ3NSB + GFyZ3MSRgoGY29uZmlnGAYgAygLMiEucHVsdW1pcnBjLlJ1blJlcXVlc3QuQ29uZmlnRW50cnlCC+I/CBIGY29uZmlnUgZjb25ma + WcSIwoGZHJ5UnVuGAcgASgIQgviPwgSBmRyeVJ1blIGZHJ5UnVuEikKCHBhcmFsbGVsGAggASgFQg3iPwoSCHBhcmFsbGVsUghwY + XJhbGxlbBI8Cg9tb25pdG9yX2FkZHJlc3MYCSABKAlCE+I/EBIObW9uaXRvckFkZHJlc3NSDm1vbml0b3JBZGRyZXNzEiwKCXF1Z + XJ5TW9kZRgKIAEoCEIO4j8LEglxdWVyeU1vZGVSCXF1ZXJ5TW9kZRJBChBjb25maWdTZWNyZXRLZXlzGAsgAygJQhXiPxISEGNvb + mZpZ1NlY3JldEtleXNSEGNvbmZpZ1NlY3JldEtleXMSNQoMb3JnYW5pemF0aW9uGAwgASgJQhHiPw4SDG9yZ2FuaXphdGlvblIMb + 3JnYW5pemF0aW9uEl0KEWNvbmZpZ1Byb3BlcnR5TWFwGA0gASgLMhcuZ29vZ2xlLnByb3RvYnVmLlN0cnVjdEIW4j8TEhFjb25ma + WdQcm9wZXJ0eU1hcFIRY29uZmlnUHJvcGVydHlNYXASNQoEaW5mbxgOIAEoCzIWLnB1bHVtaXJwYy5Qcm9ncmFtSW5mb0IJ4j8GE + gRpbmZvUgRpbmZvGk8KC0NvbmZpZ0VudHJ5EhoKA2tleRgBIAEoCUII4j8FEgNrZXlSA2tleRIgCgV2YWx1ZRgCIAEoCUIK4j8HE + gV2YWx1ZVIFdmFsdWU6AjgBIk4KC1J1blJlc3BvbnNlEiAKBWVycm9yGAEgASgJQgriPwcSBWVycm9yUgVlcnJvchIdCgRiYWlsG + AIgASgIQgniPwYSBGJhaWxSBGJhaWwitQEKGkluc3RhbGxEZXBlbmRlbmNpZXNSZXF1ZXN0Ei4KCWRpcmVjdG9yeRgBIAEoCUIQG + AHiPwsSCWRpcmVjdG9yeVIJZGlyZWN0b3J5EjAKC2lzX3Rlcm1pbmFsGAIgASgIQg/iPwwSCmlzVGVybWluYWxSCmlzVGVybWluY + WwSNQoEaW5mbxgDIAEoCzIWLnB1bHVtaXJwYy5Qcm9ncmFtSW5mb0IJ4j8GEgRpbmZvUgRpbmZvImcKG0luc3RhbGxEZXBlbmRlb + mNpZXNSZXNwb25zZRIjCgZzdGRvdXQYASABKAxCC+I/CBIGc3Rkb3V0UgZzdGRvdXQSIwoGc3RkZXJyGAIgASgMQgviPwgSBnN0Z + GVyclIGc3RkZXJyIsoBChBSdW5QbHVnaW5SZXF1ZXN0EhoKA3B3ZBgBIAEoCUII4j8FEgNwd2RSA3B3ZBIoCgdwcm9ncmFtGAIgA + SgJQg4YAeI/CRIHcHJvZ3JhbVIHcHJvZ3JhbRIdCgRhcmdzGAMgAygJQgniPwYSBGFyZ3NSBGFyZ3MSGgoDZW52GAQgAygJQgjiP + wUSA2VudlIDZW52EjUKBGluZm8YBSABKAsyFi5wdWx1bWlycGMuUHJvZ3JhbUluZm9CCeI/BhIEaW5mb1IEaW5mbyKYAQoRUnVuU + Gx1Z2luUmVzcG9uc2USJQoGc3Rkb3V0GAEgASgMQgviPwgSBnN0ZG91dEgAUgZzdGRvdXQSJQoGc3RkZXJyGAIgASgMQgviPwgSB + nN0ZGVyckgAUgZzdGRlcnISKwoIZXhpdGNvZGUYAyABKAVCDeI/ChIIZXhpdGNvZGVIAFIIZXhpdGNvZGVCCAoGb3V0cHV0IvUBC + hZHZW5lcmF0ZVByb2dyYW1SZXF1ZXN0ElIKBnNvdXJjZRgBIAMoCzItLnB1bHVtaXJwYy5HZW5lcmF0ZVByb2dyYW1SZXF1ZXN0L + lNvdXJjZUVudHJ5QgviPwgSBnNvdXJjZVIGc291cmNlEjYKDWxvYWRlcl90YXJnZXQYAiABKAlCEeI/DhIMbG9hZGVyVGFyZ2V0U + gxsb2FkZXJUYXJnZXQaTwoLU291cmNlRW50cnkSGgoDa2V5GAEgASgJQgjiPwUSA2tleVIDa2V5EiAKBXZhbHVlGAIgASgJQgriP + wcSBXZhbHVlUgV2YWx1ZToCOAEikgIKF0dlbmVyYXRlUHJvZ3JhbVJlc3BvbnNlElEKC2RpYWdub3N0aWNzGAEgAygLMh0ucHVsd + W1pcnBjLmNvZGVnZW4uRGlhZ25vc3RpY0IQ4j8NEgtkaWFnbm9zdGljc1ILZGlhZ25vc3RpY3MSUwoGc291cmNlGAIgAygLMi4uc + HVsdW1pcnBjLkdlbmVyYXRlUHJvZ3JhbVJlc3BvbnNlLlNvdXJjZUVudHJ5QgviPwgSBnNvdXJjZVIGc291cmNlGk8KC1NvdXJjZ + UVudHJ5EhoKA2tleRgBIAEoCUII4j8FEgNrZXlSA2tleRIgCgV2YWx1ZRgCIAEoDEIK4j8HEgV2YWx1ZVIFdmFsdWU6AjgBIvwDC + hZHZW5lcmF0ZVByb2plY3RSZXF1ZXN0Ej8KEHNvdXJjZV9kaXJlY3RvcnkYASABKAlCFOI/ERIPc291cmNlRGlyZWN0b3J5Ug9zb + 3VyY2VEaXJlY3RvcnkSPwoQdGFyZ2V0X2RpcmVjdG9yeRgCIAEoCUIU4j8REg90YXJnZXREaXJlY3RvcnlSD3RhcmdldERpcmVjd + G9yeRImCgdwcm9qZWN0GAMgASgJQgziPwkSB3Byb2plY3RSB3Byb2plY3QSIwoGc3RyaWN0GAQgASgIQgviPwgSBnN0cmljdFIGc + 3RyaWN0EjYKDWxvYWRlcl90YXJnZXQYBSABKAlCEeI/DhIMbG9hZGVyVGFyZ2V0Ugxsb2FkZXJUYXJnZXQSfwoSbG9jYWxfZGVwZ + W5kZW5jaWVzGAYgAygLMjgucHVsdW1pcnBjLkdlbmVyYXRlUHJvamVjdFJlcXVlc3QuTG9jYWxEZXBlbmRlbmNpZXNFbnRyeUIW4 + j8TEhFsb2NhbERlcGVuZGVuY2llc1IRbG9jYWxEZXBlbmRlbmNpZXMaWgoWTG9jYWxEZXBlbmRlbmNpZXNFbnRyeRIaCgNrZXkYA + SABKAlCCOI/BRIDa2V5UgNrZXkSIAoFdmFsdWUYAiABKAlCCuI/BxIFdmFsdWVSBXZhbHVlOgI4ASJsChdHZW5lcmF0ZVByb2plY + 3RSZXNwb25zZRJRCgtkaWFnbm9zdGljcxgBIAMoCzIdLnB1bHVtaXJwYy5jb2RlZ2VuLkRpYWdub3N0aWNCEOI/DRILZGlhZ25vc + 3RpY3NSC2RpYWdub3N0aWNzIroEChZHZW5lcmF0ZVBhY2thZ2VSZXF1ZXN0EiwKCWRpcmVjdG9yeRgBIAEoCUIO4j8LEglkaXJlY + 3RvcnlSCWRpcmVjdG9yeRIjCgZzY2hlbWEYAiABKAlCC+I/CBIGc2NoZW1hUgZzY2hlbWESYwoLZXh0cmFfZmlsZXMYAyADKAsyM + S5wdWx1bWlycGMuR2VuZXJhdGVQYWNrYWdlUmVxdWVzdC5FeHRyYUZpbGVzRW50cnlCD+I/DBIKZXh0cmFGaWxlc1IKZXh0cmFGa + WxlcxI2Cg1sb2FkZXJfdGFyZ2V0GAQgASgJQhHiPw4SDGxvYWRlclRhcmdldFIMbG9hZGVyVGFyZ2V0En8KEmxvY2FsX2RlcGVuZ + GVuY2llcxgFIAMoCzI4LnB1bHVtaXJwYy5HZW5lcmF0ZVBhY2thZ2VSZXF1ZXN0LkxvY2FsRGVwZW5kZW5jaWVzRW50cnlCFuI/E + xIRbG9jYWxEZXBlbmRlbmNpZXNSEWxvY2FsRGVwZW5kZW5jaWVzGlMKD0V4dHJhRmlsZXNFbnRyeRIaCgNrZXkYASABKAlCCOI/B + RIDa2V5UgNrZXkSIAoFdmFsdWUYAiABKAxCCuI/BxIFdmFsdWVSBXZhbHVlOgI4ARpaChZMb2NhbERlcGVuZGVuY2llc0VudHJ5E + hoKA2tleRgBIAEoCUII4j8FEgNrZXlSA2tleRIgCgV2YWx1ZRgCIAEoCUIK4j8HEgV2YWx1ZVIFdmFsdWU6AjgBImwKF0dlbmVyY + XRlUGFja2FnZVJlc3BvbnNlElEKC2RpYWdub3N0aWNzGAEgAygLMh0ucHVsdW1pcnBjLmNvZGVnZW4uRGlhZ25vc3RpY0IQ4j8NE + gtkaWFnbm9zdGljc1ILZGlhZ25vc3RpY3MioQEKC1BhY2tSZXF1ZXN0EkIKEXBhY2thZ2VfZGlyZWN0b3J5GAEgASgJQhXiPxISE + HBhY2thZ2VEaXJlY3RvcnlSEHBhY2thZ2VEaXJlY3RvcnkSTgoVZGVzdGluYXRpb25fZGlyZWN0b3J5GAIgASgJQhniPxYSFGRlc + 3RpbmF0aW9uRGlyZWN0b3J5UhRkZXN0aW5hdGlvbkRpcmVjdG9yeSJGCgxQYWNrUmVzcG9uc2USNgoNYXJ0aWZhY3RfcGF0aBgBI + AEoCUIR4j8OEgxhcnRpZmFjdFBhdGhSDGFydGlmYWN0UGF0aDKjBwoPTGFuZ3VhZ2VSdW50aW1lEmMKEkdldFJlcXVpcmVkUGx1Z + 2lucxIkLnB1bHVtaXJwYy5HZXRSZXF1aXJlZFBsdWdpbnNSZXF1ZXN0GiUucHVsdW1pcnBjLkdldFJlcXVpcmVkUGx1Z2luc1Jlc + 3BvbnNlIgASNgoDUnVuEhUucHVsdW1pcnBjLlJ1blJlcXVlc3QaFi5wdWx1bWlycGMuUnVuUmVzcG9uc2UiABJACg1HZXRQbHVna + W5JbmZvEhYuZ29vZ2xlLnByb3RvYnVmLkVtcHR5GhUucHVsdW1pcnBjLlBsdWdpbkluZm8iABJoChNJbnN0YWxsRGVwZW5kZW5ja + WVzEiUucHVsdW1pcnBjLkluc3RhbGxEZXBlbmRlbmNpZXNSZXF1ZXN0GiYucHVsdW1pcnBjLkluc3RhbGxEZXBlbmRlbmNpZXNSZ + XNwb25zZSIAMAESOwoFQWJvdXQSFi5nb29nbGUucHJvdG9idWYuRW1wdHkaGC5wdWx1bWlycGMuQWJvdXRSZXNwb25zZSIAEm8KF + kdldFByb2dyYW1EZXBlbmRlbmNpZXMSKC5wdWx1bWlycGMuR2V0UHJvZ3JhbURlcGVuZGVuY2llc1JlcXVlc3QaKS5wdWx1bWlyc + GMuR2V0UHJvZ3JhbURlcGVuZGVuY2llc1Jlc3BvbnNlIgASSgoJUnVuUGx1Z2luEhsucHVsdW1pcnBjLlJ1blBsdWdpblJlcXVlc + 3QaHC5wdWx1bWlycGMuUnVuUGx1Z2luUmVzcG9uc2UiADABEloKD0dlbmVyYXRlUHJvZ3JhbRIhLnB1bHVtaXJwYy5HZW5lcmF0Z + VByb2dyYW1SZXF1ZXN0GiIucHVsdW1pcnBjLkdlbmVyYXRlUHJvZ3JhbVJlc3BvbnNlIgASWgoPR2VuZXJhdGVQcm9qZWN0EiEuc + HVsdW1pcnBjLkdlbmVyYXRlUHJvamVjdFJlcXVlc3QaIi5wdWx1bWlycGMuR2VuZXJhdGVQcm9qZWN0UmVzcG9uc2UiABJaCg9HZ + W5lcmF0ZVBhY2thZ2USIS5wdWx1bWlycGMuR2VuZXJhdGVQYWNrYWdlUmVxdWVzdBoiLnB1bHVtaXJwYy5HZW5lcmF0ZVBhY2thZ + 2VSZXNwb25zZSIAEjkKBFBhY2sSFi5wdWx1bWlycGMuUGFja1JlcXVlc3QaFy5wdWx1bWlycGMuUGFja1Jlc3BvbnNlIgBCNFoyZ + 2l0aHViLmNvbS9wdWx1bWkvcHVsdW1pL3Nkay92My9wcm90by9nbztwdWx1bWlycGNiBnByb3RvMw==""" + ).mkString) + lazy val scalaDescriptor: _root_.scalapb.descriptors.FileDescriptor = { + val scalaProto = com.google.protobuf.descriptor.FileDescriptorProto.parseFrom(ProtoBytes) + _root_.scalapb.descriptors.FileDescriptor.buildFrom(scalaProto, dependencies.map(_.scalaDescriptor)) + } + lazy val javaDescriptor: com.google.protobuf.Descriptors.FileDescriptor = { + val javaProto = com.google.protobuf.DescriptorProtos.FileDescriptorProto.parseFrom(ProtoBytes) + com.google.protobuf.Descriptors.FileDescriptor.buildFrom(javaProto, _root_.scala.Array( + pulumirpc.codegen.hcl.HclProto.javaDescriptor, + pulumirpc.plugin.PluginProto.javaDescriptor, + com.google.protobuf.empty.EmptyProto.javaDescriptor, + com.google.protobuf.struct.StructProto.javaDescriptor + )) + } + @deprecated("Use javaDescriptor instead. In a future version this will refer to scalaDescriptor.", "ScalaPB 0.5.47") + def descriptor: com.google.protobuf.Descriptors.FileDescriptor = javaDescriptor +} \ No newline at end of file diff --git a/core/src/main/scala/besom/rpc/pulumirpc/language/LanguageRuntimeGrpc.scala b/core/src/main/scala/besom/rpc/pulumirpc/language/LanguageRuntimeGrpc.scala new file mode 100644 index 00000000..680a14a0 --- /dev/null +++ b/core/src/main/scala/besom/rpc/pulumirpc/language/LanguageRuntimeGrpc.scala @@ -0,0 +1,443 @@ +// Generated by the Scala Plugin for the Protocol Buffer Compiler. +// Do not edit! +// +// Protofile syntax: PROTO3 + +package pulumirpc.language + + +object LanguageRuntimeGrpc { + val METHOD_GET_REQUIRED_PLUGINS: _root_.io.grpc.MethodDescriptor[pulumirpc.language.GetRequiredPluginsRequest, pulumirpc.language.GetRequiredPluginsResponse] = + _root_.io.grpc.MethodDescriptor.newBuilder() + .setType(_root_.io.grpc.MethodDescriptor.MethodType.UNARY) + .setFullMethodName(_root_.io.grpc.MethodDescriptor.generateFullMethodName("pulumirpc.LanguageRuntime", "GetRequiredPlugins")) + .setSampledToLocalTracing(true) + .setRequestMarshaller(_root_.scalapb.grpc.Marshaller.forMessage[pulumirpc.language.GetRequiredPluginsRequest]) + .setResponseMarshaller(_root_.scalapb.grpc.Marshaller.forMessage[pulumirpc.language.GetRequiredPluginsResponse]) + .setSchemaDescriptor(_root_.scalapb.grpc.ConcreteProtoMethodDescriptorSupplier.fromMethodDescriptor(pulumirpc.language.LanguageProto.javaDescriptor.getServices().get(0).getMethods().get(0))) + .build() + + val METHOD_RUN: _root_.io.grpc.MethodDescriptor[pulumirpc.language.RunRequest, pulumirpc.language.RunResponse] = + _root_.io.grpc.MethodDescriptor.newBuilder() + .setType(_root_.io.grpc.MethodDescriptor.MethodType.UNARY) + .setFullMethodName(_root_.io.grpc.MethodDescriptor.generateFullMethodName("pulumirpc.LanguageRuntime", "Run")) + .setSampledToLocalTracing(true) + .setRequestMarshaller(_root_.scalapb.grpc.Marshaller.forMessage[pulumirpc.language.RunRequest]) + .setResponseMarshaller(_root_.scalapb.grpc.Marshaller.forMessage[pulumirpc.language.RunResponse]) + .setSchemaDescriptor(_root_.scalapb.grpc.ConcreteProtoMethodDescriptorSupplier.fromMethodDescriptor(pulumirpc.language.LanguageProto.javaDescriptor.getServices().get(0).getMethods().get(1))) + .build() + + val METHOD_GET_PLUGIN_INFO: _root_.io.grpc.MethodDescriptor[com.google.protobuf.empty.Empty, pulumirpc.plugin.PluginInfo] = + _root_.io.grpc.MethodDescriptor.newBuilder() + .setType(_root_.io.grpc.MethodDescriptor.MethodType.UNARY) + .setFullMethodName(_root_.io.grpc.MethodDescriptor.generateFullMethodName("pulumirpc.LanguageRuntime", "GetPluginInfo")) + .setSampledToLocalTracing(true) + .setRequestMarshaller(_root_.scalapb.grpc.Marshaller.forMessage[com.google.protobuf.empty.Empty]) + .setResponseMarshaller(_root_.scalapb.grpc.Marshaller.forMessage[pulumirpc.plugin.PluginInfo]) + .setSchemaDescriptor(_root_.scalapb.grpc.ConcreteProtoMethodDescriptorSupplier.fromMethodDescriptor(pulumirpc.language.LanguageProto.javaDescriptor.getServices().get(0).getMethods().get(2))) + .build() + + val METHOD_INSTALL_DEPENDENCIES: _root_.io.grpc.MethodDescriptor[pulumirpc.language.InstallDependenciesRequest, pulumirpc.language.InstallDependenciesResponse] = + _root_.io.grpc.MethodDescriptor.newBuilder() + .setType(_root_.io.grpc.MethodDescriptor.MethodType.SERVER_STREAMING) + .setFullMethodName(_root_.io.grpc.MethodDescriptor.generateFullMethodName("pulumirpc.LanguageRuntime", "InstallDependencies")) + .setSampledToLocalTracing(true) + .setRequestMarshaller(_root_.scalapb.grpc.Marshaller.forMessage[pulumirpc.language.InstallDependenciesRequest]) + .setResponseMarshaller(_root_.scalapb.grpc.Marshaller.forMessage[pulumirpc.language.InstallDependenciesResponse]) + .setSchemaDescriptor(_root_.scalapb.grpc.ConcreteProtoMethodDescriptorSupplier.fromMethodDescriptor(pulumirpc.language.LanguageProto.javaDescriptor.getServices().get(0).getMethods().get(3))) + .build() + + val METHOD_ABOUT: _root_.io.grpc.MethodDescriptor[com.google.protobuf.empty.Empty, pulumirpc.language.AboutResponse] = + _root_.io.grpc.MethodDescriptor.newBuilder() + .setType(_root_.io.grpc.MethodDescriptor.MethodType.UNARY) + .setFullMethodName(_root_.io.grpc.MethodDescriptor.generateFullMethodName("pulumirpc.LanguageRuntime", "About")) + .setSampledToLocalTracing(true) + .setRequestMarshaller(_root_.scalapb.grpc.Marshaller.forMessage[com.google.protobuf.empty.Empty]) + .setResponseMarshaller(_root_.scalapb.grpc.Marshaller.forMessage[pulumirpc.language.AboutResponse]) + .setSchemaDescriptor(_root_.scalapb.grpc.ConcreteProtoMethodDescriptorSupplier.fromMethodDescriptor(pulumirpc.language.LanguageProto.javaDescriptor.getServices().get(0).getMethods().get(4))) + .build() + + val METHOD_GET_PROGRAM_DEPENDENCIES: _root_.io.grpc.MethodDescriptor[pulumirpc.language.GetProgramDependenciesRequest, pulumirpc.language.GetProgramDependenciesResponse] = + _root_.io.grpc.MethodDescriptor.newBuilder() + .setType(_root_.io.grpc.MethodDescriptor.MethodType.UNARY) + .setFullMethodName(_root_.io.grpc.MethodDescriptor.generateFullMethodName("pulumirpc.LanguageRuntime", "GetProgramDependencies")) + .setSampledToLocalTracing(true) + .setRequestMarshaller(_root_.scalapb.grpc.Marshaller.forMessage[pulumirpc.language.GetProgramDependenciesRequest]) + .setResponseMarshaller(_root_.scalapb.grpc.Marshaller.forMessage[pulumirpc.language.GetProgramDependenciesResponse]) + .setSchemaDescriptor(_root_.scalapb.grpc.ConcreteProtoMethodDescriptorSupplier.fromMethodDescriptor(pulumirpc.language.LanguageProto.javaDescriptor.getServices().get(0).getMethods().get(5))) + .build() + + val METHOD_RUN_PLUGIN: _root_.io.grpc.MethodDescriptor[pulumirpc.language.RunPluginRequest, pulumirpc.language.RunPluginResponse] = + _root_.io.grpc.MethodDescriptor.newBuilder() + .setType(_root_.io.grpc.MethodDescriptor.MethodType.SERVER_STREAMING) + .setFullMethodName(_root_.io.grpc.MethodDescriptor.generateFullMethodName("pulumirpc.LanguageRuntime", "RunPlugin")) + .setSampledToLocalTracing(true) + .setRequestMarshaller(_root_.scalapb.grpc.Marshaller.forMessage[pulumirpc.language.RunPluginRequest]) + .setResponseMarshaller(_root_.scalapb.grpc.Marshaller.forMessage[pulumirpc.language.RunPluginResponse]) + .setSchemaDescriptor(_root_.scalapb.grpc.ConcreteProtoMethodDescriptorSupplier.fromMethodDescriptor(pulumirpc.language.LanguageProto.javaDescriptor.getServices().get(0).getMethods().get(6))) + .build() + + val METHOD_GENERATE_PROGRAM: _root_.io.grpc.MethodDescriptor[pulumirpc.language.GenerateProgramRequest, pulumirpc.language.GenerateProgramResponse] = + _root_.io.grpc.MethodDescriptor.newBuilder() + .setType(_root_.io.grpc.MethodDescriptor.MethodType.UNARY) + .setFullMethodName(_root_.io.grpc.MethodDescriptor.generateFullMethodName("pulumirpc.LanguageRuntime", "GenerateProgram")) + .setSampledToLocalTracing(true) + .setRequestMarshaller(_root_.scalapb.grpc.Marshaller.forMessage[pulumirpc.language.GenerateProgramRequest]) + .setResponseMarshaller(_root_.scalapb.grpc.Marshaller.forMessage[pulumirpc.language.GenerateProgramResponse]) + .setSchemaDescriptor(_root_.scalapb.grpc.ConcreteProtoMethodDescriptorSupplier.fromMethodDescriptor(pulumirpc.language.LanguageProto.javaDescriptor.getServices().get(0).getMethods().get(7))) + .build() + + val METHOD_GENERATE_PROJECT: _root_.io.grpc.MethodDescriptor[pulumirpc.language.GenerateProjectRequest, pulumirpc.language.GenerateProjectResponse] = + _root_.io.grpc.MethodDescriptor.newBuilder() + .setType(_root_.io.grpc.MethodDescriptor.MethodType.UNARY) + .setFullMethodName(_root_.io.grpc.MethodDescriptor.generateFullMethodName("pulumirpc.LanguageRuntime", "GenerateProject")) + .setSampledToLocalTracing(true) + .setRequestMarshaller(_root_.scalapb.grpc.Marshaller.forMessage[pulumirpc.language.GenerateProjectRequest]) + .setResponseMarshaller(_root_.scalapb.grpc.Marshaller.forMessage[pulumirpc.language.GenerateProjectResponse]) + .setSchemaDescriptor(_root_.scalapb.grpc.ConcreteProtoMethodDescriptorSupplier.fromMethodDescriptor(pulumirpc.language.LanguageProto.javaDescriptor.getServices().get(0).getMethods().get(8))) + .build() + + val METHOD_GENERATE_PACKAGE: _root_.io.grpc.MethodDescriptor[pulumirpc.language.GeneratePackageRequest, pulumirpc.language.GeneratePackageResponse] = + _root_.io.grpc.MethodDescriptor.newBuilder() + .setType(_root_.io.grpc.MethodDescriptor.MethodType.UNARY) + .setFullMethodName(_root_.io.grpc.MethodDescriptor.generateFullMethodName("pulumirpc.LanguageRuntime", "GeneratePackage")) + .setSampledToLocalTracing(true) + .setRequestMarshaller(_root_.scalapb.grpc.Marshaller.forMessage[pulumirpc.language.GeneratePackageRequest]) + .setResponseMarshaller(_root_.scalapb.grpc.Marshaller.forMessage[pulumirpc.language.GeneratePackageResponse]) + .setSchemaDescriptor(_root_.scalapb.grpc.ConcreteProtoMethodDescriptorSupplier.fromMethodDescriptor(pulumirpc.language.LanguageProto.javaDescriptor.getServices().get(0).getMethods().get(9))) + .build() + + val METHOD_PACK: _root_.io.grpc.MethodDescriptor[pulumirpc.language.PackRequest, pulumirpc.language.PackResponse] = + _root_.io.grpc.MethodDescriptor.newBuilder() + .setType(_root_.io.grpc.MethodDescriptor.MethodType.UNARY) + .setFullMethodName(_root_.io.grpc.MethodDescriptor.generateFullMethodName("pulumirpc.LanguageRuntime", "Pack")) + .setSampledToLocalTracing(true) + .setRequestMarshaller(_root_.scalapb.grpc.Marshaller.forMessage[pulumirpc.language.PackRequest]) + .setResponseMarshaller(_root_.scalapb.grpc.Marshaller.forMessage[pulumirpc.language.PackResponse]) + .setSchemaDescriptor(_root_.scalapb.grpc.ConcreteProtoMethodDescriptorSupplier.fromMethodDescriptor(pulumirpc.language.LanguageProto.javaDescriptor.getServices().get(0).getMethods().get(10))) + .build() + + val SERVICE: _root_.io.grpc.ServiceDescriptor = + _root_.io.grpc.ServiceDescriptor.newBuilder("pulumirpc.LanguageRuntime") + .setSchemaDescriptor(new _root_.scalapb.grpc.ConcreteProtoFileDescriptorSupplier(pulumirpc.language.LanguageProto.javaDescriptor)) + .addMethod(METHOD_GET_REQUIRED_PLUGINS) + .addMethod(METHOD_RUN) + .addMethod(METHOD_GET_PLUGIN_INFO) + .addMethod(METHOD_INSTALL_DEPENDENCIES) + .addMethod(METHOD_ABOUT) + .addMethod(METHOD_GET_PROGRAM_DEPENDENCIES) + .addMethod(METHOD_RUN_PLUGIN) + .addMethod(METHOD_GENERATE_PROGRAM) + .addMethod(METHOD_GENERATE_PROJECT) + .addMethod(METHOD_GENERATE_PACKAGE) + .addMethod(METHOD_PACK) + .build() + + /** LanguageRuntime is the interface that the planning monitor uses to drive execution of an interpreter responsible + * for confguring and creating resource objects. + */ + trait LanguageRuntime extends _root_.scalapb.grpc.AbstractService { + override def serviceCompanion: _root_.scalapb.grpc.ServiceCompanion[LanguageRuntime] = LanguageRuntime + /** GetRequiredPlugins computes the complete set of anticipated plugins required by a program. + */ + def getRequiredPlugins(request: pulumirpc.language.GetRequiredPluginsRequest): scala.concurrent.Future[pulumirpc.language.GetRequiredPluginsResponse] + /** Run executes a program and returns its result. + */ + def run(request: pulumirpc.language.RunRequest): scala.concurrent.Future[pulumirpc.language.RunResponse] + /** GetPluginInfo returns generic information about this plugin, like its version. + */ + def getPluginInfo(request: com.google.protobuf.empty.Empty): scala.concurrent.Future[pulumirpc.plugin.PluginInfo] + /** InstallDependencies will install dependencies for the project, e.g. by running `npm install` for nodejs projects. + */ + def installDependencies(request: pulumirpc.language.InstallDependenciesRequest, responseObserver: _root_.io.grpc.stub.StreamObserver[pulumirpc.language.InstallDependenciesResponse]): _root_.scala.Unit + /** About returns information about the runtime for this language. + */ + def about(request: com.google.protobuf.empty.Empty): scala.concurrent.Future[pulumirpc.language.AboutResponse] + /** GetProgramDependencies returns the set of dependencies required by the program. + */ + def getProgramDependencies(request: pulumirpc.language.GetProgramDependenciesRequest): scala.concurrent.Future[pulumirpc.language.GetProgramDependenciesResponse] + /** RunPlugin executes a plugin program and returns its result asynchronously. + */ + def runPlugin(request: pulumirpc.language.RunPluginRequest, responseObserver: _root_.io.grpc.stub.StreamObserver[pulumirpc.language.RunPluginResponse]): _root_.scala.Unit + /** GenerateProgram generates a given PCL program into a program for this language. + */ + def generateProgram(request: pulumirpc.language.GenerateProgramRequest): scala.concurrent.Future[pulumirpc.language.GenerateProgramResponse] + /** GenerateProject generates a given PCL program into a project for this language. + */ + def generateProject(request: pulumirpc.language.GenerateProjectRequest): scala.concurrent.Future[pulumirpc.language.GenerateProjectResponse] + /** GeneratePackage generates a given pulumi package into a package for this language. + */ + def generatePackage(request: pulumirpc.language.GeneratePackageRequest): scala.concurrent.Future[pulumirpc.language.GeneratePackageResponse] + /** Pack packs a package into a language specific artifact. + */ + def pack(request: pulumirpc.language.PackRequest): scala.concurrent.Future[pulumirpc.language.PackResponse] + } + + object LanguageRuntime extends _root_.scalapb.grpc.ServiceCompanion[LanguageRuntime] { + implicit def serviceCompanion: _root_.scalapb.grpc.ServiceCompanion[LanguageRuntime] = this + def javaDescriptor: _root_.com.google.protobuf.Descriptors.ServiceDescriptor = pulumirpc.language.LanguageProto.javaDescriptor.getServices().get(0) + def scalaDescriptor: _root_.scalapb.descriptors.ServiceDescriptor = pulumirpc.language.LanguageProto.scalaDescriptor.services(0) + def bindService(serviceImpl: LanguageRuntime, executionContext: scala.concurrent.ExecutionContext): _root_.io.grpc.ServerServiceDefinition = + _root_.io.grpc.ServerServiceDefinition.builder(SERVICE) + .addMethod( + METHOD_GET_REQUIRED_PLUGINS, + _root_.io.grpc.stub.ServerCalls.asyncUnaryCall((request: pulumirpc.language.GetRequiredPluginsRequest, observer: _root_.io.grpc.stub.StreamObserver[pulumirpc.language.GetRequiredPluginsResponse]) => { + serviceImpl.getRequiredPlugins(request).onComplete(scalapb.grpc.Grpc.completeObserver(observer))( + executionContext) + })) + .addMethod( + METHOD_RUN, + _root_.io.grpc.stub.ServerCalls.asyncUnaryCall((request: pulumirpc.language.RunRequest, observer: _root_.io.grpc.stub.StreamObserver[pulumirpc.language.RunResponse]) => { + serviceImpl.run(request).onComplete(scalapb.grpc.Grpc.completeObserver(observer))( + executionContext) + })) + .addMethod( + METHOD_GET_PLUGIN_INFO, + _root_.io.grpc.stub.ServerCalls.asyncUnaryCall((request: com.google.protobuf.empty.Empty, observer: _root_.io.grpc.stub.StreamObserver[pulumirpc.plugin.PluginInfo]) => { + serviceImpl.getPluginInfo(request).onComplete(scalapb.grpc.Grpc.completeObserver(observer))( + executionContext) + })) + .addMethod( + METHOD_INSTALL_DEPENDENCIES, + _root_.io.grpc.stub.ServerCalls.asyncServerStreamingCall((request: pulumirpc.language.InstallDependenciesRequest, observer: _root_.io.grpc.stub.StreamObserver[pulumirpc.language.InstallDependenciesResponse]) => { + serviceImpl.installDependencies(request, observer) + })) + .addMethod( + METHOD_ABOUT, + _root_.io.grpc.stub.ServerCalls.asyncUnaryCall((request: com.google.protobuf.empty.Empty, observer: _root_.io.grpc.stub.StreamObserver[pulumirpc.language.AboutResponse]) => { + serviceImpl.about(request).onComplete(scalapb.grpc.Grpc.completeObserver(observer))( + executionContext) + })) + .addMethod( + METHOD_GET_PROGRAM_DEPENDENCIES, + _root_.io.grpc.stub.ServerCalls.asyncUnaryCall((request: pulumirpc.language.GetProgramDependenciesRequest, observer: _root_.io.grpc.stub.StreamObserver[pulumirpc.language.GetProgramDependenciesResponse]) => { + serviceImpl.getProgramDependencies(request).onComplete(scalapb.grpc.Grpc.completeObserver(observer))( + executionContext) + })) + .addMethod( + METHOD_RUN_PLUGIN, + _root_.io.grpc.stub.ServerCalls.asyncServerStreamingCall((request: pulumirpc.language.RunPluginRequest, observer: _root_.io.grpc.stub.StreamObserver[pulumirpc.language.RunPluginResponse]) => { + serviceImpl.runPlugin(request, observer) + })) + .addMethod( + METHOD_GENERATE_PROGRAM, + _root_.io.grpc.stub.ServerCalls.asyncUnaryCall((request: pulumirpc.language.GenerateProgramRequest, observer: _root_.io.grpc.stub.StreamObserver[pulumirpc.language.GenerateProgramResponse]) => { + serviceImpl.generateProgram(request).onComplete(scalapb.grpc.Grpc.completeObserver(observer))( + executionContext) + })) + .addMethod( + METHOD_GENERATE_PROJECT, + _root_.io.grpc.stub.ServerCalls.asyncUnaryCall((request: pulumirpc.language.GenerateProjectRequest, observer: _root_.io.grpc.stub.StreamObserver[pulumirpc.language.GenerateProjectResponse]) => { + serviceImpl.generateProject(request).onComplete(scalapb.grpc.Grpc.completeObserver(observer))( + executionContext) + })) + .addMethod( + METHOD_GENERATE_PACKAGE, + _root_.io.grpc.stub.ServerCalls.asyncUnaryCall((request: pulumirpc.language.GeneratePackageRequest, observer: _root_.io.grpc.stub.StreamObserver[pulumirpc.language.GeneratePackageResponse]) => { + serviceImpl.generatePackage(request).onComplete(scalapb.grpc.Grpc.completeObserver(observer))( + executionContext) + })) + .addMethod( + METHOD_PACK, + _root_.io.grpc.stub.ServerCalls.asyncUnaryCall((request: pulumirpc.language.PackRequest, observer: _root_.io.grpc.stub.StreamObserver[pulumirpc.language.PackResponse]) => { + serviceImpl.pack(request).onComplete(scalapb.grpc.Grpc.completeObserver(observer))( + executionContext) + })) + .build() + } + + /** LanguageRuntime is the interface that the planning monitor uses to drive execution of an interpreter responsible + * for confguring and creating resource objects. + */ + trait LanguageRuntimeBlockingClient { + def serviceCompanion: _root_.scalapb.grpc.ServiceCompanion[LanguageRuntime] = LanguageRuntime + /** GetRequiredPlugins computes the complete set of anticipated plugins required by a program. + */ + def getRequiredPlugins(request: pulumirpc.language.GetRequiredPluginsRequest): pulumirpc.language.GetRequiredPluginsResponse + /** Run executes a program and returns its result. + */ + def run(request: pulumirpc.language.RunRequest): pulumirpc.language.RunResponse + /** GetPluginInfo returns generic information about this plugin, like its version. + */ + def getPluginInfo(request: com.google.protobuf.empty.Empty): pulumirpc.plugin.PluginInfo + /** InstallDependencies will install dependencies for the project, e.g. by running `npm install` for nodejs projects. + */ + def installDependencies(request: pulumirpc.language.InstallDependenciesRequest): scala.collection.Iterator[pulumirpc.language.InstallDependenciesResponse] + /** About returns information about the runtime for this language. + */ + def about(request: com.google.protobuf.empty.Empty): pulumirpc.language.AboutResponse + /** GetProgramDependencies returns the set of dependencies required by the program. + */ + def getProgramDependencies(request: pulumirpc.language.GetProgramDependenciesRequest): pulumirpc.language.GetProgramDependenciesResponse + /** RunPlugin executes a plugin program and returns its result asynchronously. + */ + def runPlugin(request: pulumirpc.language.RunPluginRequest): scala.collection.Iterator[pulumirpc.language.RunPluginResponse] + /** GenerateProgram generates a given PCL program into a program for this language. + */ + def generateProgram(request: pulumirpc.language.GenerateProgramRequest): pulumirpc.language.GenerateProgramResponse + /** GenerateProject generates a given PCL program into a project for this language. + */ + def generateProject(request: pulumirpc.language.GenerateProjectRequest): pulumirpc.language.GenerateProjectResponse + /** GeneratePackage generates a given pulumi package into a package for this language. + */ + def generatePackage(request: pulumirpc.language.GeneratePackageRequest): pulumirpc.language.GeneratePackageResponse + /** Pack packs a package into a language specific artifact. + */ + def pack(request: pulumirpc.language.PackRequest): pulumirpc.language.PackResponse + } + + class LanguageRuntimeBlockingStub(channel: _root_.io.grpc.Channel, options: _root_.io.grpc.CallOptions = _root_.io.grpc.CallOptions.DEFAULT) extends _root_.io.grpc.stub.AbstractStub[LanguageRuntimeBlockingStub](channel, options) with LanguageRuntimeBlockingClient { + /** GetRequiredPlugins computes the complete set of anticipated plugins required by a program. + */ + override def getRequiredPlugins(request: pulumirpc.language.GetRequiredPluginsRequest): pulumirpc.language.GetRequiredPluginsResponse = { + _root_.scalapb.grpc.ClientCalls.blockingUnaryCall(channel, METHOD_GET_REQUIRED_PLUGINS, options, request) + } + + /** Run executes a program and returns its result. + */ + override def run(request: pulumirpc.language.RunRequest): pulumirpc.language.RunResponse = { + _root_.scalapb.grpc.ClientCalls.blockingUnaryCall(channel, METHOD_RUN, options, request) + } + + /** GetPluginInfo returns generic information about this plugin, like its version. + */ + override def getPluginInfo(request: com.google.protobuf.empty.Empty): pulumirpc.plugin.PluginInfo = { + _root_.scalapb.grpc.ClientCalls.blockingUnaryCall(channel, METHOD_GET_PLUGIN_INFO, options, request) + } + + /** InstallDependencies will install dependencies for the project, e.g. by running `npm install` for nodejs projects. + */ + override def installDependencies(request: pulumirpc.language.InstallDependenciesRequest): scala.collection.Iterator[pulumirpc.language.InstallDependenciesResponse] = { + _root_.scalapb.grpc.ClientCalls.blockingServerStreamingCall(channel, METHOD_INSTALL_DEPENDENCIES, options, request) + } + + /** About returns information about the runtime for this language. + */ + override def about(request: com.google.protobuf.empty.Empty): pulumirpc.language.AboutResponse = { + _root_.scalapb.grpc.ClientCalls.blockingUnaryCall(channel, METHOD_ABOUT, options, request) + } + + /** GetProgramDependencies returns the set of dependencies required by the program. + */ + override def getProgramDependencies(request: pulumirpc.language.GetProgramDependenciesRequest): pulumirpc.language.GetProgramDependenciesResponse = { + _root_.scalapb.grpc.ClientCalls.blockingUnaryCall(channel, METHOD_GET_PROGRAM_DEPENDENCIES, options, request) + } + + /** RunPlugin executes a plugin program and returns its result asynchronously. + */ + override def runPlugin(request: pulumirpc.language.RunPluginRequest): scala.collection.Iterator[pulumirpc.language.RunPluginResponse] = { + _root_.scalapb.grpc.ClientCalls.blockingServerStreamingCall(channel, METHOD_RUN_PLUGIN, options, request) + } + + /** GenerateProgram generates a given PCL program into a program for this language. + */ + override def generateProgram(request: pulumirpc.language.GenerateProgramRequest): pulumirpc.language.GenerateProgramResponse = { + _root_.scalapb.grpc.ClientCalls.blockingUnaryCall(channel, METHOD_GENERATE_PROGRAM, options, request) + } + + /** GenerateProject generates a given PCL program into a project for this language. + */ + override def generateProject(request: pulumirpc.language.GenerateProjectRequest): pulumirpc.language.GenerateProjectResponse = { + _root_.scalapb.grpc.ClientCalls.blockingUnaryCall(channel, METHOD_GENERATE_PROJECT, options, request) + } + + /** GeneratePackage generates a given pulumi package into a package for this language. + */ + override def generatePackage(request: pulumirpc.language.GeneratePackageRequest): pulumirpc.language.GeneratePackageResponse = { + _root_.scalapb.grpc.ClientCalls.blockingUnaryCall(channel, METHOD_GENERATE_PACKAGE, options, request) + } + + /** Pack packs a package into a language specific artifact. + */ + override def pack(request: pulumirpc.language.PackRequest): pulumirpc.language.PackResponse = { + _root_.scalapb.grpc.ClientCalls.blockingUnaryCall(channel, METHOD_PACK, options, request) + } + + override def build(channel: _root_.io.grpc.Channel, options: _root_.io.grpc.CallOptions): LanguageRuntimeBlockingStub = new LanguageRuntimeBlockingStub(channel, options) + } + + class LanguageRuntimeStub(channel: _root_.io.grpc.Channel, options: _root_.io.grpc.CallOptions = _root_.io.grpc.CallOptions.DEFAULT) extends _root_.io.grpc.stub.AbstractStub[LanguageRuntimeStub](channel, options) with LanguageRuntime { + /** GetRequiredPlugins computes the complete set of anticipated plugins required by a program. + */ + override def getRequiredPlugins(request: pulumirpc.language.GetRequiredPluginsRequest): scala.concurrent.Future[pulumirpc.language.GetRequiredPluginsResponse] = { + _root_.scalapb.grpc.ClientCalls.asyncUnaryCall(channel, METHOD_GET_REQUIRED_PLUGINS, options, request) + } + + /** Run executes a program and returns its result. + */ + override def run(request: pulumirpc.language.RunRequest): scala.concurrent.Future[pulumirpc.language.RunResponse] = { + _root_.scalapb.grpc.ClientCalls.asyncUnaryCall(channel, METHOD_RUN, options, request) + } + + /** GetPluginInfo returns generic information about this plugin, like its version. + */ + override def getPluginInfo(request: com.google.protobuf.empty.Empty): scala.concurrent.Future[pulumirpc.plugin.PluginInfo] = { + _root_.scalapb.grpc.ClientCalls.asyncUnaryCall(channel, METHOD_GET_PLUGIN_INFO, options, request) + } + + /** InstallDependencies will install dependencies for the project, e.g. by running `npm install` for nodejs projects. + */ + override def installDependencies(request: pulumirpc.language.InstallDependenciesRequest, responseObserver: _root_.io.grpc.stub.StreamObserver[pulumirpc.language.InstallDependenciesResponse]): _root_.scala.Unit = { + _root_.scalapb.grpc.ClientCalls.asyncServerStreamingCall(channel, METHOD_INSTALL_DEPENDENCIES, options, request, responseObserver) + } + + /** About returns information about the runtime for this language. + */ + override def about(request: com.google.protobuf.empty.Empty): scala.concurrent.Future[pulumirpc.language.AboutResponse] = { + _root_.scalapb.grpc.ClientCalls.asyncUnaryCall(channel, METHOD_ABOUT, options, request) + } + + /** GetProgramDependencies returns the set of dependencies required by the program. + */ + override def getProgramDependencies(request: pulumirpc.language.GetProgramDependenciesRequest): scala.concurrent.Future[pulumirpc.language.GetProgramDependenciesResponse] = { + _root_.scalapb.grpc.ClientCalls.asyncUnaryCall(channel, METHOD_GET_PROGRAM_DEPENDENCIES, options, request) + } + + /** RunPlugin executes a plugin program and returns its result asynchronously. + */ + override def runPlugin(request: pulumirpc.language.RunPluginRequest, responseObserver: _root_.io.grpc.stub.StreamObserver[pulumirpc.language.RunPluginResponse]): _root_.scala.Unit = { + _root_.scalapb.grpc.ClientCalls.asyncServerStreamingCall(channel, METHOD_RUN_PLUGIN, options, request, responseObserver) + } + + /** GenerateProgram generates a given PCL program into a program for this language. + */ + override def generateProgram(request: pulumirpc.language.GenerateProgramRequest): scala.concurrent.Future[pulumirpc.language.GenerateProgramResponse] = { + _root_.scalapb.grpc.ClientCalls.asyncUnaryCall(channel, METHOD_GENERATE_PROGRAM, options, request) + } + + /** GenerateProject generates a given PCL program into a project for this language. + */ + override def generateProject(request: pulumirpc.language.GenerateProjectRequest): scala.concurrent.Future[pulumirpc.language.GenerateProjectResponse] = { + _root_.scalapb.grpc.ClientCalls.asyncUnaryCall(channel, METHOD_GENERATE_PROJECT, options, request) + } + + /** GeneratePackage generates a given pulumi package into a package for this language. + */ + override def generatePackage(request: pulumirpc.language.GeneratePackageRequest): scala.concurrent.Future[pulumirpc.language.GeneratePackageResponse] = { + _root_.scalapb.grpc.ClientCalls.asyncUnaryCall(channel, METHOD_GENERATE_PACKAGE, options, request) + } + + /** Pack packs a package into a language specific artifact. + */ + override def pack(request: pulumirpc.language.PackRequest): scala.concurrent.Future[pulumirpc.language.PackResponse] = { + _root_.scalapb.grpc.ClientCalls.asyncUnaryCall(channel, METHOD_PACK, options, request) + } + + override def build(channel: _root_.io.grpc.Channel, options: _root_.io.grpc.CallOptions): LanguageRuntimeStub = new LanguageRuntimeStub(channel, options) + } + + object LanguageRuntimeStub extends _root_.io.grpc.stub.AbstractStub.StubFactory[LanguageRuntimeStub] { + override def newStub(channel: _root_.io.grpc.Channel, options: _root_.io.grpc.CallOptions): LanguageRuntimeStub = new LanguageRuntimeStub(channel, options) + + implicit val stubFactory: _root_.io.grpc.stub.AbstractStub.StubFactory[LanguageRuntimeStub] = this + } + + def bindService(serviceImpl: LanguageRuntime, executionContext: scala.concurrent.ExecutionContext): _root_.io.grpc.ServerServiceDefinition = LanguageRuntime.bindService(serviceImpl, executionContext) + + def blockingStub(channel: _root_.io.grpc.Channel): LanguageRuntimeBlockingStub = new LanguageRuntimeBlockingStub(channel) + + def stub(channel: _root_.io.grpc.Channel): LanguageRuntimeStub = new LanguageRuntimeStub(channel) + + def javaDescriptor: _root_.com.google.protobuf.Descriptors.ServiceDescriptor = pulumirpc.language.LanguageProto.javaDescriptor.getServices().get(0) + +} \ No newline at end of file diff --git a/core/src/main/scala/besom/rpc/pulumirpc/language/PackRequest.scala b/core/src/main/scala/besom/rpc/pulumirpc/language/PackRequest.scala new file mode 100644 index 00000000..60aaf839 --- /dev/null +++ b/core/src/main/scala/besom/rpc/pulumirpc/language/PackRequest.scala @@ -0,0 +1,152 @@ +// Generated by the Scala Plugin for the Protocol Buffer Compiler. +// Do not edit! +// +// Protofile syntax: PROTO3 + +package pulumirpc.language + +/** @param packageDirectory + * the directory of a package to pack. + * @param destinationDirectory + * the directory to write the packed artifact to. + */ +@SerialVersionUID(0L) +final case class PackRequest( + packageDirectory: _root_.scala.Predef.String = "", + destinationDirectory: _root_.scala.Predef.String = "", + unknownFields: _root_.scalapb.UnknownFieldSet = _root_.scalapb.UnknownFieldSet.empty + ) extends scalapb.GeneratedMessage with scalapb.lenses.Updatable[PackRequest] { + @transient + private[this] var __serializedSizeMemoized: _root_.scala.Int = 0 + private[this] def __computeSerializedSize(): _root_.scala.Int = { + var __size = 0 + + { + val __value = packageDirectory + if (!__value.isEmpty) { + __size += _root_.com.google.protobuf.CodedOutputStream.computeStringSize(1, __value) + } + }; + + { + val __value = destinationDirectory + if (!__value.isEmpty) { + __size += _root_.com.google.protobuf.CodedOutputStream.computeStringSize(2, __value) + } + }; + __size += unknownFields.serializedSize + __size + } + override def serializedSize: _root_.scala.Int = { + var __size = __serializedSizeMemoized + if (__size == 0) { + __size = __computeSerializedSize() + 1 + __serializedSizeMemoized = __size + } + __size - 1 + + } + def writeTo(`_output__`: _root_.com.google.protobuf.CodedOutputStream): _root_.scala.Unit = { + { + val __v = packageDirectory + if (!__v.isEmpty) { + _output__.writeString(1, __v) + } + }; + { + val __v = destinationDirectory + if (!__v.isEmpty) { + _output__.writeString(2, __v) + } + }; + unknownFields.writeTo(_output__) + } + def withPackageDirectory(__v: _root_.scala.Predef.String): PackRequest = copy(packageDirectory = __v) + def withDestinationDirectory(__v: _root_.scala.Predef.String): PackRequest = copy(destinationDirectory = __v) + def withUnknownFields(__v: _root_.scalapb.UnknownFieldSet) = copy(unknownFields = __v) + def discardUnknownFields = copy(unknownFields = _root_.scalapb.UnknownFieldSet.empty) + def getFieldByNumber(__fieldNumber: _root_.scala.Int): _root_.scala.Any = { + (__fieldNumber: @_root_.scala.unchecked) match { + case 1 => { + val __t = packageDirectory + if (__t != "") __t else null + } + case 2 => { + val __t = destinationDirectory + if (__t != "") __t else null + } + } + } + def getField(__field: _root_.scalapb.descriptors.FieldDescriptor): _root_.scalapb.descriptors.PValue = { + _root_.scala.Predef.require(__field.containingMessage eq companion.scalaDescriptor) + (__field.number: @_root_.scala.unchecked) match { + case 1 => _root_.scalapb.descriptors.PString(packageDirectory) + case 2 => _root_.scalapb.descriptors.PString(destinationDirectory) + } + } + def toProtoString: _root_.scala.Predef.String = _root_.scalapb.TextFormat.printToUnicodeString(this) + def companion: pulumirpc.language.PackRequest.type = pulumirpc.language.PackRequest + // @@protoc_insertion_point(GeneratedMessage[pulumirpc.PackRequest]) +} + +object PackRequest extends scalapb.GeneratedMessageCompanion[pulumirpc.language.PackRequest] { + implicit def messageCompanion: scalapb.GeneratedMessageCompanion[pulumirpc.language.PackRequest] = this + def parseFrom(`_input__`: _root_.com.google.protobuf.CodedInputStream): pulumirpc.language.PackRequest = { + var __packageDirectory: _root_.scala.Predef.String = "" + var __destinationDirectory: _root_.scala.Predef.String = "" + var `_unknownFields__`: _root_.scalapb.UnknownFieldSet.Builder = null + var _done__ = false + while (!_done__) { + val _tag__ = _input__.readTag() + _tag__ match { + case 0 => _done__ = true + case 10 => + __packageDirectory = _input__.readStringRequireUtf8() + case 18 => + __destinationDirectory = _input__.readStringRequireUtf8() + case tag => + if (_unknownFields__ == null) { + _unknownFields__ = new _root_.scalapb.UnknownFieldSet.Builder() + } + _unknownFields__.parseField(tag, _input__) + } + } + pulumirpc.language.PackRequest( + packageDirectory = __packageDirectory, + destinationDirectory = __destinationDirectory, + unknownFields = if (_unknownFields__ == null) _root_.scalapb.UnknownFieldSet.empty else _unknownFields__.result() + ) + } + implicit def messageReads: _root_.scalapb.descriptors.Reads[pulumirpc.language.PackRequest] = _root_.scalapb.descriptors.Reads{ + case _root_.scalapb.descriptors.PMessage(__fieldsMap) => + _root_.scala.Predef.require(__fieldsMap.keys.forall(_.containingMessage eq scalaDescriptor), "FieldDescriptor does not match message type.") + pulumirpc.language.PackRequest( + packageDirectory = __fieldsMap.get(scalaDescriptor.findFieldByNumber(1).get).map(_.as[_root_.scala.Predef.String]).getOrElse(""), + destinationDirectory = __fieldsMap.get(scalaDescriptor.findFieldByNumber(2).get).map(_.as[_root_.scala.Predef.String]).getOrElse("") + ) + case _ => throw new RuntimeException("Expected PMessage") + } + def javaDescriptor: _root_.com.google.protobuf.Descriptors.Descriptor = LanguageProto.javaDescriptor.getMessageTypes().get(19) + def scalaDescriptor: _root_.scalapb.descriptors.Descriptor = LanguageProto.scalaDescriptor.messages(19) + def messageCompanionForFieldNumber(__number: _root_.scala.Int): _root_.scalapb.GeneratedMessageCompanion[_] = throw new MatchError(__number) + lazy val nestedMessagesCompanions: Seq[_root_.scalapb.GeneratedMessageCompanion[_ <: _root_.scalapb.GeneratedMessage]] = Seq.empty + def enumCompanionForFieldNumber(__fieldNumber: _root_.scala.Int): _root_.scalapb.GeneratedEnumCompanion[_] = throw new MatchError(__fieldNumber) + lazy val defaultInstance = pulumirpc.language.PackRequest( + packageDirectory = "", + destinationDirectory = "" + ) + implicit class PackRequestLens[UpperPB](_l: _root_.scalapb.lenses.Lens[UpperPB, pulumirpc.language.PackRequest]) extends _root_.scalapb.lenses.ObjectLens[UpperPB, pulumirpc.language.PackRequest](_l) { + def packageDirectory: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Predef.String] = field(_.packageDirectory)((c_, f_) => c_.copy(packageDirectory = f_)) + def destinationDirectory: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Predef.String] = field(_.destinationDirectory)((c_, f_) => c_.copy(destinationDirectory = f_)) + } + final val PACKAGE_DIRECTORY_FIELD_NUMBER = 1 + final val DESTINATION_DIRECTORY_FIELD_NUMBER = 2 + def of( + packageDirectory: _root_.scala.Predef.String, + destinationDirectory: _root_.scala.Predef.String + ): _root_.pulumirpc.language.PackRequest = _root_.pulumirpc.language.PackRequest( + packageDirectory, + destinationDirectory + ) + // @@protoc_insertion_point(GeneratedMessageCompanion[pulumirpc.PackRequest]) +} diff --git a/core/src/main/scala/besom/rpc/pulumirpc/language/PackResponse.scala b/core/src/main/scala/besom/rpc/pulumirpc/language/PackResponse.scala new file mode 100644 index 00000000..48d47ec1 --- /dev/null +++ b/core/src/main/scala/besom/rpc/pulumirpc/language/PackResponse.scala @@ -0,0 +1,120 @@ +// Generated by the Scala Plugin for the Protocol Buffer Compiler. +// Do not edit! +// +// Protofile syntax: PROTO3 + +package pulumirpc.language + +/** @param artifactPath + * the full path of the packed artifact. + */ +@SerialVersionUID(0L) +final case class PackResponse( + artifactPath: _root_.scala.Predef.String = "", + unknownFields: _root_.scalapb.UnknownFieldSet = _root_.scalapb.UnknownFieldSet.empty + ) extends scalapb.GeneratedMessage with scalapb.lenses.Updatable[PackResponse] { + @transient + private[this] var __serializedSizeMemoized: _root_.scala.Int = 0 + private[this] def __computeSerializedSize(): _root_.scala.Int = { + var __size = 0 + + { + val __value = artifactPath + if (!__value.isEmpty) { + __size += _root_.com.google.protobuf.CodedOutputStream.computeStringSize(1, __value) + } + }; + __size += unknownFields.serializedSize + __size + } + override def serializedSize: _root_.scala.Int = { + var __size = __serializedSizeMemoized + if (__size == 0) { + __size = __computeSerializedSize() + 1 + __serializedSizeMemoized = __size + } + __size - 1 + + } + def writeTo(`_output__`: _root_.com.google.protobuf.CodedOutputStream): _root_.scala.Unit = { + { + val __v = artifactPath + if (!__v.isEmpty) { + _output__.writeString(1, __v) + } + }; + unknownFields.writeTo(_output__) + } + def withArtifactPath(__v: _root_.scala.Predef.String): PackResponse = copy(artifactPath = __v) + def withUnknownFields(__v: _root_.scalapb.UnknownFieldSet) = copy(unknownFields = __v) + def discardUnknownFields = copy(unknownFields = _root_.scalapb.UnknownFieldSet.empty) + def getFieldByNumber(__fieldNumber: _root_.scala.Int): _root_.scala.Any = { + (__fieldNumber: @_root_.scala.unchecked) match { + case 1 => { + val __t = artifactPath + if (__t != "") __t else null + } + } + } + def getField(__field: _root_.scalapb.descriptors.FieldDescriptor): _root_.scalapb.descriptors.PValue = { + _root_.scala.Predef.require(__field.containingMessage eq companion.scalaDescriptor) + (__field.number: @_root_.scala.unchecked) match { + case 1 => _root_.scalapb.descriptors.PString(artifactPath) + } + } + def toProtoString: _root_.scala.Predef.String = _root_.scalapb.TextFormat.printToUnicodeString(this) + def companion: pulumirpc.language.PackResponse.type = pulumirpc.language.PackResponse + // @@protoc_insertion_point(GeneratedMessage[pulumirpc.PackResponse]) +} + +object PackResponse extends scalapb.GeneratedMessageCompanion[pulumirpc.language.PackResponse] { + implicit def messageCompanion: scalapb.GeneratedMessageCompanion[pulumirpc.language.PackResponse] = this + def parseFrom(`_input__`: _root_.com.google.protobuf.CodedInputStream): pulumirpc.language.PackResponse = { + var __artifactPath: _root_.scala.Predef.String = "" + var `_unknownFields__`: _root_.scalapb.UnknownFieldSet.Builder = null + var _done__ = false + while (!_done__) { + val _tag__ = _input__.readTag() + _tag__ match { + case 0 => _done__ = true + case 10 => + __artifactPath = _input__.readStringRequireUtf8() + case tag => + if (_unknownFields__ == null) { + _unknownFields__ = new _root_.scalapb.UnknownFieldSet.Builder() + } + _unknownFields__.parseField(tag, _input__) + } + } + pulumirpc.language.PackResponse( + artifactPath = __artifactPath, + unknownFields = if (_unknownFields__ == null) _root_.scalapb.UnknownFieldSet.empty else _unknownFields__.result() + ) + } + implicit def messageReads: _root_.scalapb.descriptors.Reads[pulumirpc.language.PackResponse] = _root_.scalapb.descriptors.Reads{ + case _root_.scalapb.descriptors.PMessage(__fieldsMap) => + _root_.scala.Predef.require(__fieldsMap.keys.forall(_.containingMessage eq scalaDescriptor), "FieldDescriptor does not match message type.") + pulumirpc.language.PackResponse( + artifactPath = __fieldsMap.get(scalaDescriptor.findFieldByNumber(1).get).map(_.as[_root_.scala.Predef.String]).getOrElse("") + ) + case _ => throw new RuntimeException("Expected PMessage") + } + def javaDescriptor: _root_.com.google.protobuf.Descriptors.Descriptor = LanguageProto.javaDescriptor.getMessageTypes().get(20) + def scalaDescriptor: _root_.scalapb.descriptors.Descriptor = LanguageProto.scalaDescriptor.messages(20) + def messageCompanionForFieldNumber(__number: _root_.scala.Int): _root_.scalapb.GeneratedMessageCompanion[_] = throw new MatchError(__number) + lazy val nestedMessagesCompanions: Seq[_root_.scalapb.GeneratedMessageCompanion[_ <: _root_.scalapb.GeneratedMessage]] = Seq.empty + def enumCompanionForFieldNumber(__fieldNumber: _root_.scala.Int): _root_.scalapb.GeneratedEnumCompanion[_] = throw new MatchError(__fieldNumber) + lazy val defaultInstance = pulumirpc.language.PackResponse( + artifactPath = "" + ) + implicit class PackResponseLens[UpperPB](_l: _root_.scalapb.lenses.Lens[UpperPB, pulumirpc.language.PackResponse]) extends _root_.scalapb.lenses.ObjectLens[UpperPB, pulumirpc.language.PackResponse](_l) { + def artifactPath: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Predef.String] = field(_.artifactPath)((c_, f_) => c_.copy(artifactPath = f_)) + } + final val ARTIFACT_PATH_FIELD_NUMBER = 1 + def of( + artifactPath: _root_.scala.Predef.String + ): _root_.pulumirpc.language.PackResponse = _root_.pulumirpc.language.PackResponse( + artifactPath + ) + // @@protoc_insertion_point(GeneratedMessageCompanion[pulumirpc.PackResponse]) +} diff --git a/core/src/main/scala/besom/rpc/pulumirpc/language/ProgramInfo.scala b/core/src/main/scala/besom/rpc/pulumirpc/language/ProgramInfo.scala new file mode 100644 index 00000000..ae0bf047 --- /dev/null +++ b/core/src/main/scala/besom/rpc/pulumirpc/language/ProgramInfo.scala @@ -0,0 +1,226 @@ +// Generated by the Scala Plugin for the Protocol Buffer Compiler. +// Do not edit! +// +// Protofile syntax: PROTO3 + +package pulumirpc.language + +/** ProgramInfo are the common set of options that a language runtime needs to execute or query a program. This + * is filled in by the engine based on where the `Pulumi.yaml` file was, the `runtime.options` property, and + * the `main` property. + * + * @param rootDirectory + * the root of the project, where the `Pulumi.yaml` file is located. + * @param programDirectory + * the absolute path to the directory of the program to execute. Generally, but not required to be, + * underneath the root directory. + * @param entryPoint + * the entry point of the program, normally '.' meaning to just use the program directory, but can also be + * a filename inside the program directory. How that filename is interpreted, if at all, is language + * specific. + * @param options + * JSON style options from the `Pulumi.yaml` runtime options section. + */ +@SerialVersionUID(0L) +final case class ProgramInfo( + rootDirectory: _root_.scala.Predef.String = "", + programDirectory: _root_.scala.Predef.String = "", + entryPoint: _root_.scala.Predef.String = "", + options: _root_.scala.Option[com.google.protobuf.struct.Struct] = _root_.scala.None, + unknownFields: _root_.scalapb.UnknownFieldSet = _root_.scalapb.UnknownFieldSet.empty + ) extends scalapb.GeneratedMessage with scalapb.lenses.Updatable[ProgramInfo] { + @transient + private[this] var __serializedSizeMemoized: _root_.scala.Int = 0 + private[this] def __computeSerializedSize(): _root_.scala.Int = { + var __size = 0 + + { + val __value = rootDirectory + if (!__value.isEmpty) { + __size += _root_.com.google.protobuf.CodedOutputStream.computeStringSize(1, __value) + } + }; + + { + val __value = programDirectory + if (!__value.isEmpty) { + __size += _root_.com.google.protobuf.CodedOutputStream.computeStringSize(2, __value) + } + }; + + { + val __value = entryPoint + if (!__value.isEmpty) { + __size += _root_.com.google.protobuf.CodedOutputStream.computeStringSize(3, __value) + } + }; + if (options.isDefined) { + val __value = options.get + __size += 1 + _root_.com.google.protobuf.CodedOutputStream.computeUInt32SizeNoTag(__value.serializedSize) + __value.serializedSize + }; + __size += unknownFields.serializedSize + __size + } + override def serializedSize: _root_.scala.Int = { + var __size = __serializedSizeMemoized + if (__size == 0) { + __size = __computeSerializedSize() + 1 + __serializedSizeMemoized = __size + } + __size - 1 + + } + def writeTo(`_output__`: _root_.com.google.protobuf.CodedOutputStream): _root_.scala.Unit = { + { + val __v = rootDirectory + if (!__v.isEmpty) { + _output__.writeString(1, __v) + } + }; + { + val __v = programDirectory + if (!__v.isEmpty) { + _output__.writeString(2, __v) + } + }; + { + val __v = entryPoint + if (!__v.isEmpty) { + _output__.writeString(3, __v) + } + }; + options.foreach { __v => + val __m = __v + _output__.writeTag(4, 2) + _output__.writeUInt32NoTag(__m.serializedSize) + __m.writeTo(_output__) + }; + unknownFields.writeTo(_output__) + } + def withRootDirectory(__v: _root_.scala.Predef.String): ProgramInfo = copy(rootDirectory = __v) + def withProgramDirectory(__v: _root_.scala.Predef.String): ProgramInfo = copy(programDirectory = __v) + def withEntryPoint(__v: _root_.scala.Predef.String): ProgramInfo = copy(entryPoint = __v) + def getOptions: com.google.protobuf.struct.Struct = options.getOrElse(com.google.protobuf.struct.Struct.defaultInstance) + def clearOptions: ProgramInfo = copy(options = _root_.scala.None) + def withOptions(__v: com.google.protobuf.struct.Struct): ProgramInfo = copy(options = Option(__v)) + def withUnknownFields(__v: _root_.scalapb.UnknownFieldSet) = copy(unknownFields = __v) + def discardUnknownFields = copy(unknownFields = _root_.scalapb.UnknownFieldSet.empty) + def getFieldByNumber(__fieldNumber: _root_.scala.Int): _root_.scala.Any = { + (__fieldNumber: @_root_.scala.unchecked) match { + case 1 => { + val __t = rootDirectory + if (__t != "") __t else null + } + case 2 => { + val __t = programDirectory + if (__t != "") __t else null + } + case 3 => { + val __t = entryPoint + if (__t != "") __t else null + } + case 4 => options.orNull + } + } + def getField(__field: _root_.scalapb.descriptors.FieldDescriptor): _root_.scalapb.descriptors.PValue = { + _root_.scala.Predef.require(__field.containingMessage eq companion.scalaDescriptor) + (__field.number: @_root_.scala.unchecked) match { + case 1 => _root_.scalapb.descriptors.PString(rootDirectory) + case 2 => _root_.scalapb.descriptors.PString(programDirectory) + case 3 => _root_.scalapb.descriptors.PString(entryPoint) + case 4 => options.map(_.toPMessage).getOrElse(_root_.scalapb.descriptors.PEmpty) + } + } + def toProtoString: _root_.scala.Predef.String = _root_.scalapb.TextFormat.printToUnicodeString(this) + def companion: pulumirpc.language.ProgramInfo.type = pulumirpc.language.ProgramInfo + // @@protoc_insertion_point(GeneratedMessage[pulumirpc.ProgramInfo]) +} + +object ProgramInfo extends scalapb.GeneratedMessageCompanion[pulumirpc.language.ProgramInfo] { + implicit def messageCompanion: scalapb.GeneratedMessageCompanion[pulumirpc.language.ProgramInfo] = this + def parseFrom(`_input__`: _root_.com.google.protobuf.CodedInputStream): pulumirpc.language.ProgramInfo = { + var __rootDirectory: _root_.scala.Predef.String = "" + var __programDirectory: _root_.scala.Predef.String = "" + var __entryPoint: _root_.scala.Predef.String = "" + var __options: _root_.scala.Option[com.google.protobuf.struct.Struct] = _root_.scala.None + var `_unknownFields__`: _root_.scalapb.UnknownFieldSet.Builder = null + var _done__ = false + while (!_done__) { + val _tag__ = _input__.readTag() + _tag__ match { + case 0 => _done__ = true + case 10 => + __rootDirectory = _input__.readStringRequireUtf8() + case 18 => + __programDirectory = _input__.readStringRequireUtf8() + case 26 => + __entryPoint = _input__.readStringRequireUtf8() + case 34 => + __options = _root_.scala.Option(__options.fold(_root_.scalapb.LiteParser.readMessage[com.google.protobuf.struct.Struct](_input__))(_root_.scalapb.LiteParser.readMessage(_input__, _))) + case tag => + if (_unknownFields__ == null) { + _unknownFields__ = new _root_.scalapb.UnknownFieldSet.Builder() + } + _unknownFields__.parseField(tag, _input__) + } + } + pulumirpc.language.ProgramInfo( + rootDirectory = __rootDirectory, + programDirectory = __programDirectory, + entryPoint = __entryPoint, + options = __options, + unknownFields = if (_unknownFields__ == null) _root_.scalapb.UnknownFieldSet.empty else _unknownFields__.result() + ) + } + implicit def messageReads: _root_.scalapb.descriptors.Reads[pulumirpc.language.ProgramInfo] = _root_.scalapb.descriptors.Reads{ + case _root_.scalapb.descriptors.PMessage(__fieldsMap) => + _root_.scala.Predef.require(__fieldsMap.keys.forall(_.containingMessage eq scalaDescriptor), "FieldDescriptor does not match message type.") + pulumirpc.language.ProgramInfo( + rootDirectory = __fieldsMap.get(scalaDescriptor.findFieldByNumber(1).get).map(_.as[_root_.scala.Predef.String]).getOrElse(""), + programDirectory = __fieldsMap.get(scalaDescriptor.findFieldByNumber(2).get).map(_.as[_root_.scala.Predef.String]).getOrElse(""), + entryPoint = __fieldsMap.get(scalaDescriptor.findFieldByNumber(3).get).map(_.as[_root_.scala.Predef.String]).getOrElse(""), + options = __fieldsMap.get(scalaDescriptor.findFieldByNumber(4).get).flatMap(_.as[_root_.scala.Option[com.google.protobuf.struct.Struct]]) + ) + case _ => throw new RuntimeException("Expected PMessage") + } + def javaDescriptor: _root_.com.google.protobuf.Descriptors.Descriptor = LanguageProto.javaDescriptor.getMessageTypes().get(0) + def scalaDescriptor: _root_.scalapb.descriptors.Descriptor = LanguageProto.scalaDescriptor.messages(0) + def messageCompanionForFieldNumber(__number: _root_.scala.Int): _root_.scalapb.GeneratedMessageCompanion[_] = { + var __out: _root_.scalapb.GeneratedMessageCompanion[_] = null + (__number: @_root_.scala.unchecked) match { + case 4 => __out = com.google.protobuf.struct.Struct + } + __out + } + lazy val nestedMessagesCompanions: Seq[_root_.scalapb.GeneratedMessageCompanion[_ <: _root_.scalapb.GeneratedMessage]] = Seq.empty + def enumCompanionForFieldNumber(__fieldNumber: _root_.scala.Int): _root_.scalapb.GeneratedEnumCompanion[_] = throw new MatchError(__fieldNumber) + lazy val defaultInstance = pulumirpc.language.ProgramInfo( + rootDirectory = "", + programDirectory = "", + entryPoint = "", + options = _root_.scala.None + ) + implicit class ProgramInfoLens[UpperPB](_l: _root_.scalapb.lenses.Lens[UpperPB, pulumirpc.language.ProgramInfo]) extends _root_.scalapb.lenses.ObjectLens[UpperPB, pulumirpc.language.ProgramInfo](_l) { + def rootDirectory: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Predef.String] = field(_.rootDirectory)((c_, f_) => c_.copy(rootDirectory = f_)) + def programDirectory: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Predef.String] = field(_.programDirectory)((c_, f_) => c_.copy(programDirectory = f_)) + def entryPoint: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Predef.String] = field(_.entryPoint)((c_, f_) => c_.copy(entryPoint = f_)) + def options: _root_.scalapb.lenses.Lens[UpperPB, com.google.protobuf.struct.Struct] = field(_.getOptions)((c_, f_) => c_.copy(options = _root_.scala.Option(f_))) + def optionalOptions: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Option[com.google.protobuf.struct.Struct]] = field(_.options)((c_, f_) => c_.copy(options = f_)) + } + final val ROOT_DIRECTORY_FIELD_NUMBER = 1 + final val PROGRAM_DIRECTORY_FIELD_NUMBER = 2 + final val ENTRY_POINT_FIELD_NUMBER = 3 + final val OPTIONS_FIELD_NUMBER = 4 + def of( + rootDirectory: _root_.scala.Predef.String, + programDirectory: _root_.scala.Predef.String, + entryPoint: _root_.scala.Predef.String, + options: _root_.scala.Option[com.google.protobuf.struct.Struct] + ): _root_.pulumirpc.language.ProgramInfo = _root_.pulumirpc.language.ProgramInfo( + rootDirectory, + programDirectory, + entryPoint, + options + ) + // @@protoc_insertion_point(GeneratedMessageCompanion[pulumirpc.ProgramInfo]) +} diff --git a/core/src/main/scala/besom/rpc/pulumirpc/language/RunPluginRequest.scala b/core/src/main/scala/besom/rpc/pulumirpc/language/RunPluginRequest.scala new file mode 100644 index 00000000..7a8b24e4 --- /dev/null +++ b/core/src/main/scala/besom/rpc/pulumirpc/language/RunPluginRequest.scala @@ -0,0 +1,241 @@ +// Generated by the Scala Plugin for the Protocol Buffer Compiler. +// Do not edit! +// +// Protofile syntax: PROTO3 + +package pulumirpc.language + +/** @param pwd + * the program's working directory. + * @param program + * the path to the program to execute. + * @param args + * any arguments to pass to the program. + * @param env + * any environment variables to set as part of the program. + * @param info + * the program info to use to execute the plugin. + */ +@SerialVersionUID(0L) +final case class RunPluginRequest( + pwd: _root_.scala.Predef.String = "", + @scala.deprecated(message="Marked as deprecated in proto file", "") program: _root_.scala.Predef.String = "", + args: _root_.scala.Seq[_root_.scala.Predef.String] = _root_.scala.Seq.empty, + env: _root_.scala.Seq[_root_.scala.Predef.String] = _root_.scala.Seq.empty, + info: _root_.scala.Option[pulumirpc.language.ProgramInfo] = _root_.scala.None, + unknownFields: _root_.scalapb.UnknownFieldSet = _root_.scalapb.UnknownFieldSet.empty + ) extends scalapb.GeneratedMessage with scalapb.lenses.Updatable[RunPluginRequest] { + @transient + private[this] var __serializedSizeMemoized: _root_.scala.Int = 0 + private[this] def __computeSerializedSize(): _root_.scala.Int = { + var __size = 0 + + { + val __value = pwd + if (!__value.isEmpty) { + __size += _root_.com.google.protobuf.CodedOutputStream.computeStringSize(1, __value) + } + }; + + { + val __value = program + if (!__value.isEmpty) { + __size += _root_.com.google.protobuf.CodedOutputStream.computeStringSize(2, __value) + } + }; + args.foreach { __item => + val __value = __item + __size += _root_.com.google.protobuf.CodedOutputStream.computeStringSize(3, __value) + } + env.foreach { __item => + val __value = __item + __size += _root_.com.google.protobuf.CodedOutputStream.computeStringSize(4, __value) + } + if (info.isDefined) { + val __value = info.get + __size += 1 + _root_.com.google.protobuf.CodedOutputStream.computeUInt32SizeNoTag(__value.serializedSize) + __value.serializedSize + }; + __size += unknownFields.serializedSize + __size + } + override def serializedSize: _root_.scala.Int = { + var __size = __serializedSizeMemoized + if (__size == 0) { + __size = __computeSerializedSize() + 1 + __serializedSizeMemoized = __size + } + __size - 1 + + } + def writeTo(`_output__`: _root_.com.google.protobuf.CodedOutputStream): _root_.scala.Unit = { + { + val __v = pwd + if (!__v.isEmpty) { + _output__.writeString(1, __v) + } + }; + { + val __v = program + if (!__v.isEmpty) { + _output__.writeString(2, __v) + } + }; + args.foreach { __v => + val __m = __v + _output__.writeString(3, __m) + }; + env.foreach { __v => + val __m = __v + _output__.writeString(4, __m) + }; + info.foreach { __v => + val __m = __v + _output__.writeTag(5, 2) + _output__.writeUInt32NoTag(__m.serializedSize) + __m.writeTo(_output__) + }; + unknownFields.writeTo(_output__) + } + def withPwd(__v: _root_.scala.Predef.String): RunPluginRequest = copy(pwd = __v) + def withProgram(__v: _root_.scala.Predef.String): RunPluginRequest = copy(program = __v) + def clearArgs = copy(args = _root_.scala.Seq.empty) + def addArgs(__vs: _root_.scala.Predef.String *): RunPluginRequest = addAllArgs(__vs) + def addAllArgs(__vs: Iterable[_root_.scala.Predef.String]): RunPluginRequest = copy(args = args ++ __vs) + def withArgs(__v: _root_.scala.Seq[_root_.scala.Predef.String]): RunPluginRequest = copy(args = __v) + def clearEnv = copy(env = _root_.scala.Seq.empty) + def addEnv(__vs: _root_.scala.Predef.String *): RunPluginRequest = addAllEnv(__vs) + def addAllEnv(__vs: Iterable[_root_.scala.Predef.String]): RunPluginRequest = copy(env = env ++ __vs) + def withEnv(__v: _root_.scala.Seq[_root_.scala.Predef.String]): RunPluginRequest = copy(env = __v) + def getInfo: pulumirpc.language.ProgramInfo = info.getOrElse(pulumirpc.language.ProgramInfo.defaultInstance) + def clearInfo: RunPluginRequest = copy(info = _root_.scala.None) + def withInfo(__v: pulumirpc.language.ProgramInfo): RunPluginRequest = copy(info = Option(__v)) + def withUnknownFields(__v: _root_.scalapb.UnknownFieldSet) = copy(unknownFields = __v) + def discardUnknownFields = copy(unknownFields = _root_.scalapb.UnknownFieldSet.empty) + def getFieldByNumber(__fieldNumber: _root_.scala.Int): _root_.scala.Any = { + (__fieldNumber: @_root_.scala.unchecked) match { + case 1 => { + val __t = pwd + if (__t != "") __t else null + } + case 2 => { + val __t = program + if (__t != "") __t else null + } + case 3 => args + case 4 => env + case 5 => info.orNull + } + } + def getField(__field: _root_.scalapb.descriptors.FieldDescriptor): _root_.scalapb.descriptors.PValue = { + _root_.scala.Predef.require(__field.containingMessage eq companion.scalaDescriptor) + (__field.number: @_root_.scala.unchecked) match { + case 1 => _root_.scalapb.descriptors.PString(pwd) + case 2 => _root_.scalapb.descriptors.PString(program) + case 3 => _root_.scalapb.descriptors.PRepeated(args.iterator.map(_root_.scalapb.descriptors.PString(_)).toVector) + case 4 => _root_.scalapb.descriptors.PRepeated(env.iterator.map(_root_.scalapb.descriptors.PString(_)).toVector) + case 5 => info.map(_.toPMessage).getOrElse(_root_.scalapb.descriptors.PEmpty) + } + } + def toProtoString: _root_.scala.Predef.String = _root_.scalapb.TextFormat.printToUnicodeString(this) + def companion: pulumirpc.language.RunPluginRequest.type = pulumirpc.language.RunPluginRequest + // @@protoc_insertion_point(GeneratedMessage[pulumirpc.RunPluginRequest]) +} + +object RunPluginRequest extends scalapb.GeneratedMessageCompanion[pulumirpc.language.RunPluginRequest] { + implicit def messageCompanion: scalapb.GeneratedMessageCompanion[pulumirpc.language.RunPluginRequest] = this + def parseFrom(`_input__`: _root_.com.google.protobuf.CodedInputStream): pulumirpc.language.RunPluginRequest = { + var __pwd: _root_.scala.Predef.String = "" + var __program: _root_.scala.Predef.String = "" + val __args: _root_.scala.collection.immutable.VectorBuilder[_root_.scala.Predef.String] = new _root_.scala.collection.immutable.VectorBuilder[_root_.scala.Predef.String] + val __env: _root_.scala.collection.immutable.VectorBuilder[_root_.scala.Predef.String] = new _root_.scala.collection.immutable.VectorBuilder[_root_.scala.Predef.String] + var __info: _root_.scala.Option[pulumirpc.language.ProgramInfo] = _root_.scala.None + var `_unknownFields__`: _root_.scalapb.UnknownFieldSet.Builder = null + var _done__ = false + while (!_done__) { + val _tag__ = _input__.readTag() + _tag__ match { + case 0 => _done__ = true + case 10 => + __pwd = _input__.readStringRequireUtf8() + case 18 => + __program = _input__.readStringRequireUtf8() + case 26 => + __args += _input__.readStringRequireUtf8() + case 34 => + __env += _input__.readStringRequireUtf8() + case 42 => + __info = _root_.scala.Option(__info.fold(_root_.scalapb.LiteParser.readMessage[pulumirpc.language.ProgramInfo](_input__))(_root_.scalapb.LiteParser.readMessage(_input__, _))) + case tag => + if (_unknownFields__ == null) { + _unknownFields__ = new _root_.scalapb.UnknownFieldSet.Builder() + } + _unknownFields__.parseField(tag, _input__) + } + } + pulumirpc.language.RunPluginRequest( + pwd = __pwd, + program = __program, + args = __args.result(), + env = __env.result(), + info = __info, + unknownFields = if (_unknownFields__ == null) _root_.scalapb.UnknownFieldSet.empty else _unknownFields__.result() + ) + } + implicit def messageReads: _root_.scalapb.descriptors.Reads[pulumirpc.language.RunPluginRequest] = _root_.scalapb.descriptors.Reads{ + case _root_.scalapb.descriptors.PMessage(__fieldsMap) => + _root_.scala.Predef.require(__fieldsMap.keys.forall(_.containingMessage eq scalaDescriptor), "FieldDescriptor does not match message type.") + pulumirpc.language.RunPluginRequest( + pwd = __fieldsMap.get(scalaDescriptor.findFieldByNumber(1).get).map(_.as[_root_.scala.Predef.String]).getOrElse(""), + program = __fieldsMap.get(scalaDescriptor.findFieldByNumber(2).get).map(_.as[_root_.scala.Predef.String]).getOrElse(""), + args = __fieldsMap.get(scalaDescriptor.findFieldByNumber(3).get).map(_.as[_root_.scala.Seq[_root_.scala.Predef.String]]).getOrElse(_root_.scala.Seq.empty), + env = __fieldsMap.get(scalaDescriptor.findFieldByNumber(4).get).map(_.as[_root_.scala.Seq[_root_.scala.Predef.String]]).getOrElse(_root_.scala.Seq.empty), + info = __fieldsMap.get(scalaDescriptor.findFieldByNumber(5).get).flatMap(_.as[_root_.scala.Option[pulumirpc.language.ProgramInfo]]) + ) + case _ => throw new RuntimeException("Expected PMessage") + } + def javaDescriptor: _root_.com.google.protobuf.Descriptors.Descriptor = LanguageProto.javaDescriptor.getMessageTypes().get(11) + def scalaDescriptor: _root_.scalapb.descriptors.Descriptor = LanguageProto.scalaDescriptor.messages(11) + def messageCompanionForFieldNumber(__number: _root_.scala.Int): _root_.scalapb.GeneratedMessageCompanion[_] = { + var __out: _root_.scalapb.GeneratedMessageCompanion[_] = null + (__number: @_root_.scala.unchecked) match { + case 5 => __out = pulumirpc.language.ProgramInfo + } + __out + } + lazy val nestedMessagesCompanions: Seq[_root_.scalapb.GeneratedMessageCompanion[_ <: _root_.scalapb.GeneratedMessage]] = Seq.empty + def enumCompanionForFieldNumber(__fieldNumber: _root_.scala.Int): _root_.scalapb.GeneratedEnumCompanion[_] = throw new MatchError(__fieldNumber) + lazy val defaultInstance = pulumirpc.language.RunPluginRequest( + pwd = "", + program = "", + args = _root_.scala.Seq.empty, + env = _root_.scala.Seq.empty, + info = _root_.scala.None + ) + implicit class RunPluginRequestLens[UpperPB](_l: _root_.scalapb.lenses.Lens[UpperPB, pulumirpc.language.RunPluginRequest]) extends _root_.scalapb.lenses.ObjectLens[UpperPB, pulumirpc.language.RunPluginRequest](_l) { + def pwd: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Predef.String] = field(_.pwd)((c_, f_) => c_.copy(pwd = f_)) + def program: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Predef.String] = field(_.program)((c_, f_) => c_.copy(program = f_)) + def args: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Seq[_root_.scala.Predef.String]] = field(_.args)((c_, f_) => c_.copy(args = f_)) + def env: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Seq[_root_.scala.Predef.String]] = field(_.env)((c_, f_) => c_.copy(env = f_)) + def info: _root_.scalapb.lenses.Lens[UpperPB, pulumirpc.language.ProgramInfo] = field(_.getInfo)((c_, f_) => c_.copy(info = _root_.scala.Option(f_))) + def optionalInfo: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Option[pulumirpc.language.ProgramInfo]] = field(_.info)((c_, f_) => c_.copy(info = f_)) + } + final val PWD_FIELD_NUMBER = 1 + final val PROGRAM_FIELD_NUMBER = 2 + final val ARGS_FIELD_NUMBER = 3 + final val ENV_FIELD_NUMBER = 4 + final val INFO_FIELD_NUMBER = 5 + def of( + pwd: _root_.scala.Predef.String, + program: _root_.scala.Predef.String, + args: _root_.scala.Seq[_root_.scala.Predef.String], + env: _root_.scala.Seq[_root_.scala.Predef.String], + info: _root_.scala.Option[pulumirpc.language.ProgramInfo] + ): _root_.pulumirpc.language.RunPluginRequest = _root_.pulumirpc.language.RunPluginRequest( + pwd, + program, + args, + env, + info + ) + // @@protoc_insertion_point(GeneratedMessageCompanion[pulumirpc.RunPluginRequest]) +} diff --git a/core/src/main/scala/besom/rpc/pulumirpc/language/RunPluginResponse.scala b/core/src/main/scala/besom/rpc/pulumirpc/language/RunPluginResponse.scala new file mode 100644 index 00000000..e2b08705 --- /dev/null +++ b/core/src/main/scala/besom/rpc/pulumirpc/language/RunPluginResponse.scala @@ -0,0 +1,190 @@ +// Generated by the Scala Plugin for the Protocol Buffer Compiler. +// Do not edit! +// +// Protofile syntax: PROTO3 + +package pulumirpc.language + +@SerialVersionUID(0L) +final case class RunPluginResponse( + output: pulumirpc.language.RunPluginResponse.Output = pulumirpc.language.RunPluginResponse.Output.Empty, + unknownFields: _root_.scalapb.UnknownFieldSet = _root_.scalapb.UnknownFieldSet.empty + ) extends scalapb.GeneratedMessage with scalapb.lenses.Updatable[RunPluginResponse] { + @transient + private[this] var __serializedSizeMemoized: _root_.scala.Int = 0 + private[this] def __computeSerializedSize(): _root_.scala.Int = { + var __size = 0 + if (output.stdout.isDefined) { + val __value = output.stdout.get + __size += _root_.com.google.protobuf.CodedOutputStream.computeBytesSize(1, __value) + }; + if (output.stderr.isDefined) { + val __value = output.stderr.get + __size += _root_.com.google.protobuf.CodedOutputStream.computeBytesSize(2, __value) + }; + if (output.exitcode.isDefined) { + val __value = output.exitcode.get + __size += _root_.com.google.protobuf.CodedOutputStream.computeInt32Size(3, __value) + }; + __size += unknownFields.serializedSize + __size + } + override def serializedSize: _root_.scala.Int = { + var __size = __serializedSizeMemoized + if (__size == 0) { + __size = __computeSerializedSize() + 1 + __serializedSizeMemoized = __size + } + __size - 1 + + } + def writeTo(`_output__`: _root_.com.google.protobuf.CodedOutputStream): _root_.scala.Unit = { + output.stdout.foreach { __v => + val __m = __v + _output__.writeBytes(1, __m) + }; + output.stderr.foreach { __v => + val __m = __v + _output__.writeBytes(2, __m) + }; + output.exitcode.foreach { __v => + val __m = __v + _output__.writeInt32(3, __m) + }; + unknownFields.writeTo(_output__) + } + def getStdout: _root_.com.google.protobuf.ByteString = output.stdout.getOrElse(_root_.com.google.protobuf.ByteString.EMPTY) + def withStdout(__v: _root_.com.google.protobuf.ByteString): RunPluginResponse = copy(output = pulumirpc.language.RunPluginResponse.Output.Stdout(__v)) + def getStderr: _root_.com.google.protobuf.ByteString = output.stderr.getOrElse(_root_.com.google.protobuf.ByteString.EMPTY) + def withStderr(__v: _root_.com.google.protobuf.ByteString): RunPluginResponse = copy(output = pulumirpc.language.RunPluginResponse.Output.Stderr(__v)) + def getExitcode: _root_.scala.Int = output.exitcode.getOrElse(0) + def withExitcode(__v: _root_.scala.Int): RunPluginResponse = copy(output = pulumirpc.language.RunPluginResponse.Output.Exitcode(__v)) + def clearOutput: RunPluginResponse = copy(output = pulumirpc.language.RunPluginResponse.Output.Empty) + def withOutput(__v: pulumirpc.language.RunPluginResponse.Output): RunPluginResponse = copy(output = __v) + def withUnknownFields(__v: _root_.scalapb.UnknownFieldSet) = copy(unknownFields = __v) + def discardUnknownFields = copy(unknownFields = _root_.scalapb.UnknownFieldSet.empty) + def getFieldByNumber(__fieldNumber: _root_.scala.Int): _root_.scala.Any = { + (__fieldNumber: @_root_.scala.unchecked) match { + case 1 => output.stdout.orNull + case 2 => output.stderr.orNull + case 3 => output.exitcode.orNull + } + } + def getField(__field: _root_.scalapb.descriptors.FieldDescriptor): _root_.scalapb.descriptors.PValue = { + _root_.scala.Predef.require(__field.containingMessage eq companion.scalaDescriptor) + (__field.number: @_root_.scala.unchecked) match { + case 1 => output.stdout.map(_root_.scalapb.descriptors.PByteString(_)).getOrElse(_root_.scalapb.descriptors.PEmpty) + case 2 => output.stderr.map(_root_.scalapb.descriptors.PByteString(_)).getOrElse(_root_.scalapb.descriptors.PEmpty) + case 3 => output.exitcode.map(_root_.scalapb.descriptors.PInt(_)).getOrElse(_root_.scalapb.descriptors.PEmpty) + } + } + def toProtoString: _root_.scala.Predef.String = _root_.scalapb.TextFormat.printToUnicodeString(this) + def companion: pulumirpc.language.RunPluginResponse.type = pulumirpc.language.RunPluginResponse + // @@protoc_insertion_point(GeneratedMessage[pulumirpc.RunPluginResponse]) +} + +object RunPluginResponse extends scalapb.GeneratedMessageCompanion[pulumirpc.language.RunPluginResponse] { + implicit def messageCompanion: scalapb.GeneratedMessageCompanion[pulumirpc.language.RunPluginResponse] = this + def parseFrom(`_input__`: _root_.com.google.protobuf.CodedInputStream): pulumirpc.language.RunPluginResponse = { + var __output: pulumirpc.language.RunPluginResponse.Output = pulumirpc.language.RunPluginResponse.Output.Empty + var `_unknownFields__`: _root_.scalapb.UnknownFieldSet.Builder = null + var _done__ = false + while (!_done__) { + val _tag__ = _input__.readTag() + _tag__ match { + case 0 => _done__ = true + case 10 => + __output = pulumirpc.language.RunPluginResponse.Output.Stdout(_input__.readBytes()) + case 18 => + __output = pulumirpc.language.RunPluginResponse.Output.Stderr(_input__.readBytes()) + case 24 => + __output = pulumirpc.language.RunPluginResponse.Output.Exitcode(_input__.readInt32()) + case tag => + if (_unknownFields__ == null) { + _unknownFields__ = new _root_.scalapb.UnknownFieldSet.Builder() + } + _unknownFields__.parseField(tag, _input__) + } + } + pulumirpc.language.RunPluginResponse( + output = __output, + unknownFields = if (_unknownFields__ == null) _root_.scalapb.UnknownFieldSet.empty else _unknownFields__.result() + ) + } + implicit def messageReads: _root_.scalapb.descriptors.Reads[pulumirpc.language.RunPluginResponse] = _root_.scalapb.descriptors.Reads{ + case _root_.scalapb.descriptors.PMessage(__fieldsMap) => + _root_.scala.Predef.require(__fieldsMap.keys.forall(_.containingMessage eq scalaDescriptor), "FieldDescriptor does not match message type.") + pulumirpc.language.RunPluginResponse( + output = __fieldsMap.get(scalaDescriptor.findFieldByNumber(1).get).flatMap(_.as[_root_.scala.Option[_root_.com.google.protobuf.ByteString]]).map(pulumirpc.language.RunPluginResponse.Output.Stdout(_)) + .orElse[pulumirpc.language.RunPluginResponse.Output](__fieldsMap.get(scalaDescriptor.findFieldByNumber(2).get).flatMap(_.as[_root_.scala.Option[_root_.com.google.protobuf.ByteString]]).map(pulumirpc.language.RunPluginResponse.Output.Stderr(_))) + .orElse[pulumirpc.language.RunPluginResponse.Output](__fieldsMap.get(scalaDescriptor.findFieldByNumber(3).get).flatMap(_.as[_root_.scala.Option[_root_.scala.Int]]).map(pulumirpc.language.RunPluginResponse.Output.Exitcode(_))) + .getOrElse(pulumirpc.language.RunPluginResponse.Output.Empty) + ) + case _ => throw new RuntimeException("Expected PMessage") + } + def javaDescriptor: _root_.com.google.protobuf.Descriptors.Descriptor = LanguageProto.javaDescriptor.getMessageTypes().get(12) + def scalaDescriptor: _root_.scalapb.descriptors.Descriptor = LanguageProto.scalaDescriptor.messages(12) + def messageCompanionForFieldNumber(__number: _root_.scala.Int): _root_.scalapb.GeneratedMessageCompanion[_] = throw new MatchError(__number) + lazy val nestedMessagesCompanions: Seq[_root_.scalapb.GeneratedMessageCompanion[_ <: _root_.scalapb.GeneratedMessage]] = Seq.empty + def enumCompanionForFieldNumber(__fieldNumber: _root_.scala.Int): _root_.scalapb.GeneratedEnumCompanion[_] = throw new MatchError(__fieldNumber) + lazy val defaultInstance = pulumirpc.language.RunPluginResponse( + output = pulumirpc.language.RunPluginResponse.Output.Empty + ) + sealed trait Output extends _root_.scalapb.GeneratedOneof { + def isEmpty: _root_.scala.Boolean = false + def isDefined: _root_.scala.Boolean = true + def isStdout: _root_.scala.Boolean = false + def isStderr: _root_.scala.Boolean = false + def isExitcode: _root_.scala.Boolean = false + def stdout: _root_.scala.Option[_root_.com.google.protobuf.ByteString] = _root_.scala.None + def stderr: _root_.scala.Option[_root_.com.google.protobuf.ByteString] = _root_.scala.None + def exitcode: _root_.scala.Option[_root_.scala.Int] = _root_.scala.None + } + object Output { + @SerialVersionUID(0L) + case object Empty extends pulumirpc.language.RunPluginResponse.Output { + type ValueType = _root_.scala.Nothing + override def isEmpty: _root_.scala.Boolean = true + override def isDefined: _root_.scala.Boolean = false + override def number: _root_.scala.Int = 0 + override def value: _root_.scala.Nothing = throw new java.util.NoSuchElementException("Empty.value") + } + + @SerialVersionUID(0L) + final case class Stdout(value: _root_.com.google.protobuf.ByteString) extends pulumirpc.language.RunPluginResponse.Output { + type ValueType = _root_.com.google.protobuf.ByteString + override def isStdout: _root_.scala.Boolean = true + override def stdout: _root_.scala.Option[_root_.com.google.protobuf.ByteString] = Some(value) + override def number: _root_.scala.Int = 1 + } + @SerialVersionUID(0L) + final case class Stderr(value: _root_.com.google.protobuf.ByteString) extends pulumirpc.language.RunPluginResponse.Output { + type ValueType = _root_.com.google.protobuf.ByteString + override def isStderr: _root_.scala.Boolean = true + override def stderr: _root_.scala.Option[_root_.com.google.protobuf.ByteString] = Some(value) + override def number: _root_.scala.Int = 2 + } + @SerialVersionUID(0L) + final case class Exitcode(value: _root_.scala.Int) extends pulumirpc.language.RunPluginResponse.Output { + type ValueType = _root_.scala.Int + override def isExitcode: _root_.scala.Boolean = true + override def exitcode: _root_.scala.Option[_root_.scala.Int] = Some(value) + override def number: _root_.scala.Int = 3 + } + } + implicit class RunPluginResponseLens[UpperPB](_l: _root_.scalapb.lenses.Lens[UpperPB, pulumirpc.language.RunPluginResponse]) extends _root_.scalapb.lenses.ObjectLens[UpperPB, pulumirpc.language.RunPluginResponse](_l) { + def stdout: _root_.scalapb.lenses.Lens[UpperPB, _root_.com.google.protobuf.ByteString] = field(_.getStdout)((c_, f_) => c_.copy(output = pulumirpc.language.RunPluginResponse.Output.Stdout(f_))) + def stderr: _root_.scalapb.lenses.Lens[UpperPB, _root_.com.google.protobuf.ByteString] = field(_.getStderr)((c_, f_) => c_.copy(output = pulumirpc.language.RunPluginResponse.Output.Stderr(f_))) + def exitcode: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Int] = field(_.getExitcode)((c_, f_) => c_.copy(output = pulumirpc.language.RunPluginResponse.Output.Exitcode(f_))) + def output: _root_.scalapb.lenses.Lens[UpperPB, pulumirpc.language.RunPluginResponse.Output] = field(_.output)((c_, f_) => c_.copy(output = f_)) + } + final val STDOUT_FIELD_NUMBER = 1 + final val STDERR_FIELD_NUMBER = 2 + final val EXITCODE_FIELD_NUMBER = 3 + def of( + output: pulumirpc.language.RunPluginResponse.Output + ): _root_.pulumirpc.language.RunPluginResponse = _root_.pulumirpc.language.RunPluginResponse( + output + ) + // @@protoc_insertion_point(GeneratedMessageCompanion[pulumirpc.RunPluginResponse]) +} diff --git a/core/src/main/scala/besom/rpc/pulumirpc/language/RunRequest.scala b/core/src/main/scala/besom/rpc/pulumirpc/language/RunRequest.scala new file mode 100644 index 00000000..911e7a35 --- /dev/null +++ b/core/src/main/scala/besom/rpc/pulumirpc/language/RunRequest.scala @@ -0,0 +1,676 @@ +// Generated by the Scala Plugin for the Protocol Buffer Compiler. +// Do not edit! +// +// Protofile syntax: PROTO3 + +package pulumirpc.language + +/** RunRequest asks the interpreter to execute a program. + * + * @param project + * the project name. + * @param stack + * the name of the stack being deployed into. + * @param pwd + * the program's working directory. + * @param program + * the path to the program to execute. + * @param args + * any arguments to pass to the program. + * @param config + * the configuration variables to apply before running. + * @param dryRun + * true if we're only doing a dryrun (preview). + * @param parallel + * the degree of parallelism for resource operations (<=1 for serial). + * @param monitorAddress + * the address for communicating back to the resource monitor. + * @param queryMode + * true if we're only doing a query. + * @param configSecretKeys + * the configuration keys that have secret values. + * @param organization + * the organization of the stack being deployed into. + * @param configPropertyMap + * the configuration variables to apply before running. + * @param info + * the program info to use to execute the program. + */ +@SerialVersionUID(0L) +final case class RunRequest( + project: _root_.scala.Predef.String = "", + stack: _root_.scala.Predef.String = "", + pwd: _root_.scala.Predef.String = "", + @scala.deprecated(message="Marked as deprecated in proto file", "") program: _root_.scala.Predef.String = "", + args: _root_.scala.Seq[_root_.scala.Predef.String] = _root_.scala.Seq.empty, + config: _root_.scala.collection.immutable.Map[_root_.scala.Predef.String, _root_.scala.Predef.String] = _root_.scala.collection.immutable.Map.empty, + dryRun: _root_.scala.Boolean = false, + parallel: _root_.scala.Int = 0, + monitorAddress: _root_.scala.Predef.String = "", + queryMode: _root_.scala.Boolean = false, + configSecretKeys: _root_.scala.Seq[_root_.scala.Predef.String] = _root_.scala.Seq.empty, + organization: _root_.scala.Predef.String = "", + configPropertyMap: _root_.scala.Option[com.google.protobuf.struct.Struct] = _root_.scala.None, + info: _root_.scala.Option[pulumirpc.language.ProgramInfo] = _root_.scala.None, + unknownFields: _root_.scalapb.UnknownFieldSet = _root_.scalapb.UnknownFieldSet.empty + ) extends scalapb.GeneratedMessage with scalapb.lenses.Updatable[RunRequest] { + @transient + private[this] var __serializedSizeMemoized: _root_.scala.Int = 0 + private[this] def __computeSerializedSize(): _root_.scala.Int = { + var __size = 0 + + { + val __value = project + if (!__value.isEmpty) { + __size += _root_.com.google.protobuf.CodedOutputStream.computeStringSize(1, __value) + } + }; + + { + val __value = stack + if (!__value.isEmpty) { + __size += _root_.com.google.protobuf.CodedOutputStream.computeStringSize(2, __value) + } + }; + + { + val __value = pwd + if (!__value.isEmpty) { + __size += _root_.com.google.protobuf.CodedOutputStream.computeStringSize(3, __value) + } + }; + + { + val __value = program + if (!__value.isEmpty) { + __size += _root_.com.google.protobuf.CodedOutputStream.computeStringSize(4, __value) + } + }; + args.foreach { __item => + val __value = __item + __size += _root_.com.google.protobuf.CodedOutputStream.computeStringSize(5, __value) + } + config.foreach { __item => + val __value = pulumirpc.language.RunRequest._typemapper_config.toBase(__item) + __size += 1 + _root_.com.google.protobuf.CodedOutputStream.computeUInt32SizeNoTag(__value.serializedSize) + __value.serializedSize + } + + { + val __value = dryRun + if (__value != false) { + __size += _root_.com.google.protobuf.CodedOutputStream.computeBoolSize(7, __value) + } + }; + + { + val __value = parallel + if (__value != 0) { + __size += _root_.com.google.protobuf.CodedOutputStream.computeInt32Size(8, __value) + } + }; + + { + val __value = monitorAddress + if (!__value.isEmpty) { + __size += _root_.com.google.protobuf.CodedOutputStream.computeStringSize(9, __value) + } + }; + + { + val __value = queryMode + if (__value != false) { + __size += _root_.com.google.protobuf.CodedOutputStream.computeBoolSize(10, __value) + } + }; + configSecretKeys.foreach { __item => + val __value = __item + __size += _root_.com.google.protobuf.CodedOutputStream.computeStringSize(11, __value) + } + + { + val __value = organization + if (!__value.isEmpty) { + __size += _root_.com.google.protobuf.CodedOutputStream.computeStringSize(12, __value) + } + }; + if (configPropertyMap.isDefined) { + val __value = configPropertyMap.get + __size += 1 + _root_.com.google.protobuf.CodedOutputStream.computeUInt32SizeNoTag(__value.serializedSize) + __value.serializedSize + }; + if (info.isDefined) { + val __value = info.get + __size += 1 + _root_.com.google.protobuf.CodedOutputStream.computeUInt32SizeNoTag(__value.serializedSize) + __value.serializedSize + }; + __size += unknownFields.serializedSize + __size + } + override def serializedSize: _root_.scala.Int = { + var __size = __serializedSizeMemoized + if (__size == 0) { + __size = __computeSerializedSize() + 1 + __serializedSizeMemoized = __size + } + __size - 1 + + } + def writeTo(`_output__`: _root_.com.google.protobuf.CodedOutputStream): _root_.scala.Unit = { + { + val __v = project + if (!__v.isEmpty) { + _output__.writeString(1, __v) + } + }; + { + val __v = stack + if (!__v.isEmpty) { + _output__.writeString(2, __v) + } + }; + { + val __v = pwd + if (!__v.isEmpty) { + _output__.writeString(3, __v) + } + }; + { + val __v = program + if (!__v.isEmpty) { + _output__.writeString(4, __v) + } + }; + args.foreach { __v => + val __m = __v + _output__.writeString(5, __m) + }; + config.foreach { __v => + val __m = pulumirpc.language.RunRequest._typemapper_config.toBase(__v) + _output__.writeTag(6, 2) + _output__.writeUInt32NoTag(__m.serializedSize) + __m.writeTo(_output__) + }; + { + val __v = dryRun + if (__v != false) { + _output__.writeBool(7, __v) + } + }; + { + val __v = parallel + if (__v != 0) { + _output__.writeInt32(8, __v) + } + }; + { + val __v = monitorAddress + if (!__v.isEmpty) { + _output__.writeString(9, __v) + } + }; + { + val __v = queryMode + if (__v != false) { + _output__.writeBool(10, __v) + } + }; + configSecretKeys.foreach { __v => + val __m = __v + _output__.writeString(11, __m) + }; + { + val __v = organization + if (!__v.isEmpty) { + _output__.writeString(12, __v) + } + }; + configPropertyMap.foreach { __v => + val __m = __v + _output__.writeTag(13, 2) + _output__.writeUInt32NoTag(__m.serializedSize) + __m.writeTo(_output__) + }; + info.foreach { __v => + val __m = __v + _output__.writeTag(14, 2) + _output__.writeUInt32NoTag(__m.serializedSize) + __m.writeTo(_output__) + }; + unknownFields.writeTo(_output__) + } + def withProject(__v: _root_.scala.Predef.String): RunRequest = copy(project = __v) + def withStack(__v: _root_.scala.Predef.String): RunRequest = copy(stack = __v) + def withPwd(__v: _root_.scala.Predef.String): RunRequest = copy(pwd = __v) + def withProgram(__v: _root_.scala.Predef.String): RunRequest = copy(program = __v) + def clearArgs = copy(args = _root_.scala.Seq.empty) + def addArgs(__vs: _root_.scala.Predef.String *): RunRequest = addAllArgs(__vs) + def addAllArgs(__vs: Iterable[_root_.scala.Predef.String]): RunRequest = copy(args = args ++ __vs) + def withArgs(__v: _root_.scala.Seq[_root_.scala.Predef.String]): RunRequest = copy(args = __v) + def clearConfig = copy(config = _root_.scala.collection.immutable.Map.empty) + def addConfig(__vs: (_root_.scala.Predef.String, _root_.scala.Predef.String) *): RunRequest = addAllConfig(__vs) + def addAllConfig(__vs: Iterable[(_root_.scala.Predef.String, _root_.scala.Predef.String)]): RunRequest = copy(config = config ++ __vs) + def withConfig(__v: _root_.scala.collection.immutable.Map[_root_.scala.Predef.String, _root_.scala.Predef.String]): RunRequest = copy(config = __v) + def withDryRun(__v: _root_.scala.Boolean): RunRequest = copy(dryRun = __v) + def withParallel(__v: _root_.scala.Int): RunRequest = copy(parallel = __v) + def withMonitorAddress(__v: _root_.scala.Predef.String): RunRequest = copy(monitorAddress = __v) + def withQueryMode(__v: _root_.scala.Boolean): RunRequest = copy(queryMode = __v) + def clearConfigSecretKeys = copy(configSecretKeys = _root_.scala.Seq.empty) + def addConfigSecretKeys(__vs: _root_.scala.Predef.String *): RunRequest = addAllConfigSecretKeys(__vs) + def addAllConfigSecretKeys(__vs: Iterable[_root_.scala.Predef.String]): RunRequest = copy(configSecretKeys = configSecretKeys ++ __vs) + def withConfigSecretKeys(__v: _root_.scala.Seq[_root_.scala.Predef.String]): RunRequest = copy(configSecretKeys = __v) + def withOrganization(__v: _root_.scala.Predef.String): RunRequest = copy(organization = __v) + def getConfigPropertyMap: com.google.protobuf.struct.Struct = configPropertyMap.getOrElse(com.google.protobuf.struct.Struct.defaultInstance) + def clearConfigPropertyMap: RunRequest = copy(configPropertyMap = _root_.scala.None) + def withConfigPropertyMap(__v: com.google.protobuf.struct.Struct): RunRequest = copy(configPropertyMap = Option(__v)) + def getInfo: pulumirpc.language.ProgramInfo = info.getOrElse(pulumirpc.language.ProgramInfo.defaultInstance) + def clearInfo: RunRequest = copy(info = _root_.scala.None) + def withInfo(__v: pulumirpc.language.ProgramInfo): RunRequest = copy(info = Option(__v)) + def withUnknownFields(__v: _root_.scalapb.UnknownFieldSet) = copy(unknownFields = __v) + def discardUnknownFields = copy(unknownFields = _root_.scalapb.UnknownFieldSet.empty) + def getFieldByNumber(__fieldNumber: _root_.scala.Int): _root_.scala.Any = { + (__fieldNumber: @_root_.scala.unchecked) match { + case 1 => { + val __t = project + if (__t != "") __t else null + } + case 2 => { + val __t = stack + if (__t != "") __t else null + } + case 3 => { + val __t = pwd + if (__t != "") __t else null + } + case 4 => { + val __t = program + if (__t != "") __t else null + } + case 5 => args + case 6 => config.iterator.map(pulumirpc.language.RunRequest._typemapper_config.toBase(_)).toSeq + case 7 => { + val __t = dryRun + if (__t != false) __t else null + } + case 8 => { + val __t = parallel + if (__t != 0) __t else null + } + case 9 => { + val __t = monitorAddress + if (__t != "") __t else null + } + case 10 => { + val __t = queryMode + if (__t != false) __t else null + } + case 11 => configSecretKeys + case 12 => { + val __t = organization + if (__t != "") __t else null + } + case 13 => configPropertyMap.orNull + case 14 => info.orNull + } + } + def getField(__field: _root_.scalapb.descriptors.FieldDescriptor): _root_.scalapb.descriptors.PValue = { + _root_.scala.Predef.require(__field.containingMessage eq companion.scalaDescriptor) + (__field.number: @_root_.scala.unchecked) match { + case 1 => _root_.scalapb.descriptors.PString(project) + case 2 => _root_.scalapb.descriptors.PString(stack) + case 3 => _root_.scalapb.descriptors.PString(pwd) + case 4 => _root_.scalapb.descriptors.PString(program) + case 5 => _root_.scalapb.descriptors.PRepeated(args.iterator.map(_root_.scalapb.descriptors.PString(_)).toVector) + case 6 => _root_.scalapb.descriptors.PRepeated(config.iterator.map(pulumirpc.language.RunRequest._typemapper_config.toBase(_).toPMessage).toVector) + case 7 => _root_.scalapb.descriptors.PBoolean(dryRun) + case 8 => _root_.scalapb.descriptors.PInt(parallel) + case 9 => _root_.scalapb.descriptors.PString(monitorAddress) + case 10 => _root_.scalapb.descriptors.PBoolean(queryMode) + case 11 => _root_.scalapb.descriptors.PRepeated(configSecretKeys.iterator.map(_root_.scalapb.descriptors.PString(_)).toVector) + case 12 => _root_.scalapb.descriptors.PString(organization) + case 13 => configPropertyMap.map(_.toPMessage).getOrElse(_root_.scalapb.descriptors.PEmpty) + case 14 => info.map(_.toPMessage).getOrElse(_root_.scalapb.descriptors.PEmpty) + } + } + def toProtoString: _root_.scala.Predef.String = _root_.scalapb.TextFormat.printToUnicodeString(this) + def companion: pulumirpc.language.RunRequest.type = pulumirpc.language.RunRequest + // @@protoc_insertion_point(GeneratedMessage[pulumirpc.RunRequest]) +} + +object RunRequest extends scalapb.GeneratedMessageCompanion[pulumirpc.language.RunRequest] { + implicit def messageCompanion: scalapb.GeneratedMessageCompanion[pulumirpc.language.RunRequest] = this + def parseFrom(`_input__`: _root_.com.google.protobuf.CodedInputStream): pulumirpc.language.RunRequest = { + var __project: _root_.scala.Predef.String = "" + var __stack: _root_.scala.Predef.String = "" + var __pwd: _root_.scala.Predef.String = "" + var __program: _root_.scala.Predef.String = "" + val __args: _root_.scala.collection.immutable.VectorBuilder[_root_.scala.Predef.String] = new _root_.scala.collection.immutable.VectorBuilder[_root_.scala.Predef.String] + val __config: _root_.scala.collection.mutable.Builder[(_root_.scala.Predef.String, _root_.scala.Predef.String), _root_.scala.collection.immutable.Map[_root_.scala.Predef.String, _root_.scala.Predef.String]] = _root_.scala.collection.immutable.Map.newBuilder[_root_.scala.Predef.String, _root_.scala.Predef.String] + var __dryRun: _root_.scala.Boolean = false + var __parallel: _root_.scala.Int = 0 + var __monitorAddress: _root_.scala.Predef.String = "" + var __queryMode: _root_.scala.Boolean = false + val __configSecretKeys: _root_.scala.collection.immutable.VectorBuilder[_root_.scala.Predef.String] = new _root_.scala.collection.immutable.VectorBuilder[_root_.scala.Predef.String] + var __organization: _root_.scala.Predef.String = "" + var __configPropertyMap: _root_.scala.Option[com.google.protobuf.struct.Struct] = _root_.scala.None + var __info: _root_.scala.Option[pulumirpc.language.ProgramInfo] = _root_.scala.None + var `_unknownFields__`: _root_.scalapb.UnknownFieldSet.Builder = null + var _done__ = false + while (!_done__) { + val _tag__ = _input__.readTag() + _tag__ match { + case 0 => _done__ = true + case 10 => + __project = _input__.readStringRequireUtf8() + case 18 => + __stack = _input__.readStringRequireUtf8() + case 26 => + __pwd = _input__.readStringRequireUtf8() + case 34 => + __program = _input__.readStringRequireUtf8() + case 42 => + __args += _input__.readStringRequireUtf8() + case 50 => + __config += pulumirpc.language.RunRequest._typemapper_config.toCustom(_root_.scalapb.LiteParser.readMessage[pulumirpc.language.RunRequest.ConfigEntry](_input__)) + case 56 => + __dryRun = _input__.readBool() + case 64 => + __parallel = _input__.readInt32() + case 74 => + __monitorAddress = _input__.readStringRequireUtf8() + case 80 => + __queryMode = _input__.readBool() + case 90 => + __configSecretKeys += _input__.readStringRequireUtf8() + case 98 => + __organization = _input__.readStringRequireUtf8() + case 106 => + __configPropertyMap = _root_.scala.Option(__configPropertyMap.fold(_root_.scalapb.LiteParser.readMessage[com.google.protobuf.struct.Struct](_input__))(_root_.scalapb.LiteParser.readMessage(_input__, _))) + case 114 => + __info = _root_.scala.Option(__info.fold(_root_.scalapb.LiteParser.readMessage[pulumirpc.language.ProgramInfo](_input__))(_root_.scalapb.LiteParser.readMessage(_input__, _))) + case tag => + if (_unknownFields__ == null) { + _unknownFields__ = new _root_.scalapb.UnknownFieldSet.Builder() + } + _unknownFields__.parseField(tag, _input__) + } + } + pulumirpc.language.RunRequest( + project = __project, + stack = __stack, + pwd = __pwd, + program = __program, + args = __args.result(), + config = __config.result(), + dryRun = __dryRun, + parallel = __parallel, + monitorAddress = __monitorAddress, + queryMode = __queryMode, + configSecretKeys = __configSecretKeys.result(), + organization = __organization, + configPropertyMap = __configPropertyMap, + info = __info, + unknownFields = if (_unknownFields__ == null) _root_.scalapb.UnknownFieldSet.empty else _unknownFields__.result() + ) + } + implicit def messageReads: _root_.scalapb.descriptors.Reads[pulumirpc.language.RunRequest] = _root_.scalapb.descriptors.Reads{ + case _root_.scalapb.descriptors.PMessage(__fieldsMap) => + _root_.scala.Predef.require(__fieldsMap.keys.forall(_.containingMessage eq scalaDescriptor), "FieldDescriptor does not match message type.") + pulumirpc.language.RunRequest( + project = __fieldsMap.get(scalaDescriptor.findFieldByNumber(1).get).map(_.as[_root_.scala.Predef.String]).getOrElse(""), + stack = __fieldsMap.get(scalaDescriptor.findFieldByNumber(2).get).map(_.as[_root_.scala.Predef.String]).getOrElse(""), + pwd = __fieldsMap.get(scalaDescriptor.findFieldByNumber(3).get).map(_.as[_root_.scala.Predef.String]).getOrElse(""), + program = __fieldsMap.get(scalaDescriptor.findFieldByNumber(4).get).map(_.as[_root_.scala.Predef.String]).getOrElse(""), + args = __fieldsMap.get(scalaDescriptor.findFieldByNumber(5).get).map(_.as[_root_.scala.Seq[_root_.scala.Predef.String]]).getOrElse(_root_.scala.Seq.empty), + config = __fieldsMap.get(scalaDescriptor.findFieldByNumber(6).get).map(_.as[_root_.scala.Seq[pulumirpc.language.RunRequest.ConfigEntry]]).getOrElse(_root_.scala.Seq.empty).iterator.map(pulumirpc.language.RunRequest._typemapper_config.toCustom(_)).toMap, + dryRun = __fieldsMap.get(scalaDescriptor.findFieldByNumber(7).get).map(_.as[_root_.scala.Boolean]).getOrElse(false), + parallel = __fieldsMap.get(scalaDescriptor.findFieldByNumber(8).get).map(_.as[_root_.scala.Int]).getOrElse(0), + monitorAddress = __fieldsMap.get(scalaDescriptor.findFieldByNumber(9).get).map(_.as[_root_.scala.Predef.String]).getOrElse(""), + queryMode = __fieldsMap.get(scalaDescriptor.findFieldByNumber(10).get).map(_.as[_root_.scala.Boolean]).getOrElse(false), + configSecretKeys = __fieldsMap.get(scalaDescriptor.findFieldByNumber(11).get).map(_.as[_root_.scala.Seq[_root_.scala.Predef.String]]).getOrElse(_root_.scala.Seq.empty), + organization = __fieldsMap.get(scalaDescriptor.findFieldByNumber(12).get).map(_.as[_root_.scala.Predef.String]).getOrElse(""), + configPropertyMap = __fieldsMap.get(scalaDescriptor.findFieldByNumber(13).get).flatMap(_.as[_root_.scala.Option[com.google.protobuf.struct.Struct]]), + info = __fieldsMap.get(scalaDescriptor.findFieldByNumber(14).get).flatMap(_.as[_root_.scala.Option[pulumirpc.language.ProgramInfo]]) + ) + case _ => throw new RuntimeException("Expected PMessage") + } + def javaDescriptor: _root_.com.google.protobuf.Descriptors.Descriptor = LanguageProto.javaDescriptor.getMessageTypes().get(7) + def scalaDescriptor: _root_.scalapb.descriptors.Descriptor = LanguageProto.scalaDescriptor.messages(7) + def messageCompanionForFieldNumber(__number: _root_.scala.Int): _root_.scalapb.GeneratedMessageCompanion[_] = { + var __out: _root_.scalapb.GeneratedMessageCompanion[_] = null + (__number: @_root_.scala.unchecked) match { + case 6 => __out = pulumirpc.language.RunRequest.ConfigEntry + case 13 => __out = com.google.protobuf.struct.Struct + case 14 => __out = pulumirpc.language.ProgramInfo + } + __out + } + lazy val nestedMessagesCompanions: Seq[_root_.scalapb.GeneratedMessageCompanion[_ <: _root_.scalapb.GeneratedMessage]] = + Seq[_root_.scalapb.GeneratedMessageCompanion[_ <: _root_.scalapb.GeneratedMessage]]( + _root_.pulumirpc.language.RunRequest.ConfigEntry + ) + def enumCompanionForFieldNumber(__fieldNumber: _root_.scala.Int): _root_.scalapb.GeneratedEnumCompanion[_] = throw new MatchError(__fieldNumber) + lazy val defaultInstance = pulumirpc.language.RunRequest( + project = "", + stack = "", + pwd = "", + program = "", + args = _root_.scala.Seq.empty, + config = _root_.scala.collection.immutable.Map.empty, + dryRun = false, + parallel = 0, + monitorAddress = "", + queryMode = false, + configSecretKeys = _root_.scala.Seq.empty, + organization = "", + configPropertyMap = _root_.scala.None, + info = _root_.scala.None + ) + @SerialVersionUID(0L) + final case class ConfigEntry( + key: _root_.scala.Predef.String = "", + value: _root_.scala.Predef.String = "", + unknownFields: _root_.scalapb.UnknownFieldSet = _root_.scalapb.UnknownFieldSet.empty + ) extends scalapb.GeneratedMessage with scalapb.lenses.Updatable[ConfigEntry] { + @transient + private[this] var __serializedSizeMemoized: _root_.scala.Int = 0 + private[this] def __computeSerializedSize(): _root_.scala.Int = { + var __size = 0 + + { + val __value = key + if (!__value.isEmpty) { + __size += _root_.com.google.protobuf.CodedOutputStream.computeStringSize(1, __value) + } + }; + + { + val __value = value + if (!__value.isEmpty) { + __size += _root_.com.google.protobuf.CodedOutputStream.computeStringSize(2, __value) + } + }; + __size += unknownFields.serializedSize + __size + } + override def serializedSize: _root_.scala.Int = { + var __size = __serializedSizeMemoized + if (__size == 0) { + __size = __computeSerializedSize() + 1 + __serializedSizeMemoized = __size + } + __size - 1 + + } + def writeTo(`_output__`: _root_.com.google.protobuf.CodedOutputStream): _root_.scala.Unit = { + { + val __v = key + if (!__v.isEmpty) { + _output__.writeString(1, __v) + } + }; + { + val __v = value + if (!__v.isEmpty) { + _output__.writeString(2, __v) + } + }; + unknownFields.writeTo(_output__) + } + def withKey(__v: _root_.scala.Predef.String): ConfigEntry = copy(key = __v) + def withValue(__v: _root_.scala.Predef.String): ConfigEntry = copy(value = __v) + def withUnknownFields(__v: _root_.scalapb.UnknownFieldSet) = copy(unknownFields = __v) + def discardUnknownFields = copy(unknownFields = _root_.scalapb.UnknownFieldSet.empty) + def getFieldByNumber(__fieldNumber: _root_.scala.Int): _root_.scala.Any = { + (__fieldNumber: @_root_.scala.unchecked) match { + case 1 => { + val __t = key + if (__t != "") __t else null + } + case 2 => { + val __t = value + if (__t != "") __t else null + } + } + } + def getField(__field: _root_.scalapb.descriptors.FieldDescriptor): _root_.scalapb.descriptors.PValue = { + _root_.scala.Predef.require(__field.containingMessage eq companion.scalaDescriptor) + (__field.number: @_root_.scala.unchecked) match { + case 1 => _root_.scalapb.descriptors.PString(key) + case 2 => _root_.scalapb.descriptors.PString(value) + } + } + def toProtoString: _root_.scala.Predef.String = _root_.scalapb.TextFormat.printToUnicodeString(this) + def companion: pulumirpc.language.RunRequest.ConfigEntry.type = pulumirpc.language.RunRequest.ConfigEntry + // @@protoc_insertion_point(GeneratedMessage[pulumirpc.RunRequest.ConfigEntry]) + } + + object ConfigEntry extends scalapb.GeneratedMessageCompanion[pulumirpc.language.RunRequest.ConfigEntry] { + implicit def messageCompanion: scalapb.GeneratedMessageCompanion[pulumirpc.language.RunRequest.ConfigEntry] = this + def parseFrom(`_input__`: _root_.com.google.protobuf.CodedInputStream): pulumirpc.language.RunRequest.ConfigEntry = { + var __key: _root_.scala.Predef.String = "" + var __value: _root_.scala.Predef.String = "" + var `_unknownFields__`: _root_.scalapb.UnknownFieldSet.Builder = null + var _done__ = false + while (!_done__) { + val _tag__ = _input__.readTag() + _tag__ match { + case 0 => _done__ = true + case 10 => + __key = _input__.readStringRequireUtf8() + case 18 => + __value = _input__.readStringRequireUtf8() + case tag => + if (_unknownFields__ == null) { + _unknownFields__ = new _root_.scalapb.UnknownFieldSet.Builder() + } + _unknownFields__.parseField(tag, _input__) + } + } + pulumirpc.language.RunRequest.ConfigEntry( + key = __key, + value = __value, + unknownFields = if (_unknownFields__ == null) _root_.scalapb.UnknownFieldSet.empty else _unknownFields__.result() + ) + } + implicit def messageReads: _root_.scalapb.descriptors.Reads[pulumirpc.language.RunRequest.ConfigEntry] = _root_.scalapb.descriptors.Reads{ + case _root_.scalapb.descriptors.PMessage(__fieldsMap) => + _root_.scala.Predef.require(__fieldsMap.keys.forall(_.containingMessage eq scalaDescriptor), "FieldDescriptor does not match message type.") + pulumirpc.language.RunRequest.ConfigEntry( + key = __fieldsMap.get(scalaDescriptor.findFieldByNumber(1).get).map(_.as[_root_.scala.Predef.String]).getOrElse(""), + value = __fieldsMap.get(scalaDescriptor.findFieldByNumber(2).get).map(_.as[_root_.scala.Predef.String]).getOrElse("") + ) + case _ => throw new RuntimeException("Expected PMessage") + } + def javaDescriptor: _root_.com.google.protobuf.Descriptors.Descriptor = pulumirpc.language.RunRequest.javaDescriptor.getNestedTypes().get(0) + def scalaDescriptor: _root_.scalapb.descriptors.Descriptor = pulumirpc.language.RunRequest.scalaDescriptor.nestedMessages(0) + def messageCompanionForFieldNumber(__number: _root_.scala.Int): _root_.scalapb.GeneratedMessageCompanion[_] = throw new MatchError(__number) + lazy val nestedMessagesCompanions: Seq[_root_.scalapb.GeneratedMessageCompanion[_ <: _root_.scalapb.GeneratedMessage]] = Seq.empty + def enumCompanionForFieldNumber(__fieldNumber: _root_.scala.Int): _root_.scalapb.GeneratedEnumCompanion[_] = throw new MatchError(__fieldNumber) + lazy val defaultInstance = pulumirpc.language.RunRequest.ConfigEntry( + key = "", + value = "" + ) + implicit class ConfigEntryLens[UpperPB](_l: _root_.scalapb.lenses.Lens[UpperPB, pulumirpc.language.RunRequest.ConfigEntry]) extends _root_.scalapb.lenses.ObjectLens[UpperPB, pulumirpc.language.RunRequest.ConfigEntry](_l) { + def key: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Predef.String] = field(_.key)((c_, f_) => c_.copy(key = f_)) + def value: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Predef.String] = field(_.value)((c_, f_) => c_.copy(value = f_)) + } + final val KEY_FIELD_NUMBER = 1 + final val VALUE_FIELD_NUMBER = 2 + @transient + implicit val keyValueMapper: _root_.scalapb.TypeMapper[pulumirpc.language.RunRequest.ConfigEntry, (_root_.scala.Predef.String, _root_.scala.Predef.String)] = + _root_.scalapb.TypeMapper[pulumirpc.language.RunRequest.ConfigEntry, (_root_.scala.Predef.String, _root_.scala.Predef.String)](__m => (__m.key, __m.value))(__p => pulumirpc.language.RunRequest.ConfigEntry(__p._1, __p._2)) + def of( + key: _root_.scala.Predef.String, + value: _root_.scala.Predef.String + ): _root_.pulumirpc.language.RunRequest.ConfigEntry = _root_.pulumirpc.language.RunRequest.ConfigEntry( + key, + value + ) + // @@protoc_insertion_point(GeneratedMessageCompanion[pulumirpc.RunRequest.ConfigEntry]) + } + + implicit class RunRequestLens[UpperPB](_l: _root_.scalapb.lenses.Lens[UpperPB, pulumirpc.language.RunRequest]) extends _root_.scalapb.lenses.ObjectLens[UpperPB, pulumirpc.language.RunRequest](_l) { + def project: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Predef.String] = field(_.project)((c_, f_) => c_.copy(project = f_)) + def stack: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Predef.String] = field(_.stack)((c_, f_) => c_.copy(stack = f_)) + def pwd: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Predef.String] = field(_.pwd)((c_, f_) => c_.copy(pwd = f_)) + def program: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Predef.String] = field(_.program)((c_, f_) => c_.copy(program = f_)) + def args: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Seq[_root_.scala.Predef.String]] = field(_.args)((c_, f_) => c_.copy(args = f_)) + def config: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.collection.immutable.Map[_root_.scala.Predef.String, _root_.scala.Predef.String]] = field(_.config)((c_, f_) => c_.copy(config = f_)) + def dryRun: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Boolean] = field(_.dryRun)((c_, f_) => c_.copy(dryRun = f_)) + def parallel: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Int] = field(_.parallel)((c_, f_) => c_.copy(parallel = f_)) + def monitorAddress: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Predef.String] = field(_.monitorAddress)((c_, f_) => c_.copy(monitorAddress = f_)) + def queryMode: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Boolean] = field(_.queryMode)((c_, f_) => c_.copy(queryMode = f_)) + def configSecretKeys: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Seq[_root_.scala.Predef.String]] = field(_.configSecretKeys)((c_, f_) => c_.copy(configSecretKeys = f_)) + def organization: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Predef.String] = field(_.organization)((c_, f_) => c_.copy(organization = f_)) + def configPropertyMap: _root_.scalapb.lenses.Lens[UpperPB, com.google.protobuf.struct.Struct] = field(_.getConfigPropertyMap)((c_, f_) => c_.copy(configPropertyMap = _root_.scala.Option(f_))) + def optionalConfigPropertyMap: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Option[com.google.protobuf.struct.Struct]] = field(_.configPropertyMap)((c_, f_) => c_.copy(configPropertyMap = f_)) + def info: _root_.scalapb.lenses.Lens[UpperPB, pulumirpc.language.ProgramInfo] = field(_.getInfo)((c_, f_) => c_.copy(info = _root_.scala.Option(f_))) + def optionalInfo: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Option[pulumirpc.language.ProgramInfo]] = field(_.info)((c_, f_) => c_.copy(info = f_)) + } + final val PROJECT_FIELD_NUMBER = 1 + final val STACK_FIELD_NUMBER = 2 + final val PWD_FIELD_NUMBER = 3 + final val PROGRAM_FIELD_NUMBER = 4 + final val ARGS_FIELD_NUMBER = 5 + final val CONFIG_FIELD_NUMBER = 6 + final val DRYRUN_FIELD_NUMBER = 7 + final val PARALLEL_FIELD_NUMBER = 8 + final val MONITOR_ADDRESS_FIELD_NUMBER = 9 + final val QUERYMODE_FIELD_NUMBER = 10 + final val CONFIGSECRETKEYS_FIELD_NUMBER = 11 + final val ORGANIZATION_FIELD_NUMBER = 12 + final val CONFIGPROPERTYMAP_FIELD_NUMBER = 13 + final val INFO_FIELD_NUMBER = 14 + @transient + private[language] val _typemapper_config: _root_.scalapb.TypeMapper[pulumirpc.language.RunRequest.ConfigEntry, (_root_.scala.Predef.String, _root_.scala.Predef.String)] = implicitly[_root_.scalapb.TypeMapper[pulumirpc.language.RunRequest.ConfigEntry, (_root_.scala.Predef.String, _root_.scala.Predef.String)]] + def of( + project: _root_.scala.Predef.String, + stack: _root_.scala.Predef.String, + pwd: _root_.scala.Predef.String, + program: _root_.scala.Predef.String, + args: _root_.scala.Seq[_root_.scala.Predef.String], + config: _root_.scala.collection.immutable.Map[_root_.scala.Predef.String, _root_.scala.Predef.String], + dryRun: _root_.scala.Boolean, + parallel: _root_.scala.Int, + monitorAddress: _root_.scala.Predef.String, + queryMode: _root_.scala.Boolean, + configSecretKeys: _root_.scala.Seq[_root_.scala.Predef.String], + organization: _root_.scala.Predef.String, + configPropertyMap: _root_.scala.Option[com.google.protobuf.struct.Struct], + info: _root_.scala.Option[pulumirpc.language.ProgramInfo] + ): _root_.pulumirpc.language.RunRequest = _root_.pulumirpc.language.RunRequest( + project, + stack, + pwd, + program, + args, + config, + dryRun, + parallel, + monitorAddress, + queryMode, + configSecretKeys, + organization, + configPropertyMap, + info + ) + // @@protoc_insertion_point(GeneratedMessageCompanion[pulumirpc.RunRequest]) +} diff --git a/core/src/main/scala/besom/rpc/pulumirpc/language/RunResponse.scala b/core/src/main/scala/besom/rpc/pulumirpc/language/RunResponse.scala new file mode 100644 index 00000000..aef6fbed --- /dev/null +++ b/core/src/main/scala/besom/rpc/pulumirpc/language/RunResponse.scala @@ -0,0 +1,156 @@ +// Generated by the Scala Plugin for the Protocol Buffer Compiler. +// Do not edit! +// +// Protofile syntax: PROTO3 + +package pulumirpc.language + +/** RunResponse is the response back from the interpreter/source back to the monitor. + * + * @param error + * An unhandled error if any occurred. + * @param bail + * An error happened. And it was reported to the user. Work should stop immediately + * with nothing further to print to the user. This corresponds to a "result.Bail()" + * value in the 'go' layer. + */ +@SerialVersionUID(0L) +final case class RunResponse( + error: _root_.scala.Predef.String = "", + bail: _root_.scala.Boolean = false, + unknownFields: _root_.scalapb.UnknownFieldSet = _root_.scalapb.UnknownFieldSet.empty + ) extends scalapb.GeneratedMessage with scalapb.lenses.Updatable[RunResponse] { + @transient + private[this] var __serializedSizeMemoized: _root_.scala.Int = 0 + private[this] def __computeSerializedSize(): _root_.scala.Int = { + var __size = 0 + + { + val __value = error + if (!__value.isEmpty) { + __size += _root_.com.google.protobuf.CodedOutputStream.computeStringSize(1, __value) + } + }; + + { + val __value = bail + if (__value != false) { + __size += _root_.com.google.protobuf.CodedOutputStream.computeBoolSize(2, __value) + } + }; + __size += unknownFields.serializedSize + __size + } + override def serializedSize: _root_.scala.Int = { + var __size = __serializedSizeMemoized + if (__size == 0) { + __size = __computeSerializedSize() + 1 + __serializedSizeMemoized = __size + } + __size - 1 + + } + def writeTo(`_output__`: _root_.com.google.protobuf.CodedOutputStream): _root_.scala.Unit = { + { + val __v = error + if (!__v.isEmpty) { + _output__.writeString(1, __v) + } + }; + { + val __v = bail + if (__v != false) { + _output__.writeBool(2, __v) + } + }; + unknownFields.writeTo(_output__) + } + def withError(__v: _root_.scala.Predef.String): RunResponse = copy(error = __v) + def withBail(__v: _root_.scala.Boolean): RunResponse = copy(bail = __v) + def withUnknownFields(__v: _root_.scalapb.UnknownFieldSet) = copy(unknownFields = __v) + def discardUnknownFields = copy(unknownFields = _root_.scalapb.UnknownFieldSet.empty) + def getFieldByNumber(__fieldNumber: _root_.scala.Int): _root_.scala.Any = { + (__fieldNumber: @_root_.scala.unchecked) match { + case 1 => { + val __t = error + if (__t != "") __t else null + } + case 2 => { + val __t = bail + if (__t != false) __t else null + } + } + } + def getField(__field: _root_.scalapb.descriptors.FieldDescriptor): _root_.scalapb.descriptors.PValue = { + _root_.scala.Predef.require(__field.containingMessage eq companion.scalaDescriptor) + (__field.number: @_root_.scala.unchecked) match { + case 1 => _root_.scalapb.descriptors.PString(error) + case 2 => _root_.scalapb.descriptors.PBoolean(bail) + } + } + def toProtoString: _root_.scala.Predef.String = _root_.scalapb.TextFormat.printToUnicodeString(this) + def companion: pulumirpc.language.RunResponse.type = pulumirpc.language.RunResponse + // @@protoc_insertion_point(GeneratedMessage[pulumirpc.RunResponse]) +} + +object RunResponse extends scalapb.GeneratedMessageCompanion[pulumirpc.language.RunResponse] { + implicit def messageCompanion: scalapb.GeneratedMessageCompanion[pulumirpc.language.RunResponse] = this + def parseFrom(`_input__`: _root_.com.google.protobuf.CodedInputStream): pulumirpc.language.RunResponse = { + var __error: _root_.scala.Predef.String = "" + var __bail: _root_.scala.Boolean = false + var `_unknownFields__`: _root_.scalapb.UnknownFieldSet.Builder = null + var _done__ = false + while (!_done__) { + val _tag__ = _input__.readTag() + _tag__ match { + case 0 => _done__ = true + case 10 => + __error = _input__.readStringRequireUtf8() + case 16 => + __bail = _input__.readBool() + case tag => + if (_unknownFields__ == null) { + _unknownFields__ = new _root_.scalapb.UnknownFieldSet.Builder() + } + _unknownFields__.parseField(tag, _input__) + } + } + pulumirpc.language.RunResponse( + error = __error, + bail = __bail, + unknownFields = if (_unknownFields__ == null) _root_.scalapb.UnknownFieldSet.empty else _unknownFields__.result() + ) + } + implicit def messageReads: _root_.scalapb.descriptors.Reads[pulumirpc.language.RunResponse] = _root_.scalapb.descriptors.Reads{ + case _root_.scalapb.descriptors.PMessage(__fieldsMap) => + _root_.scala.Predef.require(__fieldsMap.keys.forall(_.containingMessage eq scalaDescriptor), "FieldDescriptor does not match message type.") + pulumirpc.language.RunResponse( + error = __fieldsMap.get(scalaDescriptor.findFieldByNumber(1).get).map(_.as[_root_.scala.Predef.String]).getOrElse(""), + bail = __fieldsMap.get(scalaDescriptor.findFieldByNumber(2).get).map(_.as[_root_.scala.Boolean]).getOrElse(false) + ) + case _ => throw new RuntimeException("Expected PMessage") + } + def javaDescriptor: _root_.com.google.protobuf.Descriptors.Descriptor = LanguageProto.javaDescriptor.getMessageTypes().get(8) + def scalaDescriptor: _root_.scalapb.descriptors.Descriptor = LanguageProto.scalaDescriptor.messages(8) + def messageCompanionForFieldNumber(__number: _root_.scala.Int): _root_.scalapb.GeneratedMessageCompanion[_] = throw new MatchError(__number) + lazy val nestedMessagesCompanions: Seq[_root_.scalapb.GeneratedMessageCompanion[_ <: _root_.scalapb.GeneratedMessage]] = Seq.empty + def enumCompanionForFieldNumber(__fieldNumber: _root_.scala.Int): _root_.scalapb.GeneratedEnumCompanion[_] = throw new MatchError(__fieldNumber) + lazy val defaultInstance = pulumirpc.language.RunResponse( + error = "", + bail = false + ) + implicit class RunResponseLens[UpperPB](_l: _root_.scalapb.lenses.Lens[UpperPB, pulumirpc.language.RunResponse]) extends _root_.scalapb.lenses.ObjectLens[UpperPB, pulumirpc.language.RunResponse](_l) { + def error: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Predef.String] = field(_.error)((c_, f_) => c_.copy(error = f_)) + def bail: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Boolean] = field(_.bail)((c_, f_) => c_.copy(bail = f_)) + } + final val ERROR_FIELD_NUMBER = 1 + final val BAIL_FIELD_NUMBER = 2 + def of( + error: _root_.scala.Predef.String, + bail: _root_.scala.Boolean + ): _root_.pulumirpc.language.RunResponse = _root_.pulumirpc.language.RunResponse( + error, + bail + ) + // @@protoc_insertion_point(GeneratedMessageCompanion[pulumirpc.RunResponse]) +} diff --git a/proto/pulumi/codegen/hcl.proto b/proto/pulumi/codegen/hcl.proto new file mode 100644 index 00000000..fdeafc4d --- /dev/null +++ b/proto/pulumi/codegen/hcl.proto @@ -0,0 +1,89 @@ +// Copyright 2016-2023, Pulumi Corporation. +// +// 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. + +syntax = "proto3"; + +package pulumirpc.codegen; + +option go_package = "github.com/pulumi/pulumi/sdk/v3/proto/go/codegen"; + +// Pos represents a single position in a source file, by addressing the start byte of a unicode character +// encoded in UTF-8. +message Pos { + // Line is the source code line where this position points. Lines are counted starting at 1 and + // incremented for each newline character encountered. + int64 line = 1; + + // Column is the source code column where this position points, in unicode characters, with counting + // starting at 1. + // + // Column counts characters as they appear visually, so for example a latin letter with a combining + // diacritic mark counts as one character. This is intended for rendering visual markers against source + // code in contexts where these diacritics would be rendered in a single character cell. Technically + // speaking, Column is counting grapheme clusters as used in unicode normalization. + int64 column = 2; + + // Byte is the byte offset into the file where the indicated character begins. This is a zero-based offset + // to the first byte of the first UTF-8 codepoint sequence in the character, and thus gives a position + // that can be resolved _without_ awareness of Unicode characters. + int64 byte = 3; +} + +// Range represents a span of characters between two positions in a source file. +message Range { + // Filename is the name of the file into which this range's positions point. + string filename = 1; + + // Start and End represent the bounds of this range. Start is inclusive and End is exclusive. + Pos start = 2; + Pos end = 3; +} + +// DiagnosticSeverity is the severity level of a diagnostic message. +enum DiagnosticSeverity { + // DIAG_INVALID is the invalid zero value of DiagnosticSeverity + DIAG_INVALID = 0; + // DIAG_ERROR indicates that the problem reported by a diagnostic prevents + // further progress in parsing and/or evaluating the subject. + DIAG_ERROR = 1; + // DIAG_WARNING indicates that the problem reported by a diagnostic warrants + // user attention but does not prevent further progress. It is most + // commonly used for showing deprecation notices. + DIAG_WARNING = 2; +} + +// Diagnostic represents information to be presented to a user about an error or anomaly in parsing or evaluating configuration. +message Diagnostic { + DiagnosticSeverity severity = 1; + + // Summary and Detail contain the English-language description of the + // problem. Summary is a terse description of the general problem and + // detail is a more elaborate, often-multi-sentence description of + // the problem and what might be done to solve it. + string summary = 2; + string detail = 3; + + // Subject and Context are both source ranges relating to the diagnostic. + // + // Subject is a tight range referring to exactly the construct that + // is problematic, while Context is an optional broader range (which should + // fully contain Subject) that ought to be shown around Subject when + // generating isolated source-code snippets in diagnostic messages. + // If Context is nil, the Subject is also the Context. + // + // Some diagnostics have no source ranges at all. If Context is set then + // Subject should always also be set. + Range subject = 4; + Range context = 5; +} \ No newline at end of file diff --git a/proto/pulumi/language.proto b/proto/pulumi/language.proto new file mode 100644 index 00000000..8116cddb --- /dev/null +++ b/proto/pulumi/language.proto @@ -0,0 +1,233 @@ +// Copyright 2016-2023, Pulumi Corporation. +// +// 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. + +syntax = "proto3"; + +import "pulumi/codegen/hcl.proto"; +import "pulumi/plugin.proto"; +import "google/protobuf/empty.proto"; +import "google/protobuf/struct.proto"; + +package pulumirpc; + +option go_package = "github.com/pulumi/pulumi/sdk/v3/proto/go;pulumirpc"; + +// LanguageRuntime is the interface that the planning monitor uses to drive execution of an interpreter responsible +// for confguring and creating resource objects. +service LanguageRuntime { + // GetRequiredPlugins computes the complete set of anticipated plugins required by a program. + rpc GetRequiredPlugins(GetRequiredPluginsRequest) returns (GetRequiredPluginsResponse) {} + // Run executes a program and returns its result. + rpc Run(RunRequest) returns (RunResponse) {} + // GetPluginInfo returns generic information about this plugin, like its version. + rpc GetPluginInfo(google.protobuf.Empty) returns (PluginInfo) {} + + // InstallDependencies will install dependencies for the project, e.g. by running `npm install` for nodejs projects. + rpc InstallDependencies(InstallDependenciesRequest) returns (stream InstallDependenciesResponse) {} + + // About returns information about the runtime for this language. + rpc About(google.protobuf.Empty) returns (AboutResponse) {} + + // GetProgramDependencies returns the set of dependencies required by the program. + rpc GetProgramDependencies(GetProgramDependenciesRequest) returns (GetProgramDependenciesResponse) {} + + // RunPlugin executes a plugin program and returns its result asynchronously. + rpc RunPlugin(RunPluginRequest) returns (stream RunPluginResponse) {} + + // GenerateProgram generates a given PCL program into a program for this language. + rpc GenerateProgram(GenerateProgramRequest) returns (GenerateProgramResponse) {} + + // GenerateProject generates a given PCL program into a project for this language. + rpc GenerateProject(GenerateProjectRequest) returns (GenerateProjectResponse) {} + + // GeneratePackage generates a given pulumi package into a package for this language. + rpc GeneratePackage(GeneratePackageRequest) returns (GeneratePackageResponse) {} + + // Pack packs a package into a language specific artifact. + rpc Pack(PackRequest) returns (PackResponse) {} +} + +// ProgramInfo are the common set of options that a language runtime needs to execute or query a program. This +// is filled in by the engine based on where the `Pulumi.yaml` file was, the `runtime.options` property, and +// the `main` property. +message ProgramInfo { + // the root of the project, where the `Pulumi.yaml` file is located. + string root_directory = 1; + // the absolute path to the directory of the program to execute. Generally, but not required to be, + // underneath the root directory. + string program_directory = 2; + // the entry point of the program, normally '.' meaning to just use the program directory, but can also be + // a filename inside the program directory. How that filename is interpreted, if at all, is language + // specific. + string entry_point = 3; + // JSON style options from the `Pulumi.yaml` runtime options section. + google.protobuf.Struct options = 4; +} + +// AboutResponse returns runtime information about the language. +message AboutResponse { + string executable = 1; // the primary executable for the runtime of this language. + string version = 2; // the version of the runtime for this language. + map metadata = 3; // other information about this language. +} + +message GetProgramDependenciesRequest { + string project = 1 [deprecated = true]; // the project name, the engine always sets this to "deprecated" now. + string pwd = 2 [deprecated = true]; // the program's working directory. + string program = 3 [deprecated = true]; // the path to the program. + bool transitiveDependencies = 4; // if transitive dependencies should be included in the result. + ProgramInfo info = 5; // the program info to use to calculate dependencies. +} + +message DependencyInfo { + string name = 1; // The name of the dependency. + string version = 2; // The version of the dependency. +} + +message GetProgramDependenciesResponse { + repeated DependencyInfo dependencies = 1; // the dependencies of this program +} + +message GetRequiredPluginsRequest { + string project = 1 [deprecated = true]; // the project name, the engine always sets this to "deprecated" now. + string pwd = 2 [deprecated = true]; // the program's working directory. + string program = 3 [deprecated = true]; // the path to the program. + ProgramInfo info = 4; // the program info to use to calculate plugins. +} + +message GetRequiredPluginsResponse { + repeated PluginDependency plugins = 1; // a list of plugins required by this program. +} + +// RunRequest asks the interpreter to execute a program. +message RunRequest { + string project = 1; // the project name. + string stack = 2; // the name of the stack being deployed into. + string pwd = 3; // the program's working directory. + string program = 4 [deprecated = true]; // the path to the program to execute. + repeated string args = 5; // any arguments to pass to the program. + map config = 6; // the configuration variables to apply before running. + bool dryRun = 7; // true if we're only doing a dryrun (preview). + int32 parallel = 8; // the degree of parallelism for resource operations (<=1 for serial). + string monitor_address = 9; // the address for communicating back to the resource monitor. + bool queryMode = 10; // true if we're only doing a query. + repeated string configSecretKeys = 11; // the configuration keys that have secret values. + string organization = 12; // the organization of the stack being deployed into. + google.protobuf.Struct configPropertyMap = 13; // the configuration variables to apply before running. + ProgramInfo info = 14; // the program info to use to execute the program. +} + +// RunResponse is the response back from the interpreter/source back to the monitor. +message RunResponse { + // An unhandled error if any occurred. + string error = 1; + + // An error happened. And it was reported to the user. Work should stop immediately + // with nothing further to print to the user. This corresponds to a "result.Bail()" + // value in the 'go' layer. + bool bail = 2; +} + +message InstallDependenciesRequest { + string directory = 1 [deprecated = true]; // the program's working directory. + bool is_terminal = 2; // if we are running in a terminal and should use ANSI codes + ProgramInfo info = 3; // the program info to use to execute the plugin. +} + +message InstallDependenciesResponse { + bytes stdout = 1; // a line of stdout text. + bytes stderr = 2; // a line of stderr text. +} + +message RunPluginRequest{ + string pwd = 1; // the program's working directory. + string program = 2 [deprecated = true]; // the path to the program to execute. + repeated string args = 3; // any arguments to pass to the program. + repeated string env = 4; // any environment variables to set as part of the program. + ProgramInfo info = 5; // the program info to use to execute the plugin. +} + +message RunPluginResponse { + oneof output { + bytes stdout = 1; // a line of stdout text. + bytes stderr = 2; // a line of stderr text. + int32 exitcode = 3; // the exit code of the provider. + } +} + +message GenerateProgramRequest { + // the PCL source of the project. + map source = 1; + // The target of a codegen.LoaderServer to use for loading schemas. + string loader_target = 2; +} + +message GenerateProgramResponse { + // any diagnostics from code generation. + repeated pulumirpc.codegen.Diagnostic diagnostics = 1; + // the generated program source code. + map source = 2; +} + +message GenerateProjectRequest { + // the directory to generate the project from. + string source_directory = 1; + // the directory to generate the project in. + string target_directory = 2; + // the JSON-encoded pulumi project file. + string project = 3; + // if PCL binding should be strict or not. + bool strict = 4; + // The target of a codegen.LoaderServer to use for loading schemas. + string loader_target = 5; + // local dependencies to use instead of using the package system. This is a map of package name to a local + // path of a language specific artifact to use for the SDK for that package. + map local_dependencies = 6; +} + +message GenerateProjectResponse { + // any diagnostics from code generation. + repeated pulumirpc.codegen.Diagnostic diagnostics = 1; +} + +message GeneratePackageRequest { + // the directory to generate the package in. + string directory = 1; + // the JSON-encoded schema. + string schema = 2; + // extra files to copy to the package output. + map extra_files = 3; + // The target of a codegen.LoaderServer to use for loading schemas. + string loader_target = 4; + // local dependencies to use instead of using the package system. This is a map of package name to a local + // path of a language specific artifact to use for the SDK for that package. + map local_dependencies = 5; +} + +message GeneratePackageResponse { + // any diagnostics from code generation. + repeated pulumirpc.codegen.Diagnostic diagnostics = 1; +} + +message PackRequest { + // the directory of a package to pack. + string package_directory = 1; + // the directory to write the packed artifact to. + string destination_directory = 2; +} + +message PackResponse { + // the full path of the packed artifact. + string artifact_path = 1; +} diff --git a/scripts/Proto.scala b/scripts/Proto.scala index a2fd53ce..c9d826d4 100644 --- a/scripts/Proto.scala +++ b/scripts/Proto.scala @@ -55,10 +55,12 @@ private def copyProto(sourcePath: os.Path, targetPath: os.Path): Unit = os.rel / "pulumi" / "alias.proto", os.rel / "pulumi" / "callback.proto", os.rel / "pulumi" / "engine.proto", + os.rel / "pulumi" / "language.proto", os.rel / "pulumi" / "plugin.proto", os.rel / "pulumi" / "provider.proto", os.rel / "pulumi" / "resource.proto", os.rel / "pulumi" / "source.proto", + os.rel / "pulumi" / "codegen" / "hcl.proto", os.rel / "google" / "protobuf" / "status.proto" ) From e4ed6a5f1218620518d341807bae6f0941a45b91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Pra=C5=BCak?= Date: Wed, 15 May 2024 14:42:04 +0200 Subject: [PATCH 04/15] Add language runtime service --- core/project.scala | 2 +- .../main/scala/besom/internal/Language.scala | 114 ++++++++++++++++++ 2 files changed, 115 insertions(+), 1 deletion(-) create mode 100644 core/src/main/scala/besom/internal/Language.scala diff --git a/core/project.scala b/core/project.scala index 3ea0e590..202896d1 100644 --- a/core/project.scala +++ b/core/project.scala @@ -1,6 +1,6 @@ //> using scala "3.3.1" //> using options "-java-output-version:11", "-Ysafe-init", "-Xmax-inlines:64" -//> using options "-Werror", "-Wunused:all", "-deprecation", "-feature" +//> using options "-Werror", "-Wunused:all", "-deprecation", "-feature", "-Wconf:cat=deprecation:i" // -language:noAutoTupling // after https://github.com/VirtusLab/scala-cli/issues/2708 //> using dep "org.virtuslab::besom-json:0.4.0-SNAPSHOT" diff --git a/core/src/main/scala/besom/internal/Language.scala b/core/src/main/scala/besom/internal/Language.scala new file mode 100644 index 00000000..3761a67a --- /dev/null +++ b/core/src/main/scala/besom/internal/Language.scala @@ -0,0 +1,114 @@ +package besom.internal + +import com.google.protobuf.* +import io.grpc.netty.NettyServerBuilder +import io.grpc.stub.StreamObserver +import io.grpc.{InsecureServerCredentials, MethodDescriptor, Server, Status} +import pulumirpc.language.* +import pulumirpc.language.LanguageRuntimeGrpc.LanguageRuntime +import pulumirpc.plugin.* + +import java.util.concurrent.TimeUnit +import scala.concurrent.{ExecutionContext, Future} + +trait LanguageRuntimeService extends LanguageRuntime: + def run(request: RunRequest): Future[RunResponse] = + request.getInfo + Future.successful(RunResponse()) + + // Unimplemented on purpose + def getRequiredPlugins(request: GetRequiredPluginsRequest): Future[GetRequiredPluginsResponse] = + unimplementedUnaryCall(LanguageRuntimeGrpc.METHOD_GET_REQUIRED_PLUGINS) + + def getPluginInfo(request: empty.Empty): Future[PluginInfo] = + unimplementedUnaryCall(LanguageRuntimeGrpc.METHOD_GET_PLUGIN_INFO) + + def installDependencies(request: InstallDependenciesRequest, responseObserver: StreamObserver[InstallDependenciesResponse]): Unit = + unimplementedUnaryCall(LanguageRuntimeGrpc.METHOD_INSTALL_DEPENDENCIES, responseObserver) + + def about(request: empty.Empty): Future[AboutResponse] = + unimplementedUnaryCall(LanguageRuntimeGrpc.METHOD_ABOUT) + + def getProgramDependencies(request: GetProgramDependenciesRequest): Future[GetProgramDependenciesResponse] = + unimplementedUnaryCall(LanguageRuntimeGrpc.METHOD_GET_PROGRAM_DEPENDENCIES) + + def runPlugin(request: RunPluginRequest, responseObserver: StreamObserver[RunPluginResponse]): Unit = + unimplementedUnaryCall(LanguageRuntimeGrpc.METHOD_RUN_PLUGIN, responseObserver) + + def generateProgram(request: GenerateProgramRequest): Future[GenerateProgramResponse] = + unimplementedUnaryCall(LanguageRuntimeGrpc.METHOD_GENERATE_PROGRAM) + + def generateProject(request: GenerateProjectRequest): Future[GenerateProjectResponse] = + unimplementedUnaryCall(LanguageRuntimeGrpc.METHOD_GENERATE_PROJECT) + + def generatePackage(request: GeneratePackageRequest): Future[GeneratePackageResponse] = + unimplementedUnaryCall(LanguageRuntimeGrpc.METHOD_GENERATE_PACKAGE) + + def pack(request: PackRequest): Future[PackResponse] = + unimplementedUnaryCall(LanguageRuntimeGrpc.METHOD_PACK) + + private def unimplementedUnaryCall[A, B](methodDescriptor: MethodDescriptor[A, B]): Future[B] = + Future.failed( + Status.UNIMPLEMENTED.withDescription(s"Method ${methodDescriptor.getFullMethodName} is unimplemented").asRuntimeException() + ) + + private def unimplementedUnaryCall[A, B](methodDescriptor: MethodDescriptor[A, B], responseObserver: StreamObserver[B]): Unit = + responseObserver.onError( + Status.UNIMPLEMENTED.withDescription(s"Method ${methodDescriptor.getFullMethodName} is unimplemented").asRuntimeException() + ) + +end LanguageRuntimeService + +object LanguageRuntimeService extends LanguageRuntimeService + +object LanguageRuntimeServer: + case class Address(host: String, port: Int): + override def toString: String = s"$host:$port" + + def apply(service: LanguageRuntimeService)(using ec: ExecutionContext): LanguageRuntimeServer = + // TODO: detect that nested stack operations are not supported https://github.com/pulumi/pulumi/issues/5058 + val server = NettyServerBuilder + .forPort(0 /* random port */, InsecureServerCredentials.create()) + .addService( + LanguageRuntimeGrpc.bindService(service, ec) + ) + .build + new LanguageRuntimeServer(server) + +end LanguageRuntimeServer + +class LanguageRuntimeServer private (server: Server): + self => + + import LanguageRuntimeServer.* + + private val ShutdownTimeoutInSeconds = 30 + + def start(): Address = + try server.start() + catch + case e: java.io.IOException => + throw new RuntimeException("Failed to start LanguageRuntimeServer", e) + end try + + val _ = sys.addShutdownHook { + // Use stderr here since the logger may have been reset by its JVM shutdown hook. + System.err.println("Shutting down LanguageRuntimeServer gRPC server since JVM is shutting down") + self.stop() + } + + val address = Address("127.0.0.1", server.getPort) + println(s"LanguageRuntimeServer started, listening on $address") + address + end start + + def stop(): Unit = + try server.shutdown().awaitTermination(ShutdownTimeoutInSeconds, TimeUnit.SECONDS) + catch + case e: InterruptedException => + throw new RuntimeException("Error while awaiting for termination of LanguageRuntimeServer", e) + end try + println("LanguageRuntimeServer shut down"); + end stop + +end LanguageRuntimeServer From 6fe02d50dad7f036f043e295dbdc282a8b198f1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Pra=C5=BCak?= Date: Wed, 15 May 2024 14:55:57 +0200 Subject: [PATCH 05/15] Re-sync SemanticVersion --- .../scala/besom/model/SemanticVersion.scala | 123 ++++++++++++++++++ .../src/main/scala/besom/model/Versions.scala | 70 ---------- codegen/src/model/SemanticVersion.scala | 1 + 3 files changed, 124 insertions(+), 70 deletions(-) create mode 100644 auto/src/main/scala/besom/model/SemanticVersion.scala delete mode 100644 auto/src/main/scala/besom/model/Versions.scala diff --git a/auto/src/main/scala/besom/model/SemanticVersion.scala b/auto/src/main/scala/besom/model/SemanticVersion.scala new file mode 100644 index 00000000..38f6d8f1 --- /dev/null +++ b/auto/src/main/scala/besom/model/SemanticVersion.scala @@ -0,0 +1,123 @@ +package besom.model + +// TODO: move to separate module +// NOTICE: keep in sync with codegen/src/model/SemanticVersion.scala + +/** A semantic version as defined by https://semver.org/ + * + * @param major + * Major version number + * @param minor + * Minor version number + * @param patch + * Patch version number + * @param preRelease + * Pre-release version identifier + * @param buildMetadata + * Build metadata version identifier + */ +case class SemanticVersion( + major: Int, + minor: Int, + patch: Int, + preRelease: Option[String] = None, + buildMetadata: Option[String] = None +) extends Ordered[SemanticVersion]: + require(major >= 0, "major version must be non-negative") + require(minor >= 0, "minor version must be non-negative") + require(patch >= 0, "patch version must be non-negative") + + override def compare(that: SemanticVersion): Int = + import math.Ordered.orderingToOrdered + + val mainCompared = (major, minor, patch).compare((that.major, that.minor, that.patch)) + + // for pre release compare each dot separated identifier from left to right + lazy val thisPreRelease: Vector[Option[String]] = preRelease.map(_.split('.')).getOrElse(Array.empty[String]).toVector.map(Some(_)) + lazy val thatPreRelease: Vector[Option[String]] = that.preRelease.map(_.split('.')).getOrElse(Array.empty[String]).toVector.map(Some(_)) + + def comparePreReleaseIdentifier(thisIdentifeir: Option[String], thatIdentifier: Option[String]): Int = + (thisIdentifeir, thatIdentifier) match + case (Some(thisId), Some(thatId)) => + val thisIsNumeric = thisId.forall(_.isDigit) + val thatIsNumeric = thatId.forall(_.isDigit) + (thisIsNumeric, thatIsNumeric) match + case (true, true) => thisId.toInt.compare(thatId.toInt) + case (false, false) => thisId.compare(thatId) + case (true, false) => -1 // numeric identifiers have always lower precedence than non-numeric identifiers + case (false, true) => 1 // numeric identifiers have always lower precedence than non-numeric identifiers + /* A larger set of pre-release fields has a higher precedence than a smaller set, if all of the preceding identifiers are equal. */ + case (Some(_), None) => 1 // larger set of pre-release fields has higher precedence + case (None, Some(_)) => -1 // larger set of pre-release fields has higher precedence + case (None, None) => 0 + + lazy val preCompared: Int = + thisPreRelease + .zipAll(thatPreRelease, None, None) + .map(comparePreReleaseIdentifier.tupled) + .find(_ != 0) + .getOrElse( + thisPreRelease.length.compare(thatPreRelease.length) + ) // if all identifiers are equal, the version with fewer fields has lower precedence + + // ignore build metadata when comparing versions per semver spec https://semver.org/#spec-item-10 + + if mainCompared != 0 + then mainCompared + else if thisPreRelease.isEmpty && thatPreRelease.nonEmpty + then 1 // normal version has higher precedence than a pre-release version + else if thisPreRelease.nonEmpty && thatPreRelease.isEmpty + then -1 // normal version has higher precedence than a pre-release version + else preCompared // pre-release version has lower precedence than a normal version + end compare + + def isSnapshot: Boolean = preRelease.contains("SNAPSHOT") + + lazy val preReleaseString: String = preRelease.map("-" + _).getOrElse("") + lazy val buildMetadataString: String = buildMetadata.map("+" + _).getOrElse("") + + override def toString: String = s"$major.$minor.$patch$preReleaseString$buildMetadataString" + def toShortString: String = + val xyz = List(major) ++ Option.when(minor > 0)(minor) ++ Option.when(patch > 0)(patch) + xyz.mkString(".") + preReleaseString + buildMetadataString +end SemanticVersion + +//noinspection ScalaFileName +object SemanticVersion { + // https://semver.org/spec/v2.0.0.html#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string + private val versionRegex = + """^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$""".r + + def apply(major: Int, minor: Int, patch: Int): SemanticVersion = + new SemanticVersion(major, minor, patch, None, None) + + def apply(major: Int, minor: Int, patch: Int, preRelease: String): SemanticVersion = + new SemanticVersion(major, minor, patch, Some(preRelease), None) + + def apply(major: Int, minor: Int, patch: Int, preRelease: String, buildMetadata: String): SemanticVersion = + new SemanticVersion(major, minor, patch, Some(preRelease), Some(buildMetadata)) + + def parse(version: String): Either[Exception, SemanticVersion] = { + version match { + case versionRegex(major, minor, patch, preRelease, buildMetadata) => + Right(SemanticVersion(major.toInt, minor.toInt, patch.toInt, Option(preRelease), Option(buildMetadata))) + case _ => Left(Exception(s"Cannot parse as semantic version: '$version'")) + } + } + + /** ParseTolerant allows for certain version specifications that do not strictly adhere to semver specs to be parsed by this library. It + * does so by normalizing versions before passing them to [[parse]]. It currently trims spaces, removes a "v" prefix, and adds a 0 patch + * number to versions with only major and minor components specified. + */ + def parseTolerant(version: String): Either[Exception, SemanticVersion] = { + val str = version.trim.stripPrefix("v") + + // Split into major.minor.(patch+pr+meta) + val parts = str.split("\\.", 3) + if parts.length < 3 then + if parts.last.contains("+") || parts.last.contains("-") then + Left(Exception("Short version cannot contain PreRelease/Build meta data")) + else parse((parts.toList ::: List.fill(3 - parts.length)("0")).mkString(".")) + else parse(str) + } +} diff --git a/auto/src/main/scala/besom/model/Versions.scala b/auto/src/main/scala/besom/model/Versions.scala deleted file mode 100644 index 0905b779..00000000 --- a/auto/src/main/scala/besom/model/Versions.scala +++ /dev/null @@ -1,70 +0,0 @@ -package besom.model - -//noinspection ScalaFileName -case class SemanticVersion( - major: Int, - minor: Int, - patch: Int, - preRelease: Option[String], - buildMetadata: Option[String] -) extends Ordered[SemanticVersion]: - - override def compare(that: SemanticVersion): Int = - import math.Ordered.orderingToOrdered - - val mainCompared = (major, minor, patch).compare((that.major, that.minor, that.patch)) - - // for pre release compare each dot separated identifier from left to right - val thisPreRelease = preRelease.map(_.split('.')).getOrElse(Array.empty[String]) - val thatPreRelease = that.preRelease.map(_.split('.')).getOrElse(Array.empty[String]) - val preCompared = thisPreRelease - .zip(thatPreRelease) - .map { case (thisId, thatId) => - if thisId.forall(_.isDigit) && thatId.forall(_.isDigit) - then thisId.toInt.compare(thatId.toInt) - else thisId.compare(thatId) - } - .find(_ != 0) - .getOrElse(thisPreRelease.length.compare(thatPreRelease.length)) - // ignore build metadata when comparing versions per semver spec https://semver.org/#spec-item-10 - - if mainCompared != 0 - then mainCompared - else preCompared - - override def toString: String = - val preReleaseString = preRelease.map("-" + _).getOrElse("") - val buildMetadataString = buildMetadata.map("+" + _).getOrElse("") - s"$major.$minor.$patch$preReleaseString$buildMetadataString" - -//noinspection ScalaFileName -object SemanticVersion { - private val versionRegex = """(\d+)\.(\d+)\.(\d+)(?:-(.+))?(?:\+(.+))?""".r - - def apply(major: Int, minor: Int, patch: Int): SemanticVersion = - SemanticVersion(major, minor, patch, None, None) - - def parse(version: String): Either[Exception, SemanticVersion] = { - version match { - case versionRegex(major, minor, patch, preRelease, buildMetadata) => - Right(SemanticVersion(major.toInt, minor.toInt, patch.toInt, Option(preRelease), Option(buildMetadata))) - case _ => Left(Exception(s"Cannot parse as semantic version: '$version'")) - } - } - - /** ParseTolerant allows for certain version specifications that do not strictly adhere to semver specs to be parsed by this library. It - * does so by normalizing versions before passing them to [[parse]]. It currently trims spaces, removes a "v" prefix, and adds a 0 patch - * number to versions with only major and minor components specified. - */ - def parseTolerant(version: String): Either[Exception, SemanticVersion] = { - val str = version.trim.stripPrefix("v") - - // Split into major.minor.(patch+pr+meta) - val parts = str.split("\\.", 3) - if parts.length < 3 then - if parts.last.contains("+") || parts.last.contains("-") then - Left(Exception("Short version cannot contain PreRelease/Build meta data")) - else parse((parts.toList ::: List.fill(3 - parts.length)("0")).mkString(".")) - else parse(str) - } -} diff --git a/codegen/src/model/SemanticVersion.scala b/codegen/src/model/SemanticVersion.scala index 2bc344e7..5eb61bf7 100644 --- a/codegen/src/model/SemanticVersion.scala +++ b/codegen/src/model/SemanticVersion.scala @@ -1,6 +1,7 @@ package besom.model // TODO: move to separate module +// NOTICE: keep in sync with auto/src/main/scala/besom/model/SemanticVersion.scala /** A semantic version as defined by https://semver.org/ * From d6af9f6558192650b3804b5787f06aaede1d1d01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Pra=C5=BCak?= Date: Thu, 16 May 2024 14:40:11 +0200 Subject: [PATCH 06/15] Add more core utils --- .../scala/besom/internal/CustomTimeouts.scala | 6 ++-- core/src/main/scala/besom/internal/Env.scala | 7 +---- .../main/scala/besom/util/NotProvided.scala | 29 +++++++++++++++---- core/src/main/scala/besom/util/Util.scala | 11 +++++++ .../scala/besom/util/NotProvidedTest.scala | 18 ++++++++++++ 5 files changed, 57 insertions(+), 14 deletions(-) create mode 100644 core/src/main/scala/besom/util/Util.scala create mode 100644 core/src/test/scala/besom/util/NotProvidedTest.scala diff --git a/core/src/main/scala/besom/internal/CustomTimeouts.scala b/core/src/main/scala/besom/internal/CustomTimeouts.scala index e10c3bcc..79a59d9a 100644 --- a/core/src/main/scala/besom/internal/CustomTimeouts.scala +++ b/core/src/main/scala/besom/internal/CustomTimeouts.scala @@ -28,9 +28,9 @@ case class CustomTimeouts(create: Option[Duration], update: Option[Duration], de /** Companion object for [[CustomTimeouts]] */ object CustomTimeouts: def apply( - create: Duration | NotProvided = NotProvided, - update: Duration | NotProvided = NotProvided, - delete: Duration | NotProvided = NotProvided + create: NotProvidedOr[Duration] = NotProvided, + update: NotProvidedOr[Duration] = NotProvided, + delete: NotProvidedOr[Duration] = NotProvided ): CustomTimeouts = new CustomTimeouts(create.asOption, update.asOption, delete.asOption) // noinspection ScalaUnusedSymbol diff --git a/core/src/main/scala/besom/internal/Env.scala b/core/src/main/scala/besom/internal/Env.scala index a4896700..f6a78419 100644 --- a/core/src/main/scala/besom/internal/Env.scala +++ b/core/src/main/scala/besom/internal/Env.scala @@ -1,6 +1,6 @@ package besom.internal -import besom.util.NonEmptyString +import besom.util.* import scala.util.Try @@ -56,11 +56,6 @@ object Env: private[internal] def getConfigSecretKeys(key: String): Try[Set[NonEmptyString]] = Try { sys.env.get(key).map(_.parseJson.convertTo[Set[NonEmptyString]]).getOrElse(Set.empty) } - private[internal] def isTruthy(s: String): Boolean = - s == "1" || s.equalsIgnoreCase("true") - - private[internal] def isNotTruthy(s: String): Boolean = !isTruthy(s) - lazy val logLevel = getMaybe(EnvLogLevel).flatMap(scribe.Level.get(_)).getOrElse(scribe.Level.Warn) lazy val traceRunToFile = getMaybe(EnvEnableTraceLoggingToFile).map(isTruthy).getOrElse(false) lazy val project = getOrFail(EnvProject) diff --git a/core/src/main/scala/besom/util/NotProvided.scala b/core/src/main/scala/besom/util/NotProvided.scala index 3d0e8e3b..6ce5a169 100644 --- a/core/src/main/scala/besom/util/NotProvided.scala +++ b/core/src/main/scala/besom/util/NotProvided.scala @@ -3,8 +3,27 @@ package besom.util sealed trait NotProvided case object NotProvided extends NotProvided -extension [A](v: A | NotProvided) - def asOption: Option[A] = - v match - case NotProvided => None - case a: A @unchecked => Some(a) +opaque type NotProvidedOr[A] >: A | NotProvided = A | NotProvided + +// we do not want to infect every type so we need this +object NotProvidedOr: + given notProvidedOrOps: {} with // keep the scope clean, no free function + extension [A](npo: NotProvidedOr[A]) + def asOption: Option[A] = + npo match + case NotProvided => None + case a: A @unchecked => Some(a) + def asEither: Either[NotProvided, A] = + npo match + case NotProvided => Left(NotProvided) + case a: A @unchecked => Right(a) + def asSeq: Seq[A] = + npo match + case NotProvided => Seq.empty + case a: A @unchecked => Seq(a) + + def map[B](f: A => B): Option[B] = asOption.map[B](f) + def flatMap[B](f: A => Option[B]): Option[B] = asOption.flatMap[B](f) + def filter(p: A => Boolean): Option[A] = asOption.filter(p) + def fold[B](ifNotProvided: => B)(f: A => B): B = asOption.fold(ifNotProvided)(f) + def bimap[B](ifNotProvided: => B)(f: A => B): Option[B] = asOption.map(f).orElse(Some(ifNotProvided)) diff --git a/core/src/main/scala/besom/util/Util.scala b/core/src/main/scala/besom/util/Util.scala new file mode 100644 index 00000000..2b2c0c8d --- /dev/null +++ b/core/src/main/scala/besom/util/Util.scala @@ -0,0 +1,11 @@ +package besom.util + +private[besom] def isTruthy(s: String): Boolean = s == "1" || s.equalsIgnoreCase("true") +private[besom] def isNotTruthy(s: String): Boolean = !isTruthy(s) + +given eitherOps: {} with + + extension [E <: Throwable, A](a: Either[E, A]) def get: A = a.fold(e => throw e, identity) + + extension [L, R](a: Either[L, R]) + def bimap[L1, R1](left: L => L1, right: R => R1): Either[L1, R1] = a.fold(l => Left(left(l)), r => Right(right(r))) diff --git a/core/src/test/scala/besom/util/NotProvidedTest.scala b/core/src/test/scala/besom/util/NotProvidedTest.scala new file mode 100644 index 00000000..fb992d06 --- /dev/null +++ b/core/src/test/scala/besom/util/NotProvidedTest.scala @@ -0,0 +1,18 @@ +package besom.util + +class NotProvidedTest extends munit.FunSuite with CompileAssertions: + test("asOption works as expected") { + val a: NotProvidedOr[String] = NotProvided + val b: NotProvidedOr[String] = "hello" + + assertEquals(a.asOption, None) + assertEquals(b.asOption, Some("hello")) + } + + test("asOption does not infect every type") { + failsToCompile(""" + import besom.util.* + val x: String = "" + x.asOption + """) + } From b3df2cd6f61392c8f6dbe4a1937f1ef5de3e9d6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Pra=C5=BCak?= Date: Thu, 16 May 2024 20:08:46 +0200 Subject: [PATCH 07/15] Add auto module --- auto/src/main/scala/besom/auto/Git.scala | 4 +- .../scala/besom/auto/LocalWorkspace.scala | 4 +- .../besom/model/FullyQualifiedStackName.scala | 152 ++++++++++++++++++ .../model/FullyQualifiedStackNameTest.scala | 12 ++ 4 files changed, 168 insertions(+), 4 deletions(-) create mode 100644 auto/src/main/scala/besom/model/FullyQualifiedStackName.scala create mode 100644 auto/src/test/scala/besom/model/FullyQualifiedStackNameTest.scala diff --git a/auto/src/main/scala/besom/auto/Git.scala b/auto/src/main/scala/besom/auto/Git.scala index da1c31b3..de6c9ae6 100644 --- a/auto/src/main/scala/besom/auto/Git.scala +++ b/auto/src/main/scala/besom/auto/Git.scala @@ -51,7 +51,7 @@ object Git: val sshSessionFactory = new JschConfigSessionFactory(): override protected def configureJSch(jsch: JSch): Unit = jsch.removeAllIdentity() - jsch.addIdentity("key", key.getBytes(), null /* no pub key */, passphrase.asOption.orNull.getBytes()) + jsch.addIdentity("key", key.getBytes(), null /* no pub key */, passphrase.asOption.map(_.getBytes()).orNull) cloneCommand.setTransportConfigCallback { transport => transport.asInstanceOf[SshTransport].setSshSessionFactory(sshSessionFactory) } @@ -59,7 +59,7 @@ object Git: val sshSessionFactory = new JschConfigSessionFactory(): override protected def configureJSch(jsch: JSch): Unit = jsch.removeAllIdentity() - jsch.addIdentity(keyPath, passphrase.asOption.orNull.getBytes()) + jsch.addIdentity(keyPath, passphrase.asOption.map(_.getBytes()).orNull) cloneCommand.setTransportConfigCallback { transport => transport.asInstanceOf[SshTransport].setSshSessionFactory(sshSessionFactory) } diff --git a/auto/src/main/scala/besom/auto/LocalWorkspace.scala b/auto/src/main/scala/besom/auto/LocalWorkspace.scala index 9d57ce2a..9074dab6 100644 --- a/auto/src/main/scala/besom/auto/LocalWorkspace.scala +++ b/auto/src/main/scala/besom/auto/LocalWorkspace.scala @@ -2,9 +2,9 @@ package besom.auto import besom.json.* import besom.json.DefaultJsonProtocol.* -import besom.model.{PackageName, SemanticVersion} +import besom.model.{PackageName, SemanticVersion, FullyQualifiedStackName, StackName} import besom.util.* -import besom.{FullyQualifiedStackName, StackName, model} +import besom.model import os.Path import java.util.concurrent.atomic.AtomicReference diff --git a/auto/src/main/scala/besom/model/FullyQualifiedStackName.scala b/auto/src/main/scala/besom/model/FullyQualifiedStackName.scala new file mode 100644 index 00000000..03cb7475 --- /dev/null +++ b/auto/src/main/scala/besom/model/FullyQualifiedStackName.scala @@ -0,0 +1,152 @@ +package besom.model + +import scala.compiletime.* +import scala.compiletime.ops.string.* +import scala.language.implicitConversions + +/** A stack name formatted with the least possible specificity: `stack` or `org/stack` or `org/project/stack` or `user/project/stack` + * + * The stack name is specified in one of the following formats: + * + * - `stack`: Identifies the stack name in the current user account or default organization, and the `project` specified by the nearest + * `Pulumi.yaml` project file. + * - `org/stack`: Identifies the stack stackName in the organization `org`, and the project specified by the nearest `Pulumi.yaml` + * project file. + * - `org/project/stack`: Identifies the `stack` name in the organization `org` and the `project`, `project` must match the project + * specified by the nearest `Pulumi.yaml` project file. + * + * For self-managed backends, the `org` portion of the stack name must always be the constant value `organization`. + */ +opaque type StackName <: String = String +object StackName extends StackNameFactory + +trait StackNameFactory: + + def apply(stackName: String): StackName = parse(stackName) match + case Right(stackName) => stackName + case Left(e) => throw e + + def parse(stackName: String): Either[Exception, StackName] = + if stackName.nonEmpty + then Right(stackName.asInstanceOf[StackName]) + else Left(Exception("StackName cannot be empty")) + + extension (stackName: StackName) + /** @return + * the [[StackName]] as a [[Tuple]] of [[String]]s, in the format `(org, project, stack)` + */ + def parts: (Option[String], Option[String], String) = stackName.split("/") match + case Array(stack) if stack.nonEmpty => (None, None, stack) + case Array(project, stack) if stack.nonEmpty => (None, Some(project), stack) + case Array(org, project, stack) if stack.nonEmpty => (Some(org), Some(project), stack) + case _ => throw IllegalArgumentException(s"Invalid StackName string: ${stackName}") + + /** @return + * the [[FullyQualifiedStackName]] for this stack name + */ + def asFullyQualified( + defaultOrganization: => String = "organization", + defaultProject: => String + ): FullyQualifiedStackName = + parts match + case (None, None, stack) => FullyQualifiedStackName(defaultOrganization, defaultProject, stack) + case (None, Some(project), stack) => FullyQualifiedStackName(defaultOrganization, project, stack) + case (Some(org), None, stack) => FullyQualifiedStackName(org, defaultProject, stack) + case (Some(org), Some(project), stack) => FullyQualifiedStackName(org, project, stack) + +end StackNameFactory + +/** A stack name formatted with the greatest possible specificity: `org/project/stack` or `user/project/stack` + * + * Using this format avoids ambiguity in stack identity guards creating or selecting the wrong stack. Note that filestate backends (local + * file, S3, Azure Blob, etc.) do not support stack names, and instead prefixes the stack name with the word `organization` and the project + * name, e.g. `organization/my-project-name/my-stack-name`. + * + * See: https://github.com/pulumi/pulumi/issues/2522 + */ +opaque type FullyQualifiedStackName <: StackName = StackName +object FullyQualifiedStackName extends FullyQualifiedStackNameFactory + +trait FullyQualifiedStackNameFactory: + + private val FullyQualifiedStackNamePattern = ".+/.+/.+".r + + /** Build a fully qualified stack name from its parts with default organization. + * + * @param project + * the project name + * @param stack + * the stack name + * @return + */ + def apply(project: String, stack: String): FullyQualifiedStackName = FullyQualifiedStackName("organization", project, stack) + + /** Build a fully qualified stack name from its parts. + * + * @param org + * the organization name + * @param project + * the project name + * @param stack + * the stack name + * @return + * a [[FullyQualifiedStackName]] if the string is valid, otherwise an exception is thrown + */ + def apply(org: String, project: String, stack: String): FullyQualifiedStackName = + val fqsn = s"${org}/${project}/${stack}" + parse(fqsn) match + case Right(fqsn) => fqsn + case Left(e) => throw e + + /** Parse a string into a [[FullyQualifiedStackName]]. + * @param s + * is a string to parse + * @return + * a [[FullyQualifiedStackName]] if the string is valid, otherwise `None` + */ + def parse(s: String): Either[Exception, FullyQualifiedStackName] = + if FullyQualifiedStackNamePattern.matches(s) then Right(unsafeOf(s)) + else Left(Exception(s"Expected FullyQualifiedStackName to match '$FullyQualifiedStackNamePattern', got: '$s'")) + + /** Parse a string into a [[FullyQualifiedStackName]]. + * + * @param s + * is a string to parse + * @return + * a [[FullyQualifiedStackName]] if the string is valid, otherwise a compile time error occurs + */ + inline def apply(s: String): FullyQualifiedStackName = + requireConst(s) + inline if !constValue[Matches[s.type, ".+/.+/.+"]] then error("Invalid FullyQualifiedStackName string. Must match '.+/.+/.+'") + else s + + implicit inline def str2FullyQualifiedStackName(inline s: String): FullyQualifiedStackName = FullyQualifiedStackName(s) + implicit inline def fqsn2Str(inline fqsn: String | FullyQualifiedStackName): String = fqsn + + private[model] def unsafeOf(s: String): FullyQualifiedStackName = + s.asInstanceOf[FullyQualifiedStackName] // FIXME: why this fails without cast? + + extension (fqsn: FullyQualifiedStackName) + /** @return + * the [[FullyQualifiedStackName]] as a [[Tuple]] of [[String]]s, in the format `(org, project, stack)` + */ + def parts: (String, String, String) = fqsn match + case s"${org}/${project}/${stack}" => (org, project, stack) + case _ => throw IllegalArgumentException(s"Invalid FullyQualifiedStackName string: ${fqsn}") + + /** @return + * the organization name + */ + def organization: String = parts._1 + + /** @return + * the project name + */ + def project: String = parts._2 + + /** @return + * the stack name + */ + def stack: String = parts._3 + +end FullyQualifiedStackNameFactory diff --git a/auto/src/test/scala/besom/model/FullyQualifiedStackNameTest.scala b/auto/src/test/scala/besom/model/FullyQualifiedStackNameTest.scala new file mode 100644 index 00000000..f59e5f6b --- /dev/null +++ b/auto/src/test/scala/besom/model/FullyQualifiedStackNameTest.scala @@ -0,0 +1,12 @@ +package besom.model + +class FullyQualifiedStackNameTest extends munit.FunSuite: + test("local name") { + val stackName = FullyQualifiedStackName("my-project", "my-stack") + assertEquals(stackName, "organization/my-project/my-stack") + } + + test("full name") { + val stackName = FullyQualifiedStackName("my-organization", "my-project", "my-stack") + assertEquals(stackName, "my-organization/my-project/my-stack") + } From 257b59866937495233f6ff7bfe5a2d591232320b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Pra=C5=BCak?= Date: Thu, 16 May 2024 20:09:38 +0200 Subject: [PATCH 08/15] Add non-throwing apis to json --- besom-json/src/main/scala/besom/json/JsonFormat.scala | 8 ++++++++ besom-json/src/main/scala/besom/json/package.scala | 11 ++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/besom-json/src/main/scala/besom/json/JsonFormat.scala b/besom-json/src/main/scala/besom/json/JsonFormat.scala index f64a5fca..83777690 100644 --- a/besom-json/src/main/scala/besom/json/JsonFormat.scala +++ b/besom-json/src/main/scala/besom/json/JsonFormat.scala @@ -19,6 +19,7 @@ package besom.json import scala.annotation.implicitNotFound import scala.language.implicitConversions +import scala.util.Try /** Provides the JSON deserialization for type T. */ @@ -40,6 +41,13 @@ object JsonReader { @implicitNotFound(msg = "Cannot find JsonWriter or JsonFormat type class for ${T}") trait JsonWriter[T] { def write(obj: T): JsValue + def either(obj: T): Either[Exception, JsValue] = + Try { + write(obj) + }.toEither.left.map { + case e: SerializationException => e + case t: Throwable => DeserializationException(t.getMessage, t) + } } object JsonWriter { diff --git a/besom-json/src/main/scala/besom/json/package.scala b/besom-json/src/main/scala/besom/json/package.scala index 8c81f660..8b3bd166 100644 --- a/besom-json/src/main/scala/besom/json/package.scala +++ b/besom-json/src/main/scala/besom/json/package.scala @@ -16,6 +16,8 @@ package besom.json +import scala.util.Try + import scala.language.implicitConversions def deserializationError(msg: String, cause: Throwable = null, fieldNames: List[String] = Nil) = @@ -28,10 +30,17 @@ case class DeserializationException(msg: String, cause: Throwable = null, fieldN class SerializationException(msg: String) extends RuntimeException(msg) private[json] class RichAny[T](any: T) { - def toJson(implicit writer: JsonWriter[T]): JsValue = writer.write(any) + def toJson(implicit writer: JsonWriter[T]): JsValue = writer.write(any) + def asJson(implicit writer: JsonWriter[T]): Either[Exception, JsValue] = writer.either(any) } private[json] class RichString(string: String) { + def parseJson[T: JsonReader]: Either[Exception, T] = Try { + JsonParser(string).convertTo[T] + }.toEither.left.map { + case e: DeserializationException => e + case e => DeserializationException(e.getMessage, e) + } def parseJson: JsValue = JsonParser(string) def parseJson(settings: JsonParserSettings): JsValue = JsonParser(string, settings) } From 1de6d4140d5b5d74101a341ab416d85c42ede3be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Pra=C5=BCak?= Date: Thu, 16 May 2024 20:14:28 +0200 Subject: [PATCH 09/15] Add auto module --- .../besom/auto/{ => internal}/AutoError.scala | 2 +- .../scala/besom/auto/{ => internal}/Git.scala | 2 +- .../auto/{ => internal}/LocalWorkspace.scala | 7 ++--- .../besom/auto/{ => internal}/Stack.scala | 30 ++++++++++--------- .../besom/auto/{ => internal}/Workspace.scala | 6 +--- .../besom/auto/{ => internal}/auto.scala | 2 +- .../besom/auto/{ => internal}/shell.scala | 2 +- .../{ => internal}/LocalWorkspaceTest.scala | 20 ++++++++++--- .../besom/auto/{ => internal}/ShellTest.scala | 4 +-- .../besom/auto/{ => internal}/StackTest.scala | 2 +- auto/src/test/scala/besom/test/Naming.scala | 6 ++-- 11 files changed, 46 insertions(+), 37 deletions(-) rename auto/src/main/scala/besom/auto/{ => internal}/AutoError.scala (99%) rename auto/src/main/scala/besom/auto/{ => internal}/Git.scala (99%) rename auto/src/main/scala/besom/auto/{ => internal}/LocalWorkspace.scala (99%) rename auto/src/main/scala/besom/auto/{ => internal}/Stack.scala (98%) rename auto/src/main/scala/besom/auto/{ => internal}/Workspace.scala (99%) rename auto/src/main/scala/besom/auto/{ => internal}/auto.scala (99%) rename auto/src/main/scala/besom/auto/{ => internal}/shell.scala (99%) rename auto/src/test/scala/besom/auto/{ => internal}/LocalWorkspaceTest.scala (73%) rename auto/src/test/scala/besom/auto/{ => internal}/ShellTest.scala (94%) rename auto/src/test/scala/besom/auto/{ => internal}/StackTest.scala (96%) diff --git a/auto/src/main/scala/besom/auto/AutoError.scala b/auto/src/main/scala/besom/auto/internal/AutoError.scala similarity index 99% rename from auto/src/main/scala/besom/auto/AutoError.scala rename to auto/src/main/scala/besom/auto/internal/AutoError.scala index befe61b2..44b19c35 100644 --- a/auto/src/main/scala/besom/auto/AutoError.scala +++ b/auto/src/main/scala/besom/auto/internal/AutoError.scala @@ -1,4 +1,4 @@ -package besom.auto +package besom.auto.internal import scala.util.matching.Regex diff --git a/auto/src/main/scala/besom/auto/Git.scala b/auto/src/main/scala/besom/auto/internal/Git.scala similarity index 99% rename from auto/src/main/scala/besom/auto/Git.scala rename to auto/src/main/scala/besom/auto/internal/Git.scala index de6c9ae6..c907db86 100644 --- a/auto/src/main/scala/besom/auto/Git.scala +++ b/auto/src/main/scala/besom/auto/internal/Git.scala @@ -1,4 +1,4 @@ -package besom.auto +package besom.auto.internal import besom.util.* import com.jcraft.jsch.JSch diff --git a/auto/src/main/scala/besom/auto/LocalWorkspace.scala b/auto/src/main/scala/besom/auto/internal/LocalWorkspace.scala similarity index 99% rename from auto/src/main/scala/besom/auto/LocalWorkspace.scala rename to auto/src/main/scala/besom/auto/internal/LocalWorkspace.scala index 9074dab6..755fb4d1 100644 --- a/auto/src/main/scala/besom/auto/LocalWorkspace.scala +++ b/auto/src/main/scala/besom/auto/internal/LocalWorkspace.scala @@ -1,7 +1,6 @@ -package besom.auto +package besom.auto.internal import besom.json.* -import besom.json.DefaultJsonProtocol.* import besom.model.{PackageName, SemanticVersion, FullyQualifiedStackName, StackName} import besom.util.* import besom.model @@ -949,11 +948,11 @@ object LocalWorkspaceOption: /** The project settings for the workspace. */ - case class Project(project: besom.auto.Project) extends LocalWorkspaceOption + case class Project(project: besom.auto.internal.Project) extends LocalWorkspaceOption /** A map of `[stackName -> stack settings objects]` to seed the workspace. */ - case class Stacks(stacks: Map[String, besom.auto.ProjectStack]) extends LocalWorkspaceOption + case class Stacks(stacks: Map[String, besom.auto.internal.ProjectStack]) extends LocalWorkspaceOption /** A git repo with a Pulumi Project to clone into the `workDir`. */ diff --git a/auto/src/main/scala/besom/auto/Stack.scala b/auto/src/main/scala/besom/auto/internal/Stack.scala similarity index 98% rename from auto/src/main/scala/besom/auto/Stack.scala rename to auto/src/main/scala/besom/auto/internal/Stack.scala index 80a50588..30611000 100644 --- a/auto/src/main/scala/besom/auto/Stack.scala +++ b/auto/src/main/scala/besom/auto/internal/Stack.scala @@ -1,8 +1,7 @@ -package besom.auto +package besom.auto.internal import besom.internal.{LanguageRuntimeServer, LanguageRuntimeService} import besom.json.* -import besom.json.DefaultJsonProtocol.* import besom.util.* import scala.util.Try @@ -17,7 +16,7 @@ import scala.util.Try * the underlying [[Workspace]] backing the [[Stack]] */ case class Stack(name: String, workspace: Workspace): - import besom.auto.Stack.* + import besom.auto.internal.Stack.* protected[auto] def pulumi(additional: os.Shellable*)(opts: shell.ShellOption*): Either[ShellAutoError | AutoError, shell.Result] = for @@ -686,10 +685,10 @@ object PreviewOption: */ case class UserAgent(agent: String) extends PreviewOption - /** Colorize output. Choices are: [[besom.auto.Color.Always]], [[besom.auto.Color.Never]], [[besom.auto.Color.Raw]], - * [[besom.auto.Color.Auto]] (default "Auto") + /** Colorize output. Choices are: [[besom.auto.internal.Color.Always]], [[besom.auto.internal.Color.Never]], + * [[besom.auto.internal.Color.Raw]], [[besom.auto.internal.Color.Auto]] (default "Auto") */ - case class Color(color: besom.auto.Color) extends PreviewOption + case class Color(color: besom.auto.internal.Color) extends PreviewOption /** Saves an update plan to the given path. */ @@ -844,9 +843,10 @@ object UpOption: */ case class UserAgent(agent: String) extends UpOption - /** Colorize output. Choices are: [[besom.auto.Color.Always]], [[besom.auto.Color.Never]], [[besom.auto.Color.Raw]], + /** Colorize output. Choices are: [[besom.auto.internal.Color.Always]], [[besom.auto.internal.Color.Never]], + * [[besom.auto.internal.Color.Raw]], */ - case class Color(color: besom.auto.Color) extends UpOption + case class Color(color: besom.auto.internal.Color) extends UpOption /** Use the update plan at the given path. */ @@ -992,9 +992,10 @@ object RefreshOption: */ case class UserAgent(agent: String) extends RefreshOption - /** Colorize output. Choices are: [[besom.auto.Color.Always]], [[besom.auto.Color.Never]], [[besom.auto.Color.Raw]], + /** Colorize output. Choices are: [[besom.auto.internal.Color.Always]], [[besom.auto.internal.Color.Never]], + * [[besom.auto.internal.Color.Raw]], */ - case class Color(color: besom.auto.Color) extends RefreshOption + case class Color(color: besom.auto.internal.Color) extends RefreshOption /** Show config secrets when they appear. */ @@ -1105,9 +1106,10 @@ object DestroyOption: */ case class UserAgent(agent: String) extends DestroyOption - /** Colorize output. Choices are: [[besom.auto.Color.Always]], [[besom.auto.Color.Never]], [[besom.auto.Color.Raw]], + /** Colorize output. Choices are: [[besom.auto.internal.Color.Always]], [[besom.auto.internal.Color.Never]], + * [[besom.auto.internal.Color.Raw]], */ - case class Color(color: besom.auto.Color) extends DestroyOption + case class Color(color: besom.auto.internal.Color) extends DestroyOption /** Show config secrets when they appear. */ @@ -1243,8 +1245,8 @@ case class LoggingOptions( Option.when(debug)("--debug") ).flatten -/** Colorize output. Choices are: [[besom.auto.Color.Always]], [[besom.auto.Color.Never]], [[besom.auto.Color.Raw]], - * [[besom.auto.Color.Auto]] (default "Auto") +/** Colorize output. Choices are: [[besom.auto.internal.Color.Always]], [[besom.auto.internal.Color.Never]], + * [[besom.auto.internal.Color.Raw]], [[besom.auto.internal.Color.Auto]] (default "Auto") */ enum Color(val value: String): override def toString: String = value diff --git a/auto/src/main/scala/besom/auto/Workspace.scala b/auto/src/main/scala/besom/auto/internal/Workspace.scala similarity index 99% rename from auto/src/main/scala/besom/auto/Workspace.scala rename to auto/src/main/scala/besom/auto/internal/Workspace.scala index 6c0ed333..b90ed0f2 100644 --- a/auto/src/main/scala/besom/auto/Workspace.scala +++ b/auto/src/main/scala/besom/auto/internal/Workspace.scala @@ -1,7 +1,6 @@ -package besom.auto +package besom.auto.internal import besom.json.* -import besom.json.DefaultJsonProtocol.* import besom.model import besom.util.* import org.virtuslab.yaml.* @@ -14,15 +13,12 @@ import scala.util.Try object yamlHack: import org.virtuslab.yaml.internal.dump.present.PresenterImpl - import besom.auto.internal.HackedSerializerImpl def asYaml(node: Node): String = val events = HackedSerializerImpl.toEvents(node) PresenterImpl.asString(events) end yamlHack -given JsonProtocol = DefaultJsonProtocol - given JsonFormat[Any] = new JsonFormat[Any]: override def write(obj: Any): JsValue = obj match diff --git a/auto/src/main/scala/besom/auto/auto.scala b/auto/src/main/scala/besom/auto/internal/auto.scala similarity index 99% rename from auto/src/main/scala/besom/auto/auto.scala rename to auto/src/main/scala/besom/auto/internal/auto.scala index 55f27925..7131432a 100644 --- a/auto/src/main/scala/besom/auto/auto.scala +++ b/auto/src/main/scala/besom/auto/internal/auto.scala @@ -1,4 +1,4 @@ -package besom.auto +package besom.auto.internal import LocalWorkspaceOption.* import LocalWorkspace.* diff --git a/auto/src/main/scala/besom/auto/shell.scala b/auto/src/main/scala/besom/auto/internal/shell.scala similarity index 99% rename from auto/src/main/scala/besom/auto/shell.scala rename to auto/src/main/scala/besom/auto/internal/shell.scala index 7c210fe5..3c910550 100644 --- a/auto/src/main/scala/besom/auto/shell.scala +++ b/auto/src/main/scala/besom/auto/internal/shell.scala @@ -1,4 +1,4 @@ -package besom.auto +package besom.auto.internal import besom.util.* import os.CommandResult diff --git a/auto/src/test/scala/besom/auto/LocalWorkspaceTest.scala b/auto/src/test/scala/besom/auto/internal/LocalWorkspaceTest.scala similarity index 73% rename from auto/src/test/scala/besom/auto/LocalWorkspaceTest.scala rename to auto/src/test/scala/besom/auto/internal/LocalWorkspaceTest.scala index 8ac44938..f9ef172c 100644 --- a/auto/src/test/scala/besom/auto/LocalWorkspaceTest.scala +++ b/auto/src/test/scala/besom/auto/internal/LocalWorkspaceTest.scala @@ -1,6 +1,6 @@ -package besom.auto +package besom.auto.internal -import besom.FullyQualifiedStackName +import besom.model.FullyQualifiedStackName import besom.test.* import besom.util.eitherOps @@ -49,8 +49,20 @@ class LocalWorkspaceTest extends munit.FunSuite: res.fold( e => fail(e.getMessage, e), (prevRes, upRes) => { - println(prevRes) - println(upRes) + assertEquals(prevRes.summary, Map(OpType.Create -> 1)) + assertEquals( + upRes.outputs, + Map( + "exp_cfg" -> OutputValue(""), + "exp_secret" -> OutputValue("", secret = true), + "exp_static" -> OutputValue("foo") + ) + ) + assertEquals(upRes.summary.kind, "update") + assertEquals(upRes.summary.resourceChanges, Some(Map( + OpType.Create.toString -> 1 + ))) + assertEquals(upRes.summary.result, Some("succeeded")) } ) } diff --git a/auto/src/test/scala/besom/auto/ShellTest.scala b/auto/src/test/scala/besom/auto/internal/ShellTest.scala similarity index 94% rename from auto/src/test/scala/besom/auto/ShellTest.scala rename to auto/src/test/scala/besom/auto/internal/ShellTest.scala index 311bc904..24a0dc59 100644 --- a/auto/src/test/scala/besom/auto/ShellTest.scala +++ b/auto/src/test/scala/besom/auto/internal/ShellTest.scala @@ -1,6 +1,6 @@ -package besom.auto +package besom.auto.internal -import besom.auto.shell.* +import besom.auto.internal.shell.* class ShellTest extends munit.FunSuite: test("ShellOptions.from") { diff --git a/auto/src/test/scala/besom/auto/StackTest.scala b/auto/src/test/scala/besom/auto/internal/StackTest.scala similarity index 96% rename from auto/src/test/scala/besom/auto/StackTest.scala rename to auto/src/test/scala/besom/auto/internal/StackTest.scala index 03837ea5..7c6091cc 100644 --- a/auto/src/test/scala/besom/auto/StackTest.scala +++ b/auto/src/test/scala/besom/auto/internal/StackTest.scala @@ -1,4 +1,4 @@ -package besom.auto +package besom.auto.internal import besom.util.eitherOps diff --git a/auto/src/test/scala/besom/test/Naming.scala b/auto/src/test/scala/besom/test/Naming.scala index efad8bf3..0f052680 100644 --- a/auto/src/test/scala/besom/test/Naming.scala +++ b/auto/src/test/scala/besom/test/Naming.scala @@ -1,6 +1,6 @@ package besom.test -import besom.FullyQualifiedStackName +import besom.model.FullyQualifiedStackName /** SHA1 hash of a string * @@ -15,8 +15,8 @@ def sha1(s: String): String = { String.format("%x", new java.math.BigInteger(1, bytes)) } -def sanitizeName(name: String, replacement: String = "-", limit: Int = 40): String = - name.replaceAll("[^a-zA-Z0-9]+", replacement).toLowerCase().take(limit).stripSuffix(replacement) def stackName(name: String): String = "tests-" + sanitizeName(name) def fqsn(`class`: Class[_], test: munit.TestOptions): FullyQualifiedStackName = FullyQualifiedStackName(sanitizeName(`class`.getSimpleName, limit = 20), stackName(test.name)) +def sanitizeName(name: String, replacement: String = "-", limit: Int = 40): String = + name.replaceAll("[^a-zA-Z0-9]+", replacement).toLowerCase().take(limit).stripSuffix(replacement) From 631974c4340c6cd938eb580d626ccb10621e0e6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Pra=C5=BCak?= Date: Fri, 17 May 2024 11:32:13 +0200 Subject: [PATCH 10/15] Add auto module --- auto/project.scala | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/auto/project.scala b/auto/project.scala index 6ace65ab..30d107d2 100644 --- a/auto/project.scala +++ b/auto/project.scala @@ -5,12 +5,11 @@ //> using dep org.virtuslab::besom-json:0.4.0-SNAPSHOT //> using dep org.virtuslab::besom-core:0.4.0-SNAPSHOT //> using dep org.virtuslab::scala-yaml:0.0.8 -//> using dep com.lihaoyi::os-lib:0.9.3 -//> using dep com.lihaoyi::os-lib-watch:0.9.1 -//> using dep commons-io:commons-io:2.15.1 +//> using dep com.lihaoyi::os-lib:0.10.0 +//> using dep com.lihaoyi::os-lib-watch:0.10.0 //> using dep org.eclipse.jgit:org.eclipse.jgit:6.8.0.202311291450-r //> using dep org.eclipse.jgit:org.eclipse.jgit.ssh.jsch:6.8.0.202311291450-r -//> using dep org.slf4j:slf4j-nop:2.0.5 +//> using dep org.slf4j:slf4j-nop:2.0.13 //> using test.dep org.scalameta::munit:1.0.0-M10 From 1c317bae18930d5fb7307ceaef0a5fb5ca0c1195 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Pra=C5=BCak?= Date: Fri, 17 May 2024 11:59:32 +0200 Subject: [PATCH 11/15] Add auto module --- .../scala/besom/auto/internal/Stack.scala | 66 +++++-------------- .../scala/besom/auto/internal/shell.scala | 63 +++--------------- .../auto/internal/LocalWorkspaceTest.scala | 11 +++- 3 files changed, 35 insertions(+), 105 deletions(-) diff --git a/auto/src/main/scala/besom/auto/internal/Stack.scala b/auto/src/main/scala/besom/auto/internal/Stack.scala index 30611000..ef446aea 100644 --- a/auto/src/main/scala/besom/auto/internal/Stack.scala +++ b/auto/src/main/scala/besom/auto/internal/Stack.scala @@ -87,48 +87,14 @@ case class Stack(name: String, workspace: Workspace): Seq(s"--exec-kind=${ExecKind.AutoInline}", s"--client=$address") else Seq(s"--exec-kind=${ExecKind.AutoLocal}") - /* case class EventLogListener(path: os.Path, private val acc: scala.collection.mutable.ArrayBuffer[EngineEvent]) - extends shell.Tailer.Listener: - import shell.Tailer.Listener - override def handle(event: Listener.Event): Unit = event match - case Listener.Event.FileNotFound(path) => println(s"Event log listener file not found: $path") // TODO: log - case Listener.Event.FileRotated(path) => println(s"Event log listener file rotated: $path") // TODO: log - case Listener.Event.Error(ex) => throw AutoError("Event log listener error", ex) - case Listener.Event.Line(line) => - EngineEvent - .fromJson(line) - .fold( - ex => throw AutoError(s"Failed to parse engine event: $line", ex), - ee => acc += ee - ) - end handle - def events: Seq[EngineEvent] = acc.toSeq - def summary: Either[AutoError, SummaryEvent] = - val l = events.filter(_.summaryEvent.isDefined) - if l.isEmpty then Left(AutoError("Failed to get preview summary, got no engine events")) - else if l.size > 1 then Left(AutoError("Failed to get preview summary, got multiple engine events, expected a singleton")) - else l.head.summaryEvent.toRight(AutoError("Failed to get preview summary, got no summary event")) - end summary - end EventLogListener - object EventLogListener: - def apply(path: os.Path): EventLogListener = EventLogListener(path, scala.collection.mutable.ArrayBuffer.empty) - */ for tailerPath <- tailLogsPath("preview") - /*resultAndListener <- shell.Tailer(path = tailerPath, listener = EventLogListener.apply) { listener => - val watchArgs: Seq[String] = Seq("--event-log=" + tailerPath) - val args: Seq[String] = Seq("preview") ++ sharedArgs ++ kindArgs ++ watchArgs - val result = pulumi(args)( - // FIXME: implement progressStreams and errorProgressStreams - // shell.Option.Stdout(opts.progressStreams), - // shell.Option.Stderr(opts.errorProgressStreams) - ).left.map(AutoError("Preview failed", _)) - println(os.proc("cat", tailerPath).call().out.text()) - println(s"Preview result: $result") - (result, listener) - } - r <- resultAndListener._1 - summary <- resultAndListener._2.summary.left.map(e => AutoError("Failed to get preview summary", e))*/ + // FIXME: tailer is borked + /*tailer <- shell + .Tailer(tailerPath) { line => + println(s"> $line") + } + .tail*/ r <- { val watchArgs: Seq[String] = Seq("--event-log=" + tailerPath) val args: Seq[String] = Seq("preview") ++ sharedArgs ++ kindArgs ++ watchArgs @@ -142,11 +108,6 @@ case class Stack(name: String, workspace: Workspace): case Right(ee) if ee.summaryEvent.isDefined => ee.summaryEvent.get } .toRight(AutoError("Failed to get preview summary, got no summary event")) - /*r <- shell.Tailer2() { - val watchArgs: Seq[String] = Seq("--event-log=" + tailerPath) - val args: Seq[String] = Seq("preview") ++ sharedArgs ++ kindArgs ++ watchArgs - pulumi(args)().left.map(AutoError("Preview failed", _)) - }*/ yield PreviewResult(stdout = r.out, stderr = r.err, summary = summary.resourceChanges) end for end preview @@ -184,12 +145,12 @@ case class Stack(name: String, workspace: Workspace): Seq(s"--exec-kind=${ExecKind.AutoInline}", s"--client=$address") else Seq(s"--exec-kind=${ExecKind.AutoLocal}") - val watchArgs: Seq[String] = Seq.empty // TODO: implement watchArgs + val watchArgs: Seq[String] = Seq.empty // TODO: missing event stream, implement watchArgs val args: Seq[String] = Seq("up", "--yes", "--skip-preview") ++ sharedArgs ++ kindArgs ++ watchArgs pulumi(args)( -// FIXME: implement progressStreams and errorProgressStreams +// FIXME: missing streams, implement progressStreams and errorProgressStreams // shell.Option.Stdout(opts.progressStreams), // shell.Option.Stderr(opts.errorProgressStreams) ) match @@ -552,7 +513,7 @@ case class Stack(name: String, workspace: Workspace): val path = logsDir / "eventlog.txt" os.write(path, "") os.exists(path) match - case true => println(os.proc("ls", "-la", path).call().out.text()) + case true => println(os.proc("ls", "-la", path).call().out.text()) // FIXME: remove the println, use logger case false => throw AutoError(s"Failed to create event log file: $path") path }.toEither.left.map(e => AutoError("Failed to create temporary directory for event logs", e)) @@ -669,6 +630,8 @@ object PreviewOption: */ case class DebugLogging(debugOpts: LoggingOptions) extends PreviewOption + // TODO: missing streams + /** Allows specifying one or more Writers to redirect incremental preview stdout */ // case class ProgressStreams(writers: os.ProcessOutput*) extends PreviewOption @@ -776,6 +739,7 @@ object PreviewOptions: case PreviewOption.Target(urns*) :: tail => from(tail*).copy(target = urns.toList) case PreviewOption.TargetDependents :: tail => from(tail*).copy(targetDependents = true) case PreviewOption.DebugLogging(debugOpts) :: tail => from(tail*).copy(debugLogOpts = debugOpts) +// TODO: missing streams // case PreviewOption.ProgressStreams(writers) :: tail => from(tail*).copy(progressStreams = writers) // case PreviewOption.ErrorProgressStreams(writers) :: tail => from(tail*).copy(errorProgressStreams = writers) // case PreviewOption.EventStreams(channels) :: tail => from(tail*).copy(eventStreams = channels) @@ -829,6 +793,8 @@ object UpOption: */ case class DebugLogging(debugOpts: LoggingOptions) extends UpOption + // TODO: missing streams + /** Allows specifying one or more io.Writers to redirect incremental update stdout */ // case class ProgressStreams(writers: os.ProcessOutput*) extends UpOption @@ -936,6 +902,7 @@ object UpOptions: case UpOption.Target(urns*) :: tail => from(tail*).copy(target = urns.toList) case UpOption.TargetDependents :: tail => from(tail*).copy(targetDependents = true) case UpOption.DebugLogging(debugOpts) :: tail => from(tail*).copy(debugLogOpts = debugOpts) +// TODO: missing streams // case UpOption.ProgressStreams(writers) :: tail => from(tail*).copy(progressStreams = writers) // case UpOption.ErrorProgressStreams(writers) :: tail => from(tail*).copy(errorProgressStreams = writers) // case UpOption.EventStreams(channels) :: tail => from(tail*).copy(eventStreams = channels) @@ -974,6 +941,8 @@ object RefreshOption: */ case class Target(urns: String*) extends RefreshOption + // TODO: missing streams + /** Allows specifying one or more io.Writers to redirect incremental refresh stdout */ // case class ProgressStreams(writers: os.ProcessOutput*) extends RefreshOption @@ -1053,6 +1022,7 @@ object RefreshOptions: case RefreshOption.ExpectNoChanges :: tail => from(tail*).copy(expectNoChanges = true) case RefreshOption.Target(urns*) :: tail => from(tail*).copy(target = urns.toList) case RefreshOption.DebugLogging(debugOpts) :: tail => from(tail*).copy(debugLogOpts = debugOpts) +// TODO: missing streams // case RefreshOption.ProgressStreams(writers) :: tail => from(tail*).copy(progressStreams = writers) // case RefreshOption.ErrorProgressStreams(writers) :: tail => from(tail*).copy(errorProgressStreams = writers) // case RefreshOption.EventStreams(channels) :: tail => from(tail*).copy(eventStreams = channels) diff --git a/auto/src/main/scala/besom/auto/internal/shell.scala b/auto/src/main/scala/besom/auto/internal/shell.scala index 3c910550..ef1b9cd0 100644 --- a/auto/src/main/scala/besom/auto/internal/shell.scala +++ b/auto/src/main/scala/besom/auto/internal/shell.scala @@ -176,65 +176,21 @@ object shell: end pulumi - object Tailer: - import org.apache.commons.io as cio - - import java.nio.charset.StandardCharsets - - private val DefaultBufSize = 4096 - private val DefaultDelay = 100 - - trait Listener extends cio.input.TailerListenerAdapter: - def path: os.Path - def handle(event: Listener.Event): Unit - override def fileNotFound(): Unit = handle(Listener.Event.FileNotFound(path)) - override def fileRotated(): Unit = handle(Listener.Event.FileRotated(path)) - override def handle(ex: Exception): Unit = handle(Listener.Event.Error(AutoError(s"Failed to tail a file", ex))) - override def handle(line: String): Unit = handle(Listener.Event.Line(line)) - object Listener: - sealed trait Event - object Event: - case class FileNotFound(path: os.Path) extends Event - case class FileRotated(path: os.Path) extends Event - case class Error(ex: Exception) extends Event - case class Line(line: String) extends Event - - def apply[A, L <: Listener]( - path: os.Path, - listener: os.Path => L, - delayMillis: Long = DefaultDelay, - end: Boolean = false, - reOpen: Boolean = false, - bufSize: Int = DefaultBufSize - )(block: L => A): Either[Exception, A] = - val ls = listener(path) - val tailer = cio.input.Tailer - .builder() - .setStartThread(true) - .setPath(path.toNIO) - .setTailerListener(ls) - .setCharset(StandardCharsets.UTF_8) - .setDelayDuration(java.time.Duration.ofMillis(delayMillis)) - .setTailFromEnd(end) - .setReOpen(reOpen) - .setBufferSize(bufSize) - .get() - Using(tailer)(_ => block(ls)).toEither.left.map(AutoError("Failed to tail a file", _)) - end Tailer + private def dummyLogger(key: String, value: Any): Unit = println(s"[$key]: $value") - def watch(path: os.Path, onEvent: os.Path => Unit)(block: => Unit): Either[Exception, Unit] = + def watch(path: os.Path, onEvent: os.Path => Unit): Either[Exception, Unit] = Using( os.watch.watch( roots = Seq(path), onEvent = (ps: Set[os.Path]) => ps.filter(_ == path).foreach(onEvent), - logger = (_, _) => () /* TODO: pass a logger adapter here */ - ) - )(_ => block).toEither.left.map(AutoError("Failed to watch a path", _)) + logger = dummyLogger /* TODO: pass a logger adapter here */ + ) // FIXME: throws SIGSEGV + )(_ => ()).toEither.left.map(AutoError("Failed to watch a path", _)) - case class Tailer2(path: os.Path, onLine: String => Unit): + case class Tailer(path: os.Path)(onLine: String => Unit): private val lastPosition: AtomicLong = AtomicLong(0L) - def tail(block: => Unit): Either[Exception, Unit] = + def tail: Either[Exception, Unit] = watch( path, onEvent = p => { @@ -247,8 +203,7 @@ object shell: channel.position() }) } - )(block) - - end Tailer2 + ) + end Tailer end shell diff --git a/auto/src/test/scala/besom/auto/internal/LocalWorkspaceTest.scala b/auto/src/test/scala/besom/auto/internal/LocalWorkspaceTest.scala index f9ef172c..1eeebd16 100644 --- a/auto/src/test/scala/besom/auto/internal/LocalWorkspaceTest.scala +++ b/auto/src/test/scala/besom/auto/internal/LocalWorkspaceTest.scala @@ -59,9 +59,14 @@ class LocalWorkspaceTest extends munit.FunSuite: ) ) assertEquals(upRes.summary.kind, "update") - assertEquals(upRes.summary.resourceChanges, Some(Map( - OpType.Create.toString -> 1 - ))) + assertEquals( + upRes.summary.resourceChanges, + Some( + Map( + OpType.Create.toString -> 1 + ) + ) + ) assertEquals(upRes.summary.result, Some("succeeded")) } ) From 7a68749c179f940093728752a06dacf172990cb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Bia=C5=82y?= Date: Wed, 22 May 2024 11:58:43 +0200 Subject: [PATCH 12/15] added new tailer, some small cleanup --- auto/.scalafmt.conf | 11 ++++ auto/project.scala | 1 + .../scala/besom/auto/internal/Stack.scala | 56 +++++++++++-------- .../scala/besom/auto/internal/Workspace.scala | 2 +- .../scala/besom/auto/internal/shell.scala | 49 ++++++---------- 5 files changed, 63 insertions(+), 56 deletions(-) create mode 100644 auto/.scalafmt.conf diff --git a/auto/.scalafmt.conf b/auto/.scalafmt.conf new file mode 100644 index 00000000..81666df6 --- /dev/null +++ b/auto/.scalafmt.conf @@ -0,0 +1,11 @@ +version = 3.5.2 +runner.dialect = scala3 +project.git = true +align = most +align.openParenCallSite = false +align.openParenDefnSite = false +align.tokens = [{code = "=>", owner = "Case"}, "<-", "%", "%%", "="] +indent.defnSite = 2 +maxColumn = 140 + +rewrite.scala3.insertEndMarkerMinLines = 40 diff --git a/auto/project.scala b/auto/project.scala index 30d107d2..cf458b92 100644 --- a/auto/project.scala +++ b/auto/project.scala @@ -10,6 +10,7 @@ //> using dep org.eclipse.jgit:org.eclipse.jgit:6.8.0.202311291450-r //> using dep org.eclipse.jgit:org.eclipse.jgit.ssh.jsch:6.8.0.202311291450-r //> using dep org.slf4j:slf4j-nop:2.0.13 +//> using dep ma.chinespirit::tailf:0.1.0 //> using test.dep org.scalameta::munit:1.0.0-M10 diff --git a/auto/src/main/scala/besom/auto/internal/Stack.scala b/auto/src/main/scala/besom/auto/internal/Stack.scala index ef446aea..9bc2964f 100644 --- a/auto/src/main/scala/besom/auto/internal/Stack.scala +++ b/auto/src/main/scala/besom/auto/internal/Stack.scala @@ -88,30 +88,36 @@ case class Stack(name: String, workspace: Workspace): else Seq(s"--exec-kind=${ExecKind.AutoLocal}") for - tailerPath <- tailLogsPath("preview") - // FIXME: tailer is borked - /*tailer <- shell - .Tailer(tailerPath) { line => - println(s"> $line") - } - .tail*/ + eventsPath <- eventLogsPath("preview") r <- { - val watchArgs: Seq[String] = Seq("--event-log=" + tailerPath) + val watchArgs: Seq[String] = Seq("--event-log=" + eventsPath) val args: Seq[String] = Seq("preview") ++ sharedArgs ++ kindArgs ++ watchArgs - pulumi(args)().left.map(AutoError("Preview failed", _)) + pulumi(args)().left.map(AutoError("Preview failed", _)) // after this line pulumi cli is no longer running } - summary <- - os.read - .lines(tailerPath) - .map(EngineEvent.fromJson(_)) - .collectFirst { - case Right(ee) if ee.summaryEvent.isDefined => ee.summaryEvent.get - } - .toRight(AutoError("Failed to get preview summary, got no summary event")) + summary <- extractSummaryEventFromEventLog(eventsPath) yield PreviewResult(stdout = r.out, stderr = r.err, summary = summary.resourceChanges) - end for end preview + def extractSummaryEventFromEventLog(path: os.Path): Either[Exception, SummaryEvent] = + val maybeEvents = os.read.lines(path).map(EngineEvent.fromJson(_)) + + if maybeEvents.forall(_.isRight) then + maybeEvents + .collectFirst { case Right(ee) if ee.summaryEvent.isDefined => ee.summaryEvent.get } + .toRight(AutoError("Failed to get preview summary, got no summary event")) + else + val err = + maybeEvents + .collect { case Left(e) => e } + .foldLeft(AutoError("Failed to get event log, got invalid events")) { case (acc, e) => + acc.addSuppressed(e) + acc + } + + Left(err) + + end extractSummaryEventFromEventLog + /** Create or update the resources in a stack by executing the program in the Workspace. Update updates the resources in a stack by * executing the program in the Workspace associated with this stack, if one is provided. * @see @@ -145,7 +151,7 @@ case class Stack(name: String, workspace: Workspace): Seq(s"--exec-kind=${ExecKind.AutoInline}", s"--client=$address") else Seq(s"--exec-kind=${ExecKind.AutoLocal}") - val watchArgs: Seq[String] = Seq.empty // TODO: missing event stream, implement watchArgs + val watchArgs = Seq.empty[String] // TODO: missing event stream, implement watchArgs val args: Seq[String] = Seq("up", "--yes", "--skip-preview") ++ sharedArgs ++ kindArgs ++ watchArgs @@ -195,7 +201,9 @@ case class Stack(name: String, workspace: Workspace): ++ (if workspace.program.isDefined then Seq(s"--exec-kind=${ExecKind.AutoInline}") else Seq(s"--exec-kind=${ExecKind.AutoLocal}")) ++ remoteArgs // Apply the remote args, if needed - val args: Seq[String] = Seq("refresh", "--yes", "--skip-preview") ++ sharedArgs + val watchArgs = Seq.empty[String] // TODO: missing event stream, implement watchArgs + + val args: Seq[String] = Seq("refresh", "--yes", "--skip-preview") ++ sharedArgs ++ watchArgs pulumi(args)() match case Left(e) => Left(AutoError("Refresh failed", e)) case Right(r) => @@ -234,7 +242,9 @@ case class Stack(name: String, workspace: Workspace): ++ (if workspace.program.isDefined then Seq(s"--exec-kind=${ExecKind.AutoInline}") else Seq(s"--exec-kind=${ExecKind.AutoLocal}")) ++ remoteArgs // Apply the remote args, if needed - val args: Seq[String] = Seq("destroy", "--yes", "--skip-preview") ++ sharedArgs + val watchArgs = Seq.empty[String] // TODO: missing event stream, implement watchArgs + + val args: Seq[String] = Seq("destroy", "--yes", "--skip-preview") ++ sharedArgs ++ watchArgs pulumi(args)() match case Left(e) => Left(AutoError("Destroy failed", e)) case Right(r) => @@ -507,7 +517,7 @@ case class Stack(name: String, workspace: Workspace): case _ => throw AutoError(s"Unknown workspace type: ${workspace.getClass.getTypeName}") end remoteArgs - private def tailLogsPath(command: String): Either[Exception, os.Path] = + private def eventLogsPath(command: String): Either[Exception, os.Path] = Try { val logsDir = os.temp.dir(prefix = s"automation-logs-$command-") val path = logsDir / "eventlog.txt" @@ -517,7 +527,7 @@ case class Stack(name: String, workspace: Workspace): case false => throw AutoError(s"Failed to create event log file: $path") path }.toEither.left.map(e => AutoError("Failed to create temporary directory for event logs", e)) - end tailLogsPath + end eventLogsPath private def startLanguageRuntimeServer(): String = import concurrent.ExecutionContext.Implicits.global // FIXME: use a custom execution context diff --git a/auto/src/main/scala/besom/auto/internal/Workspace.scala b/auto/src/main/scala/besom/auto/internal/Workspace.scala index b90ed0f2..f05fcf02 100644 --- a/auto/src/main/scala/besom/auto/internal/Workspace.scala +++ b/auto/src/main/scala/besom/auto/internal/Workspace.scala @@ -703,7 +703,7 @@ case class ProjectStack( secretsProvider: Option[String] = None, encryptedKey: Option[String] = None, encryptionSalt: Option[String] = None, - config: Map[String, Any] = Map.empty, + config: Map[String, Any] = Map.empty, // TODO FIXME UNBORK Map[String, Any] to ConfigMap environment: Option[Environment] = None ) derives JsonFormat, YamlCodec: diff --git a/auto/src/main/scala/besom/auto/internal/shell.scala b/auto/src/main/scala/besom/auto/internal/shell.scala index ef1b9cd0..e7fe32be 100644 --- a/auto/src/main/scala/besom/auto/internal/shell.scala +++ b/auto/src/main/scala/besom/auto/internal/shell.scala @@ -3,10 +3,7 @@ package besom.auto.internal import besom.util.* import os.CommandResult -import java.nio.channels.Channels -import java.util.concurrent.atomic.AtomicLong import scala.io.Source -import scala.util.Using object shell: case class Result private ( @@ -176,34 +173,22 @@ object shell: end pulumi - private def dummyLogger(key: String, value: Any): Unit = println(s"[$key]: $value") - - def watch(path: os.Path, onEvent: os.Path => Unit): Either[Exception, Unit] = - Using( - os.watch.watch( - roots = Seq(path), - onEvent = (ps: Set[os.Path]) => ps.filter(_ == path).foreach(onEvent), - logger = dummyLogger /* TODO: pass a logger adapter here */ - ) // FIXME: throws SIGSEGV - )(_ => ()).toEither.left.map(AutoError("Failed to watch a path", _)) - - case class Tailer(path: os.Path)(onLine: String => Unit): - private val lastPosition: AtomicLong = AtomicLong(0L) - - def tail: Either[Exception, Unit] = - watch( - path, - onEvent = p => { - val _ = lastPosition.getAndUpdate(pos => { - val channel = os.read.channel(p).position(pos) - val inputStream = Channels.newInputStream(channel) - Using(Source.fromInputStream(inputStream)) { - _.getLines().foreach(onLine) - } - channel.position() - }) - } - ) - end Tailer + import ma.chinespirit.tailf.Tail + + // FIXME probably requires a redesign? + def tail(path: os.Path): Either[Exception, Iterator[String] & AutoCloseable] = + Tail + .follow(path.toIO) + .left + .map(e => Exception(s"Failed to open $path for tailing", e)) + .map { is => + new Iterator[String] with AutoCloseable: + val src = scala.io.Source.fromInputStream(is) + val it = src.getLines() + + def hasNext: Boolean = it.hasNext + def next(): String = it.next() + def close(): Unit = src.close() + } end shell From bffe990690eefa5501efe890727d62d9408b566f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Bia=C5=82y?= Date: Wed, 22 May 2024 13:35:57 +0200 Subject: [PATCH 13/15] increase timeout on CI --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 65ab7542..c91bcee6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -49,7 +49,7 @@ jobs: build: if: "! github.event.pull_request.head.repo.fork" runs-on: ubuntu-latest - timeout-minutes: 30 + timeout-minutes: 45 steps: - uses: actions/checkout@v4 - uses: extractions/setup-just@v1 From 8122fdf9907fba27b7d2074109ce3bd2a47f1865 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Bia=C5=82y?= Date: Wed, 22 May 2024 13:41:59 +0200 Subject: [PATCH 14/15] Revert "increase timeout on CI" This reverts commit bffe990690eefa5501efe890727d62d9408b566f. --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c91bcee6..65ab7542 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -49,7 +49,7 @@ jobs: build: if: "! github.event.pull_request.head.repo.fork" runs-on: ubuntu-latest - timeout-minutes: 45 + timeout-minutes: 30 steps: - uses: actions/checkout@v4 - uses: extractions/setup-just@v1 From e5be5b1329b9ee29caf1124b7da9e7e53bc5100a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Bia=C5=82y?= Date: Wed, 22 May 2024 13:44:23 +0200 Subject: [PATCH 15/15] bump pulumi version in CI --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 65ab7542..4b190bec 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -57,7 +57,7 @@ jobs: just-version: '1.14.0' # just for sanity - uses: pulumi/actions@v4 with: - pulumi-version: '3.94.2' + pulumi-version: '3.116.1' - uses: coursier/cache-action@v6.4.3 - uses: VirtusLab/scala-cli-setup@v1.1.0 with: