1/*
2Copyright 2014 The Kubernetes Authors.
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8    http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15*/
16
17// Package runtime defines conversions between generic types and structs to map query strings
18// to struct objects.
19package runtime
20
21import (
22	"fmt"
23	"reflect"
24	"strconv"
25	"strings"
26
27	"k8s.io/apimachinery/pkg/conversion"
28)
29
30// DefaultMetaV1FieldSelectorConversion auto-accepts metav1 values for name and namespace.
31// A cluster scoped resource specifying namespace empty works fine and specifying a particular
32// namespace will return no results, as expected.
33func DefaultMetaV1FieldSelectorConversion(label, value string) (string, string, error) {
34	switch label {
35	case "metadata.name":
36		return label, value, nil
37	case "metadata.namespace":
38		return label, value, nil
39	default:
40		return "", "", fmt.Errorf("%q is not a known field selector: only %q, %q", label, "metadata.name", "metadata.namespace")
41	}
42}
43
44// JSONKeyMapper uses the struct tags on a conversion to determine the key value for
45// the other side. Use when mapping from a map[string]* to a struct or vice versa.
46func JSONKeyMapper(key string, sourceTag, destTag reflect.StructTag) (string, string) {
47	if s := destTag.Get("json"); len(s) > 0 {
48		return strings.SplitN(s, ",", 2)[0], key
49	}
50	if s := sourceTag.Get("json"); len(s) > 0 {
51		return key, strings.SplitN(s, ",", 2)[0]
52	}
53	return key, key
54}
55
56func Convert_Slice_string_To_string(in *[]string, out *string, s conversion.Scope) error {
57	if len(*in) == 0 {
58		*out = ""
59		return nil
60	}
61	*out = (*in)[0]
62	return nil
63}
64
65func Convert_Slice_string_To_int(in *[]string, out *int, s conversion.Scope) error {
66	if len(*in) == 0 {
67		*out = 0
68		return nil
69	}
70	str := (*in)[0]
71	i, err := strconv.Atoi(str)
72	if err != nil {
73		return err
74	}
75	*out = i
76	return nil
77}
78
79// Convert_Slice_string_To_bool will convert a string parameter to boolean.
80// Only the absence of a value (i.e. zero-length slice), a value of "false", or a
81// value of "0" resolve to false.
82// Any other value (including empty string) resolves to true.
83func Convert_Slice_string_To_bool(in *[]string, out *bool, s conversion.Scope) error {
84	if len(*in) == 0 {
85		*out = false
86		return nil
87	}
88	switch {
89	case (*in)[0] == "0", strings.EqualFold((*in)[0], "false"):
90		*out = false
91	default:
92		*out = true
93	}
94	return nil
95}
96
97// Convert_Slice_string_To_bool will convert a string parameter to boolean.
98// Only the absence of a value (i.e. zero-length slice), a value of "false", or a
99// value of "0" resolve to false.
100// Any other value (including empty string) resolves to true.
101func Convert_Slice_string_To_Pointer_bool(in *[]string, out **bool, s conversion.Scope) error {
102	if len(*in) == 0 {
103		boolVar := false
104		*out = &boolVar
105		return nil
106	}
107	switch {
108	case (*in)[0] == "0", strings.EqualFold((*in)[0], "false"):
109		boolVar := false
110		*out = &boolVar
111	default:
112		boolVar := true
113		*out = &boolVar
114	}
115	return nil
116}
117
118func string_to_int64(in string) (int64, error) {
119	return strconv.ParseInt(in, 10, 64)
120}
121
122func Convert_string_To_int64(in *string, out *int64, s conversion.Scope) error {
123	if in == nil {
124		*out = 0
125		return nil
126	}
127	i, err := string_to_int64(*in)
128	if err != nil {
129		return err
130	}
131	*out = i
132	return nil
133}
134
135func Convert_Slice_string_To_int64(in *[]string, out *int64, s conversion.Scope) error {
136	if len(*in) == 0 {
137		*out = 0
138		return nil
139	}
140	i, err := string_to_int64((*in)[0])
141	if err != nil {
142		return err
143	}
144	*out = i
145	return nil
146}
147
148func Convert_string_To_Pointer_int64(in *string, out **int64, s conversion.Scope) error {
149	if in == nil {
150		*out = nil
151		return nil
152	}
153	i, err := string_to_int64(*in)
154	if err != nil {
155		return err
156	}
157	*out = &i
158	return nil
159}
160
161func Convert_Slice_string_To_Pointer_int64(in *[]string, out **int64, s conversion.Scope) error {
162	if len(*in) == 0 {
163		*out = nil
164		return nil
165	}
166	i, err := string_to_int64((*in)[0])
167	if err != nil {
168		return err
169	}
170	*out = &i
171	return nil
172}
173
174func RegisterStringConversions(s *Scheme) error {
175	if err := s.AddConversionFunc((*[]string)(nil), (*string)(nil), func(a, b interface{}, scope conversion.Scope) error {
176		return Convert_Slice_string_To_string(a.(*[]string), b.(*string), scope)
177	}); err != nil {
178		return err
179	}
180	if err := s.AddConversionFunc((*[]string)(nil), (*int)(nil), func(a, b interface{}, scope conversion.Scope) error {
181		return Convert_Slice_string_To_int(a.(*[]string), b.(*int), scope)
182	}); err != nil {
183		return err
184	}
185	if err := s.AddConversionFunc((*[]string)(nil), (*bool)(nil), func(a, b interface{}, scope conversion.Scope) error {
186		return Convert_Slice_string_To_bool(a.(*[]string), b.(*bool), scope)
187	}); err != nil {
188		return err
189	}
190	if err := s.AddConversionFunc((*[]string)(nil), (*int64)(nil), func(a, b interface{}, scope conversion.Scope) error {
191		return Convert_Slice_string_To_int64(a.(*[]string), b.(*int64), scope)
192	}); err != nil {
193		return err
194	}
195	return nil
196}
197