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  }