(
sess *provisionersdk.Session, request *proto.PlanRequest, canceledOrComplete <-chan struct{},
)
| 166 | } |
| 167 | |
| 168 | func (s *server) Plan( |
| 169 | sess *provisionersdk.Session, request *proto.PlanRequest, canceledOrComplete <-chan struct{}, |
| 170 | ) *proto.PlanComplete { |
| 171 | ctx, span := s.startTrace(sess.Context(), tracing.FuncName()) |
| 172 | defer span.End() |
| 173 | ctx, cancel, killCtx, kill := s.setupContexts(ctx, canceledOrComplete) |
| 174 | defer cancel() |
| 175 | defer kill() |
| 176 | |
| 177 | e := s.executor(sess.Files, database.ProvisionerJobTimingStagePlan) |
| 178 | if err := e.checkMinVersion(ctx); err != nil { |
| 179 | return provisionersdk.PlanErrorf("%s", err.Error()) |
| 180 | } |
| 181 | logTerraformEnvVars(sess) |
| 182 | |
| 183 | // If we're destroying, exit early if there's no state. This is necessary to |
| 184 | // avoid any cases where a workspace is "locked out" of terraform due to |
| 185 | // e.g. bad template param values and cannot be deleted. This is just for |
| 186 | // contingency, in the future we will try harder to prevent workspaces being |
| 187 | // broken this hard. |
| 188 | if request.Metadata.GetWorkspaceTransition() == proto.WorkspaceTransition_DESTROY && len(request.GetState()) == 0 { |
| 189 | sess.ProvisionLog(proto.LogLevel_INFO, "The terraform state does not exist, there is nothing to do") |
| 190 | return &proto.PlanComplete{} |
| 191 | } |
| 192 | |
| 193 | statefilePath := sess.Files.StateFilePath() |
| 194 | if len(request.GetState()) > 0 { |
| 195 | err := os.WriteFile(statefilePath, request.GetState(), 0o600) |
| 196 | if err != nil { |
| 197 | return provisionersdk.PlanErrorf("write statefile %q: %s", statefilePath, err) |
| 198 | } |
| 199 | } |
| 200 | |
| 201 | env, err := provisionEnv(sess.Config, request.Metadata, request.PreviousParameterValues, request.RichParameterValues, request.ExternalAuthProviders) |
| 202 | if err != nil { |
| 203 | return provisionersdk.PlanErrorf("setup env: %s", err) |
| 204 | } |
| 205 | env = otelEnvInject(ctx, env) |
| 206 | |
| 207 | vars, err := planVars(request) |
| 208 | if err != nil { |
| 209 | return provisionersdk.PlanErrorf("plan vars: %s", err) |
| 210 | } |
| 211 | |
| 212 | endStage := e.timings.startStage(database.ProvisionerJobTimingStagePlan) |
| 213 | resp, err := e.plan(ctx, killCtx, env, vars, sess, request) |
| 214 | endStage(err) |
| 215 | if err != nil { |
| 216 | return provisionersdk.PlanErrorf("%s", err.Error()) |
| 217 | } |
| 218 | |
| 219 | resp.Timings = e.timings.aggregate() |
| 220 | return resp |
| 221 | } |
| 222 | |
| 223 | func (s *server) Graph( |
| 224 | sess *provisionersdk.Session, request *proto.GraphRequest, canceledOrComplete <-chan struct{}, |
nothing calls this directly
no test coverage detected