// Copyright 2024 Google LLC
//
// 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 google.cloud.shell.v1;

import "google/api/annotations.proto";
import "google/api/client.proto";
import "google/api/field_behavior.proto";
import "google/api/resource.proto";
import "google/longrunning/operations.proto";
import "google/protobuf/timestamp.proto";

option go_package = "cloud.google.com/go/shell/apiv1/shellpb;shellpb";
option java_multiple_files = true;
option java_outer_classname = "CloudShellProto";
option java_package = "com.google.cloud.shell.v1";

// API for interacting with Google Cloud Shell. Each user of Cloud Shell has at
// least one environment, which has the ID "default". Environment consists of a
// Docker image defining what is installed on the environment and a home
// directory containing the user's data that will remain across sessions.
// Clients use this API to start and fetch information about their environment,
// which can then be used to connect to that environment via a separate SSH
// client.
service CloudShellService {
  option (google.api.default_host) = "cloudshell.googleapis.com";
  option (google.api.oauth_scopes) = "https://www.googleapis.com/auth/cloud-platform";

  // Gets an environment. Returns NOT_FOUND if the environment does not exist.
  rpc GetEnvironment(GetEnvironmentRequest) returns (Environment) {
    option (google.api.http) = {
      get: "/v1/{name=users/*/environments/*}"
    };
    option (google.api.method_signature) = "name";
  }

  // Starts an existing environment, allowing clients to connect to it. The
  // returned operation will contain an instance of StartEnvironmentMetadata in
  // its metadata field. Users can wait for the environment to start by polling
  // this operation via GetOperation. Once the environment has finished starting
  // and is ready to accept connections, the operation will contain a
  // StartEnvironmentResponse in its response field.
  rpc StartEnvironment(StartEnvironmentRequest) returns (google.longrunning.Operation) {
    option (google.api.http) = {
      post: "/v1/{name=users/*/environments/*}:start"
      body: "*"
    };
    option (google.longrunning.operation_info) = {
      response_type: "StartEnvironmentResponse"
      metadata_type: "StartEnvironmentMetadata"
    };
  }

  // Sends OAuth credentials to a running environment on behalf of a user. When
  // this completes, the environment will be authorized to run various Google
  // Cloud command line tools without requiring the user to manually
  // authenticate.
  rpc AuthorizeEnvironment(AuthorizeEnvironmentRequest) returns (google.longrunning.Operation) {
    option (google.api.http) = {
      post: "/v1/{name=users/*/environments/*}:authorize"
      body: "*"
    };
    option (google.longrunning.operation_info) = {
      response_type: "AuthorizeEnvironmentResponse"
      metadata_type: "AuthorizeEnvironmentMetadata"
    };
  }

  // Adds a public SSH key to an environment, allowing clients with the
  // corresponding private key to connect to that environment via SSH. If a key
  // with the same content already exists, this will error with ALREADY_EXISTS.
  rpc AddPublicKey(AddPublicKeyRequest) returns (google.longrunning.Operation) {
    option (google.api.http) = {
      post: "/v1/{environment=users/*/environments/*}:addPublicKey"
      body: "*"
    };
    option (google.longrunning.operation_info) = {
      response_type: "AddPublicKeyResponse"
      metadata_type: "AddPublicKeyMetadata"
    };
  }

  // Removes a public SSH key from an environment. Clients will no longer be
  // able to connect to the environment using the corresponding private key.
  // If a key with the same content is not present, this will error with
  // NOT_FOUND.
  rpc RemovePublicKey(RemovePublicKeyRequest) returns (google.longrunning.Operation) {
    option (google.api.http) = {
      post: "/v1/{environment=users/*/environments/*}:removePublicKey"
      body: "*"
    };
    option (google.longrunning.operation_info) = {
      response_type: "RemovePublicKeyResponse"
      metadata_type: "RemovePublicKeyMetadata"
    };
  }
}

