sigs.k8s.io/prow@v0.0.0-20240503223140-c5e374dc7eb1/pkg/sidecar/options.go (about) 1 /* 2 Copyright 2018 The Kubernetes 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 sidecar 18 19 import ( 20 "encoding/json" 21 "errors" 22 "flag" 23 "fmt" 24 25 "sigs.k8s.io/prow/pkg/gcsupload" 26 "sigs.k8s.io/prow/pkg/pod-utils/wrapper" 27 ) 28 29 // NewOptions returns an empty Options with no nil fields 30 func NewOptions() *Options { 31 return &Options{ 32 GcsOptions: gcsupload.NewOptions(), 33 // Do not instantiate DeprecatedWrapperOptions by default 34 } 35 } 36 37 // Options exposes the configuration necessary 38 // for defining the process being watched and 39 // where in GCS an upload will land. 40 type Options struct { 41 GcsOptions *gcsupload.Options `json:"gcs_options"` 42 DeprecatedWrapperOptions *wrapper.Options `json:"wrapper_options,omitempty"` // TODO(fejta): remove july 2019 43 // Additional entries to wait for if set 44 Entries []wrapper.Options `json:"entries,omitempty"` 45 46 // EntryError requires all entries to pass in order to exit cleanly. 47 EntryError bool `json:"entry_error,omitempty"` 48 49 // IgnoreInterrupts instructs the waiting process to ignore interrupt 50 // signals. An interrupt signal is sent to this process when the kubelet 51 // decides to delete the test Pod. This may be as a result of: 52 // - the ProwJob exceeding the `default_job_timeout` as configured for Prow 53 // - the ProwJob exceeding the `timeout` as configured for the job itself 54 // - the Pod exceeding the `pod_running_timeout` as configured for Prow 55 // - cluster instability causing the Pod to be evicted 56 // 57 // When this happens, the `entrypoint` process also gets the signal, and 58 // forwards it to the process under test. `entrypoint` will wait for the 59 // test process to exit, either configured with: 60 // - `grace_period` in the default decoration configurations for Prow 61 // - `grace_period` in the job's specific configuration 62 // After the grace period, `entrypoint` will forcefully terminate the test 63 // process and signal to `sidecar` that the process has exited. 64 // 65 // In parallel, the kubelet will be waiting on the Pod's `terminationGracePeriod` 66 // after sending the interrupt signal, at which point the kubelet will forcefully 67 // terminate all containers in the Pod. 68 // 69 // If `ignore_interrupts` is set, `sidecar` will do nothing upon receipt of 70 // the interrupt signal; this implicitly means that upload of logs and artifacts 71 // will begin when the test process exits, which may be as long as the grace 72 // period if the test process does not gracefully handle interrupts. This will 73 // require that the user configures the Pod's termination grace period to be 74 // longer than the `entrypoint` grace period for the test process and the time 75 // taken by `sidecar` to upload all relevant artifacts. 76 IgnoreInterrupts bool `json:"ignore_interrupts,omitempty"` 77 78 // WriteMemoryProfile makes the program write a memory profile periodically while 79 // it runs. Use the sigs.k8s.io/prow/hack/analyze-memory-profiles.py script to 80 // load the data into time series and plot it for analysis. 81 WriteMemoryProfile bool `json:"write_memory_profile,omitempty"` 82 83 // CensoringOptions are options that pertain to censoring output before upload. 84 CensoringOptions *CensoringOptions `json:"censoring_options,omitempty"` 85 86 // SecretDirectories is deprecated, use censoring_options.secret_directories instead. 87 SecretDirectories []string `json:"secret_directories,omitempty"` 88 // CensoringConcurrency is deprecated, use censoring_options.censoring_concurrency instead. 89 CensoringConcurrency *int64 `json:"censoring_concurrency,omitempty"` 90 // CensoringBufferSize is deprecated, use censoring_options.censoring_buffer_size instead. 91 CensoringBufferSize *int `json:"censoring_buffer_size,omitempty"` 92 } 93 94 type CensoringOptions struct { 95 // SecretDirectories are paths to directories containing secret data. The contents 96 // of these secret data files will be censored from the logs and artifacts uploaded 97 // to the cloud. 98 SecretDirectories []string `json:"secret_directories,omitempty"` 99 // CensoringConcurrency is the maximum number of goroutines that should be censoring 100 // artifacts and logs at any time. If unset, defaults to 10. 101 CensoringConcurrency *int64 `json:"censoring_concurrency,omitempty"` 102 // CensoringBufferSize is the size in bytes of the buffer allocated for every file 103 // being censored. We want to keep as little of the file in memory as possible in 104 // order for censoring to be reasonably performant in space. However, to guarantee 105 // that we censor every instance of every secret, our buffer size must be at least 106 // two times larger than the largest secret we are about to censor. While that size 107 // is the smallest possible buffer we could use, if the secrets being censored are 108 // small, censoring will not be performant as the number of I/O actions per file 109 // would increase. If unset, defaults to 10MiB. 110 CensoringBufferSize *int `json:"censoring_buffer_size,omitempty"` 111 112 // IncludeDirectories are directories which should have their content censored, provided 113 // as relative path globs from the base of the artifact directory for the test. If 114 // present, only content in these directories will be censored. Entries in this list 115 // are parsed with the go-zglob library, allowing for globbed matches. 116 IncludeDirectories []string `json:"include_directories,omitempty"` 117 118 // ExcludeDirectories are directories which should not have their content censored, 119 // provided as relative path globs from the base of the artifact directory for the 120 // test. If present, content in these directories will not be censored even if the 121 // directory also matches a glob in IncludeDirectories. Entries in this list are 122 // parsed with the go-zglob library, allowing for globbed matches. 123 ExcludeDirectories []string `json:"exclude_directories,omitempty"` 124 125 // IniFilenames are secret filenames that should be parsed as INI files in order to 126 // censor the values in the key-value mapping as well as the full content of the file. 127 IniFilenames []string `json:"ini_filenames,omitempty"` 128 } 129 130 func (o Options) entries() []wrapper.Options { 131 var e []wrapper.Options 132 if o.DeprecatedWrapperOptions != nil { 133 e = append(e, *o.DeprecatedWrapperOptions) 134 } 135 return append(e, o.Entries...) 136 } 137 138 // Validate ensures that the set of options are 139 // self-consistent and valid 140 func (o *Options) Validate() error { 141 opts := CensoringOptions{ 142 SecretDirectories: o.SecretDirectories, 143 CensoringConcurrency: o.CensoringConcurrency, 144 CensoringBufferSize: o.CensoringBufferSize, 145 } 146 if o.SecretDirectories != nil || o.CensoringConcurrency != nil || o.CensoringBufferSize != nil { 147 if o.CensoringOptions != nil { 148 return errors.New("cannot use deprecated options (secret_directories, censoring_{concurrency,buffer_size}) and new options (censoring_options) at the same time") 149 } 150 o.CensoringOptions = &opts 151 } 152 153 ents := o.entries() 154 if len(ents) == 0 { 155 return errors.New("no wrapper.Option entries") 156 } 157 for i, e := range ents { 158 if err := e.Validate(); err != nil { 159 return fmt.Errorf("entry %d: %w", i, err) 160 } 161 } 162 163 return o.GcsOptions.Validate() 164 } 165 166 const ( 167 // JSONConfigEnvVar is the environment variable that 168 // utilities expect to find a full JSON configuration 169 // in when run. 170 JSONConfigEnvVar = "SIDECAR_OPTIONS" 171 ) 172 173 // ConfigVar exposese the environment variable used 174 // to store serialized configuration 175 func (o *Options) ConfigVar() string { 176 return JSONConfigEnvVar 177 } 178 179 // LoadConfig loads options from serialized config 180 func (o *Options) LoadConfig(config string) error { 181 return json.Unmarshal([]byte(config), o) 182 } 183 184 // AddFlags binds flags to options 185 func (o *Options) AddFlags(flags *flag.FlagSet) { 186 o.GcsOptions.AddFlags(flags) 187 // DeprecatedWrapperOptions flags should be unused, remove immediately 188 } 189 190 // Complete internalizes command line arguments 191 func (o *Options) Complete(args []string) { 192 o.GcsOptions.Complete(args) 193 } 194 195 // Encode will encode the set of options in the format that 196 // is expected for the configuration environment variable 197 func Encode(options Options) (string, error) { 198 encoded, err := json.Marshal(options) 199 return string(encoded), err 200 }