Run implements Runnable.
(ctx context.Context, _ string, logs io.Writer)
| 121 | |
| 122 | // Run implements Runnable. |
| 123 | func (r *CleanupRunner) Run(ctx context.Context, _ string, logs io.Writer) error { |
| 124 | ctx, span := tracing.StartSpan(ctx) |
| 125 | defer span.End() |
| 126 | logs = loadtestutil.NewSyncWriter(logs) |
| 127 | logger := slog.Make(sloghuman.Sink(logs)).Leveled(slog.LevelDebug) |
| 128 | if r.workspaceID == uuid.Nil { |
| 129 | return nil |
| 130 | } |
| 131 | logger.Info(ctx, "deleting workspace", slog.F("workspace_id", r.workspaceID)) |
| 132 | r.client.SetLogger(logger) |
| 133 | r.client.SetLogBodies(true) |
| 134 | |
| 135 | ws, err := r.client.Workspace(ctx, r.workspaceID) |
| 136 | if err != nil { |
| 137 | var sdkErr *codersdk.Error |
| 138 | if xerrors.As(err, &sdkErr) && sdkErr.StatusCode() == http.StatusNotFound { |
| 139 | logger.Info(ctx, "workspace not found, skipping delete", slog.F("workspace_id", r.workspaceID)) |
| 140 | return nil |
| 141 | } |
| 142 | return err |
| 143 | } |
| 144 | |
| 145 | build, err := r.client.WorkspaceBuild(ctx, ws.LatestBuild.ID) |
| 146 | if err == nil && build.Job.Status.Active() { |
| 147 | // mark the build as canceled |
| 148 | logger.Info(ctx, "canceling workspace build", slog.F("build_id", build.ID), slog.F("workspace_id", r.workspaceID)) |
| 149 | if err = r.client.CancelWorkspaceBuild(ctx, build.ID, codersdk.CancelWorkspaceBuildParams{}); err != nil { |
| 150 | logger.Warn(ctx, "failed to cancel workspace build", slog.Error(err)) |
| 151 | } |
| 152 | // Wait for either the build or the cancellation to finish |
| 153 | // either is necessary or we'll fail at the delete step. |
| 154 | _ = waitForBuild(ctx, logs, r.client, build.ID) // it will return a "build canceled" error |
| 155 | } else { |
| 156 | logger.Warn(ctx, "unable to lookup latest workspace build, attempting to delete anyway", slog.Error(err)) |
| 157 | } |
| 158 | |
| 159 | build, err = r.client.CreateWorkspaceBuild(ctx, r.workspaceID, codersdk.CreateWorkspaceBuildRequest{ |
| 160 | Transition: codersdk.WorkspaceTransitionDelete, |
| 161 | }) |
| 162 | if err != nil { |
| 163 | return xerrors.Errorf("delete workspace: %w", err) |
| 164 | } |
| 165 | |
| 166 | err = waitForBuild(ctx, logs, r.client, build.ID) |
| 167 | if err != nil { |
| 168 | return xerrors.Errorf("wait for build: %w", err) |
| 169 | } |
| 170 | |
| 171 | return nil |
| 172 | } |
| 173 | |
| 174 | // Cleanup implements Cleanable by wrapping CleanupRunner. |
| 175 | func (r *Runner) Cleanup(ctx context.Context, id string, w io.Writer) error { |
no test coverage detected