// A Cloud Shell environment, which is defined as the combination of a Docker
// image specifying what is installed on the environment and a home directory
// containing the user's data that will remain across sessions. Each user has
// at least an environment with the ID "default".
message Environment {
  option (google.api.resource) = {
    type: "cloudshell.googleapis.com/Environment"
    pattern: "users/{user}/environments/{environment}"
  };

  // Possible execution states for an environment.
  enum State {
    // The environment's states is unknown.
    STATE_UNSPECIFIED = 0;

    // The environment is not running and can't be connected to. Starting the
    // environment will transition it to the PENDING state.
    SUSPENDED = 1;

    // The environment is being started but is not yet ready to accept
    // connections.
    PENDING = 2;

    // The environment is running and ready to accept connections. It will
    // automatically transition back to DISABLED after a period of inactivity or
    // if another environment is started.
    RUNNING = 3;

    // The environment is being deleted and can't be connected to.
    DELETING = 4;
  }

  // Immutable. Full name of this resource, in the format
  // `users/{owner_email}/environments/{environment_id}`. `{owner_email}` is the
  // email address of the user to whom this environment belongs, and
  // `{environment_id}` is the identifier of this environment. For example,
  // `users/someone@example.com/environments/default`.
  string name = 1 [(google.api.field_behavior) = IMMUTABLE];

  // Output only. The environment's identifier, unique among the user's
  // environments.
  string id = 2 [(google.api.field_behavior) = OUTPUT_ONLY];

  // Required. Immutable. Full path to the Docker image used to run this environment, e.g.
  // "gcr.io/dev-con/cloud-devshell:latest".
  string docker_image = 3 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.field_behavior) = IMMUTABLE
  ];

  // Output only. Current execution state of this environment.
  State state = 4 [(google.api.field_behavior) = OUTPUT_ONLY];

  // Output only. Host to which clients can connect to initiate HTTPS or WSS
  // connections with the environment.
  string web_host = 12 [(google.api.field_behavior) = OUTPUT_ONLY];

  // Output only. Username that clients should use when initiating SSH sessions
  // with the environment.
  string ssh_username = 5 [(google.api.field_behavior) = OUTPUT_ONLY];

  // Output only. Host to which clients can connect to initiate SSH sessions
  // with the environment.
  string ssh_host = 6 [(google.api.field_behavior) = OUTPUT_ONLY];

  // Output only. Port to which clients can connect to initiate SSH sessions
  // with the environment.
  int32 ssh_port = 7 [(google.api.field_behavior) = OUTPUT_ONLY];

  // Output only. Public keys associated with the environment. Clients can
  // connect to this environment via SSH only if they possess a private key
  // corresponding to at least one of these public keys. Keys can be added to or
  // removed from the environment using the AddPublicKey and RemovePublicKey
  // methods.
  repeated string public_keys = 8 [(google.api.field_behavior) = OUTPUT_ONLY];
}

// Request message for
// [GetEnvironment][google.cloud.shell.v1.CloudShellService.GetEnvironment].
message GetEnvironmentRequest {
  // Required. Name of the requested resource, for example `users/me/environments/default`
  // or `users/someone@example.com/environments/default`.
  string name = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "cloudshell.googleapis.com/Environment"
    }
  ];
}

// Message included in the metadata field of operations returned from
// [CreateEnvironment][google.cloud.shell.v1.CloudShellService.CreateEnvironment].
message CreateEnvironmentMetadata {

}

// Message included in the metadata field of operations returned from
// [DeleteEnvironment][google.cloud.shell.v1.CloudShellService.DeleteEnvironment].
message DeleteEnvironmentMetadata {

}

// Request message for
// [StartEnvironment][google.cloud.shell.v1.CloudShellService.StartEnvironment].
message StartEnvironmentRequest {
  // Name of the resource that should be started, for example
  // `users/me/environments/default` or
  // `users/someone@example.com/environments/default`.
  string name = 1;

  // The initial access token passed to the environment. If this is present and
  // valid, the environment will be pre-authenticated with gcloud so that the
  // user can run gcloud commands in Cloud Shell without having to log in. This
  // code can be updated later by calling AuthorizeEnvironment.
  string access_token = 2;

  // Public keys that should be added to the environment before it is started.
  repeated string public_keys = 3;
}

// Request message for
// [AuthorizeEnvironment][google.cloud.shell.v1.CloudShellService.AuthorizeEnvironment].
message AuthorizeEnvironmentRequest {
  // Name of the resource that should receive the credentials, for example
  // `users/me/environments/default` or
  // `users/someone@example.com/environments/default`.
  string name = 1;

  // The OAuth access token that should be sent to the environment.
  string access_token = 2;

  // The OAuth ID token that should be sent to the environment.
  string id_token = 4;

  // The time when the credentials expire. If not set, defaults to one hour from
  // when the server received the request.
  google.protobuf.Timestamp expire_time = 3;
}

// Response message for
// [AuthorizeEnvironment][google.cloud.shell.v1.CloudShellService.AuthorizeEnvironment].
message AuthorizeEnvironmentResponse {

}

// Message included in the metadata field of operations returned from
// [AuthorizeEnvironment][google.cloud.shell.v1.CloudShellService.AuthorizeEnvironment].
message AuthorizeEnvironmentMetadata {

}

