syntax = "proto3";

package docker.cluster.api;

import "types.proto";
import "specs.proto";
import "gogoproto/gogo.proto";

// This file contains definitions for all first-class objects in the cluster
// API. Such types typically have a corresponding specification, with the
// naming XXXSpec, but not all.

// Node provides the internal node state as seen by the cluster.
message Node {
	// ID specifies the identity of the node.
	string id = 1 [(gogoproto.customname) = "ID"];

	// Version tracks the last time the node was modified.
	Version version = 2 [(gogoproto.nullable) = false];

	// Spec defines the desired state of the node as specified by the user.
	// The system will honor this and will *never* modify it.
	NodeSpec spec = 3 [(gogoproto.nullable) = false];

	// Description encapsulated the properties of the Node as reported by the
	// agent.
	NodeDescription description = 4;

	// Status provides the current status of the node, as seen by the manager.
	NodeStatus status = 5 [(gogoproto.nullable) = false];
}

// Member provides informations about the state of a manager in the cluster.
// A Member is essentially a Manager but from a Raft role perspective
// TODO(abronan): this is not an appropriate name for a top level object (specific to raft),
// this should be changed back to 'Manager'
message Member {
	// ID specifies the identity of the manager.
	string id = 1 [(gogoproto.customname) = "ID"];

	string addr = 2;

	// MemberSpec declares labels applied to the Manager.
	MemberSpec spec = 3;

	// Description encapsulates the properties of the Member as reported by another member of the Manager set.
	MemberDescription description = 4;

	// Status provides the current status of the manager from the perspective of another manager.
	MemberStatus status = 5 [(gogoproto.nullable) = false];
}

message Service {
	string id = 1 [(gogoproto.customname) = "ID"];

	// Version tracks the last time the service was modified.
	Version version = 2 [(gogoproto.nullable) = false];

	ServiceSpec spec = 3 [(gogoproto.nullable) = false];

	// Runtime state of service endpoint. This may be different
	// from the spec version because the user may not have entered
	// the optional fields like node_port or virtual_ip and it
	// could be auto allocated by the system.
	Endpoint endpoint = 4;
}

// Task specifies the parameters for implementing a Spec. A task is effectively
// immutable and idempotent. Once it is dispatched to a node, it will not be
// dispatched to another node.
message Task {
	string id = 1 [(gogoproto.customname) = "ID"];

	// Version tracks the last time the task was modified.
	Version version = 2 [(gogoproto.nullable) = false];

	// ServiceID indicates the service under which this task is orchestrated. This
	// should almost always be set.
	string service_id = 3 [(gogoproto.customname) = "ServiceID"];

	// Instance is the instance number for a task. For example, if a
	// running service has instances = 2, there will be a task with
	// instance = 1, and another with instance = 2.
	uint64 instance = 4;

	// NodeID indicates the node to which the task is assigned. If this field
	// is empty or not set, the task is unassigned.
	string node_id = 5 [(gogoproto.customname) = "NodeID"];

	// Annotations inherits labels from the ServiceSpec.Annotations associated
	// with this task. It may include other labels added by the manager. The
	// name will be a human readable name, calculated based on the
	// ServiceSpec.Annotations.Name field.
	Annotations annotations = 6 [(gogoproto.nullable) = false];

	// Spec declares the runtime parameters for the task. This is copied out of
	// the service's template field.
	TaskSpec spec = 7 [(gogoproto.nullable) = false];

	TaskStatus status = 8 [(gogoproto.nullable) = false];

	// DesiredState is the target state for the task. It is set to
	// TaskStateRunning when a task is first created, and changed to
	// TaskStateDead if the manager wants to terminate the task. This field
	// is only written by the manager.
	TaskState desired_state = 9;

	message NetworkAttachment {
		// Network state as a whole becomes part of Task so
		// that it always is available for use in agents so
		// that agents don't have any other dependency during execution.
		Network network = 1;

		// List of IPv4/IPv6 addresses that are assigned to the task
		// as part of getting attached to this network.
		repeated string addresses = 2;
	}

	repeated NetworkAttachment networks = 10;

	// A copy of runtime state of service endpoint from Service
	// object to be distributed to agents as part of the task.
	Endpoint endpoint = 11;
}

message Volume {
	string id = 1 [(gogoproto.customname) = "ID"];

	// Version tracks the last time the volume was modified.
	Version version = 2 [(gogoproto.nullable) = false];

	VolumeSpec spec = 3 [(gogoproto.nullable) = false];

	// Driver specific operational state provided by the Volume driver.
	Driver driver_state = 4;
}

message Network {
	string id = 1 [(gogoproto.customname) = "ID"];

	// Version tracks the last time the network was modified.
	Version version = 2 [(gogoproto.nullable) = false];

	NetworkSpec spec = 3 [(gogoproto.nullable) = false];

	// Driver specific operational state provided by the network driver.
	Driver driver_state = 4;

	// Runtime state of IPAM options. This may not reflect the
	// ipam options from NetworkSpec.
	IPAMOptions ipam = 5 [(gogoproto.customname) = "IPAM"];
}
