Documentation
¶
Overview ¶
Package projectapi is how Patch reads and writes one project's resources — always as the person who asked, never as itself.
The service holds no credential for a customer's project. It has a service-account identity for asking the platform who a caller is and whether they may act on a project (see internal/auth), and that identity is deliberately good for nothing else. So every request this package makes carries the caller's own bearer token, taken from the authenticated request, and the project comes from the request the platform already authorized. A Client has no token field at all: there is nothing here to fall back to when a caller has none, which is what makes "act as the caller" a property of the type rather than a rule someone has to remember.
The wire format is plain JSON over the project's own API prefix, decoded into map[string]any rather than typed structs. That is not laziness: the whole point of the base tools is to work with any kind a project serves, including kinds this repository has never heard of, so a typed client would be a list of the kinds we happened to compile in.
Index ¶
- Constants
- Variables
- func ConditionTrue(obj Object, conditionType string) bool
- func IsForbidden(err error) bool
- func IsNotFound(err error) bool
- func Nested(obj Object, path ...string) (any, bool)
- func NestedInt64(obj Object, path ...string) (int64, bool)
- func NestedMap(obj Object, path ...string) (map[string]any, bool)
- func NestedSlice(obj Object, path ...string) ([]any, bool)
- func NestedString(obj Object, path ...string) (string, bool)
- type APIError
- type Client
- type Config
- type FieldError
- type Object
- type Project
- func (p *Project) Create(ctx context.Context, r Resource, obj Object, dryRun bool) (Object, error)
- func (p *Project) Get(ctx context.Context, r Resource, namespace, name string) (Object, error)
- func (p *Project) List(ctx context.Context, r Resource, namespace string) ([]Object, error)
- func (p *Project) Name() string
- func (p *Project) OpenAPI(ctx context.Context, group, version string) (map[string]any, error)
- func (p *Project) Resolve(ctx context.Context, group, version, kindOrResource string) (Resource, error)
- func (p *Project) Update(ctx context.Context, r Resource, obj Object, dryRun bool) (Object, error)
- type Resource
Constants ¶
const ( // DefaultTimeout bounds one request. These run inside a chat turn, so a // slow answer is worse than a fast failure the model can report. DefaultTimeout = 20 * time.Second )
Variables ¶
var ErrKindNotServed = errors.New("this project does not offer that kind of resource")
ErrKindNotServed reports that the project does not serve a kind at all — distinct from serving it and holding none of it.
The two call for opposite actions and must never arrive as the same answer: an empty list means there is nothing there yet, and a kind nobody is serving means nothing looked. Matched with errors.Is.
Functions ¶
func ConditionTrue ¶
ConditionTrue reports whether the object's status carries condition type with status "True".
func IsForbidden ¶
IsForbidden reports whether err is a "you may not" rejection.
func IsNotFound ¶
IsNotFound reports whether err is a "no such object" rejection.
func NestedInt64 ¶
NestedInt64 reads a number at a path. JSON numbers decode as float64, which is what makes this worth a helper rather than a type assertion at each site.
func NestedSlice ¶
NestedSlice reads a nested array at a path.
Types ¶
type APIError ¶
type APIError struct {
// Code is the HTTP status.
Code int
// Status is the platform's own reply, when it sent a structured one.
Status *metav1.Status
// Body is the raw reply, for the case where it did not.
Body string
}
APIError is a rejection from the platform, kept whole. The status carries the field paths a rejection names, which are the part a person acts on.
func (*APIError) FieldErrors ¶
func (e *APIError) FieldErrors() []FieldError
FieldErrors returns the field/message pairs a rejection named, plus the platform's own summary. The summary is included on purpose: it is the wording a person quotes when they escalate.
func (*APIError) IsForbidden ¶
IsForbidden reports whether the caller may not do this.
func (*APIError) IsNotFound ¶
IsNotFound reports whether the object asked for is not there.
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client reaches the platform API. It is safe for concurrent use and holds no credential: see Client.As.
func New ¶
New builds a Client. It fails only on a configuration that could never work — no base URL, or a CA bundle that is not PEM — so a deployment mistake surfaces at boot rather than as an unexplained failure mid-conversation.
func (*Client) As ¶
As returns a view of one project that acts as the holder of bearerToken.
Both arguments come from the authenticated, authorized request and from nowhere else. A Project built with an empty token can still be used, and every call it makes is refused by the platform — which is the correct outcome, and a far better one than quietly reading as the service.
type Config ¶
type Config struct {
// BaseURL is the platform API this project's resources are served from.
BaseURL string
// CACert verifies the server. Empty uses the system roots.
CACert []byte
// Timeout overrides [DefaultTimeout] when > 0.
Timeout time.Duration
// Transport is the test seam. Nil builds one from CACert.
Transport http.RoundTripper
}
Config builds a Client.
type FieldError ¶
type FieldError struct {
// Field is the path the platform named, e.g. "spec.replicas". Empty when
// the rejection is about the request as a whole.
Field string `json:"field,omitempty"`
// Message is the platform's own wording, kept verbatim so it can be quoted.
Message string `json:"message"`
}
FieldError is one rejection and the field it names.
type Project ¶
type Project struct {
// contains filtered or unexported fields
}
Project reads and writes one project's resources as one caller.
func (*Project) Create ¶
Create creates the object, or — with dryRun — asks the platform whether it would accept one without keeping anything.
func (*Project) Get ¶
Get returns one object. A missing one comes back as an *APIError that IsNotFound recognizes, so callers can tell "not there" from "went wrong".
func (*Project) List ¶
List returns every object of the kind. An empty namespace reads across all of them, which is also the only correct call for a kind held in none.
func (*Project) Resolve ¶
func (p *Project) Resolve(ctx context.Context, group, version, kindOrResource string) (Resource, error)
Resolve maps a group, version and a kind (or a plural resource name) onto the resource the project actually serves, and reports whether it is held in a namespace.
Both spellings are accepted because both turn up: a person says "Workload" and a manifest says "workloads", and asking a model to know which one this tool wants is a needless way to fail.
type Resource ¶
Resource identifies one kind as the project serves it.
func (Resource) GroupVersion ¶
GroupVersion renders "group/version", or just "version" for the core group.