package alien4cloud.configuration; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Collections; import java.util.List; import java.util.Set; import javax.annotation.PostConstruct; import javax.inject.Inject; import org.alien4cloud.tosca.catalog.ArchiveUploadService; import org.springframework.beans.factory.annotation.Value; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.context.SecurityContextImpl; import org.springframework.stereotype.Component; import com.google.common.collect.Sets; import alien4cloud.common.AlienConstants; import alien4cloud.component.repository.exception.CSARUsedInActiveDeployment; import alien4cloud.component.repository.exception.ToscaTypeAlreadyDefinedInOtherCSAR; import alien4cloud.exception.AlreadyExistException; import alien4cloud.model.components.CSARSource; import alien4cloud.plugin.PluginManager; import alien4cloud.plugin.exception.MissingPlugingDescriptorFileException; import alien4cloud.plugin.exception.PluginLoadingException; import alien4cloud.security.model.Role; import alien4cloud.tosca.context.ToscaContextInjector; import alien4cloud.tosca.parser.ParsingException; import alien4cloud.utils.FileUtil; import lombok.extern.slf4j.Slf4j; /** Load archives and plugins at bootstrap to initialize alien 4 cloud repository. */ @Slf4j @Component public class InitialLoader { private static final String ARCHIVES_FOLDER = "archives"; private static final String PLUGINS_FOLDER = "plugins"; @Inject private ArchiveUploadService csarUploadService; @Inject private PluginManager pluginManager; @Inject private ToscaContextInjector toscaContextInjector; @Value("${directories.alien_init:}") private String alienInitDirectory; private Path alienPluginsInitPath; @PostConstruct public void initialLoad() throws IOException { // Ensure tosca context injector is loaded first. if (toscaContextInjector == null) { log.error("Tosca Context Injector is required."); } // Components if (alienInitDirectory == null || alienInitDirectory.isEmpty()) { log.debug("No init directory is configured - skipping initial loading of archives and plugins."); return; } Path alienInitDirectoryPath = Paths.get(alienInitDirectory); if (!Files.exists(alienInitDirectoryPath)) { log.warn("Specified initial directory <{}> cannot be found - skipping initial loading of archives and plugins.", alienInitDirectoryPath.toString()); return; } Path alienArchivesInitPath = alienInitDirectoryPath.resolve(ARCHIVES_FOLDER); loadArchives(alienArchivesInitPath); alienPluginsInitPath = alienInitDirectoryPath.resolve(PLUGINS_FOLDER); } private void loadArchives(Path rootDirectory) { if (!Files.exists(rootDirectory) || !Files.isDirectory(rootDirectory)) { log.warn("Skipping archives' initial loading: directory cannot be found {}.", rootDirectory.toString()); return; } // this operation is performed using admin role SecurityContextImpl adminContext = new SecurityContextImpl(); Set<SimpleGrantedAuthority> authorities = Sets.newHashSet(); authorities.add(new SimpleGrantedAuthority(Role.ADMIN.name())); UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken("alien4cloud_init_loader", "alien4cloud_init_loader", authorities); adminContext.setAuthentication(auth); SecurityContextHolder.setContext(adminContext); // archives must be in zip format and placed in the actual folder try { List<Path> archives = FileUtil.listFiles(rootDirectory, ".+\\.(zip|csar)"); Collections.sort(archives); for (Path archive : archives) { try { log.debug("Initial load of archives from <{}>.", archive.toString()); csarUploadService.upload(archive, CSARSource.ALIEN, AlienConstants.GLOBAL_WORKSPACE_ID); } catch (AlreadyExistException e) { log.debug("Skipping initial upload of archive <{}>. Archive has already been loaded.", archive.toString(), e); } catch (CSARUsedInActiveDeployment e) { log.debug("Skipping initial upload of archive <{}>. Archive is used in an active depoyment, and then cannot be overrided.", archive.toString(), e); } catch (ParsingException e) { log.error("Initial upload of archive <{}> has failed.", archive.toString(), e); } catch (ToscaTypeAlreadyDefinedInOtherCSAR e) { log.debug("Skipping initial upload of archive <{}>, it's archive contain's a tosca type already defined in an other archive." + e.getMessage(), archive.toString(), e); } } } catch (IOException e) { log.error("Failed to load initial archives", e); } finally { // clear the security context SecurityContextHolder.clearContext(); } } /** * Load plugins from the initialization plugins folder. */ public void loadPlugins() { if (alienInitDirectory == null || alienInitDirectory.isEmpty() || alienPluginsInitPath == null) { log.debug("No init directory is configured - skipping initial loading of plugins."); return; } if (!Files.exists(alienPluginsInitPath) || !Files.isDirectory(alienPluginsInitPath)) { log.warn("Skipping plugins' initial loading: directory cannot be found {}.", alienPluginsInitPath.toString()); return; } try { List<Path> plugins = FileUtil.listFiles(alienPluginsInitPath, ".+\\.(zip)"); for (Path plugin : plugins) { try { pluginManager.uploadPlugin(plugin); } catch (AlreadyExistException e) { log.debug("Plugin {} has already been uploaded.", plugin.toString()); } catch (PluginLoadingException | MissingPlugingDescriptorFileException e) { log.error("Failed to load plugin from init folder. File {}", plugin.toString(), e); } } } catch (IOException e) { log.error("Failed to load initial archives", e); } } }