syntax = "proto3";

package docker.cluster.api;

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

// Specs are container objects for user provided input. All creations and
// updates are done through spec types. As a convention, user input from a spec
// is never touched in created objects. This allows one to verify that the
// users intent has not been modified.
//
// Put differently, spec types can be said to represent the desired state of
// the system. In situations where modifications need to be made to a
// particular component, API objects will either have a copy of the spec
// component or a different representation to reflect allocation or resolution.

// Annotations provide useful information to identify API objects. They are
// common to all API specs.
message Annotations {
	string name = 1;
	map<string, string> labels = 2;
}

message NodeSpec {
	Annotations annotations = 1 [(gogoproto.nullable) = false];

	enum Availability {
		option (gogoproto.goproto_enum_prefix) = false;

		// Active nodes.
		ACTIVE = 0 [(gogoproto.enumvalue_customname) = "NodeAvailabilityActive"];

		// Paused nodes won't be considered by the scheduler, preventing any
		// further task to run on them.
		PAUSE = 1 [(gogoproto.enumvalue_customname) = "NodeAvailabilityPause"];

		// Drained nodes are paused and any task already running on them will
		// be evicted.
		DRAIN = 2 [(gogoproto.enumvalue_customname) = "NodeAvailabilityDrain"];
	}

	// Availability allows a user to control the current scheduling status of a
	// node.
	Availability availability = 2;
}

message MemberSpec {
	Annotations annotations = 1 [(gogoproto.nullable) = false];
}

// ServiceSpec defines the properties of a service.
//
// A service instructs the cluster in orchestrating repeated instances of a
// template, implemented as tasks. Based on the number of instances, scheduling
// strategy and restart policy, a number of application-level behaviors can be
// defined.
message ServiceSpec {
	Annotations annotations = 1 [(gogoproto.nullable) = false];

	// Template defines the base configuration for tasks created for this service.
	TaskSpec template = 2;

	// Instances specifies the number of instances of the service service that
	// should be running.
	int64 instances = 3;

	// RestartPolicy specifies what to do when a task fails or finishes.
	RestartPolicy restart = 4;

	enum Strategy {
		option (gogoproto.goproto_enum_prefix) = false;

		// Spread instances evenly among candidate nodes.
		SERVICE_STRATEGY_SPREAD = 0 [(gogoproto.enumvalue_customname) = "ServiceStrategySpread"];

		// Pack instances tightly across available nodes.
		SERVICE_STRATEGY_BINPACK = 1 [(gogoproto.enumvalue_customname) = "ServiceStrategyBinPack"];
	}

	Strategy strategy = 5;

	enum Mode {
		option (gogoproto.goproto_enum_prefix) = false;

		// Running sets the reconcilation target to ensure there are running
		// tasks equal to the number instances. If the using the fill
		// scheduling strategy, the number of nodes will be used instead.
		SERVICE_MODE_RUNNING = 0 [(gogoproto.enumvalue_customname) = "ServiceModeRunning"];

		// Batch sets reconcilation target as number of completed tasks. If in
		// fill scheduling strategy, the number of instances will equal the number
		// of nodes.
		SERVICE_MODE_BATCH = 1 [(gogoproto.enumvalue_customname) = "ServiceModeBatch"];

		// Fill each node with instances number of tasks.
		SERVICE_MODE_FILL = 2 [(gogoproto.enumvalue_customname) = "ServiceModeFill"];

		// TODO(stevvooe): Consider specifying the node as a task completion
		// reconcilation condition. This matches with model of the
		// reconcilation loop in that we define under which conditions the
		// service is satisfied.
	}

	// Mode defines the reconcilation target for the service. This effects the
	// target state sought to satisfy the given service.
	Mode mode = 6;

	// UpdateStrategy controls the rate and policy of updates.
	UpdateStrategy update = 7;

	// Service endpoint specifies the user provided configuration
	// to properly discover and load balance a service.
	Endpoint endpoint = 8;
}

// TaskSpec defines properties required by the agent for execution.
message TaskSpec {
	oneof runtime {
		Container container = 1;
	}
}

// VolumeSpec defines the properties of a Volume.
message VolumeSpec {
	Annotations annotations = 1 [(gogoproto.nullable) = false];

	// Driver specific configuration consumed by the Volume driver.
	Driver driver_configuration = 2;
}

// NetworkSpec specifies user defined network parameters.
message NetworkSpec {
	Annotations annotations = 1 [(gogoproto.nullable) = false];

	// Driver specific configuration consumed by the network driver.
	Driver driver_configuration = 2;

	// IPv6Enabled enables support for IPv6 on the network.
	bool ipv6_enabled = 3;

	// internal restricts external access to the network. This may be
	// accomplished by disabling the default gateway or through other means.
	bool internal = 4;

	IPAMOptions ipam = 5 [(gogoproto.customname) = "IPAM"];
}