// Message included in the metadata field of operations returned from
// [StartEnvironment][google.cloud.shell.v1.CloudShellService.StartEnvironment].
message StartEnvironmentMetadata {
  // Possible states an environment might transition between during startup.
  // These states are not normally actionable by clients, but may be used to
  // show a progress message to the user. An environment won't necessarily go
  // through all of these states when starting. More states are likely to be
  // added in the future.
  enum State {
    // The environment's start state is unknown.
    STATE_UNSPECIFIED = 0;

    // The environment is in the process of being started, but no additional
    // details are available.
    STARTING = 1;

    // Startup is waiting for the user's disk to be unarchived. This can happen
    // when the user returns to Cloud Shell after not having used it for a
    // while, and suggests that startup will take longer than normal.
    UNARCHIVING_DISK = 2;

    // Startup is waiting for compute resources to be assigned to the
    // environment. This should normally happen very quickly, but an environment
    // might stay in this state for an extended period of time if the system is
    // experiencing heavy load.
    AWAITING_COMPUTE_RESOURCES = 4;

    // Startup has completed. If the start operation was successful, the user
    // should be able to establish an SSH connection to their environment.
    // Otherwise, the operation will contain details of the failure.
    FINISHED = 3;
  }

  // Current state of the environment being started.
  State state = 1;
}

// Message included in the response field of operations returned from
// [StartEnvironment][google.cloud.shell.v1.CloudShellService.StartEnvironment]
// once the operation is complete.
message StartEnvironmentResponse {
  // Environment that was started.
  Environment environment = 1;
}

// Request message for
// [AddPublicKey][google.cloud.shell.v1.CloudShellService.AddPublicKey].
message AddPublicKeyRequest {
  // Environment this key should be added to, e.g.
  // `users/me/environments/default`.
  string environment = 1;

  // Key that should be added to the environment. Supported formats are
  // `ssh-dss` (see RFC4253), `ssh-rsa` (see RFC4253), `ecdsa-sha2-nistp256`
  // (see RFC5656), `ecdsa-sha2-nistp384` (see RFC5656) and
  // `ecdsa-sha2-nistp521` (see RFC5656). It should be structured as
  // &lt;format&gt; &lt;content&gt;, where &lt;content&gt; part is encoded with
  // Base64.
  string key = 2;
}

// Response message for
// [AddPublicKey][google.cloud.shell.v1.CloudShellService.AddPublicKey].
message AddPublicKeyResponse {
  // Key that was added to the environment.
  string key = 1;
}

// Message included in the metadata field of operations returned from
// [AddPublicKey][google.cloud.shell.v1.CloudShellService.AddPublicKey].
message AddPublicKeyMetadata {

}

// Request message for
// [RemovePublicKey][google.cloud.shell.v1.CloudShellService.RemovePublicKey].
message RemovePublicKeyRequest {
  // Environment this key should be removed from, e.g.
  // `users/me/environments/default`.
  string environment = 1;

  // Key that should be removed from the environment.
  string key = 2;
}

// Response message for
// [RemovePublicKey][google.cloud.shell.v1.CloudShellService.RemovePublicKey].
message RemovePublicKeyResponse {

}

// Message included in the metadata field of operations returned from
// [RemovePublicKey][google.cloud.shell.v1.CloudShellService.RemovePublicKey].
message RemovePublicKeyMetadata {

}

// Cloud-shell specific information that will be included as details in failure
// responses.
message CloudShellErrorDetails {
  // Set of possible errors returned from API calls.
  enum CloudShellErrorCode {
    // An unknown error occurred.
    CLOUD_SHELL_ERROR_CODE_UNSPECIFIED = 0;

    // The image used by the Cloud Shell environment either does not exist or
    // the user does not have access to it.
    IMAGE_UNAVAILABLE = 1;

    // Cloud Shell has been disabled by an administrator for the user making the
    // request.
    CLOUD_SHELL_DISABLED = 2;

    // Cloud Shell has been permanently disabled due to a Terms of Service
    // violation by the user.
    TOS_VIOLATION = 4;

    // The user has exhausted their weekly Cloud Shell quota, and Cloud Shell
    // will be disabled until the quota resets.
    QUOTA_EXCEEDED = 5;

    // The Cloud Shell environment is unavailable and cannot be connected to at
    // the moment.
    ENVIRONMENT_UNAVAILABLE = 6;
  }

  // Code indicating the specific error the occurred.
  CloudShellErrorCode code = 1;
}
