Skip to content

Commit

Permalink
First pass at Atlas integration. (#6)
Browse files Browse the repository at this point in the history
- Stubs out call to Atlas with a sample controller serving up canned json while we wait for the /fetch endpoint to reach oss.
  • Loading branch information
Matt Duftler authored Mar 23, 2017
1 parent 326dfa8 commit e9cd8f7
Show file tree
Hide file tree
Showing 28 changed files with 1,210 additions and 31 deletions.
8 changes: 8 additions & 0 deletions kayenta-atlas/kayenta-atlas.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
dependencies {
compile project(":kayenta-core")
compile spinnaker.dependency('bootWeb')
compile spinnaker.dependency('lombok')
spinnaker.group('retrofitDefault')

compile "org.apache.commons:commons-io:1.3.2"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
/*
* 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 com.netflix.kayenta.atlas.config;

import com.netflix.kayenta.atlas.metrics.AtlasMetricsService;
import com.netflix.kayenta.atlas.security.AtlasCredentials;
import com.netflix.kayenta.atlas.security.AtlasNamedAccountCredentials;
import com.netflix.kayenta.atlas.service.AtlasRemoteService;
import com.netflix.kayenta.metrics.MetricsService;
import com.netflix.kayenta.retrofit.config.RetrofitClientFactory;
import com.netflix.kayenta.security.AccountCredentials;
import com.netflix.kayenta.security.AccountCredentialsRepository;
import com.squareup.okhttp.OkHttpClient;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.CollectionUtils;

import java.io.IOException;
import java.util.List;

@Configuration
@EnableConfigurationProperties
@ConditionalOnProperty("kayenta.atlas.enabled")
@ComponentScan({"com.netflix.kayenta.atlas"})
@Slf4j
public class AtlasConfiguration {

@Bean
@ConfigurationProperties("kayenta.atlas")
AtlasConfigurationProperties atlasConfigurationProperties() {
return new AtlasConfigurationProperties();
}

@Bean
MetricsService atlasMetricsService(AtlasConfigurationProperties atlasConfigurationProperties,
AccountCredentialsRepository accountCredentialsRepository,
AtlasRemoteService atlasRemoteService) throws IOException {
AtlasMetricsService.AtlasMetricsServiceBuilder atlasMetricsServiceBuilder = AtlasMetricsService.builder();

for (AtlasManagedAccount atlasManagedAccount : atlasConfigurationProperties.getAccounts()) {
String name = atlasManagedAccount.getName();
String namespace = atlasManagedAccount.getNamespace();
List<AccountCredentials.Type> supportedTypes = atlasManagedAccount.getSupportedTypes();

log.info("Registering Atlas account {} with supported types {}.", name, supportedTypes);

AtlasCredentials atlasCredentials =
AtlasCredentials
.builder()
.build();
AtlasNamedAccountCredentials.AtlasNamedAccountCredentialsBuilder atlasNamedAccountCredentialsBuilder =
AtlasNamedAccountCredentials
.builder()
.name(name)
.namespace(namespace)
.credentials(atlasCredentials);

if (!CollectionUtils.isEmpty(supportedTypes)) {
if (supportedTypes.contains(AccountCredentials.Type.METRICS_STORE)) {
atlasNamedAccountCredentialsBuilder.atlasRemoteService(atlasRemoteService);
}

atlasNamedAccountCredentialsBuilder.supportedTypes(supportedTypes);
}

AtlasNamedAccountCredentials atlasNamedAccountCredentials = atlasNamedAccountCredentialsBuilder.build();
accountCredentialsRepository.save(name, atlasNamedAccountCredentials);
atlasMetricsServiceBuilder.accountName(name);
}

AtlasMetricsService atlasMetricsService = atlasMetricsServiceBuilder.build();

log.info("Populated AtlasMetricsService with {} Atlas accounts.", atlasMetricsService.getAccountNames().size());

return atlasMetricsService;
}

@Bean
AtlasRemoteService atlasRemoteService(AtlasConfigurationProperties atlasConfigurationProperties,
RetrofitClientFactory retrofitClientFactory,
OkHttpClient okHttpClient) {
return retrofitClientFactory.createClient(AtlasRemoteService.class, atlasConfigurationProperties.getEndpoint(), okHttpClient);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* 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 com.netflix.kayenta.atlas.config;

import com.netflix.kayenta.retrofit.config.RemoteService;
import lombok.Getter;
import lombok.Setter;

import javax.validation.constraints.NotNull;
import java.util.ArrayList;
import java.util.List;

public class AtlasConfigurationProperties {

@NotNull
@Getter
@Setter
private RemoteService endpoint;

@Getter
private List<AtlasManagedAccount> accounts = new ArrayList<>();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* 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 com.netflix.kayenta.atlas.config;

import com.netflix.kayenta.security.AccountCredentials;
import lombok.Data;

import javax.validation.constraints.NotNull;
import java.util.List;

@Data
public class AtlasManagedAccount {

@NotNull
private String name;

private String namespace;

private List<AccountCredentials.Type> supportedTypes;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
* 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 com.netflix.kayenta.atlas.metrics;

import com.netflix.kayenta.atlas.model.AtlasResults;
import com.netflix.kayenta.atlas.security.AtlasNamedAccountCredentials;
import com.netflix.kayenta.atlas.service.AtlasRemoteService;
import com.netflix.kayenta.metrics.MetricsService;
import com.netflix.kayenta.security.AccountCredentialsRepository;
import lombok.Builder;
import lombok.Getter;
import lombok.Singular;
import org.springframework.beans.factory.annotation.Autowired;

import javax.validation.constraints.NotNull;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;

@Builder
public class AtlasMetricsService implements MetricsService {

@NotNull
@Singular
@Getter
private List<String> accountNames;

@Autowired
AccountCredentialsRepository accountCredentialsRepository;

@Override
public boolean servicesAccount(String accountName) {
return accountNames.contains(accountName);
}

@Override
// These are still placeholder arguments. Each metrics service will have its own set of required/optional arguments. The return type is a placeholder as well.
public Optional<Map> queryMetrics(String accountName, String instanceNamePrefix, String intervalStartTime, String intervalEndTime) throws IOException {
AtlasNamedAccountCredentials credentials = (AtlasNamedAccountCredentials)accountCredentialsRepository
.getOne(accountName)
.orElseThrow(() -> new IllegalArgumentException("Unable to resolve account " + accountName + "."));
AtlasRemoteService atlasRemoteService = credentials.getAtlasRemoteService();
AtlasResults atlasResults = atlasRemoteService.fetch("name,randomValue,:eq,:sum,(,name,),:by", "std.json");

System.out.println("** Got back from fetch: atlasResults=" + atlasResults);

return Optional.of(Collections.singletonMap("some-key", "some-value"));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* 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 com.netflix.kayenta.atlas.model;

import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;

import java.util.List;
import java.util.Map;

@Data
public class AtlasResults {

private long start;

private long step;

private List<String> legend;

@JsonProperty("metrics")
private List<Map<String, String>> metricsDescriptors;

private List<List<Double>> values;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* 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 com.netflix.kayenta.atlas.security;

import lombok.Builder;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import java.util.Optional;

@Builder
@Data
@Slf4j
// TODO: Not sure what kind of credentials or configuration is really required here yet.
public class AtlasCredentials {

private static String applicationVersion =
Optional.ofNullable(AtlasCredentials.class.getPackage().getImplementationVersion()).orElse("Unknown");
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* 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 com.netflix.kayenta.atlas.security;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.netflix.kayenta.atlas.service.AtlasRemoteService;
import com.netflix.kayenta.security.AccountCredentials;
import lombok.Builder;
import lombok.Data;
import lombok.Singular;

import javax.validation.constraints.NotNull;
import java.util.List;

@Builder
@Data
public class AtlasNamedAccountCredentials implements AccountCredentials<AtlasCredentials> {

@NotNull
private String name;

@NotNull
@Singular
private List<Type> supportedTypes;

@NotNull
private AtlasCredentials credentials;

// Any required fields to use in identifying a project space or something similar in Atlas would go here.
// This one is just an example/placeholder.
@NotNull
private String namespace;

@Override
public String getType() {
return "atlas";
}

@JsonIgnore
AtlasRemoteService atlasRemoteService;
}
Loading

0 comments on commit e9cd8f7

Please sign in to comment.