template.go 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. package template
  2. import (
  3. "bytes"
  4. "errors"
  5. "fmt"
  6. "io/fs"
  7. "os"
  8. "path/filepath"
  9. "strings"
  10. "text/template"
  11. helperpkg "git.buran.team/main/cbc/helper"
  12. )
  13. var ErrDockerfileNotExists = errors.New("dockerfile not exists")
  14. type Files map[string]string
  15. type Values map[string]any
  16. func Copy(path string, files Files, values Values) (string, error) {
  17. // Create temporary directoy
  18. sourceDirectory := helperpkg.PathNormalize(path)
  19. targetDirectory, err := os.MkdirTemp("/tmp", "cbc-*")
  20. if err != nil {
  21. return "", fmt.Errorf("can't create directory: %w", err)
  22. }
  23. // Template dockerfile
  24. sourceDockerfilePath := filepath.Join(sourceDirectory, "Dockerfile")
  25. targetDockerfilePath := filepath.Join(targetDirectory, "Dockerfile")
  26. if !fileExists(sourceDockerfilePath) {
  27. return "", ErrDockerfileNotExists
  28. }
  29. err = fileTemplate(sourceDockerfilePath, targetDockerfilePath, values)
  30. if err != nil {
  31. return "", fmt.Errorf("can't template file: %w", err)
  32. }
  33. // Template content
  34. sourceCodeDirectory := filepath.Join(sourceDirectory, "content")
  35. filepath.WalkDir(
  36. sourceCodeDirectory,
  37. func(path string, entry fs.DirEntry, err error) error {
  38. if !entry.Type().IsRegular() {
  39. return nil
  40. }
  41. err = fileTemplate(
  42. path,
  43. filepath.Join(
  44. targetDirectory,
  45. strings.Replace(path, sourceCodeDirectory, "", 1),
  46. ),
  47. values,
  48. )
  49. if err != nil {
  50. return fmt.Errorf("can't template file: %w", err)
  51. }
  52. return nil
  53. },
  54. )
  55. // Create files
  56. for filePath, fileContent := range files {
  57. err := fileCreate(
  58. filepath.Join(
  59. targetDirectory,
  60. filePath,
  61. ),
  62. []byte(fileContent),
  63. )
  64. if err != nil {
  65. return "", fmt.Errorf("can't create file: %w", err)
  66. }
  67. }
  68. return targetDirectory, nil
  69. }
  70. func Delete(path string) error {
  71. err := os.RemoveAll(path)
  72. if err != nil {
  73. return fmt.Errorf("can't delete temporary directory: %w", err)
  74. }
  75. return nil
  76. }
  77. func fileTemplate(sourcePath string, targetPath string, values Values) error {
  78. content, err := templateRender(sourcePath, values)
  79. if err != nil {
  80. return fmt.Errorf("can't render file: %w", err)
  81. }
  82. err = fileCreate(targetPath, content)
  83. if err != nil {
  84. return fmt.Errorf("can't create file: %w", err)
  85. }
  86. return nil
  87. }
  88. func fileExists(path string) bool {
  89. _, err := os.Stat(path)
  90. if err == os.ErrNotExist {
  91. return false
  92. }
  93. return true
  94. }
  95. func fileCreate(path string, content []byte) error {
  96. directory := filepath.Dir(path)
  97. err := os.MkdirAll(directory, 0o700)
  98. if err != nil {
  99. return fmt.Errorf("can't create destination directory: %w", err)
  100. }
  101. err = os.WriteFile(path, content, 0o600)
  102. if err != nil {
  103. return fmt.Errorf("can't write destination file: %w", err)
  104. }
  105. return nil
  106. }
  107. func templateRender(path string, values Values) ([]byte, error) {
  108. file, err := os.ReadFile(path)
  109. if err != nil {
  110. return nil, fmt.Errorf("can't read template: %w", err)
  111. }
  112. var buffer bytes.Buffer
  113. template, err := template.New("").Parse(string(file))
  114. if err != nil {
  115. return nil, fmt.Errorf("can't create template: %w", err)
  116. }
  117. err = template.Execute(&buffer, values)
  118. if err != nil {
  119. return nil, fmt.Errorf("can't render template: %w", err)
  120. }
  121. return buffer.Bytes(), err
  122. }