src/go/serviceconfig/service_config_fetcher.go (73 lines of code) (raw):
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package serviceconfig
import (
"fmt"
"net/http"
"time"
"github.com/GoogleCloudPlatform/esp-v2/src/go/util"
"github.com/golang/glog"
confpb "google.golang.org/genproto/googleapis/api/serviceconfig"
smpb "google.golang.org/genproto/googleapis/api/servicemanagement/v1"
)
type ServiceConfigFetcher struct {
serviceManagementUrl string
serviceName string
client *http.Client
accessToken util.GetAccessTokenFunc
retryConfigs map[int]util.RetryConfig
}
var SmRetryConfigs = map[int]util.RetryConfig{
http.StatusTooManyRequests: util.RetryConfig{
RetryNum: 30,
RetryInterval: time.Second * 10,
},
}
func NewServiceConfigFetcher(client *http.Client, serviceManagementUrl,
serviceName string, accessToken util.GetAccessTokenFunc) *ServiceConfigFetcher {
return &ServiceConfigFetcher{
client: client,
serviceName: serviceName,
serviceManagementUrl: serviceManagementUrl,
accessToken: accessToken,
retryConfigs: SmRetryConfigs,
}
}
// Fetch the service config by given configId.
func (s *ServiceConfigFetcher) FetchConfig(configId string) (*confpb.Service, error) {
serviceConfig := new(confpb.Service)
fetchConfigUrl := util.FetchConfigURL(s.serviceManagementUrl, s.serviceName, configId)
util.CallGoogleapisMu.RLock()
callGoogleapis := util.CallGoogleapis
util.CallGoogleapisMu.RUnlock()
if err := callGoogleapis(s.client, fetchConfigUrl, util.GET, s.accessToken, s.retryConfigs, serviceConfig); err != nil {
return nil, err
}
return serviceConfig, nil
}
// Fetch all the rollouts and use the latest success rollout. Among its all
// service configs, pick up the one with highest traffic percentage.
func (s *ServiceConfigFetcher) LoadConfigIdFromRollouts() (string, error) {
rollouts := new(smpb.ListServiceRolloutsResponse)
fetchRolloutUrl := util.FetchRolloutsURL(s.serviceManagementUrl, s.serviceName)
util.CallGoogleapisMu.RLock()
callGoogleapis := util.CallGoogleapis
util.CallGoogleapisMu.RUnlock()
if err := callGoogleapis(s.client, fetchRolloutUrl, util.GET, s.accessToken, s.retryConfigs, rollouts); err != nil {
return "", err
}
return highestTrafficConfigIdInLatestRollout(rollouts)
}
func highestTrafficConfigIdInLatestRollout(rollouts *smpb.ListServiceRolloutsResponse) (string, error) {
if rollouts == nil || len(rollouts.GetRollouts()) == 0 {
return "", fmt.Errorf("problematic rollouts: %v", rollouts)
}
latestRollout := rollouts.GetRollouts()[0]
highestPercent := 0.
highTrafficConfigId := ""
for configId, percent := range latestRollout.GetTrafficPercentStrategy().Percentages {
if percent > highestPercent {
highestPercent = percent
highTrafficConfigId = configId
}
}
if highestPercent < 100.0 {
glog.Warningf("though traffic percentage of configuration %v is %v%%, set it to 100%%", highTrafficConfigId, highestPercent)
}
return highTrafficConfigId, nil
}