k8s.io/apiserver@v0.31.1/pkg/util/flowcontrol/format/formatting.go (about) 1 /* 2 Copyright 2019 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 format 18 19 import ( 20 "bytes" 21 "encoding/json" 22 "fmt" 23 24 flowcontrol "k8s.io/api/flowcontrol/v1" 25 "k8s.io/apiserver/pkg/authentication/user" 26 "k8s.io/apiserver/pkg/endpoints/request" 27 ) 28 29 // This file provides an easy way to mark a value for formatting to 30 // `%s` in full detail IF it is printed but without costing a lot of 31 // CPU or memory if the value is NOT printed. The API Priority and 32 // Fairness API objects are formatted into JSON. The other types of 33 // objects here are formatted into golang source. 34 35 // Stringer marks the given value for custom formatting by this package. 36 type Stringer struct{ val interface{} } 37 38 // Fmt marks the given value for custom formatting by this package. 39 func Fmt(val interface{}) Stringer { 40 return Stringer{val} 41 } 42 43 // String formats to a string in full detail 44 func (sr Stringer) String() string { 45 if sr.val == nil { 46 return "nil" 47 } 48 switch typed := sr.val.(type) { 49 case *flowcontrol.FlowSchema, 50 flowcontrol.FlowSchema, 51 flowcontrol.FlowSchemaSpec, 52 flowcontrol.FlowDistinguisherMethod, 53 *flowcontrol.FlowDistinguisherMethod, 54 *flowcontrol.PolicyRulesWithSubjects, 55 flowcontrol.PolicyRulesWithSubjects, 56 flowcontrol.Subject, 57 flowcontrol.ResourcePolicyRule, 58 flowcontrol.NonResourcePolicyRule, 59 flowcontrol.FlowSchemaCondition, 60 *flowcontrol.PriorityLevelConfiguration, 61 flowcontrol.PriorityLevelConfiguration, 62 flowcontrol.PriorityLevelConfigurationSpec, 63 *flowcontrol.LimitedPriorityLevelConfiguration, 64 flowcontrol.LimitedPriorityLevelConfiguration, 65 flowcontrol.LimitResponse, 66 *flowcontrol.QueuingConfiguration, 67 flowcontrol.QueuingConfiguration: 68 return ToJSON(sr.val) 69 case []user.Info: 70 return FmtUsers(typed) 71 case []*request.RequestInfo: 72 return FmtRequests(typed) 73 default: 74 return fmt.Sprintf("%#+v", sr.val) 75 } 76 } 77 78 // ToJSON converts using encoding/json and handles errors by 79 // formatting them 80 func ToJSON(val interface{}) string { 81 bs, err := json.Marshal(val) 82 str := string(bs) 83 if err != nil { 84 str = str + "<" + err.Error() + ">" 85 } 86 return str 87 } 88 89 // FmtPriorityLevelConfiguration returns a golang source expression 90 // equivalent to the given value 91 func FmtPriorityLevelConfiguration(pl *flowcontrol.PriorityLevelConfiguration) string { 92 if pl == nil { 93 return "nil" 94 } 95 var buf bytes.Buffer 96 buf.WriteString(fmt.Sprintf("&flowcontrolv1.PriorityLevelConfiguration{ObjectMeta: %#+v, Spec: ", 97 pl.ObjectMeta)) 98 BufferPriorityLevelConfigurationSpec(&buf, &pl.Spec) 99 buf.WriteString(fmt.Sprintf(", Status: %#+v}", pl.Status)) 100 return buf.String() 101 } 102 103 // FmtPriorityLevelConfigurationSpec returns a golang source 104 // expression equivalent to the given value 105 func FmtPriorityLevelConfigurationSpec(plSpec *flowcontrol.PriorityLevelConfigurationSpec) string { 106 var buf bytes.Buffer 107 BufferPriorityLevelConfigurationSpec(&buf, plSpec) 108 return buf.String() 109 } 110 111 // BufferPriorityLevelConfigurationSpec writes a golang source 112 // expression for the given value to the given buffer 113 func BufferPriorityLevelConfigurationSpec(buf *bytes.Buffer, plSpec *flowcontrol.PriorityLevelConfigurationSpec) { 114 buf.WriteString(fmt.Sprintf("flowcontrolv1.PriorityLevelConfigurationSpec{Type: %#v", plSpec.Type)) 115 if plSpec.Limited != nil { 116 buf.WriteString(fmt.Sprintf(", Limited: &flowcontrol.LimitedPriorityLevelConfiguration{NominalConcurrencyShares:%d, LimitResponse:flowcontrol.LimitResponse{Type:%#v", plSpec.Limited.NominalConcurrencyShares, plSpec.Limited.LimitResponse.Type)) 117 if plSpec.Limited.LimitResponse.Queuing != nil { 118 buf.WriteString(fmt.Sprintf(", Queuing:&%#+v", *plSpec.Limited.LimitResponse.Queuing)) 119 } 120 buf.WriteString(" } }") 121 } 122 buf.WriteString("}") 123 } 124 125 // FmtFlowSchema produces a golang source expression of the value. 126 func FmtFlowSchema(fs *flowcontrol.FlowSchema) string { 127 if fs == nil { 128 return "nil" 129 } 130 var buf bytes.Buffer 131 buf.WriteString(fmt.Sprintf("&flowcontrolv1.FlowSchema{ObjectMeta: %#+v, Spec: ", 132 fs.ObjectMeta)) 133 BufferFlowSchemaSpec(&buf, &fs.Spec) 134 buf.WriteString(fmt.Sprintf(", Status: %#+v}", fs.Status)) 135 return buf.String() 136 } 137 138 // FmtFlowSchemaSpec produces a golang source expression equivalent to 139 // the given spec 140 func FmtFlowSchemaSpec(fsSpec *flowcontrol.FlowSchemaSpec) string { 141 var buf bytes.Buffer 142 BufferFlowSchemaSpec(&buf, fsSpec) 143 return buf.String() 144 } 145 146 // BufferFlowSchemaSpec writes a golang source expression for the 147 // given value to the given buffer 148 func BufferFlowSchemaSpec(buf *bytes.Buffer, fsSpec *flowcontrol.FlowSchemaSpec) { 149 buf.WriteString(fmt.Sprintf("flowcontrolv1.FlowSchemaSpec{PriorityLevelConfiguration: %#+v, MatchingPrecedence: %d, DistinguisherMethod: ", 150 fsSpec.PriorityLevelConfiguration, 151 fsSpec.MatchingPrecedence)) 152 if fsSpec.DistinguisherMethod == nil { 153 buf.WriteString("nil") 154 } else { 155 buf.WriteString(fmt.Sprintf("&%#+v", *fsSpec.DistinguisherMethod)) 156 } 157 buf.WriteString(", Rules: []flowcontrol.PolicyRulesWithSubjects{") 158 for idx, rule := range fsSpec.Rules { 159 if idx > 0 { 160 buf.WriteString(", ") 161 } 162 BufferFmtPolicyRulesWithSubjectsSlim(buf, rule) 163 } 164 buf.WriteString("}}") 165 } 166 167 // FmtPolicyRulesWithSubjects produces a golang source expression of the value. 168 func FmtPolicyRulesWithSubjects(rule flowcontrol.PolicyRulesWithSubjects) string { 169 return "flowcontrolv1.PolicyRulesWithSubjects" + FmtPolicyRulesWithSubjectsSlim(rule) 170 } 171 172 // FmtPolicyRulesWithSubjectsSlim produces a golang source expression 173 // of the value but without the leading type name. See above for an 174 // example context where this is useful. 175 func FmtPolicyRulesWithSubjectsSlim(rule flowcontrol.PolicyRulesWithSubjects) string { 176 var buf bytes.Buffer 177 BufferFmtPolicyRulesWithSubjectsSlim(&buf, rule) 178 return buf.String() 179 } 180 181 // BufferFmtPolicyRulesWithSubjectsSlim writes a golang source 182 // expression for the given value to the given buffer but excludes the 183 // leading type name 184 func BufferFmtPolicyRulesWithSubjectsSlim(buf *bytes.Buffer, rule flowcontrol.PolicyRulesWithSubjects) { 185 buf.WriteString("{Subjects: []flowcontrolv1.Subject{") 186 for jdx, subj := range rule.Subjects { 187 if jdx > 0 { 188 buf.WriteString(", ") 189 } 190 buf.WriteString(fmt.Sprintf("{Kind: %q", subj.Kind)) 191 if subj.User != nil { 192 buf.WriteString(fmt.Sprintf(", User: &%#+v", *subj.User)) 193 } 194 if subj.Group != nil { 195 buf.WriteString(fmt.Sprintf(", Group: &%#+v", *subj.Group)) 196 } 197 if subj.ServiceAccount != nil { 198 buf.WriteString(fmt.Sprintf(", ServiceAccount: &%#+v", *subj.ServiceAccount)) 199 } 200 buf.WriteString("}") 201 } 202 buf.WriteString(fmt.Sprintf("}, ResourceRules: %#+v, NonResourceRules: %#+v}", rule.ResourceRules, rule.NonResourceRules)) 203 } 204 205 // FmtUsers produces a golang source expression of the value. 206 func FmtUsers(list []user.Info) string { 207 var buf bytes.Buffer 208 buf.WriteString("[]user.Info{") 209 for idx, member := range list { 210 if idx > 0 { 211 buf.WriteString(", ") 212 } 213 buf.WriteString(fmt.Sprintf("%#+v", member)) 214 } 215 buf.WriteString("}") 216 return buf.String() 217 } 218 219 // FmtRequests produces a golang source expression of the value. 220 func FmtRequests(list []*request.RequestInfo) string { 221 var buf bytes.Buffer 222 buf.WriteString("[]*request.RequestInfo{") 223 for idx, member := range list { 224 if idx > 0 { 225 buf.WriteString(", ") 226 } 227 buf.WriteString(fmt.Sprintf("%#+v", member)) 228 } 229 buf.WriteString("}") 230 return buf.String() 231 }