use of com.netflix.spinnaker.halyard.core.problem.v1.Problem.Severity.ERROR in project halyard by spinnaker.
the class OpenstackAccountValidator method validate.
@Override
public void validate(ConfigProblemSetBuilder psBuilder, OpenstackAccount account) {
DaemonTaskHandler.message("Validating " + account.getNodeName() + " with " + OpenstackAccountValidator.class.getSimpleName());
String environment = account.getEnvironment();
String accountType = account.getAccountType();
String username = account.getUsername();
String password = account.getPassword();
String projectName = account.getPassword();
String domainName = account.getDomainName();
String authUrl = account.getAuthUrl();
List<String> regions = account.getRegions();
Boolean insecure = account.getInsecure();
String heatTemplateLocation = account.getHeatTemplateLocation();
OpenstackAccount.OpenstackLbaasOptions lbaas = account.getLbaas();
ConsulConfig consulConfig = new ConsulConfig();
String userDataFile = account.getUserDataFile();
if (StringUtils.isEmpty(environment)) {
psBuilder.addProblem(Problem.Severity.ERROR, "You must provide an environment name");
}
if (StringUtils.isEmpty(password) || StringUtils.isEmpty(username)) {
psBuilder.addProblem(Problem.Severity.ERROR, "You must provide a both a username and a password");
}
if (StringUtils.isEmpty(projectName)) {
psBuilder.addProblem(Problem.Severity.ERROR, "You must provide a project name");
}
if (!StringUtils.endsWith(authUrl, "/v3")) {
psBuilder.addProblem(Problem.Severity.WARNING, "You must use Keystone v3. The default auth url will be of the format IP:5000/v3.");
}
if (StringUtils.isEmpty(domainName)) {
psBuilder.addProblem(Problem.Severity.ERROR, "You must provide a domain name");
}
if (regions.size() == 0 || StringUtils.isEmpty(regions.get(0))) {
psBuilder.addProblem(Problem.Severity.ERROR, "You must provide one region");
}
if (insecure) {
psBuilder.addProblem(Problem.Severity.WARNING, "You've chosen to not validate SSL connections. This setup is not recommended in production deployments.");
}
if (heatTemplateLocation != null && heatTemplateLocation.isEmpty()) {
psBuilder.addProblem(Problem.Severity.ERROR, "Not a valid Heat template location: ''");
}
if (lbaas.getPollInterval() < 0) {
psBuilder.addProblem(Problem.Severity.ERROR, "Poll interval cannot be less than 0.").setRemediation("Update this value to be reasonable. Default is 5.");
}
if (lbaas.getPollTimeout() < 0) {
psBuilder.addProblem(Problem.Severity.ERROR, "Poll timeout cannot be less than 0.").setRemediation("Update this value to be reasonable. Default is 60.");
}
boolean userDataProvided = userDataFile != null && !userDataFile.isEmpty();
if (userDataProvided) {
String resolvedUserData = ValidatingFileReader.contents(psBuilder, userDataFile);
if (resolvedUserData == null) {
return;
} else if (resolvedUserData.isEmpty()) {
psBuilder.addProblem(Problem.Severity.WARNING, "The supplied user data file is empty.").setRemediation("Please provide a non empty file, or remove the user data file.");
}
List<String> validTokens = Arrays.asList("account", "accounttype", "env", "region", "group", "autogrp", "cluster", "stack", "detail", "launchconfig");
List<String> tokens = Arrays.asList(StringUtils.substringsBetween(resolvedUserData, "%%", "%%"));
List<String> invalidTokens = tokens.stream().filter(t -> !validTokens.contains(t)).collect(Collectors.toList());
if (invalidTokens.size() != 0) {
psBuilder.addProblem(Problem.Severity.WARNING, "The supplied user data file contains tokens that won't be replaced. " + "Tokens \"" + StringUtils.join(invalidTokens, ", ") + "\" are not supported.").setRemediation("Please use only the supported tokens \"" + StringUtils.join(validTokens, ", ") + "\".");
}
}
OpenstackConfigurationProperties.LbaasConfig lbaasConfig = new OpenstackConfigurationProperties.LbaasConfig();
lbaasConfig.setPollInterval(lbaas.getPollInterval());
lbaasConfig.setPollTimeout(lbaas.getPollTimeout());
try {
OpenstackNamedAccountCredentials openstackCredentials = new OpenstackNamedAccountCredentials.Builder().name(account.getName()).environment(environment).accountType(accountType).authUrl(authUrl).username(username).password(password).projectName(projectName).domainName(domainName).regions(regions).insecure(insecure).heatTemplateLocation(heatTemplateLocation).consulConfig(consulConfig).lbaasConfig(lbaasConfig).userDataFile(userDataFile).build();
credentialsList.add(openstackCredentials);
// TODO(emjburns) verify that these credentials can connect w/o error to the openstack instance
} catch (Exception e) {
psBuilder.addProblem(Problem.Severity.ERROR, "Failed to instantiate openstack credentials for account \"" + account.getName() + "\".");
}
}
use of com.netflix.spinnaker.halyard.core.problem.v1.Problem.Severity.ERROR in project halyard by spinnaker.
the class ResponseUnwrapper method formatProblemSet.
private static void formatProblemSet(ProblemSet problemSet) {
if (problemSet == null || problemSet.isEmpty()) {
return;
}
AnsiSnippet snippet = new AnsiSnippet("\r").setErase(AnsiErase.ERASE_LINE);
AnsiPrinter.err.print(snippet.toString());
Map<String, List<Problem>> locationGroup = problemSet.groupByLocation();
for (Entry<String, List<Problem>> entry : locationGroup.entrySet()) {
AnsiUi.problemLocation(entry.getKey());
for (Problem problem : entry.getValue()) {
Severity severity = problem.getSeverity();
String message = problem.getMessage();
String remediation = problem.getRemediation();
List<String> options = problem.getOptions();
switch(severity) {
case FATAL:
case ERROR:
AnsiUi.error(message);
break;
case WARNING:
AnsiUi.warning(message);
break;
default:
throw new RuntimeException("Unknown severity level " + severity);
}
if (remediation != null && !remediation.isEmpty()) {
AnsiUi.remediation(remediation);
}
if (options != null && !options.isEmpty()) {
AnsiUi.remediation("Options include: ");
options.forEach(AnsiUi::listRemediation);
}
// Newline between errors
AnsiUi.raw("");
}
}
}
use of com.netflix.spinnaker.halyard.core.problem.v1.Problem.Severity.ERROR in project halyard by spinnaker.
the class GoogleBaseImageValidator method validate.
@Override
public void validate(ConfigProblemSetBuilder p, GoogleBaseImage n) {
String sourceImage = n.getVirtualizationSettings().getSourceImage();
String sourceImageFamily = n.getVirtualizationSettings().getSourceImageFamily();
if (StringUtils.isEmpty(sourceImage) && StringUtils.isEmpty(sourceImageFamily)) {
p.addProblem(Problem.Severity.ERROR, "Either source image or source image family must be specified for " + n.getBaseImage().getId() + ".");
}
if (!StringUtils.isEmpty(sourceImage)) {
int i = 0;
boolean[] foundSourceImageHolder = new boolean[1];
while (!foundSourceImageHolder[0] && i < credentialsList.size()) {
GoogleNamedAccountCredentials credentials = credentialsList.get(i);
List<String> imageProjects = Lists.newArrayList(credentials.getProject());
imageProjects.addAll(credentials.getImageProjects());
imageProjects.addAll(baseImageProjects);
Compute compute = credentials.getCompute();
BatchRequest imageListBatch = buildBatchRequest(compute);
JsonBatchCallback<ImageList> imageListCallback = new JsonBatchCallback<ImageList>() {
@Override
public void onFailure(GoogleJsonError e, HttpHeaders responseHeaders) throws IOException {
p.addProblem(Problem.Severity.ERROR, "Error locating " + sourceImage + " in these projects: " + imageProjects + ": " + e.getMessage() + ".");
}
@Override
public void onSuccess(ImageList imageList, HttpHeaders responseHeaders) throws IOException {
// No need to look through these images if the requested image was already found.
if (!foundSourceImageHolder[0]) {
if (imageList.getItems() != null) {
foundSourceImageHolder[0] = imageList.getItems().stream().filter(image -> image.getName().equals(sourceImage)).findFirst().isPresent();
}
}
}
};
try {
for (String imageProject : imageProjects) {
compute.images().list(imageProject).queue(imageListBatch, imageListCallback);
}
imageListBatch.execute();
} catch (IOException e) {
p.addProblem(Problem.Severity.ERROR, "Error locating " + sourceImage + " in these projects: " + imageProjects + ": " + e.getMessage() + ".");
}
i++;
}
if (!foundSourceImageHolder[0]) {
p.addProblem(Problem.Severity.ERROR, "Image " + sourceImage + " not found via any configured google account.");
}
}
if (!StringUtils.isEmpty(sourceImageFamily)) {
int i = 0;
boolean[] foundSourceImageFamilyHolder = new boolean[1];
while (!foundSourceImageFamilyHolder[0] && i < credentialsList.size()) {
GoogleNamedAccountCredentials credentials = credentialsList.get(i);
List<String> imageProjects = Lists.newArrayList(credentials.getProject());
imageProjects.addAll(credentials.getImageProjects());
imageProjects.addAll(baseImageProjects);
Compute compute = credentials.getCompute();
BatchRequest imageListBatch = buildBatchRequest(compute);
JsonBatchCallback<ImageList> imageListCallback = new JsonBatchCallback<ImageList>() {
@Override
public void onFailure(GoogleJsonError e, HttpHeaders responseHeaders) throws IOException {
p.addProblem(Problem.Severity.ERROR, "Error locating " + sourceImageFamily + " in these projects: " + imageProjects + ": " + e.getMessage() + ".");
}
@Override
public void onSuccess(ImageList imageList, HttpHeaders responseHeaders) throws IOException {
// No need to look through these images if the requested image family was already found.
if (!foundSourceImageFamilyHolder[0]) {
if (imageList.getItems() != null) {
foundSourceImageFamilyHolder[0] = imageList.getItems().stream().filter(image -> sourceImageFamily.equals(image.getFamily())).findFirst().isPresent();
}
}
}
};
try {
for (String imageProject : imageProjects) {
compute.images().list(imageProject).queue(imageListBatch, imageListCallback);
}
imageListBatch.execute();
} catch (IOException e) {
p.addProblem(Problem.Severity.ERROR, "Error locating " + sourceImageFamily + " in these projects: " + imageProjects + ": " + e.getMessage() + ".");
}
i++;
}
if (!foundSourceImageFamilyHolder[0]) {
p.addProblem(Problem.Severity.ERROR, "Image family " + sourceImageFamily + " not found via any configured google account.");
}
}
if (StringUtils.isEmpty(n.getBaseImage().getPackageType())) {
p.addProblem(Problem.Severity.ERROR, "Package type must be specified for " + n.getBaseImage().getId() + ".");
}
}
use of com.netflix.spinnaker.halyard.core.problem.v1.Problem.Severity.ERROR in project halyard by spinnaker.
the class KubernetesAccountValidator method validateKubeconfig.
private void validateKubeconfig(ConfigProblemSetBuilder psBuilder, KubernetesAccount account) {
io.fabric8.kubernetes.api.model.Config kubeconfig;
String context = account.getContext();
String kubeconfigFile = account.getKubeconfigFile();
String cluster = account.getCluster();
String user = account.getUser();
List<String> namespaces = account.getNamespaces();
List<String> omitNamespaces = account.getOmitNamespaces();
// This indicates if a first pass at the config looks OK. If we don't see any serious problems, we'll do one last check
// against the requested kubernetes cluster to ensure that we can run spinnaker.
boolean smoketest = true;
boolean namespacesProvided = namespaces != null && !namespaces.isEmpty();
boolean omitNamespacesProvided = omitNamespaces != null && !omitNamespaces.isEmpty();
if (namespacesProvided && omitNamespacesProvided) {
psBuilder.addProblem(ERROR, "At most one of \"namespaces\" and \"omitNamespaces\" can be supplied.");
smoketest = false;
}
// TODO(lwander) find a good resource / list of resources for generating kubeconfig files to link to here.
try {
if (ValidatingFileReader.contents(psBuilder, kubeconfigFile) == null) {
return;
}
File kubeconfigFileOpen = new File(kubeconfigFile);
kubeconfig = KubeConfigUtils.parseConfig(kubeconfigFileOpen);
} catch (IOException e) {
psBuilder.addProblem(ERROR, e.getMessage());
return;
}
System.out.println(context);
if (context != null && !context.isEmpty()) {
Optional<NamedContext> namedContext = kubeconfig.getContexts().stream().filter(c -> c.getName().equals(context)).findFirst();
if (!namedContext.isPresent()) {
psBuilder.addProblem(ERROR, "Context \"" + context + "\" not found in kubeconfig \"" + kubeconfigFile + "\".", "context").setRemediation("Either add this context to your kubeconfig, rely on the default context, or pick another kubeconfig file.");
smoketest = false;
}
} else {
String currentContext = kubeconfig.getCurrentContext();
if (StringUtils.isEmpty(currentContext)) {
psBuilder.addProblem(ERROR, "You have not specified a Kubernetes context, and your kubeconfig \"" + kubeconfigFile + "\" has no current-context.", "context").setRemediation("Either specify a context in your halconfig, or set a current-context in your kubeconfig.");
smoketest = false;
} else {
psBuilder.addProblem(WARNING, "You have not specified a Kubernetes context in your halconfig, Spinnaker will use \"" + currentContext + "\" instead.", "context").setRemediation("We recommend explicitly setting a context in your halconfig, to ensure changes to your kubeconfig won't break your deployment.");
}
}
if (smoketest) {
Config config = KubernetesConfigParser.parse(kubeconfigFile, context, cluster, user, namespaces, false);
try {
KubernetesClient client = new DefaultKubernetesClient(config);
client.namespaces().list();
} catch (Exception e) {
ConfigProblemBuilder pb = psBuilder.addProblem(ERROR, "Unable to communicate with your Kubernetes cluster: " + e.getMessage() + ".");
if (e.getMessage().contains("Token may have expired")) {
pb.setRemediation("If you downloaded these keys with gcloud, it's possible they are in the wrong format. To fix this, run \n\n" + "gcloud config set container/use_client_certificate true\n\ngcloud container clusters get-credentials $CLUSTERNAME");
} else {
pb.setRemediation("Unable to authenticate with your Kubernetes cluster. Try using kubectl to verify your credentials.");
}
}
}
}
use of com.netflix.spinnaker.halyard.core.problem.v1.Problem.Severity.ERROR in project halyard by spinnaker.
the class DistributedDeployer method disableOrcaServerGroups.
private <T extends Account> Set<Integer> disableOrcaServerGroups(AccountDeploymentDetails<T> details, SpinnakerRuntimeSettings runtimeSettings, DistributedService<Orca, T> orcaService, RunningServiceDetails runningOrcaDetails) {
Map<Integer, List<RunningServiceDetails.Instance>> instances = runningOrcaDetails.getInstances();
List<Integer> existingVersions = new ArrayList<>(instances.keySet());
existingVersions.sort(Integer::compareTo);
Map<String, String> disableRequest = new HashMap<>();
Set<Integer> result = new HashSet<>();
disableRequest.put("enabled", "false");
List<Integer> disabledVersions = existingVersions.subList(0, existingVersions.size() - 1);
for (Integer version : disabledVersions) {
try {
for (RunningServiceDetails.Instance instance : instances.get(version)) {
log.info("Disabling instance " + instance.getId());
Orca orca = orcaService.connectToInstance(details, runtimeSettings, orcaService.getService(), instance.getId());
orca.setInstanceStatusEnabled(disableRequest);
}
result.add(version);
} catch (RetrofitError e) {
Response response = e.getResponse();
if (response == null) {
log.warn("Unexpected error disabling orca", e);
} else if (response.getStatus() == 400 && ((Map) e.getBodyAs(Map.class)).containsKey("discovery")) {
log.info("Orca instance is managed by eureka");
result.add(version);
} else {
log.warn("Orca version doesn't support explicit disabling of instances", e);
}
}
}
Set<Integer> unknownVersions = disabledVersions.stream().filter(i -> !result.contains(i)).collect(Collectors.toSet());
if (unknownVersions.size() > 0) {
log.warn("There are existing orca server groups that cannot be explicitly disabled, we will have to wait for these to drain work");
}
return unknownVersions;
}
Aggregations