View Javadoc
1   /*
2    * Copyright (c) 2002-2017, Mairie de Paris
3    * All rights reserved.
4    *
5    * Redistribution and use in source and binary forms, with or without
6    * modification, are permitted provided that the following conditions
7    * are met:
8    *
9    *  1. Redistributions of source code must retain the above copyright notice
10   *     and the following disclaimer.
11   *
12   *  2. Redistributions in binary form must reproduce the above copyright notice
13   *     and the following disclaimer in the documentation and/or other materials
14   *     provided with the distribution.
15   *
16   *  3. Neither the name of 'Mairie de Paris' nor 'Lutece' nor the names of its
17   *     contributors may be used to endorse or promote products derived from
18   *     this software without specific prior written permission.
19   *
20   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23   * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
24   * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26   * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27   * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28   * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30   * POSSIBILITY OF SUCH DAMAGE.
31   *
32   * License 1.0
33   */
34  package fr.paris.lutece.plugins.appcenter.modules.fastdeployapplication.service;
35  
36  import fr.paris.lutece.plugins.appcenter.business.User;
37  import java.util.HashMap;
38  import java.util.Locale;
39  
40  import javax.inject.Inject;
41  import javax.servlet.http.HttpServletRequest;
42  
43  import org.apache.commons.lang.StringUtils;
44  
45  import fr.paris.lutece.plugins.appcenter.modules.fastdeployapplication.business.CommandResult;
46  import fr.paris.lutece.plugins.appcenter.modules.fastdeployapplication.business.FastDeployApplicationData;
47  import fr.paris.lutece.plugins.appcenter.modules.fastdeployapplication.business.ServerApplicationInstance;
48  import fr.paris.lutece.plugins.appcenter.modules.fastdeployapplication.business.context.WorkflowDeployAppContext;
49  import fr.paris.lutece.plugins.appcenter.modules.fastdeployapplication.business.context.AbstractWorkflowDeployContext;
50  import fr.paris.lutece.plugins.appcenter.modules.fastdeployapplication.business.context.WorkflowDeployScriptContext;
51  import fr.paris.lutece.plugins.appcenter.modules.fastdeployapplication.business.fastaction.IAction;
52  import fr.paris.lutece.plugins.appcenter.modules.fastdeployapplication.service.vcs.IVCSService;
53  import fr.paris.lutece.plugins.appcenter.modules.fastdeployapplication.util.ConstanteUtils;
54  import fr.paris.lutece.plugins.appcenter.modules.fastdeployapplication.util.DeploymentUtils;
55  import fr.paris.lutece.plugins.appcenter.modules.fastdeployapplication.web.exception.VCSUserNotSignedException;
56  import fr.paris.lutece.plugins.appcenter.service.UserService;
57  import fr.paris.lutece.portal.service.datastore.DatastoreService;
58  import fr.paris.lutece.portal.service.security.UserNotSignedException;
59  import fr.paris.lutece.portal.service.util.AppException;
60  import fr.paris.lutece.portal.service.util.AppLogService;
61  
62  public class WorkflowDeploySiteService implements IWorkflowDeploySiteService
63  {
64      HashMap<Integer, Object> _mapWorkflowDeploySiteContext = new HashMap( );
65  
66     
67    
68     
69     
70      public synchronized <T extends AbstractWorkflowDeployContext>  int addWorkflowDeploySiteContext( T context )
71      {
72          int nIdKey = Integer.parseInt( DatastoreService.getDataValue( ConstanteUtils.CONSTANTE_MAX_DEPLOY_SITE_CONTEXT_KEY, "0" ) ) + 1;
73          // stored key in database
74          DatastoreService.setDataValue( ConstanteUtils.CONSTANTE_MAX_DEPLOY_SITE_CONTEXT_KEY, Integer.toString( nIdKey ) );
75          context.setId( nIdKey );
76          _mapWorkflowDeploySiteContext.put( nIdKey, context );
77  
78          return nIdKey;
79      }
80  
81      public <T extends AbstractWorkflowDeployContext> T getWorkflowDeploySiteContext( int nIdContext )
82      {
83          return (T)_mapWorkflowDeploySiteContext.get( nIdContext );
84      }
85  
86      public String checkoutSite( WorkflowDeployAppContext context, Locale locale )
87      {
88          FastDeployApplicationData  data=context.getFastDeployApplicationData( );
89          IVCSService vcsService = DeploymentUtils.getVCSService( data.getRepoType( ) );
90          context.getCommandResult( ).getLog( ).append( "Starting Action Checkout  Site...\n" );
91  
92          try
93          {
94              vcsService.checkAuthentication( data.getUrlSite( ), context.getVcsUser( ) );
95          }
96          catch ( VCSUserNotSignedException e )
97          {
98              throw new AppException();
99          }
100        
101         vcsService.doCheckoutSite( data.getArtifactId( ), data.getUrlSite( ), context.getVcsUser( ), context.getCommandResult( ), null,
102                 context.getTagToDeploy( ) );
103 
104         // throw RuntimeException for stopping Workflow
105 
106         stopWorkflowIfTechnicalError( "Error Chekout Site", context.getCommandResult( ) );
107 
108         context.getCommandResult( ).getLog( ).append( "End Action Checkout   Site...\n" );
109 
110         return null;
111     }
112 
113     
114 
115     public String assemblySite( WorkflowDeployAppContext context, Locale locale )
116     {
117         FastDeployApplicationData  data=context.getFastDeployApplicationData( );
118         
119         ServerApplicationInstance serverApplicationInstance = DeploymentFactory.getInstance( ).getServerApplicationService( data.getApplicationType( ) ).getServerApplicationInstance( data, Integer.toString( context.getIdApplication( ) ),
120                 context.getCodeServerInstance( ConstanteUtils.CONSTANTE_SERVER_TOMCAT ), context.getCodeEnvironement( ),
121                 ConstanteUtils.CONSTANTE_SERVER_TOMCAT, locale, false, false );
122         context.getCommandResult( ).getLog( ).append( "Starting Action Assembly  Site...\n" );
123         MavenService.getService( ).mvnSiteAssembly( data.getArtifactId( ),
124                 serverApplicationInstance.getMavenProfile( context.getIdApplication( ) ), context.getVcsUser( ), context.getCommandResult( ) );
125         // throw RuntimeException for stopping Workflow
126         stopWorkflowIfTechnicalError( "Error During assembly Site", context.getCommandResult( ) );
127         context.getCommandResult( ).getLog( ).append( "End Action Assembly  Site...\n" );
128 
129         return null;
130     }
131 
132     public String deploySite( WorkflowDeployAppContext context, Locale locale )
133     {
134        
135         
136         FastDeployApplicationData  data=context.getFastDeployApplicationData( );
137         IFtpService ftpService=DeploymentFactory.getInstance( ).getFtpService( data.getApplicationType( ) );
138 
139         ServerApplicationInstance serverApplicationInstance = DeploymentFactory.getInstance( ).getServerApplicationService( data.getApplicationType( ) ).getServerApplicationInstance( data, Integer.toString( context.getIdApplication( ) ),
140                 context.getCodeServerInstance( ConstanteUtils.CONSTANTE_SERVER_TOMCAT ), context.getCodeEnvironement( ),
141                 ConstanteUtils.CONSTANTE_SERVER_TOMCAT, locale, false, false );
142         context.getCommandResult( ).getLog( ).append( "Starting Action Deploy  Site...\n" );
143 
144         String strWarGeneratedName = MavenService.getService( ).getSiteWarName( data.getArtifactId( ) );
145 
146         ftpService.uploadFile( data.getWebApp( ) + ConstanteUtils.ARCHIVE_WAR_EXTENSION, DeploymentUtils.getPathArchiveGenerated(
147                 DeploymentUtils.getPathCheckoutSite( data.getArtifactId( ) ), strWarGeneratedName, ConstanteUtils.ARCHIVE_WAR_EXTENSION ),
148                 serverApplicationInstance.getFtpInfo( ), serverApplicationInstance.getFtpDirectoryInstall( ), context
149                         .getCommandResult( ), true );
150         // throw RuntimeException for stopping Workflow
151         context.getCommandResult( ).getLog( ).append( "End Action Deploy  Site...\n" );
152 
153         return null;
154     }
155 
156     public String deployScript( WorkflowDeployScriptContext context, Locale locale )
157     {
158         FastDeployApplicationData  data=context.getFastDeployApplicationData( );
159         IFtpService ftpService=DeploymentFactory.getInstance( ).getFtpService( data.getApplicationType( ) );
160         String strServerType = !StringUtils.isEmpty( context.getCodeServerInstance( ConstanteUtils.CONSTANTE_SERVER_MYSQL ) ) ? ConstanteUtils.CONSTANTE_SERVER_MYSQL
161                 : ConstanteUtils.CONSTANTE_SERVER_PSQ;
162         ServerApplicationInstance serverApplicationInstance = DeploymentFactory.getInstance( ).getServerApplicationService( data.getApplicationType( ) ).getServerApplicationInstance( data, Integer.toString( context.getIdApplication( ) ),
163                 context.getCodeServerInstance( strServerType ), context.getCodeEnvironement( ), strServerType, locale, false, false );
164 
165         context.getCommandResult( ).getLog( ).append( "Starting Action Deploy  Script...\n" );
166         if(context.getScriptFileItem()==null)
167         {
168         	 context.getCommandResult( ).getLog( ).append( "No script to Deploy  ...\n" );
169                 
170         }
171         else
172         {
173         	ftpService.uploadFile( context.getScriptFileItemName( ), context.getScriptFileItem( ), serverApplicationInstance.getFtpInfo( ),
174                 serverApplicationInstance.getFtpDirectoryScript( ), context.getCommandResult( ), false );
175         	// throw RuntimeException for stopping Workflow
176         	stopWorkflowIfTechnicalError( "Error During Deploy Script", context.getCommandResult( ) );
177         }
178         context.getCommandResult( ).getLog( ).append( "End Action Deploy  Script...\n" );
179 
180         return null;
181     }
182 
183     public  <T extends AbstractWorkflowDeployContext>  String executeServerAction( String strActionKey, HttpServletRequest request, T context, Locale locale )
184     {
185         FastDeployApplicationData  data=context.getFastDeployApplicationData( );
186         IAction action = DeploymentFactory.getInstance( ).getActionService( data.getApplicationType( ) ).getAction( strActionKey, locale );
187         // test if the server instance is in the deployment context
188         if ( context.getCodeServerInstance( action.getServerType( ) ) != null )
189         {
190 
191             ServerApplicationInstance serverApplicationInstance = DeploymentFactory.getInstance( ).getServerApplicationService( data.getApplicationType( ) ).getServerApplicationInstance( data, Integer.toString( context.getIdApplication( ) ),
192                     context.getCodeServerInstance( action.getServerType( ) ), context.getCodeEnvironement( ), action.getServerType( ), locale, false, false );
193             boolean bResult;
194             if ( action != null
195                     && DeploymentFactory.getInstance( ).getActionService( data.getApplicationType( ) ).canExecuteAction( data, action, serverApplicationInstance, context.getCommandResult( ),
196                             action.getActionParameters( context ) ) )
197             {
198                 context.getCommandResult( ).getLog( ).append( "Starting Action " + action.getName( ) + " \n" );
199                 bResult = DeploymentFactory.getInstance( ).getActionService( data.getApplicationType( ) ).executeAction( data, action, serverApplicationInstance, context.getCommandResult( ),
200                         action.getActionParameters( context ) );
201 
202                 User user = null;
203                 try
204                 {
205                     user = UserService.getCurrentUser( request );
206                 }
207                 catch( UserNotSignedException e )
208                 {
209                     DeploymentUtils.addTechnicalError( context.getCommandResult( ), "<h1>Erreur lors de la sauvegarde de la commande" + action.getCode( )
210                             + " de cloudmgrws</h1> <br> " + e.getMessage( ), e );
211                 }
212                 ActionHistoryService.saveActionHistory( action, context.getIdApplication( ), data.getApplicationType( ),serverApplicationInstance, user, action.getActionParameters( context ), bResult);
213 
214                 if ( !bResult && action.isStopWorkflowIfExecutionError( ) )
215                 {
216                     context.getCommandResult( ).setErrorType( CommandResult.ERROR_TYPE_STOP );
217                     // throw RuntimeException for stopping Workflow
218                     throw new RuntimeException( "Error During Server Action Execution" );
219 
220                 }
221                 context.getCommandResult( ).getLog( ).append( "End Action " + action.getName( ) + " \n" );
222 
223             }
224         }
225 
226         return null;
227     }
228 
229     private void stopWorkflowIfTechnicalError( String strProcess, CommandResult commandResult ) throws RuntimeException
230     {
231 
232         if ( commandResult != null && commandResult.getStatus( ) == CommandResult.STATUS_ERROR
233                 && commandResult.getErrorType( ) == CommandResult.ERROR_TYPE_STOP )
234         {
235             throw new RuntimeException( strProcess );
236         }
237     }
238     
239     /**
240      * Run a custom maven command
241      * @param context
242      *              The workflow deploy site context
243      * @param locale
244      *              The locale
245      * @return the logs of the command
246      */
247     @Override
248     public <T extends AbstractWorkflowDeployContext> String runCustomMavenCommand( T context, Locale locale )
249     {
250         FastDeployApplicationData  data=context.getFastDeployApplicationData( );
251         
252         ServerApplicationInstance serverApplicationInstance = DeploymentFactory.getInstance( ).getServerApplicationService( data.getApplicationType( ) ).getServerApplicationInstance( data, Integer.toString( context.getIdApplication( ) ),
253                 context.getCodeServerInstance( ConstanteUtils.CONSTANTE_SERVER_TOMCAT ), context.getCodeEnvironement( ),
254                 ConstanteUtils.CONSTANTE_SERVER_TOMCAT, locale, false, false );
255         
256         context.getCommandResult( ).getLog( ).append( "Starting Action Run Custom Maven Cmd " );
257         context.getCommandResult( ).getLog( ).append( context.getCustomMavenCommand( ) );
258         context.getCommandResult( ).getLog( ).append( "\n" );
259         MavenService.getService( ).runCustomMavenCommand( data.getArtifactId( ), serverApplicationInstance.getMavenProfile( data.getIdApplicationData( ) ),
260                 context.getCustomMavenCommand(), context.getCommandResult( ) );
261         
262         // throw RuntimeException for stopping Workflow
263         stopWorkflowIfTechnicalError( "Error During the run of the custom maven cmd " + context.getCustomMavenCommand(), context.getCommandResult( ) );
264         context.getCommandResult( ).getLog( ).append( "End Action Run Custom Maven Cmd \n" );
265 
266         return null;
267     }
268 
269     
270 }