GetModulesArchiveWithLimit returns the tar archive, the skipped modules, and an error if any.
(root fs.FS, maxArchiveSize int64)
| 91 | |
| 92 | // GetModulesArchiveWithLimit returns the tar archive, the skipped modules, and an error if any. |
| 93 | func GetModulesArchiveWithLimit(root fs.FS, maxArchiveSize int64) ([]byte, []string, error) { |
| 94 | modulesFileContent, err := fs.ReadFile(root, ".terraform/modules/modules.json") |
| 95 | if err != nil { |
| 96 | if xerrors.Is(err, fs.ErrNotExist) { |
| 97 | return []byte{}, []string{}, nil |
| 98 | } |
| 99 | return nil, []string{}, xerrors.Errorf("failed to read modules.json: %w", err) |
| 100 | } |
| 101 | var m modulesFile |
| 102 | if err := json.Unmarshal(modulesFileContent, &m); err != nil { |
| 103 | return nil, []string{}, xerrors.Errorf("failed to parse modules.json: %w", err) |
| 104 | } |
| 105 | |
| 106 | empty := true |
| 107 | var b bytes.Buffer |
| 108 | |
| 109 | lw := xio.NewLimitWriter(&b, maxArchiveSize) |
| 110 | w := tar.NewWriter(lw) |
| 111 | |
| 112 | sized := make([]*moduleWithEstimatedSize, 0, len(m.Modules)) |
| 113 | for _, it := range m.Modules { |
| 114 | sz, err := estimateModuleSize(root, it.Dir) |
| 115 | if err != nil { |
| 116 | return nil, []string{}, xerrors.Errorf("failed to estimate module size for %q: %w", it.Dir, err) |
| 117 | } |
| 118 | sized = append(sized, &moduleWithEstimatedSize{ |
| 119 | module: it, |
| 120 | EstimatedSize: sz, |
| 121 | }) |
| 122 | } |
| 123 | |
| 124 | // Sort modules by estimated size descending so that we skip the largest |
| 125 | slices.SortFunc(sized, func(a, b *moduleWithEstimatedSize) int { |
| 126 | return int(a.EstimatedSize - b.EstimatedSize) |
| 127 | }) |
| 128 | skippedModules := []string{} |
| 129 | |
| 130 | for _, it := range sized { |
| 131 | // Check to make sure that the module is a remote module fetched by |
| 132 | // Terraform. Any module that doesn't start with this path is already local, |
| 133 | // and should be part of the template files already. |
| 134 | if !strings.HasPrefix(it.Dir, ".terraform/modules/") { |
| 135 | continue |
| 136 | } |
| 137 | |
| 138 | // Leave 1024 bytes for the footer |
| 139 | if it.EstimatedSize > lw.Remaining()-1024 { |
| 140 | skippedModules = append(skippedModules, fmt.Sprintf("%s:%s", it.Key, it.Source)) |
| 141 | continue |
| 142 | } |
| 143 | |
| 144 | err := fs.WalkDir(root, it.Dir, func(filePath string, d fs.DirEntry, err error) error { |
| 145 | if err != nil { |
| 146 | return xerrors.Errorf("failed to create modules archive: %w", err) |
| 147 | } |
| 148 | fileMode := d.Type() |
| 149 | if !fileMode.IsRegular() && !fileMode.IsDir() { |
| 150 | return nil |