This is an automated email from the ASF dual-hosted git repository.

pabloem pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/beam.git


The following commit(s) were added to refs/heads/master by this push:
     new a3c3722  Merge pull request #16374 from [BEAM-13398][Playground] Split 
LifeCycle to DTO and business logic
a3c3722 is described below

commit a3c3722f88546c3b42d41afb09d0853900bf4a46
Author: Aydar Zainutdinov <aydar.zaynutdi...@akvelon.com>
AuthorDate: Wed Jan 12 20:51:06 2022 +0300

    Merge pull request #16374 from [BEAM-13398][Playground] Split LifeCycle to 
DTO and business logic
    
    * [BEAM-13398][Playground]
    Add LifeCycleDto to separate DTO and business logic.
    
    * [BEAM-13398][Playground]
    Change LifeCycle structure
    
    * [BEAM-13398][Playground]
    Merge with master
    
    * [BEAM-13398][Playground]
    Merge with master
    Fix using `executable_files` value
    Fix comments
    
    * [BEAM-13398][Playground]
    renaming
---
 .../internal/code_processing/code_processing.go    |  16 +-
 .../code_processing/code_processing_test.go        |  10 +-
 .../internal/environment/application_test.go       |   2 -
 playground/backend/internal/fs_tool/fs.go          |  92 +---
 playground/backend/internal/fs_tool/fs_test.go     | 530 ++++++++-------------
 playground/backend/internal/fs_tool/go_fs_test.go  |  34 +-
 playground/backend/internal/fs_tool/java_fs.go     |   6 +-
 .../backend/internal/fs_tool/java_fs_test.go       |  36 +-
 .../backend/internal/fs_tool/lc_constructor.go     |  52 +-
 .../backend/internal/fs_tool/python_fs_test.go     |  30 +-
 .../internal/preparators/java_preparators.go       |   3 +-
 .../internal/preparators/java_preparators_test.go  |  14 +-
 .../internal/setup_tools/builder/setup_builder.go  |  26 +-
 .../setup_tools/builder/setup_builder_test.go      |  16 +-
 .../setup_tools/life_cycle/life_cycle_setuper.go   |  18 +-
 .../life_cycle/life_cycle_setuper_test.go          |  58 ++-
 playground/backend/internal/utils/system_utils.go  |   3 +-
 .../backend/internal/utils/system_utils_test.go    |   9 +-
 18 files changed, 386 insertions(+), 569 deletions(-)

