/*
* Copyright 2016 Fizzed, 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.fizzed.stork.deploy;
import java.io.Closeable;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.EnumMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Assembly implements Closeable {
static private final Logger log = LoggerFactory.getLogger(Assembly.class);
private final long createdAt;
private final Archive archive;
private final Path unpackedDir;
private final String name;
private final String version;
private final boolean snapshot;
private final Map<InitType,Set<Daemon>> daemons;
private final List<Closeable> resources;
public Assembly(Archive archive, Path unpackedDir, String name, String version, boolean snapshot, List<Daemon> daemons, List<Closeable> resources) {
this.createdAt = System.currentTimeMillis();
this.archive = archive;
this.unpackedDir = unpackedDir;
this.name = name;
this.version = version;
this.snapshot = snapshot;
this.daemons = new EnumMap<>(InitType.class);
this.resources = resources;
// create set of daemons by init type
daemons.stream().forEach((d) -> {
Set<Daemon> s = this.daemons.get(d.getInitType());
if (s == null) {
s = new LinkedHashSet<>();
this.daemons.put(d.getInitType(), s);
}
s.add(d);
});
}
public long getCreatedAt() {
return createdAt;
}
public Archive getArchive() {
return this.archive;
}
public Path getArchiveFile() {
return this.archive.getFile();
}
public Path getUnpackedDir() {
return unpackedDir;
}
public String getName() {
return name;
}
public String getVersion() {
return version;
}
public boolean isSnapshot() {
return snapshot;
}
public boolean hasDirectory(String dir) {
return Files.exists(unpackedDir.resolve(dir));
}
public boolean hasDaemons() {
return !daemons.isEmpty();
}
public boolean hasDaemons(InitType initType) {
Set<Daemon> set = getDaemons(initType);
if (set == null || set.isEmpty()) {
return false;
}
return true;
}
public Map<InitType, Set<Daemon>> getDaemons() {
return daemons;
}
public Set<Daemon> getDaemons(InitType initType) {
// UPSTART -> SYSV
if (initType == InitType.UPSTART) {
initType = InitType.SYSV;
}
return daemons.get(initType);
}
public void verify() throws DeployerException {
verifyDaemons();
}
private void verifyDaemons() throws DeployerException {
// are there any daemons?
if (this.daemons.isEmpty()) {
return;
}
InitType refInitType = null;
Set<Daemon> refDaemons = null;
for (InitType initType : this.daemons.keySet()) {
if (refDaemons == null) {
refInitType = initType;
refDaemons = this.daemons.get(initType);
} else {
Set<Daemon> verifyDaemons = this.daemons.get(initType);
if (verifyDaemons.size() != refDaemons.size()) {
throw new DeployerException(
"Size mismatch between supported daemon init types: "
+ refDaemons.size() + " " + refInitType + " daemons; "
+ verifyDaemons.size() + " " + initType + " daemons!");
}
for (Daemon d : refDaemons) {
if (!verifyDaemons.contains(new Daemon(initType, d.getName(), null, null))) {
throw new DeployerException(
"Daemon missing: "
+ "a " + refInitType + " daemon named " + d.getName() + " exists but is missing for init type " + initType);
}
}
}
}
}
@Override
public String toString() {
if (snapshot) {
return name + " v" + version + " (snapshot)";
} else {
return name + " v" + version;
}
}
@Override
public void close() throws IOException {
// delete the unpacked dir and any other resources
try {
DeployHelper.deleteRecursively(this.unpackedDir);
} catch (IOException e) {
log.warn("Unable to cleanup assembly: " + e.getMessage());
}
if (this.resources != null) {
for (Closeable resource : resources) {
try {
resource.close();
} catch (IOException e) {
log.warn("Unable to cleanup assembly resources: " + e.getMessage());
}
}
}
}
}