use of com.netflix.spinnaker.halyard.core.error.v1.HalException in project halyard by spinnaker.
the class KubernetesV1DistributedService method stageProfiles.
default List<ConfigSource> stageProfiles(AccountDeploymentDetails<KubernetesAccount> details, GenerateService.ResolvedConfiguration resolvedConfiguration) {
SpinnakerService thisService = getService();
ServiceSettings thisServiceSettings = resolvedConfiguration.getServiceSettings(thisService);
SpinnakerRuntimeSettings runtimeSettings = resolvedConfiguration.getRuntimeSettings();
Integer version = getRunningServiceDetails(details, runtimeSettings).getLatestEnabledVersion();
if (version == null) {
version = 0;
} else {
version++;
}
String namespace = getNamespace(thisServiceSettings);
KubernetesV1ProviderUtils.createNamespace(details, namespace);
String name = getServiceName();
Map<String, String> env = new HashMap<>();
List<ConfigSource> configSources = new ArrayList<>();
Map<String, Profile> serviceProfiles = resolvedConfiguration.getProfilesForService(thisService.getType());
Set<String> requiredFiles = new HashSet<>();
for (SidecarService sidecarService : getSidecars(runtimeSettings)) {
for (Profile profile : sidecarService.getSidecarProfiles(resolvedConfiguration, thisService)) {
if (profile == null) {
throw new HalException(Problem.Severity.FATAL, "Service " + sidecarService.getService().getCanonicalName() + " is required but was not supplied for deployment.");
}
serviceProfiles.put(profile.getName(), profile);
requiredFiles.addAll(profile.getRequiredFiles());
}
}
Map<String, Set<Profile>> collapseByDirectory = new HashMap<>();
for (Map.Entry<String, Profile> entry : serviceProfiles.entrySet()) {
Profile profile = entry.getValue();
String mountPoint = Paths.get(profile.getOutputFile()).getParent().toString();
Set<Profile> profiles = collapseByDirectory.getOrDefault(mountPoint, new HashSet<>());
profiles.add(profile);
requiredFiles.addAll(profile.getRequiredFiles());
collapseByDirectory.put(mountPoint, profiles);
}
String stagingPath = getSpinnakerStagingPath(details.getDeploymentName());
if (!requiredFiles.isEmpty()) {
String secretName = KubernetesV1ProviderUtils.componentDependencies(name, version);
String mountPoint = null;
for (String file : requiredFiles) {
String nextMountPoint = Paths.get(file).getParent().toString();
if (mountPoint == null) {
mountPoint = nextMountPoint;
}
assert (mountPoint.equals(nextMountPoint));
}
Set<Pair<File, String>> pairs = requiredFiles.stream().map(f -> {
return new ImmutablePair<>(new File(f), new File(f).getName());
}).collect(Collectors.toSet());
KubernetesV1ProviderUtils.upsertSecret(details, pairs, secretName, namespace);
configSources.add(new ConfigSource().setId(secretName).setMountPath(mountPoint));
}
int ind = 0;
for (Map.Entry<String, Set<Profile>> entry : collapseByDirectory.entrySet()) {
env.clear();
String mountPoint = entry.getKey();
Set<Profile> profiles = entry.getValue();
env.putAll(profiles.stream().reduce(new HashMap<>(), (acc, profile) -> {
acc.putAll(profile.getEnv());
return acc;
}, (a, b) -> {
a.putAll(b);
return a;
}));
String secretName = KubernetesV1ProviderUtils.componentSecret(name + ind, version);
ind += 1;
Set<Pair<File, String>> pairs = profiles.stream().map(p -> {
return new ImmutablePair<>(new File(stagingPath, p.getName()), new File(p.getOutputFile()).getName());
}).collect(Collectors.toSet());
KubernetesV1ProviderUtils.upsertSecret(details, pairs, secretName, namespace);
configSources.add(new ConfigSource().setId(secretName).setMountPath(mountPoint).setEnv(env));
}
return configSources;
}
use of com.netflix.spinnaker.halyard.core.error.v1.HalException in project halyard by spinnaker.
the class KubernetesV1ProviderUtils method upsertSecret.
static void upsertSecret(AccountDeploymentDetails<KubernetesAccount> details, Set<Pair<File, String>> files, String secretName, String namespace) {
KubernetesClient client = getClient(details);
if (client.secrets().inNamespace(namespace).withName(secretName).get() != null) {
client.secrets().inNamespace(namespace).withName(secretName).delete();
}
Map<String, String> secretContents = new HashMap<>();
files.forEach(pair -> {
try {
File file = pair.getLeft();
String name = pair.getRight();
String data = new String(Base64.getEncoder().encode(IOUtils.toByteArray(new FileInputStream(file))));
secretContents.putIfAbsent(name, data);
} catch (IOException e) {
throw new HalException(Severity.ERROR, "Unable to read contents of \"" + pair.getLeft() + "\": " + e);
}
});
SecretBuilder secretBuilder = new SecretBuilder();
secretBuilder = secretBuilder.withNewMetadata().withName(secretName).withNamespace(namespace).endMetadata().withData(secretContents);
client.secrets().inNamespace(namespace).create(secretBuilder.build());
}
use of com.netflix.spinnaker.halyard.core.error.v1.HalException in project halyard by spinnaker.
the class KubernetesV1ProviderUtils method openProxy.
static Proxy openProxy(JobExecutor jobExecutor, AccountDeploymentDetails<KubernetesAccount> details) {
KubernetesAccount account = details.getAccount();
Proxy proxy = proxyMap.getOrDefault(Proxy.buildKey(details.getDeploymentName()), new Proxy());
String jobId = proxy.jobId;
if (StringUtils.isEmpty(jobId) || !jobExecutor.jobExists(jobId)) {
DaemonTaskHandler.newStage("Connecting to the Kubernetes cluster in account \"" + account.getName() + "\"");
List<String> command = kubectlAccountCommand(details);
command.add("proxy");
// select a random port
command.add("--port=0");
JobRequest request = new JobRequest().setTokenizedCommand(command);
proxy.jobId = jobExecutor.startJob(request);
JobStatus status = jobExecutor.updateJob(proxy.jobId);
while (status == null) {
DaemonTaskHandler.safeSleep(TimeUnit.SECONDS.toMillis(2));
status = jobExecutor.updateJob(proxy.jobId);
}
// This should be a long-running job.
if (status.getState() == JobStatus.State.COMPLETED) {
throw new HalException(Severity.FATAL, "Unable to establish a proxy against account " + account.getName() + ":\n" + status.getStdOut() + "\n" + status.getStdErr());
}
String connectionMessage = status.getStdOut();
Pattern portPattern = Pattern.compile(":(\\d+)");
Matcher matcher = portPattern.matcher(connectionMessage);
if (matcher.find()) {
proxy.setPort(Integer.valueOf(matcher.group(1)));
proxyMap.put(Proxy.buildKey(details.getDeploymentName()), proxy);
DaemonTaskHandler.message("Connected to kubernetes cluster for account " + account.getName() + " on port " + proxy.getPort());
DaemonTaskHandler.message("View the kube ui on http://localhost:" + proxy.getPort() + "/ui/");
} else {
throw new HalException(Severity.FATAL, "Could not parse connection information from:\n" + connectionMessage + "(" + status.getStdErr() + ")");
}
}
return proxy;
}
use of com.netflix.spinnaker.halyard.core.error.v1.HalException in project halyard by spinnaker.
the class GoogleDistributedService method deleteVersion.
@Override
default void deleteVersion(AccountDeploymentDetails<GoogleAccount> details, ServiceSettings settings, Integer version) {
String migName = getVersionedName(version);
String zone = settings.getLocation();
String project = details.getAccount().getProject();
Compute compute = GoogleProviderUtils.getCompute(details);
InstanceGroupManager mig;
try {
mig = compute.instanceGroupManagers().get(project, zone, migName).execute();
} catch (GoogleJsonResponseException e) {
if (e.getStatusCode() == 404) {
return;
} else {
throw new HalException(FATAL, "Failed to load mig " + migName + " in " + zone, e);
}
} catch (IOException e) {
throw new HalException(FATAL, "Failed to load mig " + migName + " in " + zone, e);
}
try {
GoogleProviderUtils.waitOnZoneOperation(compute, project, zone, compute.instanceGroupManagers().delete(project, zone, migName).execute());
} catch (IOException e) {
throw new HalException(FATAL, "Failed to delete mig " + migName + " in " + zone, e);
}
String instanceTemplateName = mig.getInstanceTemplate();
instanceTemplateName = instanceTemplateName.substring(instanceTemplateName.lastIndexOf('/') + 1);
try {
GoogleProviderUtils.waitOnGlobalOperation(compute, project, compute.instanceTemplates().delete(project, instanceTemplateName).execute());
} catch (IOException e) {
throw new HalException(FATAL, "Failed to delete template " + instanceTemplateName + " in " + zone, e);
}
}
use of com.netflix.spinnaker.halyard.core.error.v1.HalException in project halyard by spinnaker.
the class GoogleDistributedService method getRunningServiceDetails.
@Override
default RunningServiceDetails getRunningServiceDetails(AccountDeploymentDetails<GoogleAccount> details, SpinnakerRuntimeSettings runtimeSettings) {
ServiceSettings settings = runtimeSettings.getServiceSettings(getService());
RunningServiceDetails result = new RunningServiceDetails();
// All GCE load balancing is done via consul
result.setLoadBalancer(new RunningServiceDetails.LoadBalancer().setExists(true));
Compute compute = GoogleProviderUtils.getCompute(details);
GoogleAccount account = details.getAccount();
List<InstanceGroupManager> migs;
try {
migs = compute.instanceGroupManagers().list(account.getProject(), settings.getLocation()).execute().getItems();
if (migs == null) {
migs = Collections.emptyList();
}
} catch (IOException e) {
throw new HalException(FATAL, "Failed to load MIGS: " + e.getMessage(), e);
}
boolean consulEnabled = getSidecars(runtimeSettings).stream().anyMatch(s -> s.getService().getType().equals(SpinnakerService.Type.CONSUL_CLIENT));
Set<String> healthyConsulInstances = consulEnabled ? getConsulServerService().connectToPrimaryService(details, runtimeSettings).serviceHealth(getService().getCanonicalName(), true).stream().map(s -> s != null && s.getNode() != null ? s.getNode().getNodeName() : null).filter(Objects::nonNull).collect(Collectors.toSet()) : new HashSet<>();
String serviceName = getService().getServiceName();
migs = migs.stream().filter(ig -> ig.getName().startsWith(serviceName + "-v")).collect(Collectors.toList());
Map<Integer, List<RunningServiceDetails.Instance>> instances = migs.stream().reduce(new HashMap<>(), (map, mig) -> {
Names names = Names.parseName(mig.getName());
Integer version = names.getSequence();
List<RunningServiceDetails.Instance> computeInstances;
try {
List<ManagedInstance> managedInstances = compute.instanceGroupManagers().listManagedInstances(account.getProject(), settings.getLocation(), mig.getName()).execute().getManagedInstances();
if (managedInstances == null) {
managedInstances = new ArrayList<>();
}
computeInstances = managedInstances.stream().map(i -> {
String instanceUrl = i.getInstance();
String instanceStatus = i.getInstanceStatus();
boolean running = instanceStatus != null && instanceStatus.equalsIgnoreCase("running");
String instanceName = instanceUrl.substring(instanceUrl.lastIndexOf('/') + 1, instanceUrl.length());
return new RunningServiceDetails.Instance().setId(instanceName).setLocation(settings.getLocation()).setRunning(running).setHealthy(!consulEnabled || healthyConsulInstances.contains(instanceName));
}).collect(Collectors.toList());
} catch (IOException e) {
throw new HalException(FATAL, "Failed to load target pools for " + serviceName, e);
}
map.put(version, computeInstances);
return map;
}, (m1, m2) -> {
m1.putAll(m2);
return m1;
});
result.setInstances(instances);
return result;
}
Aggregations