# HG changeset patch # User Andriy Petrus # Date 1376077512 14400 # Node ID 7012500bb995f458de9c95511fbe8b28589f5f1f # Parent 69692e087b1358bd3b86fa39537c6eb76d3b5dd8 Add support for deleting of data for all agents Reviewed-by: omajid Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2013-August/007775.html diff -r 69692e087b13 -r 7012500bb995 client/cli/src/main/java/com/redhat/thermostat/client/cli/internal/Activator.java --- a/client/cli/src/main/java/com/redhat/thermostat/client/cli/internal/Activator.java Wed Aug 14 13:11:11 2013 -0400 +++ b/client/cli/src/main/java/com/redhat/thermostat/client/cli/internal/Activator.java Fri Aug 09 15:45:12 2013 -0400 @@ -56,7 +56,7 @@ reg.registerCommand("vm-stat", new VMStatCommand()); reg.registerCommand("disconnect", new DisconnectCommand()); reg.registerCommand("connect", new ConnectCommand()); - reg.registerCommand("clean-history", new CleanHistoryCommand(context)); + reg.registerCommand("clean-data", new CleanDataCommand(context)); } @Override diff -r 69692e087b13 -r 7012500bb995 client/cli/src/main/java/com/redhat/thermostat/client/cli/internal/CleanDataCommand.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/cli/src/main/java/com/redhat/thermostat/client/cli/internal/CleanDataCommand.java Fri Aug 09 15:45:12 2013 -0400 @@ -0,0 +1,200 @@ +/* + * Copyright 2013 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * . + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.client.cli.internal; + +import java.io.PrintStream; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceReference; + +import com.redhat.thermostat.common.cli.AbstractCommand; +import com.redhat.thermostat.common.cli.Arguments; +import com.redhat.thermostat.common.cli.CommandContext; +import com.redhat.thermostat.common.cli.CommandException; +import com.redhat.thermostat.common.utils.LoggingUtils; +import com.redhat.thermostat.shared.locale.Translate; +import com.redhat.thermostat.storage.core.Categories; +import com.redhat.thermostat.storage.core.Category; +import com.redhat.thermostat.storage.core.Cursor; +import com.redhat.thermostat.storage.core.DescriptorParsingException; +import com.redhat.thermostat.storage.core.HostRef; +import com.redhat.thermostat.storage.core.PreparedStatement; +import com.redhat.thermostat.storage.core.StatementDescriptor; +import com.redhat.thermostat.storage.core.StatementExecutionException; +import com.redhat.thermostat.storage.core.Storage; +import com.redhat.thermostat.storage.dao.AgentInfoDAO; +import com.redhat.thermostat.storage.model.AgentInformation; +import com.redhat.thermostat.storage.model.BasePojo; + +public class CleanDataCommand extends AbstractCommand { + + private static final Translate translator = LocaleResources.createLocalizer(); + private static final Logger logger = LoggingUtils.getLogger(CleanDataCommand.class); + private BundleContext bundleContext; + private boolean removeLiveAgent = false; + + CleanDataCommand (BundleContext bundleContext) { + this.bundleContext = bundleContext; + } + + @Override + public void run(CommandContext ctx) throws CommandException { + ServiceReference storageServiceRef = bundleContext.getServiceReference(Storage.class); + if (storageServiceRef == null) { + throw new CommandException(translator.localize(LocaleResources.STORAGE_UNAVAILABLE)); + } + Storage storage = (Storage) bundleContext.getService(storageServiceRef); + + try { + Arguments args = ctx.getArguments(); + List agentIdList = args.getNonOptionArguments(); + removeLiveAgent = args.hasArgument(CleanOptions.ALIVE.option); + PrintStream output = ctx.getConsole().getOutput(); + + if (args.hasArgument(CleanOptions.ALL.option)) { + removeDataForAllAgents(storage, output); + } else { + removeDataForSpecifiedAgents(storage, agentIdList, output); + } + } finally { + bundleContext.ungetService(storageServiceRef); + } + } + + public void removeDataForSpecifiedAgents(Storage storage, List agentIdList, PrintStream output) throws CommandException { + ServiceReference agentServiceRef = bundleContext.getServiceReference(AgentInfoDAO.class); + if (agentServiceRef == null) { + throw new CommandException(translator.localize(LocaleResources.AGENT_UNAVAILABLE)); + } + AgentInfoDAO agentInfoDAO = (AgentInfoDAO) bundleContext.getService(agentServiceRef); + + try { + Set storedAgentIdList = getAllRegisteredAgents(storage); + + for (String agentId : agentIdList) { + AgentInformation agentInfo = agentInfoDAO.getAgentInformation(new HostRef(agentId, agentId)); + if (agentInfo != null) { + removeAgentDataIfSane(storage, agentId, !agentInfo.isAlive(), output); + } else if (storedAgentIdList.contains(agentId)) { + removeAgentDataIfSane(storage, agentId, true, output); + } else { + output.println(translator.localize(LocaleResources.AGENT_NOT_FOUND, agentId).getContents()); + } + } + } finally { + bundleContext.ungetService(agentServiceRef); + } + } + + public void removeDataForAllAgents(Storage storage, PrintStream output) throws CommandException { + ServiceReference agentServiceRef = bundleContext.getServiceReference(AgentInfoDAO.class); + if (agentServiceRef == null) { + throw new CommandException(translator.localize(LocaleResources.AGENT_UNAVAILABLE)); + } + AgentInfoDAO agentInfoDAO = (AgentInfoDAO) bundleContext.getService(agentServiceRef); + + try { + Set storedAgentIdList = getAllRegisteredAgents(storage); + List aliveAgentsId = new ArrayList(); + List allAliveAgentsInfo = agentInfoDAO.getAliveAgents(); + for (AgentInformation aliveAgent : allAliveAgentsInfo) { + aliveAgentsId.add(aliveAgent.getAgentId()); + } + + for (String agentId : storedAgentIdList) { + boolean isDead = !aliveAgentsId.contains(agentId); + removeAgentDataIfSane(storage, agentId, isDead, output); + } + } finally { + bundleContext.ungetService(agentServiceRef); + } + } + + private void removeAgentDataIfSane(Storage storage, String agentId, boolean isDead, PrintStream output) { + if (isDead || removeLiveAgent) { + output.println(translator.localize(LocaleResources.PURGING_AGENT_DATA).getContents() + agentId); + storage.purge(agentId); + } else { + output.println(translator.localize(LocaleResources.CANNOT_PURGE_AGENT_RUNNING, agentId).getContents()); + } + } + + private enum CleanOptions { + ALL("all"), + + ALIVE("alive"); + + private String option; + + CleanOptions(String option) { + this.option = option; + } + } + + private Set getAllRegisteredAgents(Storage storage) { + List categories = Categories.getAllCategories(); + Set agents = new HashSet<>(); + PreparedStatement prepared = null; + Cursor agentCursor = null; + for (Category category : categories) { + String query = "QUERY " + category.getName(); + StatementDescriptor desc = new StatementDescriptor<>(category, query); + try { + prepared = storage.prepareStatement(desc); + agentCursor = prepared.executeQuery(); + } catch (DescriptorParsingException e) { + logger.log(Level.SEVERE, "Preparing query '" + desc + "' failed!", e); + return Collections.emptySet(); + } catch (StatementExecutionException e) { + logger.log(Level.SEVERE, "Executing query '" + desc + "' failed!", e); + return Collections.emptySet(); + } + while (agentCursor.hasNext()) { + agents.add(agentCursor.next().getAgentId()); + } + } + return agents; + } + +} diff -r 69692e087b13 -r 7012500bb995 client/cli/src/main/java/com/redhat/thermostat/client/cli/internal/CleanHistoryCommand.java --- a/client/cli/src/main/java/com/redhat/thermostat/client/cli/internal/CleanHistoryCommand.java Wed Aug 14 13:11:11 2013 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,110 +0,0 @@ -/* - * Copyright 2013 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2, or (at your - * option) any later version. - * - * Thermostat is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Thermostat; see the file COPYING. If not see - * . - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.client.cli.internal; - -import java.io.PrintStream; -import java.util.List; - -import org.osgi.framework.BundleContext; -import org.osgi.framework.ServiceReference; - -import com.redhat.thermostat.common.cli.AbstractCommand; -import com.redhat.thermostat.common.cli.CommandContext; -import com.redhat.thermostat.common.cli.CommandException; -import com.redhat.thermostat.shared.locale.Translate; -import com.redhat.thermostat.storage.core.HostRef; -import com.redhat.thermostat.storage.core.Storage; -import com.redhat.thermostat.storage.dao.AgentInfoDAO; -import com.redhat.thermostat.storage.model.AgentInformation; - -public class CleanHistoryCommand extends AbstractCommand { - - private static final Translate translator = LocaleResources.createLocalizer(); - private BundleContext bundleContext; - - CleanHistoryCommand (BundleContext bundleContext) { - this.bundleContext = bundleContext; - } - - @Override - public void run(CommandContext ctx) throws CommandException { - ServiceReference storageServiceRef = bundleContext.getServiceReference(Storage.class); - if (storageServiceRef == null) { - throw new CommandException(translator.localize(LocaleResources.STORAGE_UNAVAILABLE)); - } - Storage storage = (Storage) bundleContext.getService(storageServiceRef); - - try { - List agentIdList = ctx.getArguments().getNonOptionArguments(); - PrintStream output = ctx.getConsole().getOutput(); - removeDataForSpecifiedAgents(storage, agentIdList, output); - } finally { - bundleContext.ungetService(storageServiceRef); - } - } - - public void removeDataForSpecifiedAgents(Storage storage, List agentIdList, PrintStream output) throws CommandException { - ServiceReference agentServiceRef = bundleContext.getServiceReference(AgentInfoDAO.class); - if (agentServiceRef == null) { - throw new CommandException(translator.localize(LocaleResources.AGENT_UNAVAILABLE)); - } - AgentInfoDAO agentInfoDAO = (AgentInfoDAO) bundleContext.getService(agentServiceRef); - - try { - for (String agentId : agentIdList) { - AgentInformation agentInfo = agentInfoDAO.getAgentInformation(new HostRef(agentId, agentId)); - if (agentInfo != null) { - removeDataIfAgentDead(storage, agentId, agentInfo, output); - } else { - output.println(translator.localize(LocaleResources.AGENT_NOT_FOUND, agentId).getContents()); - } - } - } finally { - bundleContext.ungetService(agentServiceRef); - } - } - - private void removeDataIfAgentDead(Storage storage, String agentId, AgentInformation agentInfo, PrintStream output) { - if (!agentInfo.isAlive()) { - output.println(translator.localize(LocaleResources.PURGING_AGENT_DATA).getContents() + agentId); - storage.purge(agentId); - } else { - output.println(translator.localize(LocaleResources.CANNOT_PURGE_AGENT_RUNNING, agentId).getContents()); - } - } - -} diff -r 69692e087b13 -r 7012500bb995 client/cli/src/main/resources/com/redhat/thermostat/client/cli/strings.properties --- a/client/cli/src/main/resources/com/redhat/thermostat/client/cli/strings.properties Wed Aug 14 13:11:11 2013 -0400 +++ b/client/cli/src/main/resources/com/redhat/thermostat/client/cli/strings.properties Fri Aug 09 15:45:12 2013 -0400 @@ -49,4 +49,4 @@ STORAGE_UNAVAILABLE = Storage is unavailable AGENT_UNAVAILABLE = Agent is unavailable CANNOT_PURGE_AGENT_RUNNING = Cannot purge data for agent {0}. This agent is currently running -AGENT_NOT_FOUND = Agent with an id {0} was not found! +AGENT_NOT_FOUND = Agent with an id [{0}] was not found! diff -r 69692e087b13 -r 7012500bb995 client/cli/src/test/java/com/redhat/thermostat/client/cli/internal/CleanDataCommandTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/cli/src/test/java/com/redhat/thermostat/client/cli/internal/CleanDataCommandTest.java Fri Aug 09 15:45:12 2013 -0400 @@ -0,0 +1,265 @@ +/* + * Copyright 2013 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * . + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.client.cli.internal; + +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.isA; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import static org.mockito.Mockito.times; + +import java.io.PrintStream; +import java.util.ArrayList; +import java.util.List; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +import com.redhat.thermostat.common.cli.Arguments; +import com.redhat.thermostat.common.cli.CommandContext; +import com.redhat.thermostat.common.cli.CommandException; +import com.redhat.thermostat.common.cli.Console; +import com.redhat.thermostat.storage.core.Cursor; +import com.redhat.thermostat.storage.core.DescriptorParsingException; +import com.redhat.thermostat.storage.core.HostRef; +import com.redhat.thermostat.storage.core.PreparedStatement; +import com.redhat.thermostat.storage.core.StatementDescriptor; +import com.redhat.thermostat.storage.core.StatementExecutionException; +import com.redhat.thermostat.storage.core.Storage; +import com.redhat.thermostat.storage.dao.AgentInfoDAO; +import com.redhat.thermostat.storage.model.AgentInformation; +import com.redhat.thermostat.storage.model.BasePojo; +import com.redhat.thermostat.testutils.StubBundleContext; + +import org.powermock.api.mockito.PowerMockito; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; + +@RunWith(PowerMockRunner.class) +@PrepareForTest(AgentInformation.class) +public class CleanDataCommandTest { + + private CleanDataCommand cleanDataCommand; + private CommandContext mockCommandContext; + private Storage mockStorage; + private PrintStream mockOutput; + private AgentInfoDAO mockAgentInfoDAO; + private Arguments mockArguments; + + @Before + public void setUp() throws DescriptorParsingException, StatementExecutionException { + StubBundleContext bundleContext = new StubBundleContext(); + cleanDataCommand = new CleanDataCommand(bundleContext); + + mockStorage = mock(Storage.class); + bundleContext.registerService(Storage.class, mockStorage, null); + mockAgentInfoDAO = mock(AgentInfoDAO.class); + bundleContext.registerService(AgentInfoDAO.class, mockAgentInfoDAO, null); + + mockCommandContext = mock(CommandContext.class); + mockArguments = mock(Arguments.class); + + when(mockCommandContext.getArguments()).thenReturn(mockArguments); + when(mockArguments.getNonOptionArguments()).thenReturn(getValidAgentList()); + + Console mockConsole = mock(Console.class); + mockOutput = mock(PrintStream.class); + when(mockCommandContext.getConsole()).thenReturn(mockConsole); + when(mockConsole.getOutput()).thenReturn(mockOutput); + + List liveAgentInfoList = new ArrayList(); + AgentInformation mockAgent1 = PowerMockito.mock(AgentInformation.class); + AgentInformation mockAgent2 = PowerMockito.mock(AgentInformation.class); + AgentInformation mockAgent3 = PowerMockito.mock(AgentInformation.class); + AgentInformation mockAgent4 = PowerMockito.mock(AgentInformation.class); + AgentInformation mockAgent5 = PowerMockito.mock(AgentInformation.class); + when(mockAgent1.getAgentId()).thenReturn("agentId1"); + when(mockAgent2.getAgentId()).thenReturn("agentId2"); + when(mockAgent3.getAgentId()).thenReturn("agentId3"); + when(mockAgent4.getAgentId()).thenReturn("agentId4"); + when(mockAgent5.getAgentId()).thenReturn("agentId5"); + when(mockAgent4.isAlive()).thenReturn(true); + when(mockAgent5.isAlive()).thenReturn(true); + + liveAgentInfoList.add(mockAgent4); + liveAgentInfoList.add(mockAgent5); + when(mockAgentInfoDAO.getAliveAgents()).thenReturn(liveAgentInfoList); + when(mockAgentInfoDAO.getAgentInformation(new HostRef("agentId1", "agentId1"))).thenReturn(mockAgent1); + when(mockAgentInfoDAO.getAgentInformation(new HostRef("agentId2", "agentId2"))).thenReturn(mockAgent2); + when(mockAgentInfoDAO.getAgentInformation(new HostRef("agentId3", "agentId3"))).thenReturn(mockAgent3); + when(mockAgentInfoDAO.getAgentInformation(new HostRef("agentId4", "agentId4"))).thenReturn(mockAgent4); + when(mockAgentInfoDAO.getAgentInformation(new HostRef("agentId5", "agentId5"))).thenReturn(mockAgent5); + + Cursor agentCursor = (Cursor) mock(Cursor.class); + when(agentCursor.hasNext()).thenReturn(true).thenReturn(true).thenReturn(true).thenReturn(true).thenReturn(true).thenReturn(false); + when(agentCursor.next()).thenReturn(mockAgent1).thenReturn(mockAgent2).thenReturn(mockAgent3).thenReturn(mockAgent4).thenReturn(mockAgent5).thenReturn(null); + + PreparedStatement prepared = (PreparedStatement) mock(PreparedStatement.class); + when(mockStorage.prepareStatement((StatementDescriptor) any(StatementDescriptor.class))).thenReturn(prepared); + when(prepared.executeQuery()).thenReturn(agentCursor); + } + + @Test + public void testOneValidArgument() throws CommandException { + when(mockArguments.getNonOptionArguments()).thenReturn(getOneValidAgent()); + + cleanDataCommand.run(mockCommandContext); + + verify(mockStorage, times(1)).purge(isA(String.class)); + verify(mockStorage).purge("agentId1"); + + verify(mockOutput, times(1)).println(isA(String.class)); + verify(mockOutput).println("Purging data for agent: agentId1"); + } + + @Test + public void testMultipleValidArguments() throws CommandException { + cleanDataCommand.run(mockCommandContext); + + verify(mockStorage, times(3)).purge(isA(String.class)); + verify(mockStorage).purge("agentId1"); + verify(mockStorage).purge("agentId2"); + verify(mockStorage).purge("agentId3"); + + verify(mockOutput, times(3)).println(isA(String.class)); + verify(mockOutput).println("Purging data for agent: agentId1"); + verify(mockOutput).println("Purging data for agent: agentId2"); + verify(mockOutput).println("Purging data for agent: agentId3"); + } + + @Test + public void testUnauthorizedLiveAgents() throws CommandException { + when(mockArguments.getNonOptionArguments()).thenReturn(getAliveAgents()); + + cleanDataCommand.run(mockCommandContext); + + verify(mockStorage, never()).purge(isA(String.class)); + + verify(mockOutput, times(2)).println(isA(String.class)); + verify(mockOutput).println("Cannot purge data for agent agentId4. This agent is currently running"); + verify(mockOutput).println("Cannot purge data for agent agentId5. This agent is currently running"); + } + + @Test + public void testRemoveSpecificLiveAgents() throws CommandException { + when(mockArguments.hasArgument("alive")).thenReturn(true); + when(mockArguments.getNonOptionArguments()).thenReturn(getAliveAgents()); + + cleanDataCommand.run(mockCommandContext); + + verify(mockStorage, times(2)).purge(isA(String.class)); + verify(mockStorage).purge("agentId4"); + verify(mockStorage).purge("agentId5"); + + verify(mockOutput, times(2)).println(isA(String.class)); + verify(mockOutput).println("Purging data for agent: agentId4"); + verify(mockOutput).println("Purging data for agent: agentId5"); + } + + @Test + public void testInvalidArguments() throws CommandException { + when(mockArguments.getNonOptionArguments()).thenReturn(getInvalidAgentList()); + + cleanDataCommand.run(mockCommandContext); + + verify(mockStorage, never()).purge(isA(String.class)); + verify(mockOutput, times(3)).println(isA(String.class)); + verify(mockOutput).println("Agent with an id [invalidAgent1] was not found!"); + verify(mockOutput).println("Agent with an id [invalidAgent2] was not found!"); + verify(mockOutput).println("Agent with an id [invalidAgent3] was not found!"); + } + + @Test + public void testRemoveAllDeadAgents() throws CommandException { + when(mockArguments.hasArgument("all")).thenReturn(true); + + cleanDataCommand.run(mockCommandContext); + + verify(mockStorage, times(3)).purge(isA(String.class)); + verify(mockStorage).purge("agentId1"); + verify(mockStorage).purge("agentId2"); + verify(mockStorage).purge("agentId3"); + } + + @Test + public void testRemoveAllLiveAgents() throws CommandException { + when(mockArguments.hasArgument("all")).thenReturn(true); + when(mockArguments.hasArgument("alive")).thenReturn(true); + + cleanDataCommand.run(mockCommandContext); + + verify(mockStorage, times(5)).purge(isA(String.class)); + verify(mockStorage).purge("agentId1"); + verify(mockStorage).purge("agentId2"); + verify(mockStorage).purge("agentId3"); + verify(mockStorage).purge("agentId4"); + verify(mockStorage).purge("agentId5"); + } + + private List getValidAgentList() { + List agentIdList = new ArrayList(); + agentIdList.add("agentId1"); + agentIdList.add("agentId2"); + agentIdList.add("agentId3"); + return agentIdList; + } + + private List getInvalidAgentList() { + List agentIdList = new ArrayList(); + agentIdList.add("invalidAgent1"); + agentIdList.add("invalidAgent2"); + agentIdList.add("invalidAgent3"); + return agentIdList; + } + + private List getOneValidAgent() { + List agentIdList = new ArrayList(); + agentIdList.add("agentId1"); + return agentIdList; + } + + private List getAliveAgents() { + List agentIdList = new ArrayList(); + agentIdList.add("agentId4"); + agentIdList.add("agentId5"); + return agentIdList; + } + +} diff -r 69692e087b13 -r 7012500bb995 client/cli/src/test/java/com/redhat/thermostat/client/cli/internal/CleanHistoryCommandTest.java --- a/client/cli/src/test/java/com/redhat/thermostat/client/cli/internal/CleanHistoryCommandTest.java Wed Aug 14 13:11:11 2013 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,197 +0,0 @@ -/* - * Copyright 2013 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2, or (at your - * option) any later version. - * - * Thermostat is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Thermostat; see the file COPYING. If not see - * . - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.client.cli.internal; - -import static org.mockito.Matchers.isA; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; -import static org.mockito.Mockito.times; - -import java.io.PrintStream; -import java.util.ArrayList; -import java.util.List; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; - -import com.redhat.thermostat.common.cli.Arguments; -import com.redhat.thermostat.common.cli.CommandContext; -import com.redhat.thermostat.common.cli.CommandException; -import com.redhat.thermostat.common.cli.Console; -import com.redhat.thermostat.storage.core.HostRef; -import com.redhat.thermostat.storage.core.Storage; -import com.redhat.thermostat.storage.dao.AgentInfoDAO; -import com.redhat.thermostat.storage.model.AgentInformation; -import com.redhat.thermostat.testutils.StubBundleContext; - -import org.powermock.api.mockito.PowerMockito; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; - -@RunWith(PowerMockRunner.class) -@PrepareForTest(AgentInformation.class) -public class CleanHistoryCommandTest { - - private CleanHistoryCommand cleanHistoryCommand; - private CommandContext mockCommandContext; - private List agentIdList; - private Storage mockStorage; - private PrintStream mockOutput; - private AgentInfoDAO mockAgentInfoDAO; - - @Before - public void setUp() { - StubBundleContext bundleContext = new StubBundleContext(); - cleanHistoryCommand = new CleanHistoryCommand(bundleContext); - - mockStorage = mock(Storage.class); - bundleContext.registerService(Storage.class, mockStorage, null); - mockAgentInfoDAO = mock(AgentInfoDAO.class); - bundleContext.registerService(AgentInfoDAO.class, mockAgentInfoDAO, null); - - mockCommandContext = mock(CommandContext.class); - Arguments mockArguments = mock(Arguments.class); - - when(mockCommandContext.getArguments()).thenReturn(mockArguments); - when(mockArguments.getNonOptionArguments()).thenReturn(getArgumentList()); - - Console mockConsole = mock(Console.class); - mockOutput = mock(PrintStream.class); - when(mockCommandContext.getConsole()).thenReturn(mockConsole); - when(mockConsole.getOutput()).thenReturn(mockOutput); - } - - @Test - public void testOneValidArgument() throws CommandException { - AgentInformation mockAgent = PowerMockito.mock(AgentInformation.class); - when(mockAgent.getAgentId()).thenReturn("agentId1"); - when(mockAgent.isAlive()).thenReturn(false); - - when(mockAgentInfoDAO.getAgentInformation(new HostRef("agentId1", "agentId1"))).thenReturn((mockAgent)); - - cleanHistoryCommand.run(mockCommandContext); - - verify(mockStorage, times(1)).purge(isA(String.class)); - verify(mockStorage).purge("agentId1"); - verify(mockOutput).println("Purging data for agent: agentId1"); - } - - @Test - public void testMultipleValidArguments() throws CommandException { - AgentInformation mockAgent1 = PowerMockito.mock(AgentInformation.class); - AgentInformation mockAgent2 = PowerMockito.mock(AgentInformation.class); - AgentInformation mockAgent3 = PowerMockito.mock(AgentInformation.class); - when(mockAgent1.getAgentId()).thenReturn("agentId1"); - when(mockAgent2.getAgentId()).thenReturn("agentId2"); - when(mockAgent3.getAgentId()).thenReturn("agentId3"); - - when(mockAgentInfoDAO.getAgentInformation(new HostRef("agentId1", "agentId1"))).thenReturn((mockAgent1)); - when(mockAgentInfoDAO.getAgentInformation(new HostRef("agentId2", "agentId2"))).thenReturn((mockAgent2)); - when(mockAgentInfoDAO.getAgentInformation(new HostRef("agentId3", "agentId3"))).thenReturn((mockAgent3)); - - cleanHistoryCommand.run(mockCommandContext); - - verify(mockStorage, times(3)).purge(isA(String.class)); - verify(mockStorage).purge("agentId1"); - verify(mockStorage).purge("agentId2"); - verify(mockStorage).purge("agentId3"); - - verify(mockOutput, times(3)).println(isA(String.class)); - verify(mockOutput).println("Purging data for agent: agentId1"); - verify(mockOutput).println("Purging data for agent: agentId2"); - verify(mockOutput).println("Purging data for agent: agentId3"); - } - - @Test - public void testLiveAgents() throws CommandException { - AgentInformation mockAgent1 = PowerMockito.mock(AgentInformation.class); - AgentInformation mockAgent2 = PowerMockito.mock(AgentInformation.class); - AgentInformation mockAgent3 = PowerMockito.mock(AgentInformation.class); - when(mockAgent1.getAgentId()).thenReturn("agentId1"); - when(mockAgent2.getAgentId()).thenReturn("agentId2"); - when(mockAgent3.getAgentId()).thenReturn("agentId3"); - when(mockAgent1.isAlive()).thenReturn(true); - when(mockAgent2.isAlive()).thenReturn(false); - when(mockAgent3.isAlive()).thenReturn(true); - - when(mockAgentInfoDAO.getAgentInformation(new HostRef("agentId1", "agentId1"))).thenReturn((mockAgent1)); - when(mockAgentInfoDAO.getAgentInformation(new HostRef("agentId2", "agentId2"))).thenReturn((mockAgent2)); - when(mockAgentInfoDAO.getAgentInformation(new HostRef("agentId3", "agentId3"))).thenReturn((mockAgent3)); - - cleanHistoryCommand.run(mockCommandContext); - - verify(mockStorage, times(1)).purge(isA(String.class)); - verify(mockStorage, times(1)).purge("agentId2"); - - verify(mockOutput, times(3)).println(isA(String.class)); - verify(mockOutput).println("Cannot purge data for agent agentId1. This agent is currently running"); - verify(mockOutput).println("Purging data for agent: agentId2"); - verify(mockOutput).println("Cannot purge data for agent agentId3. This agent is currently running"); - } - - @Test - public void testInvalidArguments() throws CommandException { - AgentInformation mockAgent1 = PowerMockito.mock(AgentInformation.class); - AgentInformation mockAgent2 = PowerMockito.mock(AgentInformation.class); - when(mockAgent1.getAgentId()).thenReturn("validAgent1-in-DB"); - when(mockAgent2.getAgentId()).thenReturn("validAgent2-in-DB"); - - when(mockAgentInfoDAO.getAgentInformation(new HostRef("validAgent1-in-DB", "validAgent1-in-DB"))).thenReturn((mockAgent1)); - when(mockAgentInfoDAO.getAgentInformation(new HostRef("validAgent2-in-DB", "validAgent2-in-DB"))).thenReturn((mockAgent2)); - - cleanHistoryCommand.run(mockCommandContext); - - verify(mockStorage, never()).purge(isA(String.class)); - - verify(mockOutput, times(3)).println(isA(String.class)); - verify(mockOutput).println("Agent with an id agentId1 was not found!"); - verify(mockOutput).println("Agent with an id agentId2 was not found!"); - verify(mockOutput).println("Agent with an id agentId3 was not found!"); - } - - private List getArgumentList() { - agentIdList = new ArrayList(); - agentIdList.add("agentId1"); - agentIdList.add("agentId2"); - agentIdList.add("agentId3"); - return agentIdList; - } - -} diff -r 69692e087b13 -r 7012500bb995 distribution/config/commands/clean-data.properties --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/distribution/config/commands/clean-data.properties Fri Aug 09 15:45:12 2013 -0400 @@ -0,0 +1,31 @@ +bundles = thermostat-client-cli-${project.version}.jar, \ + thermostat-storage-mongodb-${project.version}.jar, \ + thermostat-web-common-${project.version}.jar, \ + thermostat-web-client-${project.version}.jar, \ + httpcomponents-core.jar, \ + httpcomponents-client.jar, \ + gson.jar, \ + mongo.jar, \ + commons-beanutils.jar, \ + commons-codec.jar, \ + commons-collections.jar, \ + commons-logging.jar, \ + +description = Drop all data related to all of the specified agents + +usage = clean-data [--alive] [--all] + +options = alive, all, AUTO_LOG_OPTION + +all.short = a +all.long = all +all.hasarg = false +all.required = false +all.description = clean data for all agents + +alive.long = alive +alive.hasarg = false +alive.required = false +alive.description = authorize deletion of live agents + +environments = cli, shell diff -r 69692e087b13 -r 7012500bb995 distribution/config/commands/clean-history.properties --- a/distribution/config/commands/clean-history.properties Wed Aug 14 13:11:11 2013 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,21 +0,0 @@ -bundles = thermostat-client-cli-${project.version}.jar, \ - thermostat-storage-mongodb-${project.version}.jar, \ - thermostat-web-common-${project.version}.jar, \ - thermostat-web-client-${project.version}.jar, \ - httpcomponents-core.jar, \ - httpcomponents-client.jar, \ - gson.jar, \ - mongo.jar, \ - commons-beanutils.jar, \ - commons-codec.jar, \ - commons-collections.jar, \ - commons-logging.jar, \ - -description = Drop all data related to all of the specified agents - -usage = clean-history - -# This command does not have any options -options = AUTO_LOG_OPTION - -environments = cli, shell diff -r 69692e087b13 -r 7012500bb995 storage/core/src/main/java/com/redhat/thermostat/storage/core/Categories.java --- a/storage/core/src/main/java/com/redhat/thermostat/storage/core/Categories.java Wed Aug 14 13:11:11 2013 -0400 +++ b/storage/core/src/main/java/com/redhat/thermostat/storage/core/Categories.java Fri Aug 09 15:45:12 2013 -0400 @@ -36,7 +36,10 @@ package com.redhat.thermostat.storage.core; +import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; +import java.util.List; import java.util.Map; public class Categories { @@ -62,5 +65,9 @@ return namesToCategories.get(categoryName); } + public static synchronized List getAllCategories() { + return Collections.unmodifiableList(new ArrayList(namesToCategories.values())); + } + }