From 23ce7eb223f7d073c60652eedd84c2fe1ae3aa8d Mon Sep 17 00:00:00 2001 From: Yifan Gu Date: Wed, 23 Sep 2015 18:33:42 -0700 Subject: [PATCH] spec: add ExitPolicy type in pod manifest. The optional `ExitPolicy` type defines the behavior of the pod when the apps within it exit. This PR adds 3 valid policies: - untilAll: The pod exits only when all the apps exit (no matter they are successful or not). - onAny: The pod exits when any of the apps exit (no matter they are successful or not). - onAnyFailure: The pod exits when any of the apps exit unsuccessfully. --- examples/pod_runtime.json | 3 +- schema/pod.go | 1 + schema/types/exitpolicy.go | 57 +++++++++++++++++++++++++++++++++ schema/types/exitpolicy_test.go | 34 ++++++++++++++++++++ spec/pods.md | 7 +++- 5 files changed, 100 insertions(+), 2 deletions(-) create mode 100644 schema/types/exitpolicy.go create mode 100644 schema/types/exitpolicy_test.go diff --git a/examples/pod_runtime.json b/examples/pod_runtime.json index 65dc4197..705e7534 100644 --- a/examples/pod_runtime.json +++ b/examples/pod_runtime.json @@ -102,5 +102,6 @@ "name": "ip-address", "value": "10.1.2.3" } - ] + ], + "exitPolicy": "onAnyFailure" } diff --git a/schema/pod.go b/schema/pod.go index 47e0340c..b7785d1b 100644 --- a/schema/pod.go +++ b/schema/pod.go @@ -32,6 +32,7 @@ type PodManifest struct { Isolators []types.Isolator `json:"isolators"` Annotations types.Annotations `json:"annotations"` Ports []types.ExposedPort `json:"ports"` + ExitPolicy types.ExitPolicy `json:"exitPolicy"` } // podManifest is a model to facilitate extra validation during the diff --git a/schema/types/exitpolicy.go b/schema/types/exitpolicy.go new file mode 100644 index 00000000..c7f6bc8a --- /dev/null +++ b/schema/types/exitpolicy.go @@ -0,0 +1,57 @@ +// Copyright 2015 The appc 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. + +package types + +import ( + "encoding/json" + "fmt" +) + +type ExitPolicy string + +var validPolicies = map[ExitPolicy]struct{}{ + "untilAll": struct{}{}, + "onAny": struct{}{}, + "onAnyFailure": struct{}{}, +} + +type exitPolicy ExitPolicy + +func (e *ExitPolicy) UnmarshalJSON(data []byte) error { + var ep exitPolicy + if err := json.Unmarshal(data, &ep); err != nil { + return err + } + ee := ExitPolicy(ep) + if err := ee.assertValid(); err != nil { + return err + } + *e = ee + return nil +} + +func (e ExitPolicy) MarshalJSON() ([]byte, error) { + if err := e.assertValid(); err != nil { + return nil, err + } + return json.Marshal(exitPolicy(e)) +} + +func (e ExitPolicy) assertValid() error { + if _, ok := validPolicies[e]; !ok { + return fmt.Errorf("invalid exit policy %q", string(e)) + } + return nil +} diff --git a/schema/types/exitpolicy_test.go b/schema/types/exitpolicy_test.go new file mode 100644 index 00000000..e6fa9b4b --- /dev/null +++ b/schema/types/exitpolicy_test.go @@ -0,0 +1,34 @@ +// Copyright 2015 The appc 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. + +package types + +import ( + "testing" +) + +func TestGoodExitPolicy(t *testing.T) { + for e := range validPolicies { + if err := e.assertValid(); err != nil { + t.Errorf("good exit policy failed: %v", err) + } + } +} + +func TestBadExitPolicy(t *testing.T) { + e := ExitPolicy("bad") + if err := e.assertValid(); err == nil { + t.Errorf("bad exit policy valid: %v", err) + } +} diff --git a/spec/pods.md b/spec/pods.md index 336dd26a..05fe7db2 100644 --- a/spec/pods.md +++ b/spec/pods.md @@ -150,7 +150,8 @@ JSON Schema for the Pod Manifest, conforming to [RFC4627](https://tools.ietf.org "name": "ftp", "hostPort": 2121 } - ] + ], + "exitPolicy": "onAnyFailure" } ``` @@ -179,3 +180,7 @@ JSON Schema for the Pod Manifest, conforming to [RFC4627](https://tools.ietf.org * **ports** (list of objects, optional) list of ports that SHOULD be exposed on the host. * **name** (string, required, restricted to the [AC Name](#ac-name-type) formatting) name of the port to be exposed on the host. This field is a key referencing by name ports specified in the Image Manifest(s) of the app(s) within this Pod Manifest; consequently, port names MUST be unique among apps within a pod. * **hostPort** (integer, required) port number on the host that will be mapped to the application port. +* **exitPolicy** (string, optional) a string that specify the exit policy of the pod. If it's left empty, then it's up to ACE to choose the default behavior. Valid values are: + * **untilAll** - the pod exits only when all the apps exit, no matter they are successful or not. + * **onAny** - the pod exits when any of the apps exits either successfully or unsuccessfully. + * **onAnyFailure** -the pod exits when any of the pod exits unsuccessfully, also the pod exits when there is no app running.