diff --git a/pkg/api/testing/fuzzer.go b/pkg/api/testing/fuzzer.go index 3813a61b41e..94a54192031 100644 --- a/pkg/api/testing/fuzzer.go +++ b/pkg/api/testing/fuzzer.go @@ -198,6 +198,9 @@ func FuzzerFor(t *testing.T, version string, src rand.Source) *fuzz.Fuzzer { c.FuzzNoCustom(s) // fuzz self without calling this function again s.Type = api.SecretTypeOpaque }, + func(s *api.NamespaceStatus, c fuzz.Continue) { + s.Phase = api.NamespaceActive + }, func(ep *api.Endpoint, c fuzz.Continue) { // TODO: If our API used a particular type for IP fields we could just catch that here. ep.IP = fmt.Sprintf("%d.%d.%d.%d", c.Rand.Intn(256), c.Rand.Intn(256), c.Rand.Intn(256), c.Rand.Intn(256)) diff --git a/pkg/api/types.go b/pkg/api/types.go index fae5ef304c4..c741aa1cc7d 100644 --- a/pkg/api/types.go +++ b/pkg/api/types.go @@ -895,8 +895,20 @@ type NamespaceSpec struct { // NamespaceStatus is information about the current status of a Namespace. type NamespaceStatus struct { + // Phase is the current lifecycle phase of the namespace. + Phase NamespacePhase `json:"phase,omitempty"` } +type NamespacePhase string + +// These are the valid phases of a namespace. +const ( + // NamespaceActive means the namespace is available for use in the system + NamespaceActive NamespacePhase = "Active" + // NamespaceTerminating means the namespace is undergoing graceful termination + NamespaceTerminating NamespacePhase = "Terminating" +) + // A namespace provides a scope for Names. // Use of multiple namespaces is optional type Namespace struct { diff --git a/pkg/api/v1beta1/conversion.go b/pkg/api/v1beta1/conversion.go index 1b03c5bf27b..9b2fbcff697 100644 --- a/pkg/api/v1beta1/conversion.go +++ b/pkg/api/v1beta1/conversion.go @@ -773,6 +773,9 @@ func init() { if err := s.Convert(&in.Spec, &out.Spec, 0); err != nil { return err } + if err := s.Convert(&in.Status, &out.Status, 0); err != nil { + return err + } if err := s.Convert(&in.Labels, &out.ObjectMeta.Labels, 0); err != nil { return err } diff --git a/pkg/api/v1beta1/defaults.go b/pkg/api/v1beta1/defaults.go index 0300960ea33..95f63c22633 100644 --- a/pkg/api/v1beta1/defaults.go +++ b/pkg/api/v1beta1/defaults.go @@ -95,5 +95,10 @@ func init() { obj.Path = "/" } }, + func(obj *NamespaceStatus) { + if obj.Phase == "" { + obj.Phase = NamespaceActive + } + }, ) } diff --git a/pkg/api/v1beta1/defaults_test.go b/pkg/api/v1beta1/defaults_test.go index 1a4cd66995c..f39a52564b1 100644 --- a/pkg/api/v1beta1/defaults_test.go +++ b/pkg/api/v1beta1/defaults_test.go @@ -112,3 +112,13 @@ func TestSetDefaulEndpointsProtocol(t *testing.T) { t.Errorf("Expected protocol %s, got %s", current.ProtocolTCP, out.Protocol) } } + +func TestSetDefaultNamespace(t *testing.T) { + s := ¤t.Namespace{} + obj2 := roundTrip(t, runtime.Object(s)) + s2 := obj2.(*current.Namespace) + + if s2.Status.Phase != current.NamespaceActive { + t.Errorf("Expected phase %v, got %v", current.NamespaceActive, s2.Status.Phase) + } +} diff --git a/pkg/api/v1beta1/types.go b/pkg/api/v1beta1/types.go index 942f676c513..6db65b79192 100644 --- a/pkg/api/v1beta1/types.go +++ b/pkg/api/v1beta1/types.go @@ -727,8 +727,20 @@ type NamespaceSpec struct { // NamespaceStatus is information about the current status of a Namespace. type NamespaceStatus struct { + // Phase is the current lifecycle phase of the namespace. + Phase NamespacePhase `json:"phase,omitempty" description:"phase is the current lifecycle phase of the namespace"` } +type NamespacePhase string + +// These are the valid phases of a namespace. +const ( + // NamespaceActive means the namespace is available for use in the system + NamespaceActive NamespacePhase = "Active" + // NamespaceTerminating means the namespace is undergoing graceful termination + NamespaceTerminating NamespacePhase = "Terminating" +) + // A namespace provides a scope for Names. // Use of multiple namespaces is optional type Namespace struct { diff --git a/pkg/api/v1beta2/conversion.go b/pkg/api/v1beta2/conversion.go index 1d8e4b4c6f5..e280ebe7eb8 100644 --- a/pkg/api/v1beta2/conversion.go +++ b/pkg/api/v1beta2/conversion.go @@ -693,6 +693,9 @@ func init() { if err := s.Convert(&in.Spec, &out.Spec, 0); err != nil { return err } + if err := s.Convert(&in.Status, &out.Status, 0); err != nil { + return err + } if err := s.Convert(&in.Labels, &out.ObjectMeta.Labels, 0); err != nil { return err } diff --git a/pkg/api/v1beta2/defaults.go b/pkg/api/v1beta2/defaults.go index 0f0f7628b9a..9c5cf60163a 100644 --- a/pkg/api/v1beta2/defaults.go +++ b/pkg/api/v1beta2/defaults.go @@ -97,5 +97,10 @@ func init() { obj.Path = "/" } }, + func(obj *NamespaceStatus) { + if obj.Phase == "" { + obj.Phase = NamespaceActive + } + }, ) } diff --git a/pkg/api/v1beta2/defaults_test.go b/pkg/api/v1beta2/defaults_test.go index 12cf2aef5b2..9ea852dfab4 100644 --- a/pkg/api/v1beta2/defaults_test.go +++ b/pkg/api/v1beta2/defaults_test.go @@ -112,3 +112,13 @@ func TestSetDefaulEndpointsProtocol(t *testing.T) { t.Errorf("Expected protocol %s, got %s", current.ProtocolTCP, out.Protocol) } } + +func TestSetDefaultNamespace(t *testing.T) { + s := ¤t.Namespace{} + obj2 := roundTrip(t, runtime.Object(s)) + s2 := obj2.(*current.Namespace) + + if s2.Status.Phase != current.NamespaceActive { + t.Errorf("Expected phase %v, got %v", current.NamespaceActive, s2.Status.Phase) + } +} diff --git a/pkg/api/v1beta2/types.go b/pkg/api/v1beta2/types.go index 70965fed14a..56111ab96db 100644 --- a/pkg/api/v1beta2/types.go +++ b/pkg/api/v1beta2/types.go @@ -743,8 +743,20 @@ type NamespaceSpec struct { // NamespaceStatus is information about the current status of a Namespace. type NamespaceStatus struct { + // Phase is the current lifecycle phase of the namespace. + Phase NamespacePhase `json:"phase,omitempty" description:"phase is the current lifecycle phase of the namespace"` } +type NamespacePhase string + +// These are the valid phases of a namespace. +const ( + // NamespaceActive means the namespace is available for use in the system + NamespaceActive NamespacePhase = "Active" + // NamespaceTerminating means the namespace is undergoing graceful termination + NamespaceTerminating NamespacePhase = "Terminating" +) + // A namespace provides a scope for Names. // Use of multiple namespaces is optional. // diff --git a/pkg/api/v1beta3/defaults.go b/pkg/api/v1beta3/defaults.go index 6c2baf7af69..c8732185bde 100644 --- a/pkg/api/v1beta3/defaults.go +++ b/pkg/api/v1beta3/defaults.go @@ -96,5 +96,10 @@ func init() { obj.ContainerPort = util.NewIntOrStringFromInt(obj.Port) } }, + func(obj *NamespaceStatus) { + if obj.Phase == "" { + obj.Phase = NamespaceActive + } + }, ) } diff --git a/pkg/api/v1beta3/defaults_test.go b/pkg/api/v1beta3/defaults_test.go index fe4bd8ec703..16658f48dbe 100644 --- a/pkg/api/v1beta3/defaults_test.go +++ b/pkg/api/v1beta3/defaults_test.go @@ -129,3 +129,13 @@ func TestSetDefaulServiceDestinationPort(t *testing.T) { t.Errorf("Expected ContainerPort to be unchanged, got %s", out.Spec.ContainerPort) } } + +func TestSetDefaultNamespace(t *testing.T) { + s := ¤t.Namespace{} + obj2 := roundTrip(t, runtime.Object(s)) + s2 := obj2.(*current.Namespace) + + if s2.Status.Phase != current.NamespaceActive { + t.Errorf("Expected phase %v, got %v", current.NamespaceActive, s2.Status.Phase) + } +} diff --git a/pkg/api/v1beta3/types.go b/pkg/api/v1beta3/types.go index cee57ff9e12..c6685e69419 100644 --- a/pkg/api/v1beta3/types.go +++ b/pkg/api/v1beta3/types.go @@ -916,8 +916,20 @@ type NamespaceSpec struct { // NamespaceStatus is information about the current status of a Namespace. type NamespaceStatus struct { + // Phase is the current lifecycle phase of the namespace. + Phase NamespacePhase `json:"phase,omitempty" description:"phase is the current lifecycle phase of the namespace"` } +type NamespacePhase string + +// These are the valid phases of a namespace. +const ( + // NamespaceActive means the namespace is available for use in the system + NamespaceActive NamespacePhase = "Active" + // NamespaceTerminating means the namespace is undergoing graceful termination + NamespaceTerminating NamespacePhase = "Terminating" +) + // A namespace provides a scope for Names. // Use of multiple namespaces is optional type Namespace struct { diff --git a/pkg/kubectl/resource_printer.go b/pkg/kubectl/resource_printer.go index 340c444ced0..87407f0842f 100644 --- a/pkg/kubectl/resource_printer.go +++ b/pkg/kubectl/resource_printer.go @@ -237,7 +237,7 @@ var statusColumns = []string{"STATUS"} var eventColumns = []string{"FIRSTSEEN", "LASTSEEN", "COUNT", "NAME", "KIND", "SUBOBJECT", "REASON", "SOURCE", "MESSAGE"} var limitRangeColumns = []string{"NAME"} var resourceQuotaColumns = []string{"NAME"} -var namespaceColumns = []string{"NAME", "LABELS"} +var namespaceColumns = []string{"NAME", "LABELS", "STATUS"} var secretColumns = []string{"NAME", "DATA"} // addDefaultHandlers adds print handlers for default Kubernetes types. @@ -402,7 +402,7 @@ func printEndpointsList(list *api.EndpointsList, w io.Writer) error { } func printNamespace(item *api.Namespace, w io.Writer) error { - _, err := fmt.Fprintf(w, "%s\t%s\n", item.Name, formatLabels(item.Labels)) + _, err := fmt.Fprintf(w, "%s\t%s\t%s\n", item.Name, formatLabels(item.Labels), item.Status.Phase) return err }