mirror of
https://github.com/mulgadc/spinifex.git
synced 2026-10-22 12:16:52 +00:00
refactor: use strings.CutPrefix/CutSuffix for guard-then-trim pairs
This commit is contained in:
@@ -94,7 +94,8 @@ func rekeyRecordSeparator(ctx context.Context, kvc migrate.KVContext) error {
|
||||
|
||||
moved := 0
|
||||
for _, key := range keys {
|
||||
if !strings.HasPrefix(key, slashRecordPrefix) {
|
||||
instanceID, ok := strings.CutPrefix(key, slashRecordPrefix)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -106,7 +107,7 @@ func rekeyRecordSeparator(ctx context.Context, kvc migrate.KVContext) error {
|
||||
return fmt.Errorf("read %s: %w", key, err)
|
||||
}
|
||||
|
||||
dest := instanceRecordKey(strings.TrimPrefix(key, slashRecordPrefix))
|
||||
dest := instanceRecordKey(instanceID)
|
||||
if _, err := kvc.KV.Create(ctx, dest, entry.Value()); err != nil {
|
||||
if !errors.Is(err, jetstream.ErrKeyExists) {
|
||||
return fmt.Errorf("write %s: %w", dest, err)
|
||||
@@ -151,10 +152,10 @@ func carryNodeOwnershipForward(ctx context.Context, kvc migrate.KVContext) error
|
||||
|
||||
seeded, owned := 0, 0
|
||||
for _, key := range keys {
|
||||
if !strings.HasPrefix(key, InstanceStatePrefix) {
|
||||
nodeID, ok := strings.CutPrefix(key, InstanceStatePrefix)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
nodeID := strings.TrimPrefix(key, InstanceStatePrefix)
|
||||
|
||||
if _, err := kvc.KV.Create(ctx, NodePresencePrefix+nodeID, marker); err != nil {
|
||||
// A node that has already upgraded wrote its own marker; it is the
|
||||
|
||||
@@ -58,10 +58,10 @@ func MatchesAny(filterValues []string, value string) bool {
|
||||
// Each tag:Key filter uses OR logic across its values, with wildcard support.
|
||||
func MatchesTags(filters map[string][]string, tags map[string]string) bool {
|
||||
for name, values := range filters {
|
||||
if !strings.HasPrefix(name, "tag:") {
|
||||
tagKey, ok := strings.CutPrefix(name, "tag:")
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
tagKey := name[4:] // strip "tag:" prefix
|
||||
tagValue, exists := tags[tagKey]
|
||||
if !exists {
|
||||
return false
|
||||
|
||||
@@ -192,11 +192,12 @@ func setAnthropicCompletionTexts(body []byte, texts []string) ([]byte, error) {
|
||||
// extractTokenUsage's own backend switch. ok is false when body doesn't
|
||||
// decode as backend's shape or backend has no guardrail support.
|
||||
func extractInvokePromptTexts(backend string, body []byte) (texts []string, ok bool) {
|
||||
vendor, isVendor := strings.CutPrefix(backend, providerPrefix)
|
||||
switch {
|
||||
case backend == tierSelfHost:
|
||||
return extractLlamaPromptTexts(body)
|
||||
case strings.HasPrefix(backend, providerPrefix):
|
||||
switch strings.TrimPrefix(backend, providerPrefix) {
|
||||
case isVendor:
|
||||
switch vendor {
|
||||
case vendorAnthropic:
|
||||
return extractAnthropicPromptTexts(body)
|
||||
}
|
||||
@@ -206,11 +207,12 @@ func extractInvokePromptTexts(backend string, body []byte) (texts []string, ok b
|
||||
|
||||
// extractInvokeCompletionTexts is extractInvokePromptTexts' OUTPUT sibling.
|
||||
func extractInvokeCompletionTexts(backend string, body []byte) (texts []string, ok bool) {
|
||||
vendor, isVendor := strings.CutPrefix(backend, providerPrefix)
|
||||
switch {
|
||||
case backend == tierSelfHost:
|
||||
return extractLlamaCompletionTexts(body)
|
||||
case strings.HasPrefix(backend, providerPrefix):
|
||||
switch strings.TrimPrefix(backend, providerPrefix) {
|
||||
case isVendor:
|
||||
switch vendor {
|
||||
case vendorAnthropic:
|
||||
return extractAnthropicCompletionTexts(body)
|
||||
}
|
||||
@@ -222,11 +224,12 @@ func extractInvokeCompletionTexts(backend string, body []byte) (texts []string,
|
||||
// InvokeModel response body carrying message as the assistant text, for an
|
||||
// INPUT guardrail block -- the backend is never called.
|
||||
func invokeGuardrailBlockedResponse(backend, modelID, message string) ([]byte, error) {
|
||||
vendor, isVendor := strings.CutPrefix(backend, providerPrefix)
|
||||
switch {
|
||||
case backend == tierSelfHost:
|
||||
return buildLlamaBlockedResponse(message)
|
||||
case strings.HasPrefix(backend, providerPrefix):
|
||||
switch strings.TrimPrefix(backend, providerPrefix) {
|
||||
case isVendor:
|
||||
switch vendor {
|
||||
case vendorAnthropic:
|
||||
return buildAnthropicBlockedResponse(modelID, message)
|
||||
}
|
||||
@@ -237,11 +240,12 @@ func invokeGuardrailBlockedResponse(backend, modelID, message string) ([]byte, e
|
||||
// invokeGuardrailBlockedCompletion rewrites respBody's assistant text
|
||||
// wholesale with message, for an OUTPUT guardrail block.
|
||||
func invokeGuardrailBlockedCompletion(backend string, respBody []byte, message string) ([]byte, error) {
|
||||
vendor, isVendor := strings.CutPrefix(backend, providerPrefix)
|
||||
switch {
|
||||
case backend == tierSelfHost:
|
||||
return replaceLlamaCompletion(respBody, message)
|
||||
case strings.HasPrefix(backend, providerPrefix):
|
||||
switch strings.TrimPrefix(backend, providerPrefix) {
|
||||
case isVendor:
|
||||
switch vendor {
|
||||
case vendorAnthropic:
|
||||
return replaceAnthropicCompletion(respBody, message)
|
||||
}
|
||||
@@ -252,14 +256,15 @@ func invokeGuardrailBlockedCompletion(backend string, respBody []byte, message s
|
||||
// invokeGuardrailRedactedCompletion rewrites respBody's assistant text
|
||||
// positionally with texts, for an OUTPUT ANONYMIZE redaction.
|
||||
func invokeGuardrailRedactedCompletion(backend string, respBody []byte, texts []string) ([]byte, error) {
|
||||
vendor, isVendor := strings.CutPrefix(backend, providerPrefix)
|
||||
switch {
|
||||
case backend == tierSelfHost:
|
||||
if len(texts) == 0 {
|
||||
return respBody, nil
|
||||
}
|
||||
return setLlamaCompletionText(respBody, texts[0])
|
||||
case strings.HasPrefix(backend, providerPrefix):
|
||||
switch strings.TrimPrefix(backend, providerPrefix) {
|
||||
case isVendor:
|
||||
switch vendor {
|
||||
case vendorAnthropic:
|
||||
return setAnthropicCompletionTexts(respBody, texts)
|
||||
}
|
||||
@@ -271,6 +276,7 @@ func invokeGuardrailRedactedCompletion(backend string, respBody []byte, texts []
|
||||
// invoke-stream chunk for buffered OUTPUT accumulation. ok=false is a benign
|
||||
// no-text chunk; decodeErr=true is a real JSON-decode failure (fail closed).
|
||||
func extractInvokeStreamChunkText(backend string, chunk []byte) (text string, ok bool, decodeErr bool) {
|
||||
vendor, isVendor := strings.CutPrefix(backend, providerPrefix)
|
||||
switch {
|
||||
case backend == tierSelfHost:
|
||||
var c struct {
|
||||
@@ -280,8 +286,8 @@ func extractInvokeStreamChunkText(backend string, chunk []byte) (text string, ok
|
||||
return "", false, true
|
||||
}
|
||||
return c.Generation, c.Generation != "", false
|
||||
case strings.HasPrefix(backend, providerPrefix):
|
||||
switch strings.TrimPrefix(backend, providerPrefix) {
|
||||
case isVendor:
|
||||
switch vendor {
|
||||
case vendorAnthropic:
|
||||
var c struct {
|
||||
Type string `json:"type"`
|
||||
@@ -361,11 +367,12 @@ func anthropicGuardedStreamChunks(message string, blocked bool) ([][]byte, error
|
||||
// buildGuardedInvokeStreamChunks dispatches to the family-specific guarded
|
||||
// invoke-stream chunk builder for backend.
|
||||
func buildGuardedInvokeStreamChunks(backend, message string, blocked bool) ([][]byte, error) {
|
||||
vendor, isVendor := strings.CutPrefix(backend, providerPrefix)
|
||||
switch {
|
||||
case backend == tierSelfHost:
|
||||
return llamaGuardedStreamChunks(message, blocked)
|
||||
case strings.HasPrefix(backend, providerPrefix):
|
||||
switch strings.TrimPrefix(backend, providerPrefix) {
|
||||
case isVendor:
|
||||
switch vendor {
|
||||
case vendorAnthropic:
|
||||
return anthropicGuardedStreamChunks(message, blocked)
|
||||
}
|
||||
|
||||
@@ -135,6 +135,7 @@ func (rt *InvokeRouter) InvokeModel(ctx context.Context, accountID, modelID stri
|
||||
backend = entry.Provider
|
||||
|
||||
var a InvokeAdapter
|
||||
vendor, isVendor := strings.CutPrefix(entry.Provider, providerPrefix)
|
||||
switch {
|
||||
case entry.Provider == tierSelfHost:
|
||||
// Family validation first: a model this platform cannot serve at
|
||||
@@ -150,8 +151,8 @@ func (rt *InvokeRouter) InvokeModel(ctx context.Context, accountID, modelID stri
|
||||
return nil, "", err
|
||||
}
|
||||
defer release()
|
||||
case strings.HasPrefix(entry.Provider, providerPrefix):
|
||||
switch strings.TrimPrefix(entry.Provider, providerPrefix) {
|
||||
case isVendor:
|
||||
switch vendor {
|
||||
case vendorAnthropic:
|
||||
var key string
|
||||
var resolvable bool
|
||||
@@ -323,6 +324,7 @@ func (rt *InvokeStreamRouter) InvokeModelWithResponseStream(ctx context.Context,
|
||||
// once, either explicitly here or via the slot-releasing source wrapper
|
||||
// on the success path.
|
||||
var selfHostRelease func()
|
||||
vendor, isVendor := strings.CutPrefix(entry.Provider, providerPrefix)
|
||||
switch {
|
||||
case entry.Provider == tierSelfHost:
|
||||
// Family validation first: a model this platform cannot serve at
|
||||
@@ -336,8 +338,8 @@ func (rt *InvokeStreamRouter) InvokeModelWithResponseStream(ctx context.Context,
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
case strings.HasPrefix(entry.Provider, providerPrefix):
|
||||
switch strings.TrimPrefix(entry.Provider, providerPrefix) {
|
||||
case isVendor:
|
||||
switch vendor {
|
||||
case vendorAnthropic:
|
||||
key, ok, err := rt.resolver.Resolve(ctx, accountID, vendorAnthropic)
|
||||
if err != nil {
|
||||
|
||||
@@ -133,6 +133,7 @@ func (rt *Router) Converse(ctx context.Context, accountID, modelID string, input
|
||||
backend = entry.Provider
|
||||
|
||||
var p Provider
|
||||
vendor, isVendor := strings.CutPrefix(entry.Provider, providerPrefix)
|
||||
switch {
|
||||
case entry.Provider == tierSelfHost:
|
||||
var release func()
|
||||
@@ -146,8 +147,8 @@ func (rt *Router) Converse(ctx context.Context, accountID, modelID string, input
|
||||
} else {
|
||||
p = newVLLMProvider(rt.endpointResolver)
|
||||
}
|
||||
case strings.HasPrefix(entry.Provider, providerPrefix):
|
||||
switch strings.TrimPrefix(entry.Provider, providerPrefix) {
|
||||
case isVendor:
|
||||
switch vendor {
|
||||
case vendorAnthropic:
|
||||
var key string
|
||||
var resolvable bool
|
||||
@@ -267,6 +268,7 @@ func (rt *Router) ConverseStream(ctx context.Context, accountID, modelID string,
|
||||
// whether the eventual source gets slot-release wrapping and whether an
|
||||
// error return past this point must release the slot explicitly.
|
||||
var selfHostRelease func()
|
||||
vendor, isVendor := strings.CutPrefix(entry.Provider, providerPrefix)
|
||||
switch {
|
||||
case entry.Provider == tierSelfHost:
|
||||
selfHostRelease, err = admitSelfHost(ctx, rt.provisioned, ptAccountID, modelID, entry)
|
||||
@@ -278,8 +280,8 @@ func (rt *Router) ConverseStream(ctx context.Context, accountID, modelID string,
|
||||
} else {
|
||||
p = newVLLMProvider(rt.endpointResolver)
|
||||
}
|
||||
case strings.HasPrefix(entry.Provider, providerPrefix):
|
||||
switch strings.TrimPrefix(entry.Provider, providerPrefix) {
|
||||
case isVendor:
|
||||
switch vendor {
|
||||
case vendorAnthropic:
|
||||
key, ok, err := rt.resolver.Resolve(ctx, accountID, vendorAnthropic)
|
||||
if err != nil {
|
||||
|
||||
@@ -49,15 +49,15 @@ func (s *sseScanner) Next() (sseEvent, bool, error) {
|
||||
}
|
||||
continue // keepalive blank line between records
|
||||
}
|
||||
switch {
|
||||
case strings.HasPrefix(line, ":"):
|
||||
// comment/keepalive, ignore — does not start a record
|
||||
case strings.HasPrefix(line, "event:"):
|
||||
if strings.HasPrefix(line, ":") {
|
||||
continue // comment/keepalive, does not start a record
|
||||
}
|
||||
if v, ok := strings.CutPrefix(line, "event:"); ok {
|
||||
sawAny = true
|
||||
event = strings.TrimSpace(strings.TrimPrefix(line, "event:"))
|
||||
case strings.HasPrefix(line, "data:"):
|
||||
event = strings.TrimSpace(v)
|
||||
} else if v, ok := strings.CutPrefix(line, "data:"); ok {
|
||||
sawAny = true
|
||||
dataLines = append(dataLines, strings.TrimPrefix(strings.TrimPrefix(line, "data:"), " "))
|
||||
dataLines = append(dataLines, strings.TrimPrefix(v, " "))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -114,6 +114,7 @@ func classifyTagsOperation(method, name, ref string) (ClassifiedOperation, bool)
|
||||
// classifyBlobOperation mirrors Registry.routeBlobs' dispatch exactly, so
|
||||
// every method/ref combination it accepts has a matching authorization case.
|
||||
func classifyBlobOperation(method, name, ref string, query url.Values) (ClassifiedOperation, bool) {
|
||||
uploadID, isUpload := strings.CutPrefix(ref, "uploads/")
|
||||
switch {
|
||||
case ref == "uploads/" || ref == "uploads":
|
||||
if method != http.MethodPost {
|
||||
@@ -134,8 +135,8 @@ func classifyBlobOperation(method, name, ref string, query url.Values) (Classifi
|
||||
op.Requirements = append(op.Requirements, ActionRequirement{ActionBatchCheckLayerAvailability, ScopeSource})
|
||||
}
|
||||
return op, true
|
||||
case strings.HasPrefix(ref, "uploads/"):
|
||||
if strings.TrimPrefix(ref, "uploads/") == "" {
|
||||
case isUpload:
|
||||
if uploadID == "" {
|
||||
return ClassifiedOperation{}, false
|
||||
}
|
||||
switch method {
|
||||
|
||||
@@ -164,14 +164,14 @@ func splitV2Path(path string) (name, kind, ref string, ok bool) {
|
||||
|
||||
func (reg *Registry) routeBlobs(w http.ResponseWriter, r *http.Request, name, ref string) {
|
||||
ctx := r.Context()
|
||||
uploadID, isUpload := strings.CutPrefix(ref, "uploads/")
|
||||
switch {
|
||||
case ref == "uploads/" || ref == "uploads":
|
||||
if r.Method == http.MethodPost {
|
||||
reg.startUpload(w, r, name)
|
||||
return
|
||||
}
|
||||
case strings.HasPrefix(ref, "uploads/"):
|
||||
uploadID := strings.TrimPrefix(ref, "uploads/")
|
||||
case isUpload:
|
||||
switch r.Method {
|
||||
case http.MethodPatch:
|
||||
reg.patchUpload(w, r, name, uploadID)
|
||||
|
||||
@@ -50,8 +50,7 @@ func groupMembers(sysfsRoot string, groupNum int) ([]IOMMUGroupMember, error) {
|
||||
// bind/unbind lifecycle while the endpoint is claimed.
|
||||
func isBridgeClass(class string) bool {
|
||||
s := strings.ToLower(strings.TrimSpace(class))
|
||||
s = strings.TrimPrefix(s, "0x")
|
||||
return len(s) >= 2 && s[:2] == "06"
|
||||
return strings.HasPrefix(strings.TrimPrefix(s, "0x"), "06")
|
||||
}
|
||||
|
||||
// filterBridgeMembers returns members with bridge-class devices removed.
|
||||
|
||||
@@ -434,8 +434,5 @@ func (sc *Scheduler) convergeInstanceRoles(ctx context.Context) error {
|
||||
|
||||
// accountIDFromBucket extracts the account ID from an ECS per-account bucket name.
|
||||
func accountIDFromBucket(bucket string) (string, bool) {
|
||||
if !strings.HasPrefix(bucket, KVBucketECSAccountPrefix) {
|
||||
return "", false
|
||||
}
|
||||
return strings.TrimPrefix(bucket, KVBucketECSAccountPrefix), true
|
||||
return strings.CutPrefix(bucket, KVBucketECSAccountPrefix)
|
||||
}
|
||||
|
||||
@@ -97,11 +97,12 @@ func ListAddonRecords(ctx context.Context, kv jetstream.KeyValue, cluster string
|
||||
prefix := AddonsPrefix(cluster)
|
||||
out := make([]*AddonRecord, 0)
|
||||
for _, k := range keys {
|
||||
if !strings.HasPrefix(k, prefix) {
|
||||
rest, ok := strings.CutPrefix(k, prefix)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
// Skip sub-keys (e.g. staged manifest); record keys are one segment under the prefix.
|
||||
if strings.Contains(strings.TrimPrefix(k, prefix), "/") {
|
||||
if strings.Contains(rest, "/") {
|
||||
continue
|
||||
}
|
||||
entry, err := kv.Get(ctx, k)
|
||||
|
||||
@@ -53,10 +53,10 @@ func ec2TagsFromMap(m map[string]string) []*ec2.Tag {
|
||||
func cpvpcMatchTagFilters(tagMap map[string]string, filters []*ec2.Filter) bool {
|
||||
for _, f := range filters {
|
||||
name := aws.StringValue(f.Name)
|
||||
if !strings.HasPrefix(name, "tag:") {
|
||||
key, isTag := strings.CutPrefix(name, "tag:")
|
||||
if !isTag {
|
||||
continue
|
||||
}
|
||||
key := strings.TrimPrefix(name, "tag:")
|
||||
got, ok := tagMap[key]
|
||||
if !ok {
|
||||
return false
|
||||
|
||||
@@ -63,10 +63,11 @@ type etcdSnapshotKey struct {
|
||||
// vary in length, so comparing the whole basename would not be.
|
||||
func parseEtcdSnapshotKey(basename string) (etcdSnapshotKey, bool) {
|
||||
const prefix, suffix = "etcd-", ".snap"
|
||||
if !strings.HasPrefix(basename, prefix) || !strings.HasSuffix(basename, suffix) {
|
||||
rest, prefixed := strings.CutPrefix(basename, prefix)
|
||||
mid, suffixed := strings.CutSuffix(rest, suffix)
|
||||
if !prefixed || !suffixed {
|
||||
return etcdSnapshotKey{}, false
|
||||
}
|
||||
mid := strings.TrimSuffix(strings.TrimPrefix(basename, prefix), suffix)
|
||||
i := strings.LastIndex(mid, "-")
|
||||
if i <= 0 || i == len(mid)-1 {
|
||||
return etcdSnapshotKey{}, false
|
||||
|
||||
@@ -2503,10 +2503,11 @@ func listClusterNames(ctx context.Context, kv jetstream.KeyValue) ([]string, err
|
||||
names := make([]string, 0, len(keys))
|
||||
seen := make(map[string]struct{}, len(keys))
|
||||
for _, k := range keys {
|
||||
if !strings.HasPrefix(k, "clusters/") || !strings.HasSuffix(k, suffix) {
|
||||
rest, prefixed := strings.CutPrefix(k, "clusters/")
|
||||
name, suffixed := strings.CutSuffix(rest, suffix)
|
||||
if !prefixed || !suffixed {
|
||||
continue
|
||||
}
|
||||
name := strings.TrimSuffix(strings.TrimPrefix(k, "clusters/"), suffix)
|
||||
if name == "" || strings.Contains(name, "/") {
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -42,11 +42,10 @@ type TokenVerifyResponse struct {
|
||||
// `k8s-aws-v1.<base64url>` bearer token. The encoding is base64url without
|
||||
// padding, matching the aws-iam-authenticator / aws-cli get-token output.
|
||||
func DecodeGetToken(token string) (string, error) {
|
||||
token = strings.TrimSpace(token)
|
||||
if !strings.HasPrefix(token, getTokenV1Prefix) {
|
||||
encoded, ok := strings.CutPrefix(strings.TrimSpace(token), getTokenV1Prefix)
|
||||
if !ok {
|
||||
return "", ErrMalformedToken
|
||||
}
|
||||
encoded := strings.TrimPrefix(token, getTokenV1Prefix)
|
||||
raw, err := base64.RawURLEncoding.DecodeString(encoded)
|
||||
if err != nil {
|
||||
return "", ErrMalformedToken
|
||||
|
||||
@@ -81,8 +81,8 @@ func imdsAction(method, path string) string {
|
||||
return "imds.public-keys"
|
||||
}
|
||||
|
||||
if strings.HasPrefix(path, prefixSecurityCreds) {
|
||||
if len(path) > len(prefixSecurityCreds) {
|
||||
if role, ok := strings.CutPrefix(path, prefixSecurityCreds); ok {
|
||||
if role != "" {
|
||||
return "imds.iam.security-credentials.role"
|
||||
}
|
||||
return "imds.iam.security-credentials.list"
|
||||
|
||||
@@ -157,8 +157,8 @@ func (s *IMDSServiceImpl) dispatch(w http.ResponseWriter, r *http.Request, eni *
|
||||
slog.InfoContext(ctx, "IMDS: serving metadata request", "path", path,
|
||||
"instance_id", eni.instanceID, "private_ip", eni.privateIP, "public_ip", eni.publicIP)
|
||||
|
||||
if strings.HasPrefix(path, prefixSecurityCreds) && len(path) > len(prefixSecurityCreds) {
|
||||
s.serveRoleCredentials(ctx, w, eni, strings.TrimPrefix(path, prefixSecurityCreds))
|
||||
if role, ok := strings.CutPrefix(path, prefixSecurityCreds); ok && role != "" {
|
||||
s.serveRoleCredentials(ctx, w, eni, role)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -132,7 +132,8 @@ func (r *metadataResolver) findENIByID(ctx context.Context, eniID string) (strin
|
||||
|
||||
suffix := "." + eniID
|
||||
for _, key := range keys {
|
||||
if !strings.HasSuffix(key, suffix) {
|
||||
accountID, ok := strings.CutSuffix(key, suffix)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
entry, err := r.eniKV.Get(ctx, key)
|
||||
@@ -142,7 +143,7 @@ func (r *metadataResolver) findENIByID(ctx context.Context, eniID string) (strin
|
||||
}
|
||||
return "", nil, fmt.Errorf("get eni record %s: %w", key, err)
|
||||
}
|
||||
return strings.TrimSuffix(key, suffix), entry.Value(), nil
|
||||
return accountID, entry.Value(), nil
|
||||
}
|
||||
return "", nil, nil
|
||||
}
|
||||
|
||||
@@ -168,13 +168,14 @@ func (f *fakeVPC) DescribeNetworkInterfaces(_ context.Context, in *ec2.DescribeN
|
||||
for _, filter := range in.Filters {
|
||||
name := aws.StringValue(filter.Name)
|
||||
var got string
|
||||
tagKey, isTag := strings.CutPrefix(name, "tag:")
|
||||
switch {
|
||||
case name == "subnet-id":
|
||||
got = aws.StringValue(ni.SubnetId)
|
||||
case name == "description":
|
||||
got = aws.StringValue(ni.Description)
|
||||
case strings.HasPrefix(name, "tag:"):
|
||||
got = tagValue(ni.TagSet, strings.TrimPrefix(name, "tag:"))
|
||||
case isTag:
|
||||
got = tagValue(ni.TagSet, tagKey)
|
||||
default:
|
||||
return nil, fmt.Errorf("fakeVPC: unsupported ENI filter %q", name)
|
||||
}
|
||||
|
||||
@@ -306,10 +306,11 @@ func ListDBParameterGroupNames(ctx context.Context, kv jetstream.KeyValue) ([]st
|
||||
prefix := DBParameterGroupsPrefix()
|
||||
names := make([]string, 0, len(keys))
|
||||
for _, key := range keys {
|
||||
if !strings.HasPrefix(key, prefix) || !strings.HasSuffix(key, "/meta") {
|
||||
rest, prefixed := strings.CutPrefix(key, prefix)
|
||||
name, suffixed := strings.CutSuffix(rest, "/meta")
|
||||
if !prefixed || !suffixed {
|
||||
continue
|
||||
}
|
||||
name := strings.TrimSuffix(strings.TrimPrefix(key, prefix), "/meta")
|
||||
if name == "" || strings.Contains(name, "/") {
|
||||
continue
|
||||
}
|
||||
@@ -388,10 +389,10 @@ func listNames(ctx context.Context, kv jetstream.KeyValue, prefix string) ([]str
|
||||
}
|
||||
names := make([]string, 0, len(keys))
|
||||
for _, key := range keys {
|
||||
if !strings.HasPrefix(key, prefix) {
|
||||
name, ok := strings.CutPrefix(key, prefix)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
name := strings.TrimPrefix(key, prefix)
|
||||
if name == "" || strings.Contains(name, "/") {
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -226,19 +226,23 @@ type MIGProfileSpec struct {
|
||||
MemoryMiB int64
|
||||
}
|
||||
|
||||
// migTypePrefix marks an instance type name as a MIG profile type.
|
||||
const migTypePrefix = "mig."
|
||||
|
||||
// IsMIGType reports whether the instance type name is a MIG profile type
|
||||
// (i.e. was produced by GenerateMIGTypes).
|
||||
func IsMIGType(instanceType string) bool {
|
||||
return strings.HasPrefix(instanceType, "mig.")
|
||||
return strings.HasPrefix(instanceType, migTypePrefix)
|
||||
}
|
||||
|
||||
// MIGProfileFromType extracts the nvidia-smi profile name from a MIG instance
|
||||
// type name (e.g. "mig.1g.10gb" → "1g.10gb"). Returns "" for non-MIG types.
|
||||
func MIGProfileFromType(instanceType string) string {
|
||||
if !IsMIGType(instanceType) {
|
||||
profile, ok := strings.CutPrefix(instanceType, migTypePrefix)
|
||||
if !ok {
|
||||
return ""
|
||||
}
|
||||
return strings.TrimPrefix(instanceType, "mig.")
|
||||
return profile
|
||||
}
|
||||
|
||||
// GenerateMIGTypes returns one InstanceTypeInfo per unique MIG profile. Instance
|
||||
@@ -247,7 +251,7 @@ func MIGProfileFromType(instanceType string) string {
|
||||
func GenerateMIGTypes(profiles []MIGProfileSpec, arch string) map[string]*ec2.InstanceTypeInfo {
|
||||
types := make(map[string]*ec2.InstanceTypeInfo)
|
||||
for _, p := range profiles {
|
||||
name := "mig." + p.Name
|
||||
name := migTypePrefix + p.Name
|
||||
if _, exists := types[name]; exists {
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -48,11 +48,11 @@ func ListIMDSTaps(ctx context.Context, r Runner) ([]IMDSTapEndpoint, error) {
|
||||
// a port missing it can never be a member of the live set either way, and one
|
||||
// structurally broken port must not stall every reconcile pass.
|
||||
ifaceID, ok := row.externalIDs["iface-id"]
|
||||
if !ok || !strings.HasPrefix(ifaceID, ovsIfaceIDPrefix) {
|
||||
eniID, prefixed := strings.CutPrefix(ifaceID, ovsIfaceIDPrefix)
|
||||
if !ok || !prefixed {
|
||||
slog.Warn("IMDS: skipping IMDS patch port with unexpected iface-id", "port", row.name, "iface_id", ifaceID)
|
||||
continue
|
||||
}
|
||||
eniID := strings.TrimPrefix(ifaceID, ovsIfaceIDPrefix)
|
||||
taps = append(taps, IMDSTapEndpoint{ENIID: eniID, Endpoint: IMDSEndpointName(eniID)})
|
||||
}
|
||||
return taps, nil
|
||||
|
||||
@@ -87,6 +87,8 @@ func parseNbdkitCmdline(cmdline []byte) (disc discoveredNbdkit, ok bool) {
|
||||
args := bytes.Split(bytes.TrimRight(cmdline, "\x00"), []byte{0})
|
||||
for i := 0; i < len(args); i++ {
|
||||
arg := string(args[i])
|
||||
volume, isVolume := strings.CutPrefix(arg, "volume=")
|
||||
baseDir, isBaseDir := strings.CutPrefix(arg, "base_dir=")
|
||||
switch {
|
||||
case arg == "--unix" && i+1 < len(args):
|
||||
disc.Socket = string(args[i+1])
|
||||
@@ -96,10 +98,10 @@ func parseNbdkitCmdline(cmdline []byte) (disc discoveredNbdkit, ok bool) {
|
||||
disc.Port = port
|
||||
}
|
||||
i++
|
||||
case strings.HasPrefix(arg, "volume="):
|
||||
disc.Volume = strings.TrimPrefix(arg, "volume=")
|
||||
case strings.HasPrefix(arg, "base_dir="):
|
||||
disc.BaseDir = strings.TrimPrefix(arg, "base_dir=")
|
||||
case isVolume:
|
||||
disc.Volume = volume
|
||||
case isBaseDir:
|
||||
disc.BaseDir = baseDir
|
||||
case strings.HasSuffix(arg, ".so"):
|
||||
disc.Plugin = arg
|
||||
}
|
||||
|
||||
@@ -194,10 +194,11 @@ func parseSumsFile(body []byte, filename string) (string, error) {
|
||||
}
|
||||
case 4:
|
||||
// BSD-style: "<algo> (<name>) = <hex>". The "=" guard rejects PGP armor lines that happen to tokenise to 4 fields.
|
||||
if fields[2] != "=" || !strings.HasPrefix(fields[1], "(") || !strings.HasSuffix(fields[1], ")") {
|
||||
inner, open := strings.CutPrefix(fields[1], "(")
|
||||
name, closed := strings.CutSuffix(inner, ")")
|
||||
if fields[2] != "=" || !open || !closed {
|
||||
continue
|
||||
}
|
||||
name := strings.TrimSuffix(strings.TrimPrefix(fields[1], "("), ")")
|
||||
if name == filename {
|
||||
return fields[3], nil
|
||||
}
|
||||
|
||||
@@ -56,11 +56,10 @@ func pidFileOwners(runtimeDir string) map[int]string {
|
||||
return owners
|
||||
}
|
||||
for _, entry := range entries {
|
||||
name := entry.Name()
|
||||
if !strings.HasSuffix(name, ".pid") {
|
||||
id, ok := strings.CutSuffix(entry.Name(), ".pid")
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
id := strings.TrimSuffix(name, ".pid")
|
||||
if pid, err := utils.ReadPidFileFrom(runtimeDir, id); err == nil {
|
||||
owners[pid] = id
|
||||
}
|
||||
|
||||
@@ -285,10 +285,8 @@ func subjectsOverlap(a, b []string) bool {
|
||||
// matches anything sharing its prefix; two wildcards match if one prefix
|
||||
// contains the other.
|
||||
func subjectMatch(x, y string) bool {
|
||||
xw := strings.HasSuffix(x, ".*")
|
||||
yw := strings.HasSuffix(y, ".*")
|
||||
xp := strings.TrimSuffix(x, ".*")
|
||||
yp := strings.TrimSuffix(y, ".*")
|
||||
xp, xw := strings.CutSuffix(x, ".*")
|
||||
yp, yw := strings.CutSuffix(y, ".*")
|
||||
switch {
|
||||
case xw && yw:
|
||||
return xp == yp || strings.HasPrefix(xp, yp+".") || strings.HasPrefix(yp, xp+".")
|
||||
|
||||
@@ -389,10 +389,11 @@ func runGuestChurnRound(t *testing.T, fix *Fixture, instanceID, origType, keyPat
|
||||
// Bash strips the ".nano" suffix and appends ".small" — same family,
|
||||
// more RAM at matching vCPU. Avoids xlarge (16 GiB) which the CI host
|
||||
// can't satisfy.
|
||||
if !strings.HasSuffix(origType, ".nano") {
|
||||
family, ok := strings.CutSuffix(origType, ".nano")
|
||||
if !ok {
|
||||
t.Fatalf("phase7b: expected discovered instance type to end with .nano, got %q", origType)
|
||||
}
|
||||
modifyType := strings.TrimSuffix(origType, ".nano") + ".small"
|
||||
modifyType := family + ".small"
|
||||
harness.Detail(t, "from_type", origType, "to_type", modifyType)
|
||||
|
||||
// Stop the instance first — ModifyInstanceAttribute on a running
|
||||
|
||||
Reference in New Issue
Block a user