/*
	Copyright The containerd Authors.

	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 containerd.services.containers.v1;

import weak "gogoproto/gogo.proto";
import "google/protobuf/any.proto";
import "google/protobuf/empty.proto";
import "google/protobuf/field_mask.proto";
import "google/protobuf/timestamp.proto";

option go_package = "github.com/containerd/containerd/api/services/containers/v1;containers";

// Containers provides metadata storage for containers used in the execution
// service.
//
// The objects here provide an state-independent view of containers for use in
// management and resource pinning. From that perspective, containers do not
// have a "state" but rather this is the set of resources that will be
// considered in use by the container.
//
// From the perspective of the execution service, these objects represent the
// base parameters for creating a container process.
//
// In general, when looking to add fields for this type, first ask yourself
// whether or not the function of the field has to do with runtime execution or
// is invariant of the runtime state of the container. If it has to do with
// runtime, or changes as the "container" is started and stops, it probably
// doesn't belong on this object.
service Containers {
	rpc Get(GetContainerRequest) returns (GetContainerResponse);
	rpc List(ListContainersRequest) returns (ListContainersResponse);
	rpc ListStream(ListContainersRequest) returns (stream ListContainerMessage);
	rpc Create(CreateContainerRequest) returns (CreateContainerResponse);
	rpc Update(UpdateContainerRequest) returns (UpdateContainerResponse);
	rpc Delete(DeleteContainerRequest) returns (google.protobuf.Empty);
}

message Container {
	// ID is the user-specified identifier.
	//
	// This field may not be updated.
	string id = 1;

	// Labels provides an area to include arbitrary data on containers.
	//
	// The combined size of a key/value pair cannot exceed 4096 bytes.
	//
	// Note that to add a new value to this field, read the existing set and
	// include the entire result in the update call.
	map<string, string> labels  = 2;

	// Image contains the reference of the image used to build the
	// specification and snapshots for running this container.
	//
	// If this field is updated, the spec and rootfs needed to updated, as well.
	string image = 3;

	message Runtime {
		// Name is the name of the runtime.
		string name = 1;
		// Options specify additional runtime initialization options.
		google.protobuf.Any options = 2;
	}
	// Runtime specifies which runtime to use for executing this container.
	Runtime runtime = 4;

	// Spec to be used when creating the container. This is runtime specific.
	google.protobuf.Any spec = 5;

	// Snapshotter specifies the snapshotter name used for rootfs
	string snapshotter = 6;

	// SnapshotKey specifies the snapshot key to use for the container's root
	// filesystem. When starting a task from this container, a caller should
	// look up the mounts from the snapshot service and include those on the
	// task create request.
	//
	// Snapshots referenced in this field will not be garbage collected.
	//
	// This field is set to empty when the rootfs is not a snapshot.
	//
	// This field may be updated.
	string snapshot_key = 7;

	// CreatedAt is the time the container was first created.
	google.protobuf.Timestamp created_at = 8 [(gogoproto.stdtime) = true, (gogoproto.nullable) = false];

	// UpdatedAt is the last time the container was mutated.
	google.protobuf.Timestamp updated_at = 9 [(gogoproto.stdtime) = true, (gogoproto.nullable) = false];

	// Extensions allow clients to provide zero or more blobs that are directly
	// associated with the container. One may provide protobuf, json, or other
	// encoding formats. The primary use of this is to further decorate the
	// container object with fields that may be specific to a client integration.
	//
	// The key portion of this map should identify a "name" for the extension
	// that should be unique against other extensions. When updating extension
	// data, one should only update the specified extension using field paths
	// to select a specific map key.
	map<string, google.protobuf.Any> extensions = 10 [(gogoproto.nullable) = false];
}

message GetContainerRequest {
	string id = 1;
}

message GetContainerResponse {
	Container container = 1 [(gogoproto.nullable) = false];
}

message ListContainersRequest {
	// Filters contains one or more filters using the syntax defined in the
	// containerd filter package.
	//
	// The returned result will be those that match any of the provided
	// filters. Expanded, containers that match the following will be
	// returned:
	//
	//	filters[0] or filters[1] or ... or filters[n-1] or filters[n]
	//
	// If filters is zero-length or nil, all items will be returned.
	repeated string filters = 1;
}

message ListContainersResponse {
	repeated Container containers = 1 [(gogoproto.nullable) = false];
}

message CreateContainerRequest {
	Container container = 1 [(gogoproto.nullable) = false];
}

message CreateContainerResponse {
	Container container = 1 [(gogoproto.nullable) = false];
}

// UpdateContainerRequest updates the metadata on one or more container.
//
// The operation should follow semantics described in
// https://developers.google.com/protocol-buffers/docs/reference/csharp/class/google/protobuf/well-known-types/field-mask,
// unless otherwise qualified.
message UpdateContainerRequest {
	// Container provides the target values, as declared by the mask, for the update.
	//
	// The ID field must be set.
	Container container = 1 [(gogoproto.nullable) = false];

	// UpdateMask specifies which fields to perform the update on. If empty,
	// the operation applies to all fields.
	google.protobuf.FieldMask update_mask = 2;
}

message UpdateContainerResponse {
	Container container = 1 [(gogoproto.nullable) = false];
}

message DeleteContainerRequest {
	string id = 1;
}

message ListContainerMessage {
	Container container = 1;
}
