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 5242f2f2024..92af31a4f21 100644 --- a/pkg/api/types.go +++ b/pkg/api/types.go @@ -914,8 +914,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 e59f4f6318b..b1635dc9e5b 100644 --- a/pkg/api/v1beta1/conversion.go +++ b/pkg/api/v1beta1/conversion.go @@ -779,6 +779,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 911b52bb8c8..924b3d768a9 100644 --- a/pkg/api/v1beta1/types.go +++ b/pkg/api/v1beta1/types.go @@ -746,8 +746,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 a7cf98ec6c6..d6cf154f26c 100644 --- a/pkg/api/v1beta2/conversion.go +++ b/pkg/api/v1beta2/conversion.go @@ -699,6 +699,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 978ba094b73..58a853b1344 100644 --- a/pkg/api/v1beta2/types.go +++ b/pkg/api/v1beta2/types.go @@ -762,8 +762,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 2f6640e5a95..c347a25f4a8 100644 --- a/pkg/api/v1beta3/types.go +++ b/pkg/api/v1beta3/types.go @@ -935,8 +935,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 }