knative.dev/pkg@v0.0.0-20260602142205-ac97e43f6622/testing/duck/testbindable.go (about)

     1  /*
     2  Copyright 2019 The Knative Authors
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package duck
    18  
    19  import (
    20  	"context"
    21  
    22  	corev1 "k8s.io/api/core/v1"
    23  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    24  	"k8s.io/apimachinery/pkg/runtime"
    25  	"k8s.io/apimachinery/pkg/runtime/schema"
    26  	"knative.dev/pkg/apis"
    27  	"knative.dev/pkg/apis/duck"
    28  	duckv1 "knative.dev/pkg/apis/duck/v1"
    29  	duckv1alpha1 "knative.dev/pkg/apis/duck/v1alpha1"
    30  	"knative.dev/pkg/tracker"
    31  )
    32  
    33  // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
    34  
    35  // TestBindable is a simple resource that's compatible with our webhook
    36  type TestBindable struct {
    37  	metav1.TypeMeta   `json:",inline"`
    38  	metav1.ObjectMeta `json:"metadata,omitempty"`
    39  
    40  	Spec   TestBindableSpec   `json:"spec,omitempty"`
    41  	Status TestBindableStatus `json:"status,omitempty"`
    42  }
    43  
    44  // Check that TestBindable may be validated and defaulted.
    45  var (
    46  	_ apis.Listable = (*TestBindable)(nil)
    47  	_ duck.Bindable = (*TestBindable)(nil)
    48  )
    49  
    50  // TestBindableSpec represents test resource spec.
    51  type TestBindableSpec struct {
    52  	duckv1alpha1.BindingSpec `json:",inline"`
    53  
    54  	Foo string `json:"foo"`
    55  }
    56  
    57  // TestBindableStatus represents the status of our test binding.
    58  type TestBindableStatus struct {
    59  	duckv1.Status `json:",inline"`
    60  }
    61  
    62  // GetGroupVersionKind returns the GroupVersionKind.
    63  func (tb *TestBindable) GetGroupVersionKind() schema.GroupVersionKind {
    64  	return SchemeGroupVersion.WithKind("TestBindable")
    65  }
    66  
    67  // GetUntypedSpec returns the spec of the resource.
    68  func (tb *TestBindable) GetUntypedSpec() interface{} {
    69  	return tb.Spec
    70  }
    71  
    72  // GetListType implements apis.Listable
    73  func (tb *TestBindable) GetListType() runtime.Object {
    74  	return &TestBindableList{}
    75  }
    76  
    77  // GetSubject implements psbinding.Bindable
    78  func (tb *TestBindable) GetSubject() tracker.Reference {
    79  	return tb.Spec.Subject
    80  }
    81  
    82  // GetBindingStatus implements psbinding.Bindable
    83  func (tb *TestBindable) GetBindingStatus() duck.BindableStatus {
    84  	return &tb.Status
    85  }
    86  
    87  // SetObservedGeneration implements psbinding.BindableStatus
    88  func (tbs *TestBindableStatus) SetObservedGeneration(gen int64) {
    89  	tbs.ObservedGeneration = gen
    90  }
    91  
    92  // Do implements psbinding.Bindable
    93  func (tb *TestBindable) Do(ctx context.Context, ps *duckv1.WithPod) {
    94  	// First undo so that we can just unconditionally append below.
    95  	tb.Undo(ctx, ps)
    96  
    97  	spec := ps.Spec.Template.Spec
    98  	for i := range spec.InitContainers {
    99  		spec.InitContainers[i].Env = append(spec.InitContainers[i].Env, corev1.EnvVar{
   100  			Name:  "FOO",
   101  			Value: tb.Spec.Foo,
   102  		})
   103  	}
   104  	for i := range spec.Containers {
   105  		spec.Containers[i].Env = append(spec.Containers[i].Env, corev1.EnvVar{
   106  			Name:  "FOO",
   107  			Value: tb.Spec.Foo,
   108  		})
   109  	}
   110  }
   111  
   112  func (tb *TestBindable) Undo(ctx context.Context, ps *duckv1.WithPod) {
   113  	spec := ps.Spec.Template.Spec
   114  	for i, c := range spec.InitContainers {
   115  		for j, ev := range c.Env {
   116  			if ev.Name == "FOO" {
   117  				spec.InitContainers[i].Env = append(spec.InitContainers[i].Env[:j], spec.InitContainers[i].Env[j+1:]...)
   118  				break
   119  			}
   120  		}
   121  	}
   122  	for i, c := range spec.Containers {
   123  		for j, ev := range c.Env {
   124  			if ev.Name == "FOO" {
   125  				spec.Containers[i].Env = append(spec.Containers[i].Env[:j], spec.Containers[i].Env[j+1:]...)
   126  				break
   127  			}
   128  		}
   129  	}
   130  }
   131  
   132  var tbCondSet = apis.NewLivingConditionSet()
   133  
   134  // clearLTT clears the last transition time from our conditions because
   135  // they are hard to ignore in the context of *unstructured.Unstructured,
   136  // which is how psbinding updates statuses.
   137  func (tbs *TestBindableStatus) clearLTT() {
   138  	for i := range tbs.Conditions {
   139  		tbs.Conditions[i].LastTransitionTime = apis.VolatileTime{}
   140  	}
   141  }
   142  
   143  // InitializeConditions populates the TestBindableStatus's conditions field
   144  // with all of its conditions configured to Unknown.
   145  func (tbs *TestBindableStatus) InitializeConditions() {
   146  	tbCondSet.Manage(tbs).InitializeConditions()
   147  	tbs.clearLTT()
   148  }
   149  
   150  // MarkBindingUnavailable marks the TestBindable's Ready condition to False with
   151  // the provided reason and message.
   152  func (tbs *TestBindableStatus) MarkBindingUnavailable(reason, message string) {
   153  	tbCondSet.Manage(tbs).MarkFalse(apis.ConditionReady, reason, message)
   154  	tbs.clearLTT()
   155  }
   156  
   157  // MarkBindingAvailable marks the TestBindable's Ready condition to True.
   158  func (tbs *TestBindableStatus) MarkBindingAvailable() {
   159  	tbCondSet.Manage(tbs).MarkTrue(apis.ConditionReady)
   160  	tbs.clearLTT()
   161  }
   162  
   163  // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
   164  
   165  // TestBindableList is a list of TestBindable resources
   166  type TestBindableList struct {
   167  	metav1.TypeMeta `json:",inline"`
   168  	metav1.ListMeta `json:"metadata"`
   169  
   170  	Items []TestBindable `json:"items"`
   171  }