istio.io/istio@v0.0.0-20240520182934-d79c90f27776/pkg/test/framework/components/namespace/namespace.go (about) 1 // Copyright Istio Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package namespace 16 17 import ( 18 "time" 19 20 "istio.io/istio/pkg/test" 21 "istio.io/istio/pkg/test/framework/resource" 22 "istio.io/istio/pkg/test/scopes" 23 ) 24 25 // Config contains configuration information about the namespace instance 26 type Config struct { 27 // Prefix to use for autogenerated namespace name 28 Prefix string 29 // Inject indicates whether to add sidecar injection label to this namespace 30 Inject bool 31 // Revision is the namespace of custom injector instance 32 Revision string 33 // Labels to be applied to namespace 34 Labels map[string]string 35 // SkipDump, if enabled, will disable dumping the namespace. This is useful to avoid duplicate 36 // dumping of istio-system. 37 SkipDump bool 38 // SkipCleanup, if enabled, the namespace will not be deleted during cleanup. Used for istio-system namespace 39 SkipCleanup bool 40 } 41 42 func (c *Config) overwriteRevisionIfEmpty(revision string) { 43 // Overwrite the default namespace label (istio-injection=enabled) 44 // with istio.io/rev=XXX. If a revision label is already provided, 45 // the label will remain as is. 46 if c.Revision == "" { 47 c.Revision = revision 48 } 49 // Allow setting revision explicitly to `default` to avoid configuration overwrite 50 if c.Revision == "default" { 51 c.Revision = "" 52 } 53 } 54 55 // Instance represents an allocated namespace that can be used to create config, or deploy components in. 56 type Instance interface { 57 Name() string 58 SetLabel(key, value string) error 59 RemoveLabel(key string) error 60 Prefix() string 61 Labels() (map[string]string, error) 62 IsAmbient() bool 63 IsInjected() bool 64 } 65 66 // Claim an existing namespace in all clusters, or create a new one if doesn't exist. 67 func Claim(ctx resource.Context, cfg Config) (i Instance, err error) { 68 cfg.overwriteRevisionIfEmpty(ctx.Settings().Revisions.Default()) 69 return claimKube(ctx, cfg) 70 } 71 72 // ClaimOrFail calls Claim and fails test if it returns error 73 func ClaimOrFail(t test.Failer, ctx resource.Context, name string) Instance { 74 t.Helper() 75 nsCfg := Config{ 76 Prefix: name, 77 Inject: true, 78 } 79 i, err := Claim(ctx, nsCfg) 80 if err != nil { 81 t.Fatalf("namespace.ClaimOrFail:: %v", err) 82 } 83 return i 84 } 85 86 // New creates a new Namespace in all clusters. 87 func New(ctx resource.Context, cfg Config) (i Instance, err error) { 88 start := time.Now() 89 scopes.Framework.Infof("=== BEGIN: Create namespace %s ===", cfg.Prefix) 90 defer func() { 91 if err != nil { 92 scopes.Framework.Errorf("=== FAILED: Create namespace %s ===", cfg.Prefix) 93 scopes.Framework.Error(err) 94 } else { 95 scopes.Framework.Infof("=== SUCCEEDED: Create namespace %s in %v ===", cfg.Prefix, time.Since(start)) 96 } 97 }() 98 99 if ctx.Settings().StableNamespaces { 100 return Claim(ctx, cfg) 101 } 102 cfg.overwriteRevisionIfEmpty(ctx.Settings().Revisions.Default()) 103 return newKube(ctx, cfg) 104 } 105 106 // NewOrFail calls New and fails test if it returns error 107 func NewOrFail(t test.Failer, ctx resource.Context, nsConfig Config) Instance { 108 t.Helper() 109 i, err := New(ctx, nsConfig) 110 if err != nil { 111 t.Fatalf("namespace.NewOrFail: %v", err) 112 } 113 return i 114 } 115 116 // GetAll returns all namespaces that have exist in the context. 117 func GetAll(ctx resource.Context) ([]Instance, error) { 118 var out []Instance 119 if err := ctx.GetResource(&out); err != nil { 120 return nil, err 121 } 122 return out, nil 123 } 124 125 // Setup is a utility function for creating a namespace in a test suite. 126 func Setup(ns *Instance, cfg Config) resource.SetupFn { 127 return func(ctx resource.Context) (err error) { 128 *ns, err = New(ctx, cfg) 129 return 130 } 131 } 132 133 // Getter for a namespace Instance 134 type Getter func() Instance 135 136 // Get is a utility method that helps in readability of call sites. 137 func (g Getter) Get() Instance { 138 return g() 139 } 140 141 // Future creates a Getter for a variable that namespace that will be set at sometime in the future. 142 // This is helpful for configuring a setup chain for a test suite that operates on global variables. 143 func Future(ns *Instance) Getter { 144 return func() Instance { 145 return *ns 146 } 147 } 148 149 func Dump(ctx resource.Context, name string) { 150 ns := &kubeNamespace{ 151 ctx: ctx, 152 prefix: name, 153 name: name, 154 } 155 ns.Dump(ctx) 156 } 157 158 // NilGetter is a Getter that always returns nil. 159 var NilGetter = func() Instance { 160 return nil 161 }