github.com/fafucoder/cilium@v1.6.11/cilium/cmd/service_update.go (about) 1 // Copyright 2017 Authors of Cilium 2 // 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 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package cmd 16 17 import ( 18 "bufio" 19 "fmt" 20 "net" 21 "os" 22 "strconv" 23 "strings" 24 25 "github.com/cilium/cilium/api/v1/models" 26 "github.com/cilium/cilium/pkg/loadbalancer" 27 28 "github.com/spf13/cobra" 29 ) 30 31 var ( 32 addRev bool 33 idU uint64 34 frontend string 35 backends []string 36 ) 37 38 // serviceUpdateCmd represents the service_update command 39 var serviceUpdateCmd = &cobra.Command{ 40 Use: "update", 41 Short: "Update a service", 42 Run: func(cmd *cobra.Command, args []string) { 43 updateService(cmd, args) 44 }, 45 } 46 47 func init() { 48 serviceCmd.AddCommand(serviceUpdateCmd) 49 serviceUpdateCmd.Flags().BoolVarP(&addRev, "rev", "", true, "Add reverse translation") 50 serviceUpdateCmd.Flags().Uint64VarP(&idU, "id", "", 0, "Identifier") 51 serviceUpdateCmd.Flags().StringVarP(&frontend, "frontend", "", "", "Frontend address") 52 serviceUpdateCmd.Flags().StringSliceVarP(&backends, "backends", "", []string{}, "Backend address or addresses followed by optional weight (<IP:Port>[/weight])") 53 } 54 55 func parseFrontendAddress(address string) (*models.FrontendAddress, net.IP) { 56 frontend, err := net.ResolveTCPAddr("tcp", address) 57 if err != nil { 58 Fatalf("Unable to parse frontend address: %s\n", err) 59 } 60 61 // FIXME support more than TCP 62 return &models.FrontendAddress{ 63 IP: frontend.IP.String(), 64 Port: uint16(frontend.Port), 65 Protocol: models.FrontendAddressProtocolTCP, 66 }, frontend.IP 67 } 68 69 func updateService(cmd *cobra.Command, args []string) { 70 id := int64(idU) 71 fa, faIP := parseFrontendAddress(frontend) 72 73 var spec *models.ServiceSpec 74 svc, err := client.GetServiceID(id) 75 switch { 76 case err == nil && (svc.Status == nil || svc.Status.Realized == nil): 77 Fatalf("Cannot update service %d: empty state", id) 78 79 case err == nil: 80 spec = svc.Status.Realized 81 fmt.Printf("Updating existing service with id '%v'\n", id) 82 83 default: 84 spec = &models.ServiceSpec{ID: id} 85 fmt.Printf("Creating new service with id '%v'\n", id) 86 } 87 88 // This can happen when we create a new service or when the service returned 89 // to us has no flags set 90 if spec.Flags == nil { 91 spec.Flags = &models.ServiceSpecFlags{} 92 } 93 94 spec.FrontendAddress = fa 95 spec.Flags.DirectServerReturn = addRev 96 97 if len(backends) == 0 { 98 fmt.Printf("Reading backend list from stdin...\n") 99 100 scanner := bufio.NewScanner(os.Stdin) 101 for scanner.Scan() { 102 backends = append(backends, scanner.Text()) 103 } 104 } 105 106 spec.BackendAddresses = nil 107 for _, backend := range backends { 108 tmp := strings.Split(backend, "/") 109 if len(tmp) > 2 { 110 Fatalf("Incorrect backend specification %s\n", backend) 111 } 112 addr := tmp[0] 113 weight := uint64(0) 114 if len(tmp) == 2 { 115 var err error 116 weight, err = strconv.ParseUint(tmp[1], 10, 16) 117 if err != nil { 118 Fatalf("Error converting weight %s\n", err) 119 } 120 } 121 beAddr, err := net.ResolveTCPAddr("tcp", addr) 122 if err != nil { 123 Fatalf("Cannot parse backend address \"%s\": %s", backend, err) 124 } 125 126 // Backend ID will be set by the daemon 127 be := loadbalancer.NewLBBackEnd(0, loadbalancer.TCP, beAddr.IP, uint16(beAddr.Port), uint16(weight)) 128 129 if be.IsIPv6() && faIP.To4() != nil { 130 Fatalf("Address mismatch between frontend and backend %s", backend) 131 } 132 133 if fa.Port == 0 && beAddr.Port != 0 { 134 Fatalf("L4 backend found (%v) with L3 frontend", beAddr) 135 } 136 137 ba := be.GetBackendModel() 138 spec.BackendAddresses = append(spec.BackendAddresses, ba) 139 } 140 141 if created, err := client.PutServiceID(id, spec); err != nil { 142 Fatalf("Cannot add/update service: %s", err) 143 } else if created { 144 fmt.Printf("Added service with %d backends\n", len(spec.BackendAddresses)) 145 } else { 146 fmt.Printf("Updated service with %d backends\n", len(spec.BackendAddresses)) 147 } 148 }