syntax = "proto3";

package docker.swarmkit.v1;

import "types.proto";
import "specs.proto";
import "timestamp/timestamp.proto"; // TODO(stevvooe): use our own until we fix gogoproto/deepcopy
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.

// Meta contains metadata about objects. Every object contains a meta field.
message Meta {
	// Version tracks the current version of the object.
	Version version = 1 [(gogoproto.nullable) = false];

	// Object timestamps.
	Timestamp created_at = 2;
	Timestamp updated_at = 3;
}

// 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"];

	Meta meta = 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];

	// ManagerStatus provides the current status of the node's manager
	// component, if the node is a manager.
	ManagerStatus manager_status = 6;

	// The node attachment to the ingress network.
	NetworkAttachment attachment = 7;

	// Certificate is the TLS certificate issued for the node, if any.
	Certificate certificate = 8 [(gogoproto.nullable) = false];
}

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

	Meta meta = 2 [(gogoproto.nullable) = false];

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

	// PreviousSpec is the previous service spec that was in place before
	// "Spec".
	ServiceSpec previous_spec = 6;

	// 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;

	// UpdateStatus contains the status of an update, if one is in
	// progress.
	UpdateStatus update_status = 5;
}

// Endpoint specified all the network parameters required to
// correctly discover and load balance a service
message Endpoint {
	EndpointSpec spec = 1;

	// Runtime state of the exposed ports which may carry
	// auto-allocated swarm ports in addition to the user
	// configured information.
	repeated PortConfig ports = 2;

	// An endpoint attachment specifies the data that the process
	// of attaching an endpoint to a network creates.

	// VirtualIP specifies a set of networks this endpoint will be attached to
	// and the IP addresses the target service will be made available under.
	message VirtualIP {
		// NetworkID for which this endpoint attachment was created.
		string network_id = 1 [(gogoproto.customname) = "NetworkID"];

		// A virtual IP is used to address this service in IP
		// layer that the client can use to send requests to
		// this service. A DNS A/AAAA query on the service
		// name might return this IP to the client. This is
		// strictly a logical IP and there may not be any
		// interfaces assigned this IP address or any route
		// created for this address.  More than one to
		// accomodate for both IPv4 and IPv6
		string addr = 2;
	}

	// VirtualIPs specifies the IP addresses under which this endpoint will be
	// made available.
	repeated VirtualIP virtual_ips = 3 [(gogoproto.customname) = "VirtualIPs"];
}

// 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"];

	Meta meta = 2 [(gogoproto.nullable) = false];

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

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

	// Slot is the service slot number for a task.
	// For example, if a replicated service has replicas = 2, there will be a
	// task with slot = 1, and another with slot = 2.
	uint64 slot = 5;

	// 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 = 6 [(gogoproto.customname) = "NodeID"];

	// Annotations defines the names and labels for the runtime, as set by
	// the cluster manager.
	//
	// As backup, if this field has an empty name, the runtime will
	// allocate a unique name for the actual container.
	//
	// NOTE(stevvooe): The preserves the ability for us to making naming
	// decisions for tasks in orchestrator, albeit, this is left empty for now.
	Annotations annotations = 7 [(gogoproto.nullable) = false];

	// ServiceAnnotations is a direct copy of the service name and labels when
	// this task is created.
	//
	// Labels set here will *not* be propagated to the runtime target, such as a
	// container. Use labels on the runtime target for that purpose.
	Annotations service_annotations = 8 [(gogoproto.nullable) = false];

	TaskStatus status = 9 [(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
	// TaskStateShutdown if the manager wants to terminate the task. This field
	// is only written by the manager.
	TaskState desired_state = 10;

	// List of network attachments by the task.
	repeated NetworkAttachment networks = 11;

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

	// LogDriver specifies the selected log driver to use for the task. Agent
	// processes should always favor the value in this field.
	//
	// If present in the TaskSpec, this will be a copy of that value. The
	// orchestrator may choose to insert a value here, which should be honored,
	// such a cluster default or policy-based value.
	//
	// If not present, the daemon's default will be used.
	Driver log_driver = 13;
}

// NetworkAttachment specifies the network parameters of attachment to
// a single network by an object such as task or node.
message NetworkAttachment {
	// Network state as a whole becomes part of the object 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 object
	// as part of getting attached to this network.
	repeated string addresses = 2;

	// List of aliases by which a task is resolved in a network
	repeated string aliases = 3;
}

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

	Meta meta = 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"];
}

// Cluster provides global cluster settings.
message Cluster {
	string id = 1 [(gogoproto.customname) = "ID"];

	Meta meta = 2 [(gogoproto.nullable) = false];

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

	// RootCA contains key material for the root CA.
	RootCA root_ca = 4 [(gogoproto.nullable)=false, (gogoproto.customname) = "RootCA"];

	// Symmetric encryption key distributed by the lead manager. Used by agents
	// for securing network bootstrapping and communication.
	repeated EncryptionKey network_bootstrap_keys = 5;

	// Logical clock used to timestamp every key.  It allows other managers
	// and agents to unambiguously identify the older key to be deleted when
	// a new key is allocated on key rotation.
	uint64 encryption_key_lamport_clock = 6;
}