blob: c890fd4f6abbaa7b911df46e9c3b6b8242bcbf66 [file] [log] [blame]
/*
Copyright 2017 Google Inc.
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 adapter
import (
"encoding/json"
"fmt"
"net/http"
"sync"
"time"
"github.com/apid/istioApigeeAdapter/common"
)
const (
defaultProductsFetch = time.Minute
)
type productManager struct {
fetchURL string
products map[string]*common.APIProduct
refresh time.Duration
expiration time.Time
latch *sync.Mutex
}
func newProductManager(fetchURL string, refreshTime time.Duration) *productManager {
return &productManager{
fetchURL: fetchURL,
refresh: refreshTime,
latch: &sync.Mutex{},
}
}
/*
getProducts returns the products that match a list of names. For now it is simple -- we will
use a mutex and update the list when it's expired. In the future we can be fancier with
periodic refresh.
*/
func (m *productManager) getProducts(names []string) ([]common.APIProduct, error) {
m.latch.Lock()
defer m.latch.Unlock()
if m.products == nil || m.expiration.Before(time.Now()) {
err := m.fetchProductList()
if err != nil {
return nil, err
}
}
var products []common.APIProduct
for _, name := range names {
p := m.products[name]
if p != nil {
products = append(products, *p)
}
}
return products, nil
}
func (m *productManager) fetchProductList() error {
resp, err := http.Get(m.fetchURL)
if err != nil {
return err
}
defer resp.Body.Close()
if resp.StatusCode != 200 {
return fmt.Errorf("HTTP error %d fetching API product list", resp.StatusCode)
}
var pl common.APIProductResponse
jr := json.NewDecoder(resp.Body)
err = jr.Decode(&pl)
if err != nil {
return err
}
m.products = make(map[string]*common.APIProduct)
for _, p := range pl.Products {
m.products[p.Name] = &p
}
m.expiration = time.Now().Add(m.refresh)
return nil
}