service_basic.go 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. /*
  2. Copyright 2016 The Kubernetes Authors.
  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. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package kubectl
  14. import (
  15. "fmt"
  16. "strconv"
  17. "strings"
  18. "k8s.io/kubernetes/pkg/api"
  19. "k8s.io/kubernetes/pkg/runtime"
  20. "k8s.io/kubernetes/pkg/util/intstr"
  21. )
  22. type ServiceCommonGeneratorV1 struct {
  23. Name string
  24. TCP []string
  25. Type api.ServiceType
  26. ClusterIP string
  27. }
  28. type ServiceClusterIPGeneratorV1 struct {
  29. ServiceCommonGeneratorV1
  30. }
  31. type ServiceNodePortGeneratorV1 struct {
  32. ServiceCommonGeneratorV1
  33. }
  34. type ServiceLoadBalancerGeneratorV1 struct {
  35. ServiceCommonGeneratorV1
  36. }
  37. func (ServiceClusterIPGeneratorV1) ParamNames() []GeneratorParam {
  38. return []GeneratorParam{
  39. {"name", true},
  40. {"tcp", true},
  41. {"clusterip", false},
  42. }
  43. }
  44. func (ServiceNodePortGeneratorV1) ParamNames() []GeneratorParam {
  45. return []GeneratorParam{
  46. {"name", true},
  47. {"tcp", true},
  48. }
  49. }
  50. func (ServiceLoadBalancerGeneratorV1) ParamNames() []GeneratorParam {
  51. return []GeneratorParam{
  52. {"name", true},
  53. {"tcp", true},
  54. }
  55. }
  56. func parsePorts(portString string) (int32, intstr.IntOrString, error) {
  57. portStringSlice := strings.Split(portString, ":")
  58. port, err := strconv.Atoi(portStringSlice[0])
  59. if err != nil {
  60. return 0, intstr.FromInt(0), err
  61. }
  62. if len(portStringSlice) == 1 {
  63. return int32(port), intstr.FromInt(int(port)), nil
  64. }
  65. var targetPort intstr.IntOrString
  66. if portNum, err := strconv.Atoi(portStringSlice[1]); err != nil {
  67. targetPort = intstr.FromString(portStringSlice[1])
  68. } else {
  69. targetPort = intstr.FromInt(portNum)
  70. }
  71. return int32(port), targetPort, nil
  72. }
  73. func (s ServiceCommonGeneratorV1) GenerateCommon(params map[string]interface{}) error {
  74. name, isString := params["name"].(string)
  75. if !isString {
  76. return fmt.Errorf("expected string, saw %v for 'name'", name)
  77. }
  78. tcpStrings, isArray := params["tcp"].([]string)
  79. if !isArray {
  80. return fmt.Errorf("expected []string, found :%v", tcpStrings)
  81. }
  82. clusterip, isString := params["clusterip"].(string)
  83. if !isString {
  84. return fmt.Errorf("expected string, saw %v for 'clusterip'", clusterip)
  85. }
  86. s.Name = name
  87. s.TCP = tcpStrings
  88. s.ClusterIP = clusterip
  89. return nil
  90. }
  91. func (s ServiceLoadBalancerGeneratorV1) Generate(params map[string]interface{}) (runtime.Object, error) {
  92. err := ValidateParams(s.ParamNames(), params)
  93. if err != nil {
  94. return nil, err
  95. }
  96. delegate := &ServiceCommonGeneratorV1{Type: api.ServiceTypeLoadBalancer, ClusterIP: ""}
  97. err = delegate.GenerateCommon(params)
  98. if err != nil {
  99. return nil, err
  100. }
  101. return delegate.StructuredGenerate()
  102. }
  103. func (s ServiceNodePortGeneratorV1) Generate(params map[string]interface{}) (runtime.Object, error) {
  104. err := ValidateParams(s.ParamNames(), params)
  105. if err != nil {
  106. return nil, err
  107. }
  108. delegate := &ServiceCommonGeneratorV1{Type: api.ServiceTypeNodePort, ClusterIP: ""}
  109. err = delegate.GenerateCommon(params)
  110. if err != nil {
  111. return nil, err
  112. }
  113. return delegate.StructuredGenerate()
  114. }
  115. func (s ServiceClusterIPGeneratorV1) Generate(params map[string]interface{}) (runtime.Object, error) {
  116. err := ValidateParams(s.ParamNames(), params)
  117. if err != nil {
  118. return nil, err
  119. }
  120. delegate := &ServiceCommonGeneratorV1{Type: api.ServiceTypeClusterIP, ClusterIP: ""}
  121. err = delegate.GenerateCommon(params)
  122. if err != nil {
  123. return nil, err
  124. }
  125. return delegate.StructuredGenerate()
  126. }
  127. // validate validates required fields are set to support structured generation
  128. func (s ServiceCommonGeneratorV1) validate() error {
  129. if len(s.Name) == 0 {
  130. return fmt.Errorf("name must be specified")
  131. }
  132. if len(s.Type) == 0 {
  133. return fmt.Errorf("type must be specified")
  134. }
  135. if s.ClusterIP == api.ClusterIPNone && s.Type != api.ServiceTypeClusterIP {
  136. return fmt.Errorf("ClusterIP=None can only be used with ClusterIP service type")
  137. }
  138. if s.ClusterIP == api.ClusterIPNone && len(s.TCP) > 0 {
  139. return fmt.Errorf("can not map ports with clusterip=None")
  140. }
  141. if s.ClusterIP != api.ClusterIPNone && len(s.TCP) == 0 {
  142. return fmt.Errorf("at least one tcp port specifier must be provided")
  143. }
  144. return nil
  145. }
  146. func (s ServiceCommonGeneratorV1) StructuredGenerate() (runtime.Object, error) {
  147. err := s.validate()
  148. if err != nil {
  149. return nil, err
  150. }
  151. ports := []api.ServicePort{}
  152. for _, tcpString := range s.TCP {
  153. port, targetPort, err := parsePorts(tcpString)
  154. if err != nil {
  155. return nil, err
  156. }
  157. portName := strings.Replace(tcpString, ":", "-", -1)
  158. ports = append(ports, api.ServicePort{
  159. Name: portName,
  160. Port: port,
  161. TargetPort: targetPort,
  162. Protocol: api.Protocol("TCP"),
  163. })
  164. }
  165. // setup default label and selector
  166. labels := map[string]string{}
  167. labels["app"] = s.Name
  168. selector := map[string]string{}
  169. selector["app"] = s.Name
  170. service := api.Service{
  171. ObjectMeta: api.ObjectMeta{
  172. Name: s.Name,
  173. Labels: labels,
  174. },
  175. Spec: api.ServiceSpec{
  176. Type: api.ServiceType(s.Type),
  177. Selector: selector,
  178. Ports: ports,
  179. },
  180. }
  181. if len(s.ClusterIP) > 0 {
  182. service.Spec.ClusterIP = s.ClusterIP
  183. }
  184. return &service, nil
  185. }