зеркало из https://github.com/microsoft/Oryx.git
run script changes (#1430)
* run script changes * testing * changes * test for run changes * Test for the run.sh task * changes * run.sh changes * addressed PR commends * run command integration test * merged with main branch * run command changes * address pr changes * customized run command for Node, PhP * python run command change * run command changes * addressed PR changes * bug fix
This commit is contained in:
Родитель
b4dcd1107c
Коммит
e45c810dc9
|
@ -13,3 +13,4 @@ const Logger string = "/opt/oryx/logger"
|
|||
const Bash string = "/bin/bash"
|
||||
const Benv string = "/opt/oryx/benv"
|
||||
const PreRunCommandEnvVarName string = "PRE_RUN_COMMAND"
|
||||
const AppSvcFileName string = "appsvc.yaml"
|
||||
|
|
|
@ -60,6 +60,28 @@ func WriteScript(filePath string, command string) {
|
|||
ioutil.WriteFile(filePath, []byte(command), 0755)
|
||||
}
|
||||
|
||||
// Appends command to a file
|
||||
func AppendScript(filePath string, command string) {
|
||||
|
||||
if command == "" {
|
||||
return
|
||||
}
|
||||
|
||||
file, err := os.OpenFile(filePath, os.O_APPEND|os.O_WRONLY, 0755)
|
||||
if err != nil {
|
||||
fmt.Println("Unable to read provided file to append command to. Error: " + err.Error())
|
||||
return
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
fmt.Println("Appending provided command to '" + filePath + "'")
|
||||
// Appends the command at the end of the file
|
||||
if _, err := file.WriteString("\n" + command); err != nil {
|
||||
fmt.Println("Unable to write in the file. Error: " + err.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Try to add a permission to a file
|
||||
func TryAddPermission(filePath string, permission os.FileMode) bool {
|
||||
err := os.Chmod(filePath, permission)
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
// --------------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
// --------------------------------------------------------------------------------------------
|
||||
|
||||
package common
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func ParseUserRunCommand(sourcePath string) string {
|
||||
|
||||
appsvcFile, err := os.Open(sourcePath)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
defer appsvcFile.Close()
|
||||
|
||||
const runHeading string = "run:" // format of run command- "run: gunicorn myapp.app --workers 5"
|
||||
runCommand := ""
|
||||
var isRunCommandFound bool
|
||||
scanner := bufio.NewScanner(appsvcFile)
|
||||
|
||||
for scanner.Scan() {
|
||||
indexOfRunHeading := strings.Index(scanner.Text(), runHeading)
|
||||
isCurrentLineContainsAnyHeading := strings.Contains(scanner.Text(), ":")
|
||||
|
||||
if isCurrentLineContainsAnyHeading && isRunCommandFound {
|
||||
// runCommand already found
|
||||
// not considering any other customized commands
|
||||
break
|
||||
}
|
||||
|
||||
isValidRunCommand := indexOfRunHeading == 0 && len(scanner.Text()) > len(runHeading)
|
||||
if isRunCommandFound || isValidRunCommand {
|
||||
if isRunCommandFound {
|
||||
runCommand += "\n"
|
||||
runCommand += strings.TrimSpace(scanner.Text())
|
||||
} else {
|
||||
isRunCommandFound = true
|
||||
runCommand += strings.TrimSpace(scanner.Text()[indexOfRunHeading+len(runHeading):]) //gets the run command and trim to get rid of the forward and trailing spaces
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Println("User provided run command: " + runCommand)
|
||||
|
||||
if err := scanner.Err(); err != nil {
|
||||
fmt.Println(err)
|
||||
return ""
|
||||
}
|
||||
|
||||
return runCommand
|
||||
}
|
|
@ -130,6 +130,9 @@ func main() {
|
|||
}
|
||||
|
||||
common.WriteScript(fullOutputPath, command)
|
||||
|
||||
userRunCommand := common.ParseUserRunCommand(filepath.Join(fullAppPath, consts.AppSvcFileName))
|
||||
common.AppendScript(fullOutputPath, userRunCommand)
|
||||
}
|
||||
|
||||
if setupEnvCommand.Parsed() {
|
||||
|
|
|
@ -11,6 +11,7 @@ import (
|
|||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
@ -101,6 +102,9 @@ func main() {
|
|||
}
|
||||
script := gen.GenerateEntrypointScript()
|
||||
common.WriteScript(*outputPathPtr, script)
|
||||
|
||||
userRunCommand := common.ParseUserRunCommand(filepath.Join(fullAppPath, consts.AppSvcFileName))
|
||||
common.AppendScript(*outputPathPtr, userRunCommand)
|
||||
}
|
||||
|
||||
if setupEnvCommand.Parsed() {
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
"common"
|
||||
"common/consts"
|
||||
"flag"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
@ -58,5 +59,8 @@ func main() {
|
|||
|
||||
command := entrypointGenerator.GenerateEntrypointScript()
|
||||
common.WriteScript(*outputPathPtr, command)
|
||||
|
||||
userRunCommand := common.ParseUserRunCommand(filepath.Join(fullAppPath, consts.AppSvcFileName))
|
||||
common.AppendScript(*outputPathPtr, userRunCommand)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ import (
|
|||
"common/consts"
|
||||
"flag"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
|
@ -87,6 +88,9 @@ func main() {
|
|||
|
||||
command := entrypointGenerator.GenerateEntrypointScript()
|
||||
common.WriteScript(*outputPathPtr, command)
|
||||
|
||||
userRunCommand := common.ParseUserRunCommand(filepath.Join(fullAppPath, consts.AppSvcFileName))
|
||||
common.AppendScript(*outputPathPtr, userRunCommand)
|
||||
}
|
||||
|
||||
if setupEnvCommand.Parsed() {
|
||||
|
|
|
@ -10,6 +10,7 @@ import (
|
|||
"common/consts"
|
||||
"flag"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
|
@ -73,16 +74,19 @@ func main() {
|
|||
configuration.PreRunCommand = viperConfig.GetString(consts.PreRunCommandEnvVarName)
|
||||
|
||||
gen := RubyStartupScriptGenerator{
|
||||
SourcePath: fullAppPath,
|
||||
UserStartupCommand: *userStartupCommandPtr,
|
||||
DefaultAppFilePath: fullDefaultAppFilePath,
|
||||
RailEnv: *railEnvironment,
|
||||
BindPort: *bindPortPtr,
|
||||
Manifest: buildManifest,
|
||||
Configuration: configuration,
|
||||
SourcePath: fullAppPath,
|
||||
UserStartupCommand: *userStartupCommandPtr,
|
||||
DefaultAppFilePath: fullDefaultAppFilePath,
|
||||
RailEnv: *railEnvironment,
|
||||
BindPort: *bindPortPtr,
|
||||
Manifest: buildManifest,
|
||||
Configuration: configuration,
|
||||
}
|
||||
script := gen.GenerateEntrypointScript()
|
||||
common.WriteScript(*outputPathPtr, script)
|
||||
|
||||
userRunCommand := common.ParseUserRunCommand(filepath.Join(fullAppPath, consts.AppSvcFileName))
|
||||
common.AppendScript(*outputPathPtr, userRunCommand)
|
||||
}
|
||||
|
||||
if setupEnvCommand.Parsed() {
|
||||
|
@ -107,4 +111,4 @@ func main() {
|
|||
buildManifest.RubyVersion))
|
||||
common.SetupEnv(finalScript)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Oryx.BuildScriptGenerator;
|
||||
using Microsoft.Oryx.BuildScriptGenerator.Common;
|
||||
using Microsoft.Oryx.BuildScriptGenerator.DotNetCore;
|
||||
using Microsoft.Oryx.BuildScriptGeneratorCli;
|
||||
|
@ -71,6 +72,71 @@ namespace Microsoft.Oryx.Integration.Tests
|
|||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CanBuildAndRun_NetCore60MvcApp_WithCustomizedRunCommand()
|
||||
{
|
||||
// Arrange
|
||||
var dotnetcoreVersion = DotNetCoreRunTimeVersions.NetCoreApp60;
|
||||
var hostDir = Path.Combine(_hostSamplesDir, "DotNetCore", NetCoreApp60MvcApp);
|
||||
var tmpDir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tmpDir);
|
||||
try
|
||||
{
|
||||
var tmpVolume = DockerVolume.CreateMirror(tmpDir, true);
|
||||
var tmpContainerDir = tmpVolume.ContainerDir;
|
||||
var volume = DockerVolume.CreateMirror(hostDir);
|
||||
var appDir = volume.ContainerDir;
|
||||
var appOutputDirVolume = CreateAppOutputDirVolume();
|
||||
var appOutputDir = appOutputDirVolume.ContainerDir;
|
||||
var appsvcFile = appOutputDirVolume.ContainerDir + "/appsvc.yaml";
|
||||
var runCommand = "echo 'Hello Azure! New Feature!!'";
|
||||
var buildImageScript = new ShellScriptBuilder()
|
||||
.AddDefaultTestEnvironmentVariables()
|
||||
.AddCommand(
|
||||
$"oryx build {appDir} -i /tmp/int --platform {DotNetCoreConstants.PlatformName} " +
|
||||
$"--platform-version {dotnetcoreVersion} -o {appOutputDir}")
|
||||
.ToString();
|
||||
var runtimeImageScript = new ShellScriptBuilder()
|
||||
.CreateFile(appsvcFile, $"\"run: {runCommand}\"")
|
||||
.AddCommand(
|
||||
$"oryx create-script -appPath {appOutputDir} -bindPort {ContainerPort} -output {tmpContainerDir}/run.sh")
|
||||
.AddCommand($".{tmpContainerDir}/run.sh")
|
||||
.ToString();
|
||||
|
||||
await EndToEndTestHelper.BuildRunAndAssertAppAsync(
|
||||
NetCoreApp60MvcApp,
|
||||
_output,
|
||||
new DockerVolume[] { volume, appOutputDirVolume, tmpVolume },
|
||||
_imageHelper.GetGitHubActionsBuildImage(),
|
||||
"/bin/sh",
|
||||
new[]
|
||||
{
|
||||
"-c",
|
||||
buildImageScript
|
||||
},
|
||||
_imageHelper.GetRuntimeImage("dotnetcore", "6.0"),
|
||||
ContainerPort,
|
||||
"/bin/sh",
|
||||
new[]
|
||||
{
|
||||
"-c",
|
||||
runtimeImageScript
|
||||
},
|
||||
async (hostPort) =>
|
||||
{
|
||||
var data = await _httpClient.GetStringAsync($"http://localhost:{hostPort}/");
|
||||
Assert.Contains("Welcome to ASP.NET Core MVC!", data);
|
||||
|
||||
var runScript = File.ReadAllText(Path.Combine(tmpDir, "run.sh"));
|
||||
Assert.Contains(runCommand, runScript);
|
||||
});
|
||||
}
|
||||
finally
|
||||
{
|
||||
Directory.Delete(tmpDir, true);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CanBuildAndRun_Adds_Oryx_AppInsights_Codeless_ConfigurationAsync()
|
||||
{
|
||||
|
|
|
@ -53,13 +53,13 @@ namespace Microsoft.Oryx.Tests.Common
|
|||
/// </summary>
|
||||
/// <param name="hostDir">local directory to be used in a container</param>
|
||||
/// <returns>DockerVolume instance that can be used to mount the new copy of `originalDir`.</returns>
|
||||
public static DockerVolume CreateMirror(string hostDir)
|
||||
/// <param name="writeToHostDir">a boolean which indicates if we want the actual directory or the copy of the actual directory</param>
|
||||
public static DockerVolume CreateMirror(string hostDir, bool writeToHostDir = false)
|
||||
{
|
||||
if (string.IsNullOrEmpty(hostDir))
|
||||
{
|
||||
throw new ArgumentException($"'{nameof(hostDir)}' cannot be null or empty.");
|
||||
}
|
||||
|
||||
if (!Directory.Exists(hostDir))
|
||||
{
|
||||
throw new ArgumentException($"'{nameof(hostDir)}' must point to an existing directory.");
|
||||
|
@ -90,12 +90,15 @@ namespace Microsoft.Oryx.Tests.Common
|
|||
tempDirRoot = Path.Combine(Path.GetTempPath(), MountedHostDirRootName);
|
||||
}
|
||||
|
||||
var writableHostDir = Path.Combine(
|
||||
tempDirRoot,
|
||||
Guid.NewGuid().ToString("N"),
|
||||
dirInfo.Name);
|
||||
CopyDirectories(hostDir, writableHostDir, copySubDirs: true);
|
||||
|
||||
var writableHostDir = hostDir;
|
||||
if (!writeToHostDir)
|
||||
{
|
||||
writableHostDir = Path.Combine(
|
||||
tempDirRoot,
|
||||
Guid.NewGuid().ToString("N"),
|
||||
dirInfo.Name);
|
||||
CopyDirectories(hostDir, writableHostDir, copySubDirs: true);
|
||||
}
|
||||
// Grant permissions to the folder we just copied on the host machine. The permisions here allow the
|
||||
// user(a non-root user) in the container to read/write/execute files.
|
||||
var linuxOS = OSPlatform.Create("LINUX");
|
||||
|
|
Загрузка…
Ссылка в новой задаче