| // 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 apidApigeeSync |
| |
| import ( |
| "fmt" |
| "net/http" |
| "os" |
| "time" |
| |
| "github.com/apid/apid-core" |
| "github.com/apid/apid-core/util" |
| ) |
| |
| const ( |
| configPollInterval = "apigeesync_poll_interval" |
| configProxyServerBaseURI = "apigeesync_proxy_server_base" |
| configSnapServerBaseURI = "apigeesync_snapshot_server_base" |
| configChangeServerBaseURI = "apigeesync_change_server_base" |
| configConsumerKey = "apigeesync_consumer_key" |
| configConsumerSecret = "apigeesync_consumer_secret" |
| configApidClusterId = "apigeesync_cluster_id" |
| configSnapshotProtocol = "apigeesync_snapshot_proto" |
| configName = "apigeesync_instance_name" |
| configDiagnosticMode = "apigeesync_diagnostic_mode" |
| // special value - set by ApigeeSync, not taken from configuration |
| configApidInstanceID = "apigeesync_apid_instance_id" |
| // This will not be needed once we have plugin handling tokens. |
| configBearerToken = "apigeesync_bearer_token" |
| configLocalStoragePath = "local_storage_path" |
| ) |
| |
| const ( |
| ApigeeSyncEventSelector = "ApigeeSync" |
| ) |
| |
| var ( |
| /* All set during plugin initialization */ |
| log apid.LogService |
| config apid.ConfigService |
| dataService apid.DataService |
| eventService apid.EventsService |
| apiService apid.APIService |
| apidInfo apidInstanceInfo |
| |
| /* Set during post plugin initialization |
| * set this as a default, so that it's guaranteed to be valid even if postInitPlugins isn't called |
| */ |
| apidPluginDetails string = `[{"name":"apidApigeeSync","schemaVer":"1.0"}]` |
| ) |
| |
| type apidInstanceInfo struct { |
| InstanceID, InstanceName, ClusterID, LastSnapshot string |
| IsNewInstance bool |
| } |
| |
| type pluginDetail struct { |
| Name string `json:"name"` |
| SchemaVersion string `json:"schemaVer"` |
| } |
| |
| func init() { |
| apid.RegisterPlugin(initPlugin, PluginData) |
| } |
| |
| func initConfigDefaults() { |
| config.SetDefault(configPollInterval, 120*time.Second) |
| config.SetDefault(configSnapshotProtocol, "sqlite") |
| config.SetDefault(configDiagnosticMode, false) |
| |
| name, errh := os.Hostname() |
| if (errh != nil) && (len(config.GetString(configName)) == 0) { |
| log.Errorf("Not able to get hostname for kernel. Please set '%s' property in config", configName) |
| name = "Undefined" |
| } |
| config.SetDefault(configName, name) |
| log.Debugf("Using %s as display name", config.GetString(configName)) |
| } |
| |
| func checkForRequiredValues(isOfflineMode bool) error { |
| required := []string{configProxyServerBaseURI, configConsumerKey, configConsumerSecret} |
| if !isOfflineMode { |
| required = append(required, configSnapServerBaseURI, configChangeServerBaseURI) |
| } |
| // check for required values |
| for _, key := range required { |
| if !config.IsSet(key) { |
| return fmt.Errorf("missing required config value: %s", key) |
| } |
| } |
| proto := config.GetString(configSnapshotProtocol) |
| if proto != "sqlite" { |
| return fmt.Errorf("illegal value for %s. Only currently supported snashot protocol is sqlite", configSnapshotProtocol) |
| } |
| |
| return nil |
| } |
| |
| func SetLogger(logger apid.LogService) { |
| log = logger |
| } |
| |
| func initManagers(isOfflineMode bool) (*listenerManager, *ApiManager, error) { |
| // check for forward proxy |
| var tr *http.Transport |
| tr = util.Transport(config.GetString(util.ConfigfwdProxyPortURL)) |
| tr.MaxIdleConnsPerHost = maxIdleConnsPerHost |
| |
| apidDbManager := creatDbManager() |
| db, err := dataService.DB() |
| if err != nil { |
| return nil, nil, fmt.Errorf("unable to access DB: %v", err) |
| } |
| apidDbManager.setDB(db) |
| err = apidDbManager.initDB() |
| if err != nil { |
| return nil, nil, fmt.Errorf("unable to access DB: %v", err) |
| } |
| |
| apidInfo, err = apidDbManager.getApidInstanceInfo() |
| if err != nil { |
| return nil, nil, fmt.Errorf("unable to get apid instance info: %v", err) |
| } |
| |
| if config.IsSet(configApidInstanceID) { |
| log.Warnf("ApigeeSync plugin overriding %s.", configApidInstanceID) |
| } |
| config.Set(configApidInstanceID, apidInfo.InstanceID) |
| |
| apidTokenManager := createApidTokenManager(apidInfo.IsNewInstance) |
| var snapMan snapshotManager |
| var apidChangeManager changeManager |
| |
| if isOfflineMode { |
| snapMan = &offlineSnapshotManager{ |
| dbMan: apidDbManager, |
| } |
| apidChangeManager = &offlineChangeManager{} |
| } else { |
| httpClient := &http.Client{ |
| Transport: tr, |
| Timeout: httpTimeout, |
| CheckRedirect: func(req *http.Request, _ []*http.Request) error { |
| req.Header.Set("Authorization", "Bearer "+apidTokenManager.getBearerToken()) |
| return nil |
| }, |
| } |
| snapMan = createSnapShotManager(apidDbManager, apidTokenManager, httpClient) |
| apidChangeManager = createChangeManager(apidDbManager, snapMan, apidTokenManager, httpClient) |
| } |
| |
| listenerMan := &listenerManager{ |
| changeMan: apidChangeManager, |
| snapMan: snapMan, |
| tokenMan: apidTokenManager, |
| isOfflineMode: isOfflineMode, |
| } |
| |
| apiMan := &ApiManager{ |
| endpoint: tokenEndpoint, |
| tokenMan: apidTokenManager, |
| } |
| return listenerMan, apiMan, nil |
| } |
| |
| func initPlugin(services apid.Services) (apid.PluginData, error) { |
| SetLogger(services.Log().ForModule("apigeeSync")) |
| dataService = services.Data() |
| eventService = services.Events() |
| apiService = services.API() |
| log.Debug("start init") |
| config = services.Config() |
| initConfigDefaults() |
| |
| isOfflineMode := false |
| if config.GetBool(configDiagnosticMode) { |
| log.Warn("Diagnostic mode: will not download changelist and snapshots!") |
| isOfflineMode = true |
| } |
| |
| err := checkForRequiredValues(isOfflineMode) |
| if err != nil { |
| return PluginData, err |
| } |
| if err != nil { |
| return PluginData, err |
| } |
| listenerMan, apiMan, err := initManagers(isOfflineMode) |
| if err != nil { |
| return PluginData, err |
| } |
| listenerMan.init() |
| apiMan.InitAPI(apiService) |
| |
| log.Debug("end init") |
| return PluginData, nil |
| } |