blob: 729858e0c19df7f393d82ed28f6344efda1c13ca [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "config/client_config.h"
#include <memory>
#include <string>
#include <utility>
#include "./logging.h"
#include "config/cobalt_registry.pb.h"
#include "config/encoding_config.h"
#include "config/encodings.pb.h"
#include "config/metric_config.h"
#include "config/metrics.pb.h"
#include "util/crypto_util/base64.h"
namespace cobalt {
namespace config {
namespace {
std::string ErrorMessage(Status status) {
switch (status) {
case kOK:
return "No error";
case kFileOpenError:
return "Unable to open file: ";
case kParsingError:
return "Error while parsing file: ";
case kDuplicateRegistration:
return "Duplicate ID found in file: ";
default:
return "Unknown problem with: ";
}
}
} // namespace
std::unique_ptr<ClientConfig> ClientConfig::CreateFromCobaltRegistryBase64(
const std::string& cobalt_registry_base64) {
std::string cobalt_registry_bytes;
if (!crypto::Base64Decode(cobalt_registry_base64, &cobalt_registry_bytes)) {
LOG(ERROR) << "Unable to parse the provided string as base-64";
return nullptr;
}
return CreateFromCobaltRegistryBytes(cobalt_registry_bytes);
}
std::unique_ptr<ClientConfig> ClientConfig::CreateFromCobaltRegistryBytes(
const std::string& cobalt_registry_bytes) {
auto cobalt_registry = std::make_unique<CobaltRegistry>();
if (!cobalt_registry->ParseFromString(cobalt_registry_bytes)) {
LOG(ERROR) << "Unable to parse a CobaltRegistry from the provided bytes.";
return nullptr;
}
return CreateFromCobaltRegistryProto(std::move(cobalt_registry));
}
std::pair<std::unique_ptr<ClientConfig>, uint32_t>
ClientConfig::CreateFromCobaltProjectRegistryBytes(
const std::string& cobalt_registry_bytes) {
auto client_config = CreateFromCobaltRegistryBytes(cobalt_registry_bytes);
if (!client_config) {
return std::make_pair(nullptr, 0);
}
if (client_config->is_empty()) {
LOG(ERROR) << "No project data found in the provided CobaltRegistry.";
return std::make_pair(nullptr, 0);
}
if (!client_config->is_single_project()) {
LOG(ERROR) << "More than one project found in the provided CobaltRegistry.";
return std::make_pair(nullptr, 0);
}
return std::make_pair(std::move(client_config),
client_config->single_project_id());
}
std::unique_ptr<ClientConfig> ClientConfig::CreateFromCobaltRegistryProto(
std::unique_ptr<CobaltRegistry> cobalt_registry) {
return CreateFromCobaltRegistry(cobalt_registry.get());
}
// DEPRECATED: As soon as we are able to delete this method, move its logic
// into CreateFromCobaltRegistryProto() above instead.
std::unique_ptr<ClientConfig> ClientConfig::CreateFromCobaltRegistry(
CobaltRegistry* cobalt_registry) {
RegisteredEncodings registered_encodings;
registered_encodings.mutable_element()->Swap(
cobalt_registry->mutable_encoding_configs());
auto encoding_registry_and_status =
EncodingRegistry::TakeFrom(&registered_encodings, nullptr);
if (encoding_registry_and_status.second != config::kOK) {
LOG(ERROR) << "Invalid EncodingConfigs. "
<< ErrorMessage(encoding_registry_and_status.second);
return std::unique_ptr<ClientConfig>(nullptr);
}
RegisteredMetrics registered_metrics;
registered_metrics.mutable_element()->Swap(
cobalt_registry->mutable_metric_configs());
auto metrics_registry_and_status =
MetricRegistry::TakeFrom(&registered_metrics, nullptr);
if (metrics_registry_and_status.second != config::kOK) {
LOG(ERROR) << "Error getting Metrics from registry. "
<< ErrorMessage(metrics_registry_and_status.second);
return std::unique_ptr<ClientConfig>(nullptr);
}
auto client_config = std::unique_ptr<ClientConfig>(
new ClientConfig(std::move(encoding_registry_and_status.first),
std::move(metrics_registry_and_status.first)));
// Deprecated: Delete this block once TakeCustomerConfig() has no more uses.
size_t num_customers = cobalt_registry->customers_size();
if (num_customers == 0) {
// There is no Cobalt 1.0 data. We are done.
return client_config;
}
// Since there is Cobalt 1.0 data, any previous computation regarding
// whether or not there is a single project based on the Cobalt 0.1 data
// only is invalid. Initialize is_single_project to false.
client_config->is_single_project_ = false;
if (!client_config->is_empty_) {
// There is both Cobalt 0.1 and Cobalt 1.0 data.
return client_config;
}
client_config->is_empty_ = false;
if (num_customers > 1) {
// There is more than one Cobalt 1.0 customer.
return client_config;
}
auto* single_customer = cobalt_registry->mutable_customers(0);
if (single_customer->projects_size() != 1) {
// The first Cobalt 1.0 customer does not have exactly one project.
return client_config;
}
auto single_project = single_customer->projects(0);
client_config->is_single_project_ = true;
client_config->single_customer_id_ = single_customer->customer_id();
client_config->single_project_id_ = single_project.project_id();
client_config->single_customer_config_.reset(new CustomerConfig());
client_config->single_customer_config_->Swap(single_customer);
return client_config;
}
const EncodingConfig* ClientConfig::EncodingConfig(
uint32_t customer_id, uint32_t project_id, uint32_t encoding_config_id) {
return encoding_configs_->Get(customer_id, project_id, encoding_config_id);
}
const Metric* ClientConfig::Metric(uint32_t customer_id, uint32_t project_id,
uint32_t metric_id) {
return metrics_->Get(customer_id, project_id, metric_id);
}
const Metric* ClientConfig::Metric(uint32_t customer_id, uint32_t project_id,
const std::string& metric_name) {
return metrics_->Get(customer_id, project_id, metric_name);
}
ClientConfig::ClientConfig(
std::unique_ptr<config::EncodingRegistry> encoding_configs,
std::unique_ptr<config::MetricRegistry> metrics)
: encoding_configs_(std::move(encoding_configs)),
metrics_(std::move(metrics)) {
CHECK(metrics_);
CHECK(encoding_configs_);
is_empty_ = encoding_configs_->size() == 0 && metrics_->size() == 0;
DetermineIfSingleProject();
}
void ClientConfig::DetermineIfSingleProject() {
is_single_project_ = false;
if (is_empty_) {
return;
}
bool first = true;
for (const class EncodingConfig& encoding_config : *encoding_configs_) {
if (first) {
first = false;
is_single_project_ = true;
single_customer_id_ = encoding_config.customer_id();
single_project_id_ = encoding_config.project_id();
} else if (encoding_config.customer_id() != single_customer_id_ ||
encoding_config.project_id() != single_project_id_) {
is_single_project_ = false;
return;
}
}
for (const class Metric& metric : *metrics_) {
if (first) {
first = false;
is_single_project_ = true;
single_customer_id_ = metric.customer_id();
single_project_id_ = metric.project_id();
} else if (metric.customer_id() != single_customer_id_ ||
metric.project_id() != single_project_id_) {
is_single_project_ = false;
return;
}
}
}
} // namespace config
} // namespace cobalt