k8s.io/registry.k8s.io@v0.3.1/pkg/net/cloudcidrs/internal/ranges2go/parse_gcp.go (about) 1 /* 2 Copyright 2023 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 main 18 19 import ( 20 "encoding/json" 21 "errors" 22 "net/netip" 23 "sort" 24 ) 25 26 // parseGCP parses raw GCP cloud.json data 27 // and processes it to a regionsToPrefixes map 28 func parseGCP(raw string) (regionsToPrefixes, error) { 29 parsed, err := parseGCPCloudJSON([]byte(raw)) 30 if err != nil { 31 return nil, err 32 } 33 return gcpRegionsToPrefixesFromData(parsed) 34 } 35 36 type GCPCloudJSON struct { 37 Prefixes []GCPPrefix `json:"prefixes"` 38 // syncToken and createDate omitted 39 } 40 41 type GCPPrefix struct { 42 IPv4Prefix string `json:"ipv4Prefix"` 43 IPv6Prefix string `json:"ipv6Prefix"` 44 Scope string `json:"scope"` 45 // service omitted 46 } 47 48 // parseGCPCloudJSON parses GCP cloud.json IP ranges JSON data 49 func parseGCPCloudJSON(rawJSON []byte) (*GCPCloudJSON, error) { 50 r := &GCPCloudJSON{} 51 if err := json.Unmarshal(rawJSON, r); err != nil { 52 return nil, err 53 } 54 return r, nil 55 } 56 57 // gcpRegionsToPrefixesFromData processes the raw unmarshalled JSON into regionsToPrefixes map 58 func gcpRegionsToPrefixesFromData(data *GCPCloudJSON) (regionsToPrefixes, error) { 59 // convert from AWS published structure to a map by region, parse Prefixes 60 rtp := regionsToPrefixes{} 61 for _, prefix := range data.Prefixes { 62 region := prefix.Scope 63 if prefix.IPv4Prefix != "" { 64 ipPrefix, err := netip.ParsePrefix(prefix.IPv4Prefix) 65 if err != nil { 66 return nil, err 67 } 68 rtp[region] = append(rtp[region], ipPrefix) 69 } else if prefix.IPv6Prefix != "" { 70 ipPrefix, err := netip.ParsePrefix(prefix.IPv6Prefix) 71 if err != nil { 72 return nil, err 73 } 74 rtp[region] = append(rtp[region], ipPrefix) 75 } else { 76 return nil, errors.New("unexpected entry with no ipv4Prefix or ipv6Prefix") 77 } 78 } 79 80 // flatten 81 numPrefixes := 0 82 for region := range rtp { 83 // this approach allows us to produce consistent generated results 84 // since the ip ranges will be ordered 85 sort.Slice(rtp[region], func(i, j int) bool { 86 return rtp[region][i].String() < rtp[region][j].String() 87 }) 88 rtp[region] = dedupeSortedPrefixes(rtp[region]) 89 numPrefixes += len(rtp[region]) 90 } 91 92 return rtp, nil 93 }