diff --git a/playground/backend/internal/code_processing/code_processing.go 
b/playground/backend/internal/code_processing/code_processing.go
index 255056c..8e6d59e 100644
--- a/playground/backend/internal/code_processing/code_processing.go
+++ b/playground/backend/internal/code_processing/code_processing.go
@@ -70,7 +70,7 @@ func Process(ctx context.Context, cacheService cache.Cache, 
lc *fs_tool.LifeCycl
 
        go cancelCheck(pipelineLifeCycleCtx, pipelineId, cancelChannel, 
cacheService)
 
-       executorBuilder, err := builder.SetupExecutorBuilder(lc, 
utils.ReduceWhiteSpacesToSinge(pipelineOptions), sdkEnv)
+       executorBuilder, err := builder.SetupExecutorBuilder(lc.Paths, 
utils.ReduceWhiteSpacesToSinge(pipelineOptions), sdkEnv)
        if err != nil {
                _ = processSetupError(err, pipelineId, cacheService, 
pipelineLifeCycleCtx)
                return
@@ -133,7 +133,7 @@ func Process(ctx context.Context, cacheService cache.Cache, 
lc *fs_tool.LifeCycl
                // Compile
                if sdkEnv.ApacheBeamSdk == pb.Sdk_SDK_JAVA {
                        executor = executorBuilder.WithCompiler().
-                               
WithFileName(builder.GetFileNameFromFolder(lc.GetAbsoluteSourceFolderPath())).Build()
 // Need changed name for unit tests
+                               
WithFileName(builder.GetFileNameFromFolder(lc.Paths.AbsoluteSourceFileFolderPath,
 filepath.Ext(lc.Paths.SourceFileName))).Build() // Need changed name for unit 
tests
                }
                logger.Infof("%s: Compile() ...\n", pipelineId)
                compileCmd := executor.Compile(pipelineLifeCycleCtx)
@@ -158,7 +158,7 @@ func Process(ctx context.Context, cacheService cache.Cache, 
lc *fs_tool.LifeCycl
 
        // Run
        if sdkEnv.ApacheBeamSdk == pb.Sdk_SDK_JAVA {
-               executor, err = setJavaExecutableFile(lc, pipelineId, 
cacheService, pipelineLifeCycleCtx, executorBuilder, 
filepath.Join(appEnv.WorkingDir(), appEnv.PipelinesFolder()))
+               executor, err = setJavaExecutableFile(lc.Paths, pipelineId, 
cacheService, pipelineLifeCycleCtx, executorBuilder, 
filepath.Join(appEnv.WorkingDir(), appEnv.PipelinesFolder()))
                if err != nil {
                        return
                }
@@ -167,11 +167,11 @@ func Process(ctx context.Context, cacheService 
cache.Cache, lc *fs_tool.LifeCycl
        runCmd := getExecuteCmd(&validationResults, &executor, 
pipelineLifeCycleCtx)
        var runError bytes.Buffer
        runOutput := streaming.RunOutputWriter{Ctx: pipelineLifeCycleCtx, 
CacheService: cacheService, PipelineId: pipelineId}
-       go readLogFile(pipelineLifeCycleCtx, ctx, cacheService, 
lc.GetAbsoluteLogFilePath(), pipelineId, stopReadLogsChannel, 
finishReadLogsChannel)
+       go readLogFile(pipelineLifeCycleCtx, ctx, cacheService, 
lc.Paths.AbsoluteLogFilePath, pipelineId, stopReadLogsChannel, 
finishReadLogsChannel)
 
        if sdkEnv.ApacheBeamSdk == pb.Sdk_SDK_GO {
                // For go SDK all logs are placed to stdErr.
-               file, err := os.Create(lc.GetAbsoluteLogFilePath())
+               file, err := os.Create(lc.Paths.AbsoluteLogFilePath)
                if err != nil {
                        // If some error with creating a log file do the same 
as with other SDK.
                        logger.Errorf("%s: error during create log file (go 
sdk): %s", pipelineId, err.Error())
@@ -202,7 +202,7 @@ func Process(ctx context.Context, cacheService cache.Cache, 
lc *fs_tool.LifeCycl
                // Run step is finished, but code contains some error (divide 
by 0 for example)
                if sdkEnv.ApacheBeamSdk == pb.Sdk_SDK_GO {
                        // For Go SDK stdErr was redirected to the log file.
-                       errData, err := os.ReadFile(lc.GetAbsoluteLogFilePath())
+                       errData, err := 
os.ReadFile(lc.Paths.AbsoluteLogFilePath)
                        if err != nil {
                                logger.Errorf("%s: error during read errors 
from log file (go sdk): %s", pipelineId, err.Error())
                        }
@@ -227,8 +227,8 @@ func getExecuteCmd(valRes *sync.Map, executor 
*executors.Executor, ctxWithTimeou
 }
 
 // setJavaExecutableFile sets executable file name to runner (JAVA class name 
is known after compilation step)
-func setJavaExecutableFile(lc *fs_tool.LifeCycle, id uuid.UUID, service 
cache.Cache, ctx context.Context, executorBuilder *executors.ExecutorBuilder, 
dir string) (executors.Executor, error) {
-       className, err := lc.ExecutableName(id, dir)
+func setJavaExecutableFile(paths fs_tool.LifeCyclePaths, id uuid.UUID, service 
cache.Cache, ctx context.Context, executorBuilder *executors.ExecutorBuilder, 
dir string) (executors.Executor, error) {
+       className, err := paths.ExecutableName(id, dir)
        if err != nil {
                if err = processSetupError(err, id, service, ctx); err != nil {
                        return executorBuilder.Build(), err
diff --git 
a/playground/backend/internal/code_processing/code_processing_test.go 
b/playground/backend/internal/code_processing/code_processing_test.go
index ca4e1bb..f70065f 100644
--- a/playground/backend/internal/code_processing/code_processing_test.go
+++ b/playground/backend/internal/code_processing/code_processing_test.go
@@ -248,7 +248,7 @@ func Test_Process(t *testing.T) {
                                t.Fatalf("error during prepare folders: %s", 
err.Error())
                        }
                        if tt.createExecFile {
-                               _, _ = lc.CreateSourceCodeFile(tt.code)
+                               _ = lc.CreateSourceCodeFile(tt.code)
                        }
                        if err = utils.SetToCache(tt.args.ctx, cacheService, 
tt.args.pipelineId, cache.Canceled, false); err != nil {
                                t.Fatal("error during set cancel flag to cache")
@@ -269,7 +269,7 @@ func Test_Process(t *testing.T) {
 
                        compileOutput, _ := cacheService.GetValue(tt.args.ctx, 
tt.args.pipelineId, cache.CompileOutput)
                        if tt.expectedCompileOutput != nil && 
strings.Contains(tt.expectedCompileOutput.(string), "%s") {
-                               tt.expectedCompileOutput = 
fmt.Sprintf(tt.expectedCompileOutput.(string), lc.GetAbsoluteSourceFilePath())
+                               tt.expectedCompileOutput = 
fmt.Sprintf(tt.expectedCompileOutput.(string), lc.Paths.AbsoluteSourceFilePath)
                        }
                        if !reflect.DeepEqual(compileOutput, 
tt.expectedCompileOutput) {
                                t.Errorf("processCode() set compileOutput: %s, 
but expectes: %s", compileOutput, tt.expectedCompileOutput)
@@ -535,7 +535,7 @@ func TestGetLastIndex(t *testing.T) {
 func Test_setJavaExecutableFile(t *testing.T) {
        pipelineId := uuid.New()
        lc, _ := fs_tool.NewLifeCycle(pb.Sdk_SDK_JAVA, pipelineId, 
filepath.Join(os.Getenv("APP_WORK_DIR"), pipelinesFolder))
-       lc.ExecutableName = fakeExecutableName
+       lc.Paths.ExecutableName = fakeExecutableName
        executorBuilder := 
executors.NewExecutorBuilder().WithRunner().WithCommand("fake 
cmd").ExecutorBuilder
        type args struct {
                lc              *fs_tool.LifeCycle
@@ -572,7 +572,7 @@ func Test_setJavaExecutableFile(t *testing.T) {
        }
        for _, tt := range tests {
                t.Run(tt.name, func(t *testing.T) {
-                       got, err := setJavaExecutableFile(tt.args.lc, 
tt.args.id, tt.args.service, tt.args.ctx, tt.args.executorBuilder, tt.args.dir)
+                       got, err := setJavaExecutableFile(tt.args.lc.Paths, 
tt.args.id, tt.args.service, tt.args.ctx, tt.args.executorBuilder, tt.args.dir)
                        if (err != nil) != tt.wantErr {
                                t.Errorf("setJavaExecutableFile() error = %v, 
wantErr %v", err, tt.wantErr)
                        }
@@ -692,7 +692,7 @@ func prepareFiles(b *testing.B, pipelineId uuid.UUID, code 
string, sdk pb.Sdk) *
        if err != nil {
                b.Fatalf("error during prepare folders: %s", err.Error())
        }
-       _, err = lc.CreateSourceCodeFile(code)
+       err = lc.CreateSourceCodeFile(code)
        if err != nil {
                b.Fatalf("error during prepare source code file: %s", 
err.Error())
        }
diff --git a/playground/backend/internal/environment/application_test.go 
b/playground/backend/internal/environment/application_test.go
index 7b4eab1..92f2aeb 100644
--- a/playground/backend/internal/environment/application_test.go
+++ b/playground/backend/internal/environment/application_test.go
@@ -348,8 +348,6 @@ func TestApplicationEnvs_PipelinesFolder(t *testing.T) {
                workingDir             string
                cacheEnvs              *CacheEnvs
                pipelineExecuteTimeout time.Duration
-               launchSite             string
-               projectId              string
                pipelinesFolder        string
        }
        tests := []struct {
diff --git a/playground/backend/internal/fs_tool/fs.go 
b/playground/backend/internal/fs_tool/fs.go
index fae99d9..0d0b523 100644
--- a/playground/backend/internal/fs_tool/fs.go
+++ b/playground/backend/internal/fs_tool/fs.go
@@ -30,29 +30,23 @@ const (
        logFileName = "logs.log"
 )
 
-// Folder contains names of folders with executable and compiled files.
-// For each SDK these values should be set depending on folders that need for 
the SDK.
-type Folder struct {
-       BaseFolder           string
-       SourceFileFolder     string
-       ExecutableFileFolder string
+// LifeCyclePaths contains all files/folders paths
+type LifeCyclePaths struct {
+       SourceFileName                   string // 
{pipelineId}.{sourceFileExtension}
+       AbsoluteSourceFileFolderPath     string // 
/path/to/workingDir/pipelinesFolder/{pipelineId}/src
+       AbsoluteSourceFilePath           string // 
/path/to/workingDir/pipelinesFolder/{pipelineId}/src/{pipelineId}.{sourceFileExtension}
+       ExecutableFileName               string // 
{pipelineId}.{executableFileExtension}
+       AbsoluteExecutableFileFolderPath string // 
/path/to/workingDir/pipelinesFolder/{pipelineId}/bin
+       AbsoluteExecutableFilePath       string // 
/path/to/workingDir/pipelinesFolder/{pipelineId}/bin/{pipelineId}.{executableFileExtension}
+       AbsoluteBaseFolderPath           string // 
/path/to/workingDir/pipelinesFolder/{pipelineId}
+       AbsoluteLogFilePath              string // 
/path/to/workingDir/pipelinesFolder/{pipelineId}/logs.log
+       ExecutableName                   func(uuid.UUID, string) (string, error)
 }
 
-// Extension contains executable and compiled files' extensions.
-// For each SDK these values should be set depending on SDK's extensions.
-type Extension struct {
-       SourceFileExtension     string
-       ExecutableFileExtension string
-}
-
-// LifeCycle is used for preparing folders and files to process code for one 
request.
-// For each SDK folders (Folder) and extensions (Extension) should be set 
correctly.
+// LifeCycle is used for preparing folders and files to process code for one 
code processing request.
 type LifeCycle struct {
-       folderGlobs    []string //folders that should be created to process code
-       Folder         Folder
-       Extension      Extension
-       ExecutableName func(uuid.UUID, string) (string, error)
-       pipelineId     uuid.UUID
+       folderGlobs []string // folders that should be created to process code
+       Paths       LifeCyclePaths
 }
 
 // NewLifeCycle returns a corresponding LifeCycle depending on the given SDK.
@@ -70,8 +64,8 @@ func NewLifeCycle(sdk pb.Sdk, pipelineId uuid.UUID, 
pipelinesFolder string) (*Li
 }
 
 // CreateFolders creates all folders which will be used for code execution.
-func (l *LifeCycle) CreateFolders() error {
-       for _, folder := range l.folderGlobs {
+func (lc *LifeCycle) CreateFolders() error {
+       for _, folder := range lc.folderGlobs {
                err := os.MkdirAll(folder, fs.ModePerm)
                if err != nil {
                        return err
@@ -81,8 +75,8 @@ func (l *LifeCycle) CreateFolders() error {
 }
 
 // DeleteFolders deletes all previously provisioned folders.
-func (l *LifeCycle) DeleteFolders() error {
-       for _, folder := range l.folderGlobs {
+func (lc *LifeCycle) DeleteFolders() error {
+       for _, folder := range lc.folderGlobs {
                err := os.RemoveAll(folder)
                if err != nil {
                        return err
@@ -92,30 +86,21 @@ func (l *LifeCycle) DeleteFolders() error {
 }
 
 // CreateSourceCodeFile creates an executable file (i.e. 
file.{sourceFileExtension}).
-func (l *LifeCycle) CreateSourceCodeFile(code string) (string, error) {
-       if _, err := os.Stat(l.Folder.SourceFileFolder); os.IsNotExist(err) {
-               return "", err
+func (lc *LifeCycle) CreateSourceCodeFile(code string) error {
+       if _, err := os.Stat(lc.Paths.AbsoluteSourceFileFolderPath); 
os.IsNotExist(err) {
+               return err
        }
 
-       fileName := l.pipelineId.String() + l.Extension.SourceFileExtension
-       filePath := filepath.Join(l.Folder.SourceFileFolder, fileName)
+       filePath := lc.Paths.AbsoluteSourceFilePath
        err := os.WriteFile(filePath, []byte(code), fileMode)
        if err != nil {
-               return "", err
+               return err
        }
-       return fileName, nil
-}
-
-// GetAbsoluteSourceFilePath returns absolute filepath to executable file 
(/path/to/workingDir/pipelinesFolder/{pipelineId}/src/{pipelineId}.{sourceFileExtension}).
-func (l *LifeCycle) GetAbsoluteSourceFilePath() string {
-       fileName := l.pipelineId.String() + l.Extension.SourceFileExtension
-       filePath := filepath.Join(l.Folder.SourceFileFolder, fileName)
-       absoluteFilePath, _ := filepath.Abs(filePath)
-       return absoluteFilePath
+       return nil
 }
 
 // CopyFile copies a file with fileName from sourceDir to destinationDir.
-func (l *LifeCycle) CopyFile(fileName, sourceDir, destinationDir string) error 
{
+func (lc *LifeCycle) CopyFile(fileName, sourceDir, destinationDir string) 
error {
        absSourcePath := filepath.Join(sourceDir, fileName)
        absDestinationPath := filepath.Join(destinationDir, fileName)
        sourceFileStat, err := os.Stat(absSourcePath)
@@ -144,30 +129,3 @@ func (l *LifeCycle) CopyFile(fileName, sourceDir, 
destinationDir string) error {
        }
        return nil
 }
-
-// GetAbsoluteExecutableFilePath returns absolute filepath to compiled file 
(/path/to/workingDir/pipelinesFolder/{pipelineId}/bin/{pipelineId}.{executableExtension}).
-func (l *LifeCycle) GetAbsoluteExecutableFilePath() string {
-       fileName := l.pipelineId.String() + l.Extension.ExecutableFileExtension
-       filePath := filepath.Join(l.Folder.ExecutableFileFolder, fileName)
-       absoluteFilePath, _ := filepath.Abs(filePath)
-       return absoluteFilePath
-}
-
-// GetAbsoluteBaseFolderPath returns absolute path to executable folder 
(/path/to/workingDir/pipelinesFolder/{pipelineId}).
-func (l *LifeCycle) GetAbsoluteBaseFolderPath() string {
-       absoluteFilePath, _ := filepath.Abs(l.Folder.BaseFolder)
-       return absoluteFilePath
-}
-
-// GetAbsoluteLogFilePath returns absolute path to the logs file 
(/path/to/workingDir/pipelinesFolder/{pipelineId}/logs.log)
-func (l *LifeCycle) GetAbsoluteLogFilePath() string {
-       filePath := filepath.Join(l.Folder.BaseFolder, logFileName)
-       absoluteFilePath, _ := filepath.Abs(filePath)
-       return absoluteFilePath
-}
-
-// GetAbsoluteSourceFolderPath returns absolute path to executable folder 
(/path/to/workingDir/pipelinesFolder/{pipelineId}/src).
-func (l *LifeCycle) GetAbsoluteSourceFolderPath() string {
-       absoluteFilePath, _ := filepath.Abs(l.Folder.SourceFileFolder)
-       return absoluteFilePath
-}
diff --git a/playground/backend/internal/fs_tool/fs_test.go 
b/playground/backend/internal/fs_tool/fs_test.go
index c46fbe3..58ddbf3 100644
--- a/playground/backend/internal/fs_tool/fs_test.go
+++ b/playground/backend/internal/fs_tool/fs_test.go
@@ -17,10 +17,8 @@ package fs_tool
 
 import (
        pb "beam.apache.org/playground/backend/internal/api/v1"
-       "beam.apache.org/playground/backend/internal/logger"
        "fmt"
        "github.com/google/uuid"
-       "io/fs"
        "os"
        "path/filepath"
        "reflect"
@@ -30,132 +28,108 @@ import (
 const (
        sourceDir       = "sourceDir"
        destinationDir  = "destinationDir"
+       testFileMode    = 0755
        pipelinesFolder = "executable_files"
 )
 
-func TestMain(m *testing.M) {
-       err := setupPreparedFiles()
-       if err != nil {
-               logger.Fatal(err)
-       }
-       defer teardown()
-       m.Run()
-}
-
-func setupPreparedFiles() error {
-       err := os.Mkdir(sourceDir, 0755)
+func prepareFiles() error {
+       err := os.Mkdir(sourceDir, testFileMode)
        if err != nil {
                return err
        }
-       err = os.Mkdir(destinationDir, 0755)
+       err = os.Mkdir(destinationDir, testFileMode)
        if err != nil {
                return err
        }
        filePath := filepath.Join(sourceDir, "file.txt")
        _, err = os.Create(filePath)
-       if err != nil {
-               return err
-       }
-       return nil
+       return err
 }
 
-func teardown() {
+func teardownFiles() error {
        err := os.RemoveAll(sourceDir)
        if err != nil {
-               logger.Fatal(err)
-       }
-       err = os.RemoveAll(destinationDir)
-       if err != nil {
-               logger.Fatal(err)
-       }
-       err = os.RemoveAll(pipelinesFolder)
-       if err != nil {
-               logger.Fatal(err)
+               return err
        }
+       return os.RemoveAll(destinationDir)
 }
 
-func TestLifeCycle_CreateExecutableFile(t *testing.T) {
-       pipelineId := uuid.New()
-       baseFileFolder := fmt.Sprintf("%s/%s", pipelinesFolder, pipelineId)
-       srcFileFolder := baseFileFolder + "/src"
-       binFileFolder := baseFileFolder + "/bin"
+func prepareFolders(baseFileFolder string) error {
+       srcFileFolder := filepath.Join(baseFileFolder, "src")
+
+       return os.MkdirAll(srcFileFolder, testFileMode)
+}
+
+func teardownFolders(baseFileFolder string) error {
+       err := os.RemoveAll(baseFileFolder)
+       return err
+}
+
+func TestLifeCycle_CopyFile(t *testing.T) {
+       if err := prepareFiles(); err != nil {
+               t.Fatalf("Error during preparing files for test: %s", err)
+       }
+       defer teardownFiles()
 
        type fields struct {
                folderGlobs []string
-               folder      Folder
-               extension   Extension
-               pipelineId  uuid.UUID
+               Paths       LifeCyclePaths
        }
        type args struct {
-               code string
+               fileName       string
+               sourceDir      string
+               destinationDir string
        }
        tests := []struct {
-               name          string
-               createFolders []string
-               fields        fields
-               args          args
-               want          string
-               wantErr       bool
+               name    string
+               fields  fields
+               args    args
+               wantErr bool
        }{
                {
-                       name: "executable folder doesn't exist",
+                       name: "file doesn't exist",
                        fields: fields{
-                               folder: Folder{
-                                       SourceFileFolder:     srcFileFolder,
-                                       ExecutableFileFolder: binFileFolder,
-                               },
-                               pipelineId: pipelineId,
+                               folderGlobs: nil,
+                       },
+                       args: args{
+                               fileName:       "file1.txt",
+                               sourceDir:      sourceDir,
+                               destinationDir: destinationDir,
                        },
-                       args:    args{},
-                       want:    "",
                        wantErr: true,
                },
                {
-                       name:          "executable folder exists",
-                       createFolders: []string{srcFileFolder},
+                       name: "file exists",
                        fields: fields{
-                               folder:     Folder{SourceFileFolder: 
srcFileFolder},
-                               extension:  Extension{SourceFileExtension: 
JavaSourceFileExtension},
-                               pipelineId: pipelineId,
+                               folderGlobs: nil,
+                       },
+                       args: args{
+                               fileName:       "file.txt",
+                               sourceDir:      sourceDir,
+                               destinationDir: destinationDir,
                        },
-                       args:    args{code: "TEST_CODE"},
-                       want:    pipelineId.String() + JavaSourceFileExtension,
                        wantErr: false,
                },
        }
        for _, tt := range tests {
-               for _, folder := range tt.createFolders {
-                       os.MkdirAll(folder, fs.ModePerm)
-               }
                t.Run(tt.name, func(t *testing.T) {
                        l := &LifeCycle{
                                folderGlobs: tt.fields.folderGlobs,
-                               Folder:      tt.fields.folder,
-                               Extension:   tt.fields.extension,
-                               pipelineId:  tt.fields.pipelineId,
+                               Paths:       tt.fields.Paths,
                        }
-                       got, err := l.CreateSourceCodeFile(tt.args.code)
-                       if (err != nil) != tt.wantErr {
-                               t.Errorf("CreateSourceCodeFile() error = %v, 
wantErr %v", err, tt.wantErr)
-                               return
-                       }
-                       if got != tt.want {
-                               t.Errorf("CreateSourceCodeFile() got = %v, want 
%v", got, tt.want)
+                       if err := l.CopyFile(tt.args.fileName, 
tt.args.sourceDir, tt.args.destinationDir); (err != nil) != tt.wantErr {
+                               t.Errorf("CopyFile() error = %v, wantErr %v", 
err, tt.wantErr)
                        }
                })
-               os.RemoveAll(baseFileFolder)
        }
 }
 
 func TestLifeCycle_CreateFolders(t *testing.T) {
        pipelineId := uuid.New()
-       baseFileFolder := fmt.Sprintf("%s/%s", pipelinesFolder, pipelineId)
+       baseFileFolder := pipelineId.String()
 
        type fields struct {
                folderGlobs []string
-               folder      Folder
-               extension   Extension
-               pipelineId  uuid.UUID
        }
        tests := []struct {
                name    string
@@ -172,356 +146,234 @@ func TestLifeCycle_CreateFolders(t *testing.T) {
                t.Run(tt.name, func(t *testing.T) {
                        l := &LifeCycle{
                                folderGlobs: tt.fields.folderGlobs,
-                               Folder:      tt.fields.folder,
-                               Extension:   tt.fields.extension,
-                               pipelineId:  tt.fields.pipelineId,
                        }
                        if err := l.CreateFolders(); (err != nil) != tt.wantErr 
{
                                t.Errorf("CreateFolders() error = %v, wantErr 
%v", err, tt.wantErr)
                        }
-                       for _, folder := range tt.fields.folderGlobs {
-                               if _, err := os.Stat(folder); 
os.IsNotExist(err) {
-                                       t.Errorf("CreateFolders() should create 
folder %s, but it dosn't", folder)
-                               }
-                       }
                })
                os.RemoveAll(baseFileFolder)
        }
 }
 
-func TestLifeCycle_DeleteFolders(t *testing.T) {
+func TestLifeCycle_CreateSourceCodeFile(t *testing.T) {
        pipelineId := uuid.New()
-       baseFileFolder := fmt.Sprintf("%s/%s", pipelinesFolder, pipelineId)
+       baseFileFolder, _ := filepath.Abs(pipelineId.String())
+       if err := prepareFolders(baseFileFolder); err != nil {
+               t.Fatalf("Error during preparing folders for test: %s", err)
+       }
+       defer teardownFolders(baseFileFolder)
 
        type fields struct {
-               folderGlobs []string
-               folder      Folder
-               extension   Extension
-               pipelineId  uuid.UUID
+               Paths LifeCyclePaths
        }
-       tests := []struct {
-               name    string
-               fields  fields
-               wantErr bool
-       }{
-               {
-                       name: "DeleteFolders",
-                       fields: fields{
-                               folderGlobs: []string{baseFileFolder},
-                               pipelineId:  pipelineId,
-                       },
-                       wantErr: false,
-               },
-       }
-       for _, tt := range tests {
-               t.Run(tt.name, func(t *testing.T) {
-                       l := &LifeCycle{
-                               folderGlobs: tt.fields.folderGlobs,
-                               Folder:      tt.fields.folder,
-                               Extension:   tt.fields.extension,
-                               pipelineId:  tt.fields.pipelineId,
-                       }
-                       if err := l.DeleteFolders(); (err != nil) != tt.wantErr 
{
-                               t.Errorf("DeleteFolders() error = %v, wantErr 
%v", err, tt.wantErr)
-                       }
-               })
-       }
-}
-
-func TestNewLifeCycle(t *testing.T) {
-       pipelineId := uuid.New()
-       workingDir := "workingDir"
-       preparedPipelinesFolder := filepath.Join(workingDir, pipelinesFolder)
-       baseFileFolder := fmt.Sprintf("%s/%s", preparedPipelinesFolder, 
pipelineId)
-       srcFileFolder := baseFileFolder + "/src"
-       binFileFolder := baseFileFolder + "/bin"
-
        type args struct {
-               sdk             pb.Sdk
-               pipelineId      uuid.UUID
-               pipelinesFolder string
+               code string
        }
        tests := []struct {
                name    string
+               fields  fields
                args    args
-               want    *LifeCycle
                wantErr bool
        }{
                {
-                       name: "Available SDK",
-                       args: args{
-                               sdk:             pb.Sdk_SDK_JAVA,
-                               pipelineId:      pipelineId,
-                               pipelinesFolder: preparedPipelinesFolder,
-                       },
-                       want: &LifeCycle{
-                               folderGlobs: []string{baseFileFolder, 
srcFileFolder, binFileFolder},
-                               Folder: Folder{
-                                       BaseFolder:           baseFileFolder,
-                                       SourceFileFolder:     srcFileFolder,
-                                       ExecutableFileFolder: binFileFolder,
-                               },
-                               Extension: Extension{
-                                       SourceFileExtension:     
JavaSourceFileExtension,
-                                       ExecutableFileExtension: 
javaCompiledFileExtension,
+                       name: "source file folder path doesn't exist",
+                       fields: fields{
+                               Paths: LifeCyclePaths{
+                                       AbsoluteSourceFileFolderPath: "src",
                                },
-                               ExecutableName: executableName,
-                               pipelineId:     pipelineId,
-                       },
-                       wantErr: false,
+                       }, wantErr: true,
                },
                {
-                       name: "Unavailable SDK",
-                       args: args{
-                               sdk:             pb.Sdk_SDK_UNSPECIFIED,
-                               pipelineId:      pipelineId,
-                               pipelinesFolder: preparedPipelinesFolder,
-                       },
-                       want:    nil,
-                       wantErr: true,
-               },
-       }
-       for _, tt := range tests {
-               t.Run(tt.name, func(t *testing.T) {
-                       got, err := NewLifeCycle(tt.args.sdk, 
tt.args.pipelineId, tt.args.pipelinesFolder)
-                       if (err != nil) != tt.wantErr {
-                               t.Errorf("NewLifeCycle() error = %v, wantErr 
%v", err, tt.wantErr)
-                               return
-                       }
-                       if !tt.wantErr && !reflect.DeepEqual(got.folderGlobs, 
tt.want.folderGlobs) {
-                               t.Errorf("NewLifeCycle() folderGlobs = %v, want 
%v", got.folderGlobs, tt.want.folderGlobs)
-                       }
-                       if !tt.wantErr && !reflect.DeepEqual(got.Folder, 
tt.want.Folder) {
-                               t.Errorf("NewLifeCycle() Folder = %v, want %v", 
got.Folder, tt.want.Folder)
-                       }
-                       if !tt.wantErr && !reflect.DeepEqual(got.Extension, 
tt.want.Extension) {
-                               t.Errorf("NewLifeCycle() Extension = %v, want 
%v", got.Extension, tt.want.Extension)
-                       }
-                       if !tt.wantErr && !reflect.DeepEqual(got.pipelineId, 
tt.want.pipelineId) {
-                               t.Errorf("NewLifeCycle() pipelineId = %v, want 
%v", got.pipelineId, tt.want.pipelineId)
-                       }
-               })
-       }
-}
-
-func TestLifeCycle_GetAbsoluteExecutableFilePath(t *testing.T) {
-       pipelineId := uuid.New()
-       baseFileFolder := fmt.Sprintf("%s/%s", pipelinesFolder, pipelineId)
-       srcFileFolder := baseFileFolder + "/src"
-
-       filePath := filepath.Join(srcFileFolder, fmt.Sprintf("%s%s", 
pipelineId.String(), JavaSourceFileExtension))
-       absolutePath, _ := filepath.Abs(filePath)
-       type fields struct {
-               folderGlobs []string
-               Folder      Folder
-               Extension   Extension
-               pipelineId  uuid.UUID
-       }
-       tests := []struct {
-               name    string
-               fields  fields
-               want    string
-               wantErr bool
-       }{
-               {
-                       name: "GetAbsoluteSourceFilePath",
+                       name: "source file folder path exists",
                        fields: fields{
-                               Folder: Folder{
-                                       BaseFolder:       baseFileFolder,
-                                       SourceFileFolder: srcFileFolder,
+                               Paths: LifeCyclePaths{
+                                       AbsoluteSourceFileFolderPath: 
filepath.Join(baseFileFolder, "src"),
+                                       AbsoluteSourceFilePath:       
filepath.Join(baseFileFolder, "src", fmt.Sprintf("%s.%s", pipelineId.String(), 
"txt")),
                                },
-                               Extension:  Extension{SourceFileExtension: 
JavaSourceFileExtension},
-                               pipelineId: pipelineId,
                        },
-                       want: absolutePath,
+                       args:    args{code: "TEST_CODE"},
+                       wantErr: false,
                },
        }
        for _, tt := range tests {
                t.Run(tt.name, func(t *testing.T) {
                        l := &LifeCycle{
-                               folderGlobs: tt.fields.folderGlobs,
-                               Folder:      tt.fields.Folder,
-                               Extension:   tt.fields.Extension,
-                               pipelineId:  tt.fields.pipelineId,
+                               Paths: tt.fields.Paths,
                        }
-                       got := l.GetAbsoluteSourceFilePath()
-                       if got != tt.want {
-                               t.Errorf("GetAbsoluteSourceFilePath() got = %v, 
want %v", got, tt.want)
+                       if err := l.CreateSourceCodeFile(tt.args.code); (err != 
nil) != tt.wantErr {
+                               t.Errorf("CreateSourceCodeFile() error = %v, 
wantErr %v", err, tt.wantErr)
+                       }
+                       if !tt.wantErr {
+                               if _, err := 
os.Stat(l.Paths.AbsoluteSourceFilePath); os.IsNotExist(err) {
+                                       t.Error("CreateSourceCodeFile() should 
create a new file, but it doesn't")
+                               } else {
+                                       data, err := 
os.ReadFile(l.Paths.AbsoluteSourceFilePath)
+                                       if err != nil {
+                                               
t.Errorf("CreateSourceCodeFile() error during open created file: %s", err)
+                                       }
+                                       if string(data) != tt.args.code {
+                                               
t.Errorf("CreateSourceCodeFile() code = %s, want code %s", string(data), 
tt.args.code)
+                                       }
+                               }
                        }
                })
        }
 }
 
-func TestLifeCycle_GetAbsoluteExecutableFilesFolderPath(t *testing.T) {
+func TestLifeCycle_DeleteFolders(t *testing.T) {
        pipelineId := uuid.New()
-       baseFileFolder := fmt.Sprintf("%s/%s", pipelinesFolder, pipelineId)
+       baseFileFolder := pipelineId.String()
+       if err := prepareFolders(baseFileFolder); err != nil {
+               t.Fatalf("Error during preparing folders for test: %s", err)
+       }
 
-       absolutePath, _ := filepath.Abs(baseFileFolder)
        type fields struct {
                folderGlobs []string
-               Folder      Folder
-               Extension   Extension
-               pipelineId  uuid.UUID
        }
        tests := []struct {
                name    string
                fields  fields
-               want    string
                wantErr bool
        }{
                {
-                       name: "GetAbsoluteExecutableFolderPath",
-                       fields: fields{
-                               Folder:     Folder{BaseFolder: baseFileFolder},
-                               Extension:  Extension{SourceFileExtension: 
JavaSourceFileExtension},
-                               pipelineId: pipelineId,
-                       },
-                       want: absolutePath,
+                       name:    "DeleteFolders",
+                       fields:  fields{folderGlobs: []string{baseFileFolder}},
+                       wantErr: false,
                },
        }
        for _, tt := range tests {
                t.Run(tt.name, func(t *testing.T) {
                        l := &LifeCycle{
                                folderGlobs: tt.fields.folderGlobs,
-                               Folder:      tt.fields.Folder,
-                               Extension:   tt.fields.Extension,
-                               pipelineId:  tt.fields.pipelineId,
                        }
-                       got := l.GetAbsoluteBaseFolderPath()
-                       if got != tt.want {
-                               t.Errorf("GetAbsoluteBaseFolderPath() got = %v, 
want %v", got, tt.want)
+                       if err := l.DeleteFolders(); (err != nil) != tt.wantErr 
{
+                               t.Errorf("DeleteFolders() error = %v, wantErr 
%v", err, tt.wantErr)
+                       }
+                       if !tt.wantErr {
+                               if _, err := os.Stat(baseFileFolder); err == 
nil || !os.IsNotExist(err) {
+                                       t.Error("DeleteFolders() should remove 
folders, but it doesn't")
+                               }
                        }
                })
        }
 }
 
-func TestLifeCycle_ExecutableName(t *testing.T) {
+func TestNewLifeCycle(t *testing.T) {
        pipelineId := uuid.New()
-       baseFileFolder := fmt.Sprintf("%s/%s", pipelinesFolder, pipelineId)
-       binFileFolder := baseFileFolder + "/bin"
+       pipelinesFolder, _ := filepath.Abs(pipelinesFolder)
+       baseFileFolder := filepath.Join(pipelinesFolder, pipelineId.String())
+       srcFileFolder := filepath.Join(baseFileFolder, "src")
+       execFileFolder := filepath.Join(baseFileFolder, "bin")
 
-       type fields struct {
-               folderGlobs    []string
-               Folder         Folder
-               Extension      Extension
-               ExecutableName func(uuid.UUID, string) (string, error)
-               pipelineId     uuid.UUID
+       type args struct {
+               sdk             pb.Sdk
+               pipelineId      uuid.UUID
+               pipelinesFolder string
        }
        tests := []struct {
                name    string
-               fields  fields
-               want    string
+               args    args
+               want    *LifeCycle
                wantErr bool
        }{
                {
-                       name: "ExecutableName",
-                       fields: fields{
-                               Folder: Folder{
-                                       BaseFolder:           baseFileFolder,
-                                       ExecutableFileFolder: binFileFolder,
-                               },
-                               ExecutableName: func(u uuid.UUID, s string) 
(string, error) {
-                                       return "MOCK_EXECUTABLE_NAME", nil
+                       name: "Java LifeCycle",
+                       args: args{
+                               sdk:             pb.Sdk_SDK_JAVA,
+                               pipelineId:      pipelineId,
+                               pipelinesFolder: pipelinesFolder,
+                       },
+                       want: &LifeCycle{
+                               folderGlobs: []string{baseFileFolder, 
srcFileFolder, execFileFolder},
+                               Paths: LifeCyclePaths{
+                                       SourceFileName:                   
fmt.Sprintf("%s%s", pipelineId.String(), javaSourceFileExtension),
+                                       AbsoluteSourceFileFolderPath:     
srcFileFolder,
+                                       AbsoluteSourceFilePath:           
filepath.Join(srcFileFolder, fmt.Sprintf("%s%s", pipelineId.String(), 
javaSourceFileExtension)),
+                                       ExecutableFileName:               
fmt.Sprintf("%s%s", pipelineId.String(), javaCompiledFileExtension),
+                                       AbsoluteExecutableFileFolderPath: 
execFileFolder,
+                                       AbsoluteExecutableFilePath:       
filepath.Join(execFileFolder, fmt.Sprintf("%s%s", pipelineId.String(), 
javaCompiledFileExtension)),
+                                       AbsoluteBaseFolderPath:           
baseFileFolder,
+                                       AbsoluteLogFilePath:              
filepath.Join(baseFileFolder, logFileName),
                                },
-                               pipelineId:  pipelineId,
-                               folderGlobs: []string{baseFileFolder, 
binFileFolder},
                        },
-                       want:    "MOCK_EXECUTABLE_NAME",
-                       wantErr: false,
                },
-       }
-       for _, tt := range tests {
-               t.Run(tt.name, func(t *testing.T) {
-                       l := &LifeCycle{
-                               folderGlobs:    tt.fields.folderGlobs,
-                               Folder:         tt.fields.Folder,
-                               Extension:      tt.fields.Extension,
-                               ExecutableName: tt.fields.ExecutableName,
-                               pipelineId:     tt.fields.pipelineId,
-                       }
-                       got, err := l.ExecutableName(pipelineId, 
pipelinesFolder)
-                       if got != tt.want {
-                               t.Errorf("GetExecutableName() got = %v, want 
%v", got, tt.want)
-                       }
-                       if (err != nil) != tt.wantErr {
-                               t.Errorf("GetExecutableName() error = %v, 
wantErr %v", err, tt.wantErr)
-                       }
-               })
-       }
-}
-
-func TestCopyFile(t *testing.T) {
-       type fields struct {
-               folderGlobs    []string
-               Folder         Folder
-               Extension      Extension
-               ExecutableName func(uuid.UUID, string) (string, error)
-               pipelineId     uuid.UUID
-       }
-       type args struct {
-               fileName       string
-               sourceDir      string
-               destinationDir string
-       }
-       tests := []struct {
-               name    string
-               fields  fields
-               args    args
-               wantErr bool
-       }{
                {
-                       name: "file doesn't exist",
-                       fields: fields{
-                               folderGlobs:    nil,
-                               Folder:         Folder{},
-                               Extension:      Extension{},
-                               ExecutableName: nil,
-                               pipelineId:     uuid.UUID{},
-                       },
+                       name: "Go LifeCycle",
                        args: args{
-                               fileName:       "file1.txt",
-                               sourceDir:      sourceDir,
-                               destinationDir: destinationDir,
+                               sdk:             pb.Sdk_SDK_GO,
+                               pipelineId:      pipelineId,
+                               pipelinesFolder: pipelinesFolder,
+                       },
+                       want: &LifeCycle{
+                               folderGlobs: []string{baseFileFolder, 
srcFileFolder, execFileFolder},
+                               Paths: LifeCyclePaths{
+                                       SourceFileName:                   
fmt.Sprintf("%s%s", pipelineId.String(), goSourceFileExtension),
+                                       AbsoluteSourceFileFolderPath:     
srcFileFolder,
+                                       AbsoluteSourceFilePath:           
filepath.Join(srcFileFolder, fmt.Sprintf("%s%s", pipelineId.String(), 
goSourceFileExtension)),
+                                       ExecutableFileName:               
fmt.Sprintf("%s%s", pipelineId.String(), goExecutableFileExtension),
+                                       AbsoluteExecutableFileFolderPath: 
execFileFolder,
+                                       AbsoluteExecutableFilePath:       
filepath.Join(execFileFolder, fmt.Sprintf("%s%s", pipelineId.String(), 
goExecutableFileExtension)),
+                                       AbsoluteBaseFolderPath:           
baseFileFolder,
+                                       AbsoluteLogFilePath:              
filepath.Join(baseFileFolder, logFileName),
+                               },
                        },
-                       wantErr: true,
                },
                {
-                       name: "file exists",
-                       fields: fields{
-                               folderGlobs:    nil,
-                               Folder:         Folder{},
-                               Extension:      Extension{},
-                               ExecutableName: nil,
-                               pipelineId:     uuid.UUID{},
+                       name: "Python LifeCycle",
+                       args: args{
+                               sdk:             pb.Sdk_SDK_PYTHON,
+                               pipelineId:      pipelineId,
+                               pipelinesFolder: pipelinesFolder,
                        },
+                       want: &LifeCycle{
+                               folderGlobs: []string{baseFileFolder},
+                               Paths: LifeCyclePaths{
+                                       SourceFileName:                   
fmt.Sprintf("%s%s", pipelineId.String(), pythonExecutableFileExtension),
+                                       AbsoluteSourceFileFolderPath:     
baseFileFolder,
+                                       AbsoluteSourceFilePath:           
filepath.Join(baseFileFolder, fmt.Sprintf("%s%s", pipelineId.String(), 
pythonExecutableFileExtension)),
+                                       ExecutableFileName:               
fmt.Sprintf("%s%s", pipelineId.String(), pythonExecutableFileExtension),
+                                       AbsoluteExecutableFileFolderPath: 
baseFileFolder,
+                                       AbsoluteExecutableFilePath:       
filepath.Join(baseFileFolder, fmt.Sprintf("%s%s", pipelineId.String(), 
pythonExecutableFileExtension)),
+                                       AbsoluteBaseFolderPath:           
baseFileFolder,
+                                       AbsoluteLogFilePath:              
filepath.Join(baseFileFolder, logFileName),
+                               },
+                       },
+               },
+               {
+                       name: "Unavailable SDK",
                        args: args{
-                               fileName:       "file.txt",
-                               sourceDir:      sourceDir,
-                               destinationDir: destinationDir,
+                               sdk:             pb.Sdk_SDK_UNSPECIFIED,
+                               pipelineId:      pipelineId,
+                               pipelinesFolder: pipelinesFolder,
                        },
-                       wantErr: false,
+                       want:    nil,
+                       wantErr: true,
                },
        }
        for _, tt := range tests {
                t.Run(tt.name, func(t *testing.T) {
-                       l := &LifeCycle{
-                               folderGlobs:    tt.fields.folderGlobs,
-                               Folder:         tt.fields.Folder,
-                               Extension:      tt.fields.Extension,
-                               ExecutableName: tt.fields.ExecutableName,
-                               pipelineId:     tt.fields.pipelineId,
-                       }
-                       err := l.CopyFile(tt.args.fileName, tt.args.sourceDir, 
tt.args.destinationDir)
+                       got, err := NewLifeCycle(tt.args.sdk, 
tt.args.pipelineId, tt.args.pipelinesFolder)
                        if (err != nil) != tt.wantErr {
-                               t.Errorf("CopyFile() error = %v, wantErr %v", 
err, tt.wantErr)
+                               t.Errorf("NewLifeCycle() error = %v, wantErr 
%v", err, tt.wantErr)
+                               return
                        }
-                       if err == nil && !tt.wantErr {
-                               newFilePath := filepath.Join(destinationDir, 
tt.args.fileName)
-                               _, err = os.Stat(newFilePath)
-                               if os.IsNotExist(err) {
-                                       t.Errorf("CopyFile() should create a 
new file: %s", newFilePath)
-                               }
+                       if !tt.wantErr && !reflect.DeepEqual(got.folderGlobs, 
tt.want.folderGlobs) {
+                               t.Errorf("NewLifeCycle() got folderGlobs = %v, 
want folderGlobs %v", got.folderGlobs, tt.want.folderGlobs)
+                       }
+                       if !tt.wantErr && !checkPathsEqual(got.Paths, 
tt.want.Paths) {
+                               t.Errorf("NewLifeCycle() got Paths = %v, want 
Paths %v", got.Paths, tt.want.Paths)
                        }
                })
        }
 }
+
+func checkPathsEqual(paths1, paths2 LifeCyclePaths) bool {
+       return paths1.SourceFileName == paths2.SourceFileName &&
+               paths1.AbsoluteSourceFileFolderPath == 
paths2.AbsoluteSourceFileFolderPath &&
+               paths1.AbsoluteSourceFilePath == paths2.AbsoluteSourceFilePath 
&&
+               paths1.ExecutableFileName == paths2.ExecutableFileName &&
+               paths1.AbsoluteExecutableFileFolderPath == 
paths2.AbsoluteExecutableFileFolderPath &&
+               paths1.AbsoluteExecutableFilePath == 
paths2.AbsoluteExecutableFilePath &&
+               paths1.AbsoluteBaseFolderPath == paths2.AbsoluteBaseFolderPath 
&&
+               paths1.AbsoluteLogFilePath == paths2.AbsoluteLogFilePath
+}
diff --git a/playground/backend/internal/fs_tool/go_fs_test.go 
b/playground/backend/internal/fs_tool/go_fs_test.go
index 7148b6c..55dbf96 100644
--- a/playground/backend/internal/fs_tool/go_fs_test.go
+++ b/playground/backend/internal/fs_tool/go_fs_test.go
@@ -24,10 +24,10 @@ import (
 
 func Test_newGoLifeCycle(t *testing.T) {
        pipelineId := uuid.New()
-       workingDir := "workingDir"
+       workingDir, _ := filepath.Abs("workingDir")
        baseFileFolder := filepath.Join(workingDir, pipelinesFolder, 
pipelineId.String())
-       srcFileFolder := baseFileFolder + "/src"
-       binFileFolder := baseFileFolder + "/bin"
+       srcFileFolder := filepath.Join(baseFileFolder, "src")
+       binFileFolder := filepath.Join(baseFileFolder, "bin")
 
        type args struct {
                pipelineId      uuid.UUID
@@ -48,16 +48,16 @@ func Test_newGoLifeCycle(t *testing.T) {
                        },
                        want: &LifeCycle{
                                folderGlobs: []string{baseFileFolder, 
srcFileFolder, binFileFolder},
-                               Folder: Folder{
-                                       BaseFolder:           baseFileFolder,
-                                       SourceFileFolder:     srcFileFolder,
-                                       ExecutableFileFolder: binFileFolder,
+                               Paths: LifeCyclePaths{
+                                       SourceFileName:                   
pipelineId.String() + goSourceFileExtension,
+                                       AbsoluteSourceFileFolderPath:     
srcFileFolder,
+                                       AbsoluteSourceFilePath:           
filepath.Join(srcFileFolder, pipelineId.String()+goSourceFileExtension),
+                                       ExecutableFileName:               
pipelineId.String() + goExecutableFileExtension,
+                                       AbsoluteExecutableFileFolderPath: 
binFileFolder,
+                                       AbsoluteExecutableFilePath:       
filepath.Join(binFileFolder, pipelineId.String()+goExecutableFileExtension),
+                                       AbsoluteBaseFolderPath:           
baseFileFolder,
+                                       AbsoluteLogFilePath:              
filepath.Join(baseFileFolder, logFileName),
                                },
-                               Extension: Extension{
-                                       SourceFileExtension:     
goSourceFileExtension,
-                                       ExecutableFileExtension: 
goExecutableFileExtension,
-                               },
-                               pipelineId: pipelineId,
                        },
                },
        }
@@ -67,14 +67,8 @@ func Test_newGoLifeCycle(t *testing.T) {
                        if !reflect.DeepEqual(got.folderGlobs, 
tt.want.folderGlobs) {
                                t.Errorf("newGoLifeCycle() folderGlobs = %v, 
want %v", got.folderGlobs, tt.want.folderGlobs)
                        }
-                       if !reflect.DeepEqual(got.Folder, tt.want.Folder) {
-                               t.Errorf("newGoLifeCycle() Folder = %v, want 
%v", got.Folder, tt.want.Folder)
-                       }
-                       if !reflect.DeepEqual(got.Extension, tt.want.Extension) 
{
-                               t.Errorf("newGoLifeCycle() Extension = %v, want 
%v", got.Extension, tt.want.Extension)
-                       }
-                       if !reflect.DeepEqual(got.pipelineId, 
tt.want.pipelineId) {
-                               t.Errorf("newGoLifeCycle() pipelineId = %v, 
want %v", got.pipelineId, tt.want.pipelineId)
+                       if !reflect.DeepEqual(got.Paths, tt.want.Paths) {
+                               t.Errorf("newGoLifeCycle() Paths = %v, want 
%v", got.Paths, tt.want.Paths)
                        }
                })
        }
diff --git a/playground/backend/internal/fs_tool/java_fs.go 
b/playground/backend/internal/fs_tool/java_fs.go
index f5608a2..1e81553 100644
--- a/playground/backend/internal/fs_tool/java_fs.go
+++ b/playground/backend/internal/fs_tool/java_fs.go
@@ -24,14 +24,14 @@ import (
 )
 
 const (
-       JavaSourceFileExtension   = ".java"
+       javaSourceFileExtension   = ".java"
        javaCompiledFileExtension = ".class"
 )
 
 // newJavaLifeCycle creates LifeCycle with java SDK environment.
 func newJavaLifeCycle(pipelineId uuid.UUID, pipelinesFolder string) *LifeCycle 
{
-       javaLifeCycle := newCompilingLifeCycle(pipelineId, pipelinesFolder, 
JavaSourceFileExtension, javaCompiledFileExtension)
-       javaLifeCycle.ExecutableName = executableName
+       javaLifeCycle := newCompilingLifeCycle(pipelineId, pipelinesFolder, 
javaSourceFileExtension, javaCompiledFileExtension)
+       javaLifeCycle.Paths.ExecutableName = executableName
        return javaLifeCycle
 }
 
diff --git a/playground/backend/internal/fs_tool/java_fs_test.go 
b/playground/backend/internal/fs_tool/java_fs_test.go
index aa3445f..6a414cf 100644
--- a/playground/backend/internal/fs_tool/java_fs_test.go
+++ b/playground/backend/internal/fs_tool/java_fs_test.go
@@ -25,10 +25,10 @@ import (
 
 func Test_newJavaLifeCycle(t *testing.T) {
        pipelineId := uuid.New()
-       workingDir := "workingDir"
+       workingDir, _ := filepath.Abs("workingDir")
        baseFileFolder := filepath.Join(workingDir, pipelinesFolder, 
pipelineId.String())
-       srcFileFolder := baseFileFolder + "/src"
-       binFileFolder := baseFileFolder + "/bin"
+       srcFileFolder := filepath.Join(baseFileFolder, "src")
+       binFileFolder := filepath.Join(baseFileFolder, "bin")
 
        type args struct {
                pipelineId      uuid.UUID
@@ -49,17 +49,17 @@ func Test_newJavaLifeCycle(t *testing.T) {
                        },
                        want: &LifeCycle{
                                folderGlobs: []string{baseFileFolder, 
srcFileFolder, binFileFolder},
-                               Folder: Folder{
-                                       BaseFolder:           baseFileFolder,
-                                       SourceFileFolder:     srcFileFolder,
-                                       ExecutableFileFolder: binFileFolder,
+                               Paths: LifeCyclePaths{
+                                       SourceFileName:                   
pipelineId.String() + javaSourceFileExtension,
+                                       AbsoluteSourceFileFolderPath:     
srcFileFolder,
+                                       AbsoluteSourceFilePath:           
filepath.Join(srcFileFolder, pipelineId.String()+javaSourceFileExtension),
+                                       ExecutableFileName:               
pipelineId.String() + javaCompiledFileExtension,
+                                       AbsoluteExecutableFileFolderPath: 
binFileFolder,
+                                       AbsoluteExecutableFilePath:       
filepath.Join(binFileFolder, pipelineId.String()+javaCompiledFileExtension),
+                                       AbsoluteBaseFolderPath:           
baseFileFolder,
+                                       AbsoluteLogFilePath:              
filepath.Join(baseFileFolder, logFileName),
+                                       ExecutableName:                   
executableName,
                                },
-                               Extension: Extension{
-                                       SourceFileExtension:     
JavaSourceFileExtension,
-                                       ExecutableFileExtension: 
javaCompiledFileExtension,
-                               },
-                               ExecutableName: executableName,
-                               pipelineId:     pipelineId,
                        },
                },
        }
@@ -69,14 +69,8 @@ func Test_newJavaLifeCycle(t *testing.T) {
                        if !reflect.DeepEqual(got.folderGlobs, 
tt.want.folderGlobs) {
                                t.Errorf("newJavaLifeCycle() folderGlobs = %v, 
want %v", got.folderGlobs, tt.want.folderGlobs)
                        }
-                       if !reflect.DeepEqual(got.Folder, tt.want.Folder) {
-                               t.Errorf("newJavaLifeCycle() Folder = %v, want 
%v", got.Folder, tt.want.Folder)
-                       }
-                       if !reflect.DeepEqual(got.Extension, tt.want.Extension) 
{
-                               t.Errorf("newJavaLifeCycle() Extension = %v, 
want %v", got.Extension, tt.want.Extension)
-                       }
-                       if !reflect.DeepEqual(got.pipelineId, 
tt.want.pipelineId) {
-                               t.Errorf("newJavaLifeCycle() pipelineId = %v, 
want %v", got.pipelineId, tt.want.pipelineId)
+                       if !checkPathsEqual(got.Paths, tt.want.Paths) {
+                               t.Errorf("newJavaLifeCycle() Paths = %v, want 
%v", got.Paths, tt.want.Paths)
                        }
                })
        }
diff --git a/playground/backend/internal/fs_tool/lc_constructor.go 
b/playground/backend/internal/fs_tool/lc_constructor.go
index 66e9bbf..097c554 100644
--- a/playground/backend/internal/fs_tool/lc_constructor.go
+++ b/playground/backend/internal/fs_tool/lc_constructor.go
@@ -30,35 +30,51 @@ func newCompilingLifeCycle(pipelineId uuid.UUID, 
pipelinesFolder, sourceFileExte
        baseFileFolder := filepath.Join(pipelinesFolder, pipelineId.String())
        srcFileFolder := filepath.Join(baseFileFolder, sourceFolderName)
        binFileFolder := filepath.Join(baseFileFolder, compiledFolderName)
+
+       srcFileName := pipelineId.String() + sourceFileExtension
+       absSrcFileFolderPath, _ := filepath.Abs(srcFileFolder)
+       absSrcFilePath, _ := filepath.Abs(filepath.Join(absSrcFileFolderPath, 
srcFileName))
+       execFileName := pipelineId.String() + compiledFileExtension
+       absExecFileFolderPath, _ := filepath.Abs(binFileFolder)
+       absExecFilePath, _ := filepath.Abs(filepath.Join(absExecFileFolderPath, 
execFileName))
+       absBaseFolderPath, _ := filepath.Abs(baseFileFolder)
+       absLogFilePath, _ := filepath.Abs(filepath.Join(absBaseFolderPath, 
logFileName))
+
        return &LifeCycle{
                folderGlobs: []string{baseFileFolder, srcFileFolder, 
binFileFolder},
-               Folder: Folder{
-                       BaseFolder:           baseFileFolder,
-                       SourceFileFolder:     srcFileFolder,
-                       ExecutableFileFolder: binFileFolder,
-               },
-               Extension: Extension{
-                       SourceFileExtension:     sourceFileExtension,
-                       ExecutableFileExtension: compiledFileExtension,
+               Paths: LifeCyclePaths{
+                       SourceFileName:                   srcFileName,
+                       AbsoluteSourceFileFolderPath:     absSrcFileFolderPath,
+                       AbsoluteSourceFilePath:           absSrcFilePath,
+                       ExecutableFileName:               execFileName,
+                       AbsoluteExecutableFileFolderPath: absExecFileFolderPath,
+                       AbsoluteExecutableFilePath:       absExecFilePath,
+                       AbsoluteBaseFolderPath:           absBaseFolderPath,
+                       AbsoluteLogFilePath:              absLogFilePath,
                },
-               pipelineId: pipelineId,
        }
 }
 
 // newInterpretedLifeCycle creates LifeCycle for interpreted SDK environment.
 func newInterpretedLifeCycle(pipelineId uuid.UUID, pipelinesFolder, 
sourceFileExtension string) *LifeCycle {
        sourceFileFolder := filepath.Join(pipelinesFolder, pipelineId.String())
+
+       fileName := pipelineId.String() + sourceFileExtension
+       absFileFolderPath, _ := filepath.Abs(sourceFileFolder)
+       absFilePath, _ := filepath.Abs(filepath.Join(absFileFolderPath, 
fileName))
+       absLogFilePath, _ := filepath.Abs(filepath.Join(absFileFolderPath, 
logFileName))
+
        return &LifeCycle{
                folderGlobs: []string{sourceFileFolder},
-               Folder: Folder{
-                       BaseFolder:           sourceFileFolder,
-                       SourceFileFolder:     sourceFileFolder,
-                       ExecutableFileFolder: sourceFileFolder,
-               },
-               Extension: Extension{
-                       ExecutableFileExtension: sourceFileExtension,
-                       SourceFileExtension:     sourceFileExtension,
+               Paths: LifeCyclePaths{
+                       SourceFileName:                   fileName,
+                       AbsoluteSourceFileFolderPath:     absFileFolderPath,
+                       AbsoluteSourceFilePath:           absFilePath,
+                       ExecutableFileName:               fileName,
+                       AbsoluteExecutableFileFolderPath: absFileFolderPath,
+                       AbsoluteExecutableFilePath:       absFilePath,
+                       AbsoluteBaseFolderPath:           absFileFolderPath,
+                       AbsoluteLogFilePath:              absLogFilePath,
                },
-               pipelineId: pipelineId,
        }
 }
diff --git a/playground/backend/internal/fs_tool/python_fs_test.go 
b/playground/backend/internal/fs_tool/python_fs_test.go
index 412a52d..628722c 100644
--- a/playground/backend/internal/fs_tool/python_fs_test.go
+++ b/playground/backend/internal/fs_tool/python_fs_test.go
@@ -24,7 +24,7 @@ import (
 
 func Test_newPythonLifeCycle(t *testing.T) {
        pipelineId := uuid.New()
-       workingDir := "workingDir"
+       workingDir, _ := filepath.Abs("workingDir")
        baseFileFolder := filepath.Join(workingDir, pipelinesFolder, 
pipelineId.String())
 
        type args struct {
@@ -46,16 +46,16 @@ func Test_newPythonLifeCycle(t *testing.T) {
                        },
                        want: &LifeCycle{
                                folderGlobs: []string{baseFileFolder},
-                               Folder: Folder{
-                                       BaseFolder:           baseFileFolder,
-                                       SourceFileFolder:     baseFileFolder,
-                                       ExecutableFileFolder: baseFileFolder,
+                               Paths: LifeCyclePaths{
+                                       SourceFileName:                   
pipelineId.String() + pythonExecutableFileExtension,
+                                       AbsoluteSourceFileFolderPath:     
baseFileFolder,
+                                       AbsoluteSourceFilePath:           
filepath.Join(baseFileFolder, 
pipelineId.String()+pythonExecutableFileExtension),
+                                       ExecutableFileName:               
pipelineId.String() + pythonExecutableFileExtension,
+                                       AbsoluteExecutableFileFolderPath: 
baseFileFolder,
+                                       AbsoluteExecutableFilePath:       
filepath.Join(baseFileFolder, 
pipelineId.String()+pythonExecutableFileExtension),
+                                       AbsoluteBaseFolderPath:           
baseFileFolder,
+                                       AbsoluteLogFilePath:              
filepath.Join(baseFileFolder, logFileName),
                                },
-                               Extension: Extension{
-                                       SourceFileExtension:     
pythonExecutableFileExtension,
-                                       ExecutableFileExtension: 
pythonExecutableFileExtension,
-                               },
-                               pipelineId: pipelineId,
                        },
                },
        }
@@ -65,14 +65,8 @@ func Test_newPythonLifeCycle(t *testing.T) {
                        if !reflect.DeepEqual(got.folderGlobs, 
tt.want.folderGlobs) {
                                t.Errorf("newPythonLifeCycle() folderGlobs = 
%v, want %v", got.folderGlobs, tt.want.folderGlobs)
                        }
-                       if !reflect.DeepEqual(got.Folder, tt.want.Folder) {
-                               t.Errorf("newPythonLifeCycle() Folder = %v, 
want %v", got.Folder, tt.want.Folder)
-                       }
-                       if !reflect.DeepEqual(got.Extension, tt.want.Extension) 
{
-                               t.Errorf("newPythonLifeCycle() Extension = %v, 
want %v", got.Extension, tt.want.Extension)
-                       }
-                       if !reflect.DeepEqual(got.pipelineId, 
tt.want.pipelineId) {
-                               t.Errorf("newPythonLifeCycle() pipelineId = %v, 
want %v", got.pipelineId, tt.want.pipelineId)
+                       if !checkPathsEqual(got.Paths, tt.want.Paths) {
+                               t.Errorf("newPythonLifeCycle() Paths = %v, want 
%v", got.Paths, tt.want.Paths)
                        }
                })
        }
diff --git a/playground/backend/internal/preparators/java_preparators.go 
b/playground/backend/internal/preparators/java_preparators.go
index 26e5d6e..07b0a6a 100644
--- a/playground/backend/internal/preparators/java_preparators.go
+++ b/playground/backend/internal/preparators/java_preparators.go
@@ -16,7 +16,6 @@
 package preparators
 
 import (
-       "beam.apache.org/playground/backend/internal/fs_tool"
        "beam.apache.org/playground/backend/internal/logger"
        "beam.apache.org/playground/backend/internal/validators"
        "bufio"
@@ -203,7 +202,7 @@ func changeJavaTestFileName(args ...interface{}) error {
 
 func renameJavaFile(filePath string, className string) error {
        currentFileName := filepath.Base(filePath)
-       newFilePath := strings.Replace(filePath, currentFileName, 
fmt.Sprintf("%s%s", className, fs_tool.JavaSourceFileExtension), 1)
+       newFilePath := strings.Replace(filePath, currentFileName, 
fmt.Sprintf("%s%s", className, filepath.Ext(currentFileName)), 1)
        err := os.Rename(filePath, newFilePath)
        return err
 }
diff --git a/playground/backend/internal/preparators/java_preparators_test.go 
b/playground/backend/internal/preparators/java_preparators_test.go
index 7385c56..145d703 100644
--- a/playground/backend/internal/preparators/java_preparators_test.go
+++ b/playground/backend/internal/preparators/java_preparators_test.go
@@ -28,8 +28,6 @@ import (
        "testing"
 )
 
-const pipelinesFolder = "executable_files"
-
 func Test_replace(t *testing.T) {
        codeWithPublicClass := "package org.apache.beam.sdk.transforms; \n 
public class Class {\n    public static void main(String[] args) {\n        
System.out.println(\"Hello World!\");\n    }\n}"
        codeWithoutPublicClass := "package org.apache.beam.sdk.transforms; \n 
class Class {\n    public static void main(String[] args) {\n        
System.out.println(\"Hello World!\");\n    }\n}"
@@ -42,7 +40,7 @@ func Test_replace(t *testing.T) {
        lc, _ := fs_tool.NewLifeCycle(pb.Sdk_SDK_JAVA, uuid.New(), 
filepath.Join(path, "temp"))
        _ = lc.CreateFolders()
        defer os.RemoveAll(filepath.Join(path, "temp"))
-       _, _ = lc.CreateSourceCodeFile(codeWithPublicClass)
+       _ = lc.CreateSourceCodeFile(codeWithPublicClass)
 
        type args struct {
                args []interface{}
@@ -60,14 +58,14 @@ func Test_replace(t *testing.T) {
                },
                {
                        name:     "original file exists",
-                       args:     
args{[]interface{}{lc.GetAbsoluteSourceFilePath(), 
classWithPublicModifierPattern, classWithoutPublicModifierPattern}},
+                       args:     
args{[]interface{}{lc.Paths.AbsoluteSourceFilePath, 
classWithPublicModifierPattern, classWithoutPublicModifierPattern}},
                        wantCode: codeWithoutPublicClass,
                        wantErr:  false,
                },
                {
                        // Test that file where package is used changes to 
import all dependencies from this package
                        name:     "original file with package",
-                       args:     
args{[]interface{}{lc.GetAbsoluteSourceFilePath(), packagePattern, 
importStringPattern}},
+                       args:     
args{[]interface{}{lc.Paths.AbsoluteSourceFilePath, packagePattern, 
importStringPattern}},
                        wantCode: codeWithImportedPackage,
                        wantErr:  false,
                },
@@ -123,7 +121,7 @@ func Test_changeJavaTestFileName(t *testing.T) {
        lc, _ := fs_tool.NewLifeCycle(pb.Sdk_SDK_JAVA, uuid.New(), 
filepath.Join(path, "temp"))
        _ = lc.CreateFolders()
        defer os.RemoveAll(filepath.Join(path, "temp"))
-       _, _ = lc.CreateSourceCodeFile(codeWithPublicClass)
+       _ = lc.CreateSourceCodeFile(codeWithPublicClass)
        validationResults := sync.Map{}
        validationResults.Store(validators.UnitTestValidatorName, true)
 
@@ -139,7 +137,7 @@ func Test_changeJavaTestFileName(t *testing.T) {
                {
                        // Test that file changes its name to the name of its 
public class
                        name:     "file with java unit test code to be renamed",
-                       args:     
args{[]interface{}{lc.GetAbsoluteSourceFilePath(), &validationResults}},
+                       args:     
args{[]interface{}{lc.Paths.AbsoluteSourceFilePath, &validationResults}},
                        wantErr:  false,
                        wantName: "Class.java",
                },
@@ -149,7 +147,7 @@ func Test_changeJavaTestFileName(t *testing.T) {
                        if err := changeJavaTestFileName(tt.args.args...); (err 
!= nil) != tt.wantErr {
                                t.Errorf("changeJavaTestFileName() error = %v, 
wantErr %v", err, tt.wantErr)
                        }
-                       files, err := filepath.Glob(fmt.Sprintf("%s/*java", 
lc.GetAbsoluteSourceFolderPath()))
+                       files, err := filepath.Glob(fmt.Sprintf("%s/*java", 
lc.Paths.AbsoluteSourceFileFolderPath))
                        if err != nil {
                                t.Errorf("changeJavaTestFileName() error = %v, 
wantErr %v", err, tt.wantErr)
                        }
diff --git a/playground/backend/internal/setup_tools/builder/setup_builder.go 
b/playground/backend/internal/setup_tools/builder/setup_builder.go
index cb92f04..19847de 100644
--- a/playground/backend/internal/setup_tools/builder/setup_builder.go
+++ b/playground/backend/internal/setup_tools/builder/setup_builder.go
@@ -32,25 +32,25 @@ const (
 )
 
 // SetupExecutorBuilder return executor with set args for validator, 
preparator, compiler and runner
-func SetupExecutorBuilder(lc *fs_tool.LifeCycle, pipelineOptions string, 
sdkEnv *environment.BeamEnvs) (*executors.ExecutorBuilder, error) {
+func SetupExecutorBuilder(paths fs_tool.LifeCyclePaths, pipelineOptions 
string, sdkEnv *environment.BeamEnvs) (*executors.ExecutorBuilder, error) {
        sdk := sdkEnv.ApacheBeamSdk
 
        if sdk == pb.Sdk_SDK_JAVA {
                pipelineOptions = utils.ReplaceSpacesWithEquals(pipelineOptions)
        }
 
-       val, err := utils.GetValidators(sdk, lc.GetAbsoluteSourceFilePath())
+       val, err := utils.GetValidators(sdk, paths.AbsoluteSourceFilePath)
        if err != nil {
                return nil, err
        }
-       prep, err := utils.GetPreparators(sdk, lc.GetAbsoluteSourceFilePath())
+       prep, err := utils.GetPreparators(sdk, paths.AbsoluteSourceFilePath)
        if err != nil {
                return nil, err
        }
        executorConfig := sdkEnv.ExecutorConfig
        builder := executors.NewExecutorBuilder().
-               WithExecutableFileName(lc.GetAbsoluteExecutableFilePath()).
-               WithWorkingDir(lc.GetAbsoluteBaseFolderPath()).
+               WithExecutableFileName(paths.AbsoluteExecutableFilePath).
+               WithWorkingDir(paths.AbsoluteBaseFolderPath).
                WithValidator().
                WithSdkValidators(val).
                WithPreparator().
@@ -58,7 +58,7 @@ func SetupExecutorBuilder(lc *fs_tool.LifeCycle, 
pipelineOptions string, sdkEnv
                WithCompiler().
                WithCommand(executorConfig.CompileCmd).
                WithArgs(executorConfig.CompileArgs).
-               WithFileName(lc.GetAbsoluteSourceFilePath()).
+               WithFileName(paths.AbsoluteSourceFilePath).
                WithRunner().
                WithCommand(executorConfig.RunCmd).
                WithArgs(executorConfig.RunArgs).
@@ -66,7 +66,7 @@ func SetupExecutorBuilder(lc *fs_tool.LifeCycle, 
pipelineOptions string, sdkEnv
                WithTestRunner().
                WithCommand(executorConfig.TestCmd).
                WithArgs(executorConfig.TestArgs).
-               WithWorkingDir(lc.GetAbsoluteSourceFolderPath()).
+               WithWorkingDir(paths.AbsoluteSourceFileFolderPath).
                ExecutorBuilder
 
        switch sdk {
@@ -74,20 +74,20 @@ func SetupExecutorBuilder(lc *fs_tool.LifeCycle, 
pipelineOptions string, sdkEnv
                args := make([]string, 0)
                for _, arg := range executorConfig.RunArgs {
                        if strings.Contains(arg, javaLogConfigFilePlaceholder) {
-                               logConfigFilePath := 
filepath.Join(lc.GetAbsoluteBaseFolderPath(), javaLogConfigFileName)
+                               logConfigFilePath := 
filepath.Join(paths.AbsoluteBaseFolderPath, javaLogConfigFileName)
                                arg = strings.Replace(arg, 
javaLogConfigFilePlaceholder, logConfigFilePath, 1)
                        }
                        args = append(args, arg)
                }
                builder = builder.WithRunner().WithArgs(args).ExecutorBuilder
-               builder = 
builder.WithTestRunner().WithWorkingDir(lc.GetAbsoluteBaseFolderPath()).ExecutorBuilder
 //change directory for unit test
+               builder = 
builder.WithTestRunner().WithWorkingDir(paths.AbsoluteBaseFolderPath).ExecutorBuilder
 //change directory for unit test
        case pb.Sdk_SDK_GO: //go run command is executable file itself
                builder = builder.
                        WithExecutableFileName("").
                        WithRunner().
-                       
WithCommand(lc.GetAbsoluteExecutableFilePath()).ExecutorBuilder
+                       
WithCommand(paths.AbsoluteExecutableFilePath).ExecutorBuilder
        case pb.Sdk_SDK_PYTHON:
-               builder = 
*builder.WithExecutableFileName(lc.GetAbsoluteExecutableFilePath())
+               builder = 
*builder.WithExecutableFileName(paths.AbsoluteExecutableFilePath)
        case pb.Sdk_SDK_SCIO:
                return nil, fmt.Errorf("SCIO is not supported yet")
        default:
@@ -97,7 +97,7 @@ func SetupExecutorBuilder(lc *fs_tool.LifeCycle, 
pipelineOptions string, sdkEnv
 }
 
 // GetFileNameFromFolder return a name of the first file in a specified folder
-func GetFileNameFromFolder(folderAbsolutePath string) string {
-       files, _ := filepath.Glob(fmt.Sprintf("%s/*%s", folderAbsolutePath, 
fs_tool.JavaSourceFileExtension))
+func GetFileNameFromFolder(folderAbsolutePath, extension string) string {
+       files, _ := filepath.Glob(fmt.Sprintf("%s/*%s", folderAbsolutePath, 
extension))
        return files[0]
 }
diff --git 
a/playground/backend/internal/setup_tools/builder/setup_builder_test.go 
b/playground/backend/internal/setup_tools/builder/setup_builder_test.go
index 0b7487d..f862c7c 100644
--- a/playground/backend/internal/setup_tools/builder/setup_builder_test.go
+++ b/playground/backend/internal/setup_tools/builder/setup_builder_test.go
@@ -47,7 +47,7 @@ func TestSetupExecutor(t *testing.T) {
                panic(err)
        }
 
-       srcFilePath := lc.GetAbsoluteSourceFilePath()
+       srcFilePath := lc.Paths.AbsoluteSourceFilePath
 
        sdkEnv := environment.NewBeamEnvs(sdk, executorConfig, "", 0)
        val, err := utils.GetValidators(sdk, srcFilePath)
@@ -60,8 +60,8 @@ func TestSetupExecutor(t *testing.T) {
        }
 
        wantExecutor := executors.NewExecutorBuilder().
-               WithExecutableFileName(lc.GetAbsoluteExecutableFilePath()).
-               WithWorkingDir(lc.GetAbsoluteBaseFolderPath()).
+               WithExecutableFileName(lc.Paths.AbsoluteExecutableFilePath).
+               WithWorkingDir(lc.Paths.AbsoluteBaseFolderPath).
                WithValidator().
                WithSdkValidators(val).
                WithPreparator().
@@ -77,11 +77,11 @@ func TestSetupExecutor(t *testing.T) {
                WithTestRunner().
                WithCommand(executorConfig.TestCmd).
                WithArgs(executorConfig.TestArgs).
-               WithWorkingDir(lc.GetAbsoluteBaseFolderPath()).
+               WithWorkingDir(lc.Paths.AbsoluteBaseFolderPath).
                ExecutorBuilder
 
        type args struct {
-               lc              *fs_tool.LifeCycle
+               dto             fs_tool.LifeCyclePaths
                pipelineOptions string
                sdkEnv          *environment.BeamEnvs
        }
@@ -95,7 +95,7 @@ func TestSetupExecutor(t *testing.T) {
                        // Test case with calling Setup with incorrect SDK.
                        // As a result, want to receive an error.
                        name:    "incorrect sdk",
-                       args:    args{lc, pipelineOptions, 
environment.NewBeamEnvs(pb.Sdk_SDK_UNSPECIFIED, executorConfig, "", 0)},
+                       args:    args{lc.Paths, pipelineOptions, 
environment.NewBeamEnvs(pb.Sdk_SDK_UNSPECIFIED, executorConfig, "", 0)},
                        want:    nil,
                        wantErr: true,
                },
@@ -103,14 +103,14 @@ func TestSetupExecutor(t *testing.T) {
                        // Test case with calling Setup with correct SDK.
                        // As a result, want to receive an expected builder.
                        name:    "correct sdk",
-                       args:    args{lc, pipelineOptions, sdkEnv},
+                       args:    args{lc.Paths, pipelineOptions, sdkEnv},
                        want:    &wantExecutor,
                        wantErr: false,
                },
        }
        for _, tt := range tests {
                t.Run(tt.name, func(t *testing.T) {
-                       got, err := SetupExecutorBuilder(tt.args.lc, 
tt.args.pipelineOptions, tt.args.sdkEnv)
+                       got, err := SetupExecutorBuilder(tt.args.dto, 
tt.args.pipelineOptions, tt.args.sdkEnv)
                        if (err != nil) != tt.wantErr {
                                t.Errorf("SetupExecutorBuilder() error = %v, 
wantErr %v", err, tt.wantErr)
                                return
diff --git 
a/playground/backend/internal/setup_tools/life_cycle/life_cycle_setuper.go 
b/playground/backend/internal/setup_tools/life_cycle/life_cycle_setuper.go
index c23d9f3..b9fd155 100644
--- a/playground/backend/internal/setup_tools/life_cycle/life_cycle_setuper.go
+++ b/playground/backend/internal/setup_tools/life_cycle/life_cycle_setuper.go
@@ -68,7 +68,7 @@ func Setup(sdk pb.Sdk, code string, pipelineId uuid.UUID, 
workingDir, pipelinesF
        }
 
        // create file with code
-       _, err = lc.CreateSourceCodeFile(code)
+       err = lc.CreateSourceCodeFile(code)
        if err != nil {
                logger.Errorf("%s: RunCode(): CreateSourceCodeFile(): %s\n", 
pipelineId, err.Error())
                lc.DeleteFolders()
@@ -80,11 +80,11 @@ func Setup(sdk pb.Sdk, code string, pipelineId uuid.UUID, 
workingDir, pipelinesF
 // prepareGoFiles prepares file for Go environment.
 // Copy go.mod and go.sum file from /path/to/preparedModDir to 
/path/to/workingDir/pipelinesFolder/{pipelineId}
 func prepareGoFiles(lc *fs_tool.LifeCycle, preparedModDir string, pipelineId 
uuid.UUID) error {
-       if err := lc.CopyFile(goModFileName, preparedModDir, 
lc.Folder.BaseFolder); err != nil {
+       if err := lc.CopyFile(goModFileName, preparedModDir, 
lc.Paths.AbsoluteBaseFolderPath); err != nil {
                logger.Errorf("%s: error during copying %s file: %s\n", 
pipelineId, goModFileName, err.Error())
                return err
        }
-       if err := lc.CopyFile(goSumFileName, preparedModDir, 
lc.Folder.BaseFolder); err != nil {
+       if err := lc.CopyFile(goSumFileName, preparedModDir, 
lc.Paths.AbsoluteBaseFolderPath); err != nil {
                logger.Errorf("%s: error during copying %s file: %s\n", 
pipelineId, goSumFileName, err.Error())
                return err
        }
@@ -95,12 +95,12 @@ func prepareGoFiles(lc *fs_tool.LifeCycle, preparedModDir 
string, pipelineId uui
 // Copy log config file from /path/to/workingDir to 
/path/to/workingDir/pipelinesFolder/{pipelineId}
 //     and update this file according to pipeline.
 func prepareJavaFiles(lc *fs_tool.LifeCycle, workingDir string, pipelineId 
uuid.UUID) error {
-       err := lc.CopyFile(javaLogConfigFileName, workingDir, 
lc.Folder.BaseFolder)
+       err := lc.CopyFile(javaLogConfigFileName, workingDir, 
lc.Paths.AbsoluteBaseFolderPath)
        if err != nil {
                logger.Errorf("%s: error during copying logging.properties 
file: %s\n", pipelineId, err.Error())
                return err
        }
-       err = updateJavaLogConfigFile(lc)
+       err = updateJavaLogConfigFile(lc.Paths)
        if err != nil {
                logger.Errorf("%s: error during updating logging.properties 
file: %s\n", pipelineId, err.Error())
                return err
@@ -109,9 +109,9 @@ func prepareJavaFiles(lc *fs_tool.LifeCycle, workingDir 
string, pipelineId uuid.
 }
 
 // updateJavaLogConfigFile updates java log config file according to pipeline
-func updateJavaLogConfigFile(lc *fs_tool.LifeCycle) error {
-       logConfigFilePath := filepath.Join(lc.Folder.BaseFolder, 
javaLogConfigFileName)
-       logConfigUpdatedFilePath := filepath.Join(lc.Folder.BaseFolder, 
javaTmpLogConfigFile)
+func updateJavaLogConfigFile(paths fs_tool.LifeCyclePaths) error {
+       logConfigFilePath := filepath.Join(paths.AbsoluteBaseFolderPath, 
javaLogConfigFileName)
+       logConfigUpdatedFilePath := filepath.Join(paths.AbsoluteBaseFolderPath, 
javaTmpLogConfigFile)
        if _, err := os.Stat(logConfigFilePath); os.IsNotExist(err) {
                return err
        }
@@ -129,7 +129,7 @@ func updateJavaLogConfigFile(lc *fs_tool.LifeCycle) error {
 
        for scanner.Scan() {
                line := scanner.Text()
-               line = strings.ReplaceAll(line, javaLogFilePlaceholder, 
lc.GetAbsoluteLogFilePath())
+               line = strings.ReplaceAll(line, javaLogFilePlaceholder, 
paths.AbsoluteLogFilePath)
                if _, err = io.WriteString(updatedFile, line+"\n"); err != nil {
                        return err
                }
diff --git 
a/playground/backend/internal/setup_tools/life_cycle/life_cycle_setuper_test.go 
b/playground/backend/internal/setup_tools/life_cycle/life_cycle_setuper_test.go
index cd335c9..a698991 100644
--- 
a/playground/backend/internal/setup_tools/life_cycle/life_cycle_setuper_test.go
+++ 
b/playground/backend/internal/setup_tools/life_cycle/life_cycle_setuper_test.go
@@ -18,25 +18,30 @@ package life_cycle
 import (
        playground "beam.apache.org/playground/backend/internal/api/v1"
        "beam.apache.org/playground/backend/internal/fs_tool"
+       "fmt"
        "github.com/google/uuid"
        "io/fs"
        "os"
        "path/filepath"
-       "reflect"
        "testing"
 )
 
 const (
-       workingDir              = "workingDir"
-       sourceFolder            = "src"
-       executableFolder        = "bin"
-       javaSourceFileExtension = ".java"
-       pipelinesFolder         = "executable_files"
+       workingDir                = "workingDir"
+       sourceFolder              = "src"
+       executableFolder          = "bin"
+       javaSourceFileExtension   = ".java"
+       javaCompiledFileExtension = ".class"
+       pipelinesFolder           = "executable_files"
+       logFileName               = "logs.log"
 )
 
 func TestSetup(t *testing.T) {
        errorPipelineId := uuid.New()
        successPipelineId := uuid.New()
+       baseFileFolder, _ := filepath.Abs(filepath.Join(workingDir, 
pipelinesFolder, successPipelineId.String()))
+       srcFileFolder := filepath.Join(baseFileFolder, sourceFolder)
+       execFileFolder := filepath.Join(baseFileFolder, executableFolder)
 
        err := os.MkdirAll(workingDir, fs.ModePerm)
        if err != nil {
@@ -47,11 +52,6 @@ func TestSetup(t *testing.T) {
                panic(err)
        }
        defer os.RemoveAll(workingDir)
-
-       lc, err := fs_tool.NewLifeCycle(playground.Sdk_SDK_JAVA, 
successPipelineId, filepath.Join(workingDir, pipelinesFolder))
-       if err != nil {
-               panic(err)
-       }
        type args struct {
                sdk             playground.Sdk
                code            string
@@ -114,7 +114,18 @@ func TestSetup(t *testing.T) {
                                }
                                return true
                        },
-                       want:    lc,
+                       want: &fs_tool.LifeCycle{
+                               Paths: fs_tool.LifeCyclePaths{
+                                       SourceFileName:                   
fmt.Sprintf("%s%s", successPipelineId.String(), javaSourceFileExtension),
+                                       AbsoluteSourceFileFolderPath:     
srcFileFolder,
+                                       AbsoluteSourceFilePath:           
filepath.Join(srcFileFolder, fmt.Sprintf("%s%s", successPipelineId.String(), 
javaSourceFileExtension)),
+                                       ExecutableFileName:               
fmt.Sprintf("%s%s", successPipelineId.String(), javaCompiledFileExtension),
+                                       AbsoluteExecutableFileFolderPath: 
execFileFolder,
+                                       AbsoluteExecutableFilePath:       
filepath.Join(execFileFolder, fmt.Sprintf("%s%s", successPipelineId.String(), 
javaCompiledFileExtension)),
+                                       AbsoluteBaseFolderPath:           
baseFileFolder,
+                                       AbsoluteLogFilePath:              
filepath.Join(baseFileFolder, logFileName),
+                               },
+                       },
                        wantErr: false,
                },
        }
@@ -126,17 +137,22 @@ func TestSetup(t *testing.T) {
                                return
                        }
                        if got != nil {
-                               if !reflect.DeepEqual(got.Folder, 
tt.want.Folder) {
-                                       t.Errorf("Setup() got.Folder = %v, want 
%v", got.Folder, tt.want.Folder)
-                               }
-                               if !reflect.DeepEqual(got.Extension, 
tt.want.Extension) {
-                                       t.Errorf("Setup() got.Extension = %v, 
want %v", got.Extension, tt.want.Extension)
-                               }
-                               if !tt.check() {
-                                       t.Errorf("Setup() doesn't prepare 
necessary files/folders")
+                               if !checkPathsEqual(got.Paths, tt.want.Paths) {
+                                       t.Errorf("Setup() got.Paths = %v, want 
%v", got.Paths, tt.want.Paths)
                                }
                        }
-                       os.RemoveAll(tt.args.pipelinesFolder)
+                       os.RemoveAll(pipelinesFolder)
                })
        }
 }
+
+func checkPathsEqual(paths1, paths2 fs_tool.LifeCyclePaths) bool {
+       return paths1.SourceFileName == paths2.SourceFileName &&
+               paths1.AbsoluteSourceFileFolderPath == 
paths2.AbsoluteSourceFileFolderPath &&
+               paths1.AbsoluteSourceFilePath == paths2.AbsoluteSourceFilePath 
&&
+               paths1.ExecutableFileName == paths2.ExecutableFileName &&
+               paths1.AbsoluteExecutableFileFolderPath == 
paths2.AbsoluteExecutableFileFolderPath &&
+               paths1.AbsoluteExecutableFilePath == 
paths2.AbsoluteExecutableFilePath &&
+               paths1.AbsoluteBaseFolderPath == paths2.AbsoluteBaseFolderPath 
&&
+               paths1.AbsoluteLogFilePath == paths2.AbsoluteLogFilePath
+}
diff --git a/playground/backend/internal/utils/system_utils.go 
b/playground/backend/internal/utils/system_utils.go
index 2a35705..51628fe 100644
--- a/playground/backend/internal/utils/system_utils.go
+++ b/playground/backend/internal/utils/system_utils.go
@@ -56,11 +56,10 @@ func GetReadinessFunction(envs *environment.Environment) 
func(writer http.Respon
 }
 
 // checkNumOfTheParallelJobs checks the number of currently working code 
executions.
-//  It counts by the number of the 
/path/to/workingDir/executable_files/{pipelineId} folders.
+//  It counts by the number of the 
/path/to/workingDir/executableFiles/{pipelineId} folders.
 // If it is equals or more than numOfParallelJobs, then returns false.
 // If it is less than numOfParallelJobs, then returns true.
 func checkNumOfTheParallelJobs(workingDir string, numOfParallelJobs int) bool {
-       // TODO [BEAM-13308] add getting of dir executable_files from 
environments.
        baseFileFolder := filepath.Join(workingDir, executableFiles)
        _, err := os.Stat(baseFileFolder)
        if os.IsNotExist(err) {
diff --git a/playground/backend/internal/utils/system_utils_test.go 
b/playground/backend/internal/utils/system_utils_test.go
index b745934..34b6d33 100644
--- a/playground/backend/internal/utils/system_utils_test.go
+++ b/playground/backend/internal/utils/system_utils_test.go
@@ -47,7 +47,6 @@ func TestGetFuncName(t *testing.T) {
 }
 
 func Test_checkNumOfTheParallelJobs(t *testing.T) {
-       baseFileFolder := "executable_files"
        type args struct {
                workingDir        string
                numOfParallelJobs int
@@ -78,7 +77,7 @@ func Test_checkNumOfTheParallelJobs(t *testing.T) {
                                numOfParallelJobs: 2,
                        },
                        prepareFunc: func() {
-                               err := 
os.MkdirAll(filepath.Join(baseFileFolder, "1"), fs.ModePerm)
+                               err := 
os.MkdirAll(filepath.Join(executableFiles, "1"), fs.ModePerm)
                                if err != nil {
                                        panic(err)
                                }
@@ -94,7 +93,7 @@ func Test_checkNumOfTheParallelJobs(t *testing.T) {
                                numOfParallelJobs: 1,
                        },
                        prepareFunc: func() {
-                               err := 
os.MkdirAll(filepath.Join(baseFileFolder, "1"), fs.ModePerm)
+                               err := 
os.MkdirAll(filepath.Join(executableFiles, "1"), fs.ModePerm)
                                if err != nil {
                                        panic(err)
                                }
@@ -110,7 +109,7 @@ func Test_checkNumOfTheParallelJobs(t *testing.T) {
                                numOfParallelJobs: 0,
                        },
                        prepareFunc: func() {
-                               err := 
os.MkdirAll(filepath.Join(baseFileFolder, "1"), fs.ModePerm)
+                               err := 
os.MkdirAll(filepath.Join(executableFiles, "1"), fs.ModePerm)
                                if err != nil {
                                        panic(err)
                                }
@@ -124,7 +123,7 @@ func Test_checkNumOfTheParallelJobs(t *testing.T) {
                        if got := checkNumOfTheParallelJobs(tt.args.workingDir, 
tt.args.numOfParallelJobs); got != tt.want {
                                t.Errorf("checkNumOfTheParallelJobs() = %v, 
want %v", got, tt.want)
                        }
-                       os.RemoveAll(baseFileFolder)
+                       os.RemoveAll(executableFiles)
                })
        }
 }

Reply via email to