use of com.netflix.spinnaker.halyard.config.problem.v1.ConfigProblemSetBuilder 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.config.problem.v1.ConfigProblemSetBuilder 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.config.problem.v1.ConfigProblemSetBuilder in project halyard by spinnaker.
the class AppengineAccountValidator method validate.
@Override
public void validate(ConfigProblemSetBuilder p, AppengineAccount account) {
String jsonKey = null;
String jsonPath = account.getJsonPath();
String project = account.getProject();
String knownHostsPath = account.getSshKnownHostsFilePath();
AppengineNamedAccountCredentials credentials = null;
boolean hasPassword = account.getGitHttpsPassword() != null;
boolean hasUsername = account.getGitHttpsUsername() != null && !account.getGitHttpsUsername().isEmpty();
if (hasPassword != hasUsername) {
if (!hasUsername) {
p.addProblem(Severity.ERROR, "Git HTTPS password supplied without git HTTPS username.");
} else {
p.addProblem(Severity.ERROR, "Git HTTPS username supplied without git HTTPS password.");
}
}
boolean hasSshPrivateKeyPassphrase = account.getSshPrivateKeyPassphrase() != null;
boolean hasSshPrivateKeyFilePath = account.getSshPrivateKeyFilePath() != null && !account.getSshPrivateKeyFilePath().isEmpty();
if (hasSshPrivateKeyPassphrase != hasSshPrivateKeyFilePath) {
if (!hasSshPrivateKeyFilePath) {
p.addProblem(Severity.ERROR, "SSH private key passphrase supplied without SSH private key filepath.");
} else {
p.addProblem(Severity.ERROR, "SSH private key filepath supplied without SSH private key passphrase.");
}
} else if (hasSshPrivateKeyPassphrase && hasSshPrivateKeyFilePath) {
String sshPrivateKey = ValidatingFileReader.contents(p, account.getSshPrivateKeyFilePath());
if (sshPrivateKey == null) {
return;
} else if (sshPrivateKey.isEmpty()) {
p.addProblem(Severity.WARNING, "The supplied SSH private key file is empty.");
} else {
try {
// Assumes that the public key is sitting next to the private key with the extension ".pub".
KeyPair keyPair = KeyPair.load(new JSch(), account.getSshPrivateKeyFilePath());
boolean decrypted = keyPair.decrypt(account.getSshPrivateKeyPassphrase());
if (!decrypted) {
p.addProblem(Severity.ERROR, "Could not unlock SSH public/private keypair with supplied passphrase.");
}
} catch (JSchException e) {
p.addProblem(Severity.ERROR, "Could not unlock SSH public/private keypair: " + e.getMessage() + ".");
}
}
}
if (knownHostsPath != null && !knownHostsPath.isEmpty()) {
String knownHosts = ValidatingFileReader.contents(p, knownHostsPath);
if (knownHosts == null) {
return;
}
if (knownHosts.isEmpty()) {
p.addProblem(Severity.WARNING, "The supplied known_hosts file is empty.");
}
}
if (jsonPath != null && !jsonPath.isEmpty()) {
jsonKey = ValidatingFileReader.contents(p, account.getJsonPath());
if (jsonKey == null) {
return;
}
if (jsonKey.isEmpty()) {
p.addProblem(Severity.WARNING, "The supplied credentials file is empty.");
}
}
if (jsonPath != null && !jsonPath.isEmpty() && account.isSshTrustUnknownHosts()) {
p.addProblem(Severity.WARNING, "You have supplied a known_hosts file path and set the `--ssh-trust-unknown-hosts` flag to true." + " Spinnaker will ignore your `--ssh-trust-unknown-hosts` flag.").setRemediation("Run `--ssh-trust-unknown-hosts false`.");
}
if (account.getProject() == null || account.getProject().isEmpty()) {
p.addProblem(Severity.ERROR, "No appengine project supplied.");
return;
}
try {
credentials = new AppengineNamedAccountCredentials.Builder().jsonKey(jsonKey).project(project).region("halyard").applicationName("halyard " + halyardVersion).build();
} catch (Exception e) {
p.addProblem(Severity.ERROR, "Error instantiating appengine credentials: " + e.getMessage() + ".");
return;
}
try {
credentials.getAppengine().apps().get(project).execute();
} catch (GoogleJsonResponseException e) {
if (e.getStatusCode() == 404) {
p.addProblem(Severity.ERROR, "No appengine application found for project " + project + ".").setRemediation("Run `gcloud app create --region <region>` to create an appengine application.");
} else {
p.addProblem(Severity.ERROR, "Failed to connect to appengine Admin API: " + e.getMessage() + ".");
}
} catch (Exception e) {
p.addProblem(Severity.ERROR, "Failed to connect to appengine Admin API: " + e.getMessage() + ".");
}
}
use of com.netflix.spinnaker.halyard.config.problem.v1.ConfigProblemSetBuilder in project halyard by spinnaker.
the class DCOSAccountValidator method validateClusters.
private void validateClusters(final ConfigProblemSetBuilder problems, final DCOSAccount account) {
final NodeIterator children = account.getParent().getChildren();
Node n = children.getNext();
Set<String> definedClusters = new HashSet<>();
while (n != null) {
if (n instanceof DCOSCluster) {
definedClusters.add(((DCOSCluster) n).getName());
}
n = children.getNext();
}
final Set<String> accountClusters = account.getClusters().stream().map(c -> c.getName()).collect(Collectors.toSet());
accountClusters.removeAll(definedClusters);
accountClusters.forEach(c -> problems.addProblem(ERROR, "Cluster \"" + c.toString() + "\" not defined for provider").setRemediation("Add cluster to the provider or remove from the account").setOptions(Lists.newArrayList(definedClusters)));
Set<List<String>> credentials = new HashSet<>();
account.getClusters().forEach(c -> {
final List<String> key = Lists.newArrayList(c.getName(), c.getUid());
if (credentials.contains(key)) {
problems.addProblem(ERROR, "Account contains duplicate credentials for cluster \"" + c.getName() + "\" and user id \"" + c.getUid() + "\".").setRemediation("Remove the duplicate credentials");
} else {
credentials.add(key);
}
// we can connect without a password
if (Strings.isStringEmpty(c.getPassword()) && Strings.isStringEmpty(c.getServiceKeyFile())) {
problems.addProblem(WARNING, "Account has no password or service key. Unless the cluster has security disabled this may be an error").setRemediation("Add a password or service key.");
}
if (!Strings.isStringEmpty(c.getPassword()) && !Strings.isStringEmpty(c.getServiceKeyFile())) {
problems.addProblem(ERROR, "Account has both a password and service key").setRemediation("Remove either the password or service key.");
}
if (!Strings.isStringEmpty(c.getServiceKeyFile())) {
String resolvedServiceKey = ValidatingFileReader.contents(problems, c.getServiceKeyFile());
if (Strings.isStringEmpty(resolvedServiceKey)) {
problems.addProblem(ERROR, "The supplied service key file does not exist or is empty.").setRemediation("Supply a valid service key file.");
}
}
});
}
use of com.netflix.spinnaker.halyard.config.problem.v1.ConfigProblemSetBuilder in project halyard by spinnaker.
the class OptionsService method options.
public <T extends Node> FieldOptions options(NodeFilter filter, Class<T> nodeClass, String field) {
ConfigProblemSetBuilder problemSetBuilder = new ConfigProblemSetBuilder(applicationContext);
List<T> nodes = lookupService.getMatchingNodesOfType(filter, nodeClass);
List<String> options = nodes.stream().map(n -> {
problemSetBuilder.setNode(n);
return n.fieldOptions(problemSetBuilder, field);
}).reduce(new ArrayList<>(), (a, b) -> {
a.addAll(b);
return a;
});
return new FieldOptions().setOptions(options).setProblemSet(problemSetBuilder.build());
}
Aggregations