resourceReplaceLogWriter highlights log lines relating to resource replacement by elevating their log level. This will help template admins to visually find problematic resources easier. The WriteCloser must be closed by the caller to end logging, after which the returned channel will be closed to
(sink logSink, logger slog.Logger)
| 433 | // The WriteCloser must be closed by the caller to end logging, after which the returned channel will be closed to |
| 434 | // indicate that logging of the written data has finished. Failure to close the WriteCloser will leak a goroutine. |
| 435 | func resourceReplaceLogWriter(sink logSink, logger slog.Logger) (io.WriteCloser, <-chan struct{}) { |
| 436 | r, w := io.Pipe() |
| 437 | done := make(chan struct{}) |
| 438 | |
| 439 | go func() { |
| 440 | defer close(done) |
| 441 | |
| 442 | scanner := bufio.NewScanner(r) |
| 443 | for scanner.Scan() { |
| 444 | line := scanner.Bytes() |
| 445 | level := proto.LogLevel_INFO |
| 446 | |
| 447 | // Terraform indicates that a resource will be deleted and recreated by showing the change along with this substring. |
| 448 | if bytes.Contains(line, []byte("# forces replacement")) { |
| 449 | level = proto.LogLevel_WARN |
| 450 | } |
| 451 | |
| 452 | sink.ProvisionLog(level, string(line)) |
| 453 | } |
| 454 | if err := scanner.Err(); err != nil { |
| 455 | logger.Error(context.Background(), "failed to read terraform log", slog.Error(err)) |
| 456 | } |
| 457 | }() |
| 458 | return w, done |
| 459 | } |
| 460 | |
| 461 | // showPlan must only be called while the lock is held. |
| 462 | func (e *executor) showPlan(ctx, killCtx context.Context, stdoutWriter, stderrWriter io.WriteCloser, planfilePath string) error { |