package retriever import ( "context" "database/sql" "fmt" "slices" "edge-infra.dev/pkg/lib/fog" "edge-infra.dev/pkg/sds/emergencyaccess/apierror" ) // Client is capable of retrieving operator intervention artifacts. A single // instance of Client is expected to be used for the duration of the program if // multiple artifacts are to be retrieved. type Client struct { db *sql.DB } // New creates a new instance of Client. func New(db *sql.DB) (*Client, error) { return &Client{db: db}, nil } // Artifact returns an artifact given a name and type func (c *Client) Artifact(ctx context.Context, name string, artifactType ArtifactType) (Artifact, error) { artifact := Artifact{ Name: name, Type: artifactType, } err := verifyArtifactType(artifactType) if err != nil { return artifact, err } row := c.db.QueryRowContext(ctx, sqlStmt, name, artifactType) err = row.Scan(&artifact.Artifact, &artifact.SHA) switch { case err == sql.ErrNoRows: return artifact, apierror.E( apierror.ErrUnknownCommand, fmt.Errorf("unknown artifact: (name: %q), (type: %q)", name, string(artifactType)), fmt.Sprintf("Command %q of type %q is unknown", name, userType(artifactType)), ) case err != nil: return artifact, fmt.Errorf("error scanning row: %w", err) } fog.FromContext(ctx).Info( "Retrieved artifact from the db", "artifactName", artifact.Name, "artifactType", artifact.Type, "artifactSHA", fmt.Sprintf("%x", artifact.SHA), ) return artifact, nil } // Returns an error if the supplied artifactType is not known to this package func verifyArtifactType(artifactType ArtifactType) error { if !slices.Contains(allArtifactTypes, artifactType) { return fmt.Errorf("unknown artifact type: %q", artifactType) } return nil } // userType returns the user facing name for the given artifactType func userType(artifactType ArtifactType) string { name := "" if artifactType == Executable { name = "script" } return name }