Ejemplo n.º 1
0
        public async Task <HttpResponseMessage> OneDeploy(
            [FromUri] string type      = null,
            [FromUri] bool async       = false,
            [FromUri] string path      = null,
            [FromUri] bool?restart     = true,
            [FromUri] bool?clean       = null,
            [FromUri] bool ignoreStack = false
            )
        {
            using (_tracer.Step(Constants.OneDeploy))
            {
                JObject requestObject = null;

                try
                {
                    if (ArmUtils.IsArmRequest(Request))
                    {
                        requestObject = await Request.Content.ReadAsAsync <JObject>();

                        var armProperties = requestObject.Value <JObject>("properties");

                        type        = armProperties.Value <string>("type");
                        async       = armProperties.Value <bool>("async");
                        path        = armProperties.Value <string>("path");
                        restart     = armProperties.Value <bool?>("restart");
                        clean       = armProperties.Value <bool?>("clean");
                        ignoreStack = armProperties.Value <bool>("ignorestack");
                    }
                }
                catch (Exception ex)
                {
                    return(ArmUtils.CreateErrorResponse(Request, HttpStatusCode.BadRequest, ex));
                }

                //
                // 'async' is not a CSharp-ish variable name. And although it is a valid variable name, some
                // IDEs confuse it to be the 'async' keyword in C#.
                // On the other hand, isAsync is not a good name for the query-parameter.
                // So we use 'async' as the query parameter, and then assign it to the C# variable 'isAsync'
                // at the earliest. Hereon, we use just 'isAsync'.
                //
                bool isAsync = async;

                ArtifactType artifactType = ArtifactType.Unknown;
                try
                {
                    artifactType = (ArtifactType)Enum.Parse(typeof(ArtifactType), type, ignoreCase: true);
                }
                catch
                {
                    return(StatusCode400($"type='{type}' not recognized"));
                }

                var deploymentInfo = new ArtifactDeploymentInfo(_environment, _traceFactory)
                {
                    AllowDeploymentWhileScmDisabled = true,
                    Deployer                = Constants.OneDeploy,
                    IsContinuous            = false,
                    AllowDeferredDeployment = false,
                    IsReusable              = false,
                    TargetRootPath          = _environment.WebRootPath,
                    TargetChangeset         = DeploymentManager.CreateTemporaryChangeSet(message: Constants.OneDeploy),
                    CommitId                = null,
                    RepositoryType          = RepositoryType.None,
                    Fetch = OneDeployFetch,
                    DoFullBuildByDefault = false,
                    Message                = Constants.OneDeploy,
                    WatchedFileEnabled     = false,
                    CleanupTargetDirectory = clean.GetValueOrDefault(false),
                    RestartAllowed         = restart.GetValueOrDefault(true),
                };

                string error;
                switch (artifactType)
                {
                case ArtifactType.War:
                    if (!OneDeployHelper.EnsureValidStack(OneDeployHelper.Tomcat, ignoreStack, out error))
                    {
                        return(StatusCode400(error));
                    }

                    // If path is non-null, we assume this is a legacy war deployment, i.e. equivalent of wardeploy
                    if (!string.IsNullOrWhiteSpace(path))
                    {
                        //
                        // For legacy war deployments, the only path allowed is webapps/<directory-name>
                        //

                        if (!OneDeployHelper.IsLegacyWarPathValid(path))
                        {
                            return(StatusCode400($"path='{path}'. Only allowed path when type={artifactType} is webapps/<directory-name>. Example: path=webapps/ROOT"));
                        }

                        deploymentInfo.TargetRootPath = Path.Combine(_environment.WebRootPath, path);
                        deploymentInfo.Fetch          = LocalZipHandler;

                        // Legacy war deployment is equivalent to wardeploy
                        // So always do clean deploy.
                        deploymentInfo.CleanupTargetDirectory = true;
                        artifactType = ArtifactType.Zip;
                    }
                    else
                    {
                        // For type=war, if no path is specified, the target file is app.war
                        deploymentInfo.TargetFileName = "app.war";
                    }

                    break;

                case ArtifactType.Jar:
                    if (!OneDeployHelper.EnsureValidStack(OneDeployHelper.JavaSE, ignoreStack, out error))
                    {
                        return(StatusCode400(error));
                    }

                    deploymentInfo.TargetFileName = "app.jar";
                    break;

                case ArtifactType.Ear:
                    if (!OneDeployHelper.EnsureValidStack(OneDeployHelper.JBossEap, ignoreStack, out error))
                    {
                        return(StatusCode400(error));
                    }

                    deploymentInfo.TargetFileName = "app.ear";
                    break;

                case ArtifactType.Lib:
                    if (!OneDeployHelper.EnsureValidPath(artifactType, path, out error))
                    {
                        return(StatusCode400(error));
                    }

                    deploymentInfo.TargetRootPath = OneDeployHelper.GetLibsDirectoryAbsolutePath(_environment);
                    OneDeployHelper.SetTargetSubDirectoyAndFileNameFromPath(deploymentInfo, path);
                    break;

                case ArtifactType.Startup:
                    deploymentInfo.TargetRootPath = OneDeployHelper.GetScriptsDirectoryAbsolutePath(_environment);
                    OneDeployHelper.SetTargetSubDirectoyAndFileNameFromPath(deploymentInfo, OneDeployHelper.GetStartupFileName());
                    break;

                case ArtifactType.Script:
                    if (!OneDeployHelper.EnsureValidPath(artifactType, path, out error))
                    {
                        return(StatusCode400(error));
                    }

                    deploymentInfo.TargetRootPath = OneDeployHelper.GetScriptsDirectoryAbsolutePath(_environment);
                    OneDeployHelper.SetTargetSubDirectoyAndFileNameFromPath(deploymentInfo, path);

                    break;

                case ArtifactType.Static:
                    if (!OneDeployHelper.EnsureValidPath(artifactType, path, out error))
                    {
                        return(StatusCode400(error));
                    }

                    OneDeployHelper.SetTargetSubDirectoyAndFileNameFromPath(deploymentInfo, path);

                    break;

                case ArtifactType.Zip:
                    deploymentInfo.Fetch = LocalZipHandler;
                    deploymentInfo.TargetSubDirectoryRelativePath = path;

                    // Deployments for type=zip default to clean=true
                    deploymentInfo.CleanupTargetDirectory = clean.GetValueOrDefault(true);

                    break;

                default:
                    return(StatusCode400($"Artifact type '{artifactType}' not supported"));
                }

                return(await PushDeployAsync(deploymentInfo, isAsync, requestObject, artifactType));
            }
        }
        public async Task <IActionResult> OneDeploy(
            [FromQuery] string type      = null,
            [FromQuery] bool async       = false,
            [FromQuery] string path      = null,
            [FromQuery] bool?restart     = true,
            [FromQuery] bool?clean       = null,
            [FromQuery] bool ignoreStack = false
            )
        {
            string remoteArtifactUrl = null;

            using (_tracer.Step(Constants.OneDeploy))
            {
                string deploymentId = GetExternalDeploymentId(Request);

                try
                {
                    if (Request.MediaTypeContains("application/json"))
                    {
                        string jsonString;
                        using (StreamReader reader = new StreamReader(Request.Body, Encoding.UTF8))
                        {
                            jsonString = await reader.ReadToEndAsync();
                        }

                        var requestJson = JObject.Parse(jsonString);

                        if (ArmUtils.IsArmRequest(Request))
                        {
                            requestJson = requestJson.Value <JObject>("properties");

                            type        = requestJson.Value <string>("type");
                            async       = requestJson.Value <bool>("async");
                            path        = requestJson.Value <string>("path");
                            restart     = requestJson.Value <bool?>("restart");
                            clean       = requestJson.Value <bool?>("clean");
                            ignoreStack = requestJson.Value <bool>("ignorestack");
                        }

                        remoteArtifactUrl = GetArtifactURLFromJSON(requestJson);
                    }
                }
                catch (Exception ex)
                {
                    return(StatusCode400(ex.ToString()));
                }

                //
                // 'async' is not a CSharp-ish variable name. And although it is a valid variable name, some
                // IDEs confuse it to be the 'async' keyword in C#.
                // On the other hand, isAsync is not a good name for the query-parameter.
                // So we use 'async' as the query parameter, and then assign it to the C# variable 'isAsync'
                // at the earliest. Hereon, we use just 'isAsync'.
                //
                bool isAsync = async;

                ArtifactType artifactType = ArtifactType.Unknown;
                try
                {
                    artifactType = (ArtifactType)Enum.Parse(typeof(ArtifactType), type, ignoreCase: true);
                }
                catch
                {
                    return(StatusCode400($"type='{type}' not recognized"));
                }

                var deploymentInfo = new ArtifactDeploymentInfo(_environment, _traceFactory)
                {
                    ArtifactType = artifactType,
                    AllowDeploymentWhileScmDisabled = true,
                    Deployer                = Constants.OneDeploy,
                    IsContinuous            = false,
                    AllowDeferredDeployment = false,
                    IsReusable              = false,
                    TargetRootPath          = _environment.WebRootPath,
                    TargetChangeset         = DeploymentManager.CreateTemporaryChangeSet(message: Constants.OneDeploy),
                    CommitId                = null,
                    ExternalDeploymentId    = deploymentId,
                    RepositoryType          = RepositoryType.None,
                    RemoteURL               = remoteArtifactUrl,
                    Fetch = OneDeployFetch,
                    DoFullBuildByDefault = false,
                    Message                = Constants.OneDeploy,
                    WatchedFileEnabled     = false,
                    CleanupTargetDirectory = clean.GetValueOrDefault(false),
                    RestartAllowed         = restart.GetValueOrDefault(true),
                };

                string error;
                switch (artifactType)
                {
                case ArtifactType.War:
                    if (!OneDeployHelper.EnsureValidStack(artifactType, new List <string> {
                        OneDeployHelper.Tomcat, OneDeployHelper.JBossEap
                    }, ignoreStack, out error))
                    {
                        return(StatusCode400(error));
                    }

                    // If path is non-null, we assume this is a legacy war deployment, i.e. equivalent of wardeploy
                    if (!string.IsNullOrWhiteSpace(path))
                    {
                        //
                        // For legacy war deployments, the only path allowed is webapps/<directory-name>
                        //

                        if (!OneDeployHelper.EnsureValidPath(artifactType, OneDeployHelper.WwwrootDirectoryRelativePath, ref path, out error))
                        {
                            return(StatusCode400(error));
                        }

                        if (!OneDeployHelper.IsLegacyWarPathValid(path))
                        {
                            return(StatusCode400($"path='{path}' is invalid. When type={artifactType}, the only allowed paths are webapps/<directory-name> or /home/site/wwwroot/webapps/<directory-name>. " +
                                                 $"Example: path=webapps/ROOT or path=/home/site/wwwroot/webapps/ROOT"));
                        }

                        deploymentInfo.TargetRootPath = Path.Combine(_environment.WebRootPath, path);
                        deploymentInfo.Fetch          = LocalZipHandler;

                        // Legacy war deployment is equivalent to wardeploy
                        // So always do clean deploy.
                        deploymentInfo.CleanupTargetDirectory = true;
                        artifactType = ArtifactType.Zip;
                    }
                    else
                    {
                        // For type=war, if no path is specified, the target file is app.war
                        deploymentInfo.TargetFileName = "app.war";
                    }

                    break;

                case ArtifactType.Jar:
                    if (!OneDeployHelper.EnsureValidStack(artifactType, new List <string> {
                        OneDeployHelper.JavaSE
                    }, ignoreStack, out error))
                    {
                        return(StatusCode400(error));
                    }

                    deploymentInfo.TargetFileName = "app.jar";
                    break;

                case ArtifactType.Ear:
                    if (!OneDeployHelper.EnsureValidStack(artifactType, new List <string> {
                        OneDeployHelper.JBossEap
                    }, ignoreStack, out error))
                    {
                        return(StatusCode400(error));
                    }

                    deploymentInfo.TargetFileName = "app.ear";
                    break;

                case ArtifactType.Lib:
                    if (!OneDeployHelper.EnsureValidPath(artifactType, OneDeployHelper.LibsDirectoryRelativePath, ref path, out error))
                    {
                        return(StatusCode400(error));
                    }

                    deploymentInfo.TargetRootPath = OneDeployHelper.GetAbsolutePath(_environment, OneDeployHelper.LibsDirectoryRelativePath);
                    OneDeployHelper.SetTargetSubDirectoyAndFileNameFromRelativePath(deploymentInfo, path);
                    break;

                case ArtifactType.Startup:
                    deploymentInfo.TargetRootPath = OneDeployHelper.GetAbsolutePath(_environment, OneDeployHelper.ScriptsDirectoryRelativePath);
                    OneDeployHelper.SetTargetSubDirectoyAndFileNameFromRelativePath(deploymentInfo, OneDeployHelper.GetStartupFileName());
                    break;

                case ArtifactType.Script:
                    if (!OneDeployHelper.EnsureValidPath(artifactType, OneDeployHelper.ScriptsDirectoryRelativePath, ref path, out error))
                    {
                        return(StatusCode400(error));
                    }

                    deploymentInfo.TargetRootPath = OneDeployHelper.GetAbsolutePath(_environment, OneDeployHelper.ScriptsDirectoryRelativePath);
                    OneDeployHelper.SetTargetSubDirectoyAndFileNameFromRelativePath(deploymentInfo, path);

                    break;

                case ArtifactType.Static:
                    if (!OneDeployHelper.EnsureValidPath(artifactType, OneDeployHelper.WwwrootDirectoryRelativePath, ref path, out error))
                    {
                        return(StatusCode400(error));
                    }

                    OneDeployHelper.SetTargetSubDirectoyAndFileNameFromRelativePath(deploymentInfo, path);

                    break;

                case ArtifactType.Zip:
                    deploymentInfo.Fetch = LocalZipHandler;
                    deploymentInfo.TargetSubDirectoryRelativePath = path;

                    // Deployments for type=zip default to clean=true
                    deploymentInfo.CleanupTargetDirectory = clean.GetValueOrDefault(true);

                    break;

                default:
                    return(StatusCode400($"Artifact type '{artifactType}' not supported"));
                }

                return(await PushDeployAsync(deploymentInfo, isAsync, HttpContext));
            }
        }