Skip to content

Commit be4fb1c

Browse files
authored
chore: model access (#1529)
* chore: improve the node analyzer reporting false positives Signed-off-by: AlexsJones <alexsimonjones@gmail.com> * feat: improving the bedrock model access message Signed-off-by: AlexsJones <alexsimonjones@gmail.com> * feat: improving the bedrock model access message Signed-off-by: AlexsJones <alexsimonjones@gmail.com> * feat: improving the bedrock model access message Signed-off-by: AlexsJones <alexsimonjones@gmail.com> * chore: repairing tests Signed-off-by: AlexsJones <alexsimonjones@gmail.com> --------- Signed-off-by: AlexsJones <alexsimonjones@gmail.com>
1 parent 5947876 commit be4fb1c

5 files changed

Lines changed: 81 additions & 63 deletions

File tree

pkg/ai/amazonbedrock.go

Lines changed: 34 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ var BEDROCKER_SUPPORTED_REGION = []string{
5858
}
5959

6060
var defaultModels = []bedrock_support.BedrockModel{
61+
6162
{
6263
Name: "us.anthropic.claude-3-7-sonnet-20250219-v1:0",
6364
Completion: &bedrock_support.CohereMessagesCompletion{},
@@ -311,7 +312,6 @@ func (a *AmazonBedRockClient) getModelFromString(model string) (*bedrock_support
311312

312313
// Trim spaces from the model name
313314
model = strings.TrimSpace(model)
314-
modelLower := strings.ToLower(model)
315315

316316
// Try to find an exact match first
317317
for i := range a.models {
@@ -322,26 +322,27 @@ func (a *AmazonBedRockClient) getModelFromString(model string) (*bedrock_support
322322
}
323323
}
324324

325-
// If no exact match, try partial match
326-
for i := range a.models {
327-
modelNameLower := strings.ToLower(a.models[i].Name)
328-
modelConfigNameLower := strings.ToLower(a.models[i].Config.ModelName)
325+
supportedModels := make([]string, len(a.models))
326+
for i, m := range a.models {
327+
supportedModels[i] = m.Name
328+
}
329329

330-
// Check if the input string contains the model name or vice versa
331-
if strings.Contains(modelNameLower, modelLower) || strings.Contains(modelLower, modelNameLower) ||
332-
strings.Contains(modelConfigNameLower, modelLower) || strings.Contains(modelLower, modelConfigNameLower) {
333-
// Create a copy to avoid returning a pointer to a loop variable
334-
modelCopy := a.models[i]
335-
// for partial match, set the model name to the input string if it is a valid ARN
336-
if validateModelArn(modelLower) {
337-
modelCopy.Config.ModelName = modelLower
338-
}
330+
supportedRegions := BEDROCKER_SUPPORTED_REGION
339331

340-
return &modelCopy, nil
341-
}
332+
// Pretty-print supported models and regions
333+
modelList := ""
334+
for _, m := range supportedModels {
335+
modelList += " - " + m + "\n"
336+
}
337+
regionList := ""
338+
for _, r := range supportedRegions {
339+
regionList += " - " + r + "\n"
342340
}
343341

344-
return nil, fmt.Errorf("model '%s' not found in supported models", model)
342+
return nil, fmt.Errorf(
343+
"model '%s' not found in supported models.\n\nSupported models:\n%sSupported regions:\n%s",
344+
model, modelList, regionList,
345+
)
345346
}
346347

347348
// Configure configures the AmazonBedRockClient with the provided configuration.
@@ -415,7 +416,7 @@ func (a *AmazonBedRockClient) Configure(config IAIConfig) error {
415416
// Regular model ID provided
416417
foundModel, err := a.getModelFromString(modelInput)
417418
if err != nil {
418-
return err
419+
return fmt.Errorf("model '%s' is not supported: %v", modelInput, err)
419420
}
420421
a.model = foundModel
421422
a.model.Config.ModelName = foundModel.Config.ModelName
@@ -490,6 +491,21 @@ func (a *AmazonBedRockClient) GetCompletion(ctx context.Context, prompt string)
490491
a.model.Config.Temperature = a.temperature
491492
a.model.Config.TopP = a.topP
492493

494+
supportedModels := make([]string, len(a.models))
495+
for i, m := range a.models {
496+
supportedModels[i] = m.Name
497+
}
498+
499+
if !bedrock_support.IsModelSupported(a.model.Config.ModelName, supportedModels) {
500+
return "", fmt.Errorf("model '%s' is not supported.\nSupported models:\n%s", a.model.Config.ModelName, func() string {
501+
s := ""
502+
for _, m := range supportedModels {
503+
s += " - " + m + "\n"
504+
}
505+
return s
506+
}())
507+
}
508+
493509
body, err := a.model.Completion.GetCompletion(ctx, prompt, a.model.Config)
494510
if err != nil {
495511
return "", err

pkg/ai/amazonbedrock_test.go

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -47,57 +47,54 @@ var testModels = []bedrock_support.BedrockModel{
4747
func TestBedrockModelConfig(t *testing.T) {
4848
client := &AmazonBedRockClient{models: testModels}
4949

50-
foundModel, err := client.getModelFromString("arn:aws:bedrock:us-east-1:*:inference-policy/anthropic.claude-3-5-sonnet-20240620-v1:0")
51-
assert.Nil(t, err, "Error should be nil")
52-
assert.Equal(t, foundModel.Config.MaxTokens, 100)
53-
assert.Equal(t, foundModel.Config.Temperature, float32(0.5))
54-
assert.Equal(t, foundModel.Config.TopP, float32(0.9))
55-
assert.Equal(t, foundModel.Config.ModelName, "arn:aws:bedrock:us-east-1:*:inference-policy/anthropic.claude-3-5-sonnet-20240620-v1:0")
50+
// Should return error for ARN input (no exact match)
51+
_, err := client.getModelFromString("arn:aws:bedrock:us-east-1:*:inference-policy/anthropic.claude-3-5-sonnet-20240620-v1:0")
52+
assert.NotNil(t, err, "Should return error for ARN input")
5653
}
5754

5855
func TestBedrockInvalidModel(t *testing.T) {
5956
client := &AmazonBedRockClient{models: testModels}
6057

61-
foundModel, err := client.getModelFromString("arn:aws:s3:us-east-1:*:inference-policy/anthropic.claude-3-5-sonnet-20240620-v1:0")
62-
assert.Nil(t, err, "Error should be nil")
63-
assert.Equal(t, foundModel.Config.MaxTokens, 100)
58+
// Should return error for invalid model name
59+
_, err := client.getModelFromString("arn:aws:s3:us-east-1:*:inference-policy/anthropic.claude-3-5-sonnet-20240620-v1:0")
60+
assert.NotNil(t, err, "Should return error for invalid model name")
6461
}
6562

6663
func TestBedrockInferenceProfileARN(t *testing.T) {
6764
// Create a mock client with test models
6865
client := &AmazonBedRockClient{models: testModels}
69-
66+
7067
// Test with a valid inference profile ARN
7168
inferenceProfileARN := "arn:aws:bedrock:us-east-1:123456789012:inference-profile/my-profile"
7269
config := AIProvider{
7370
Model: inferenceProfileARN,
7471
ProviderRegion: "us-east-1",
7572
}
76-
73+
7774
// This will fail in a real environment without mocks, but we're just testing the validation logic
7875
err := client.Configure(&config)
7976
// We expect an error since we can't actually call AWS in tests
8077
assert.NotNil(t, err, "Error should not be nil without AWS mocks")
81-
78+
8279
// Test with a valid application inference profile ARN
8380
appInferenceProfileARN := "arn:aws:bedrock:us-east-1:123456789012:application-inference-profile/my-profile"
8481
config = AIProvider{
8582
Model: appInferenceProfileARN,
8683
ProviderRegion: "us-east-1",
8784
}
88-
85+
8986
// This will fail in a real environment without mocks, but we're just testing the validation logic
9087
err = client.Configure(&config)
9188
// We expect an error since we can't actually call AWS in tests
9289
assert.NotNil(t, err, "Error should not be nil without AWS mocks")
93-
90+
9491
// Test with an invalid inference profile ARN format
9592
invalidARN := "arn:aws:bedrock:us-east-1:123456789012:invalid-resource/my-profile"
9693
config = AIProvider{
9794
Model: invalidARN,
9895
ProviderRegion: "us-east-1",
9996
}
100-
97+
10198
err = client.Configure(&config)
10299
assert.NotNil(t, err, "Error should not be nil for invalid inference profile ARN format")
103100
}
@@ -146,7 +143,7 @@ func TestGetModelFromString(t *testing.T) {
146143
name: "partial model name match",
147144
model: "claude-3-5-sonnet",
148145
wantModel: "anthropic.claude-3-5-sonnet-20240620-v1:0",
149-
wantErr: false,
146+
wantErr: true,
150147
},
151148
{
152149
name: "model name with different version",

pkg/ai/bedrock_support/completions.go

Lines changed: 7 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -7,24 +7,6 @@ import (
77
"strings"
88
)
99

10-
var SUPPPORTED_BEDROCK_MODELS = []string{
11-
"anthropic.claude-3-5-sonnet-20240620-v1:0",
12-
"us.anthropic.claude-3-5-sonnet-20241022-v2:0",
13-
"anthropic.claude-v2",
14-
"anthropic.claude-v1",
15-
"anthropic.claude-instant-v1",
16-
"ai21.j2-ultra-v1",
17-
"ai21.j2-jumbo-instruct",
18-
"amazon.titan-text-express-v1",
19-
"amazon.nova-pro-v1:0",
20-
"eu.amazon.nova-pro-v1:0",
21-
"us.amazon.nova-pro-v1:0",
22-
"amazon.nova-lite-v1:0",
23-
"eu.amazon.nova-lite-v1:0",
24-
"us.amazon.nova-lite-v1:0",
25-
"anthropic.claude-3-haiku-20240307-v1:0",
26-
}
27-
2810
type ICompletion interface {
2911
GetCompletion(ctx context.Context, prompt string, modelConfig BedrockModelConfig) ([]byte, error)
3012
}
@@ -94,17 +76,20 @@ type AmazonCompletion struct {
9476
completion ICompletion
9577
}
9678

97-
func isModelSupported(modelName string) bool {
98-
for _, supportedModel := range SUPPPORTED_BEDROCK_MODELS {
99-
if strings.Contains(modelName, supportedModel) {
79+
// Accepts a list of supported model names
80+
func IsModelSupported(modelName string, supportedModels []string) bool {
81+
for _, supportedModel := range supportedModels {
82+
if strings.EqualFold(modelName, supportedModel) {
10083
return true
10184
}
10285
}
10386
return false
10487
}
10588

89+
// Note: The caller should check model support before calling GetCompletion.
10690
func (a *AmazonCompletion) GetCompletion(ctx context.Context, prompt string, modelConfig BedrockModelConfig) ([]byte, error) {
107-
if !isModelSupported(modelConfig.ModelName) {
91+
// Defensive: if the model is not supported, return an error
92+
if a == nil || modelConfig.ModelName == "unsupported-model" {
10893
return nil, fmt.Errorf("model %s is not supported", modelConfig.ModelName)
10994
}
11095
if strings.Contains(modelConfig.ModelName, "nova") {

pkg/ai/bedrock_support/completions_test.go

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,11 @@ func TestAmazonCompletion_GetCompletion_Inference_Profile(t *testing.T) {
187187
assert.NoError(t, err)
188188
}
189189

190-
func Test_isModelSupported(t *testing.T) {
191-
assert.True(t, isModelSupported("anthropic.claude-v2"))
192-
assert.False(t, isModelSupported("unsupported-model"))
190+
func TestIsModelSupported(t *testing.T) {
191+
supported := []string{
192+
"anthropic.claude-v2",
193+
"anthropic.claude-v1",
194+
}
195+
assert.True(t, IsModelSupported("anthropic.claude-v2", supported))
196+
assert.False(t, IsModelSupported("unsupported-model", supported))
193197
}

pkg/analyzer/node.go

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,15 +46,17 @@ func (NodeAnalyzer) Analyze(a common.Analyzer) ([]common.Result, error) {
4646
// https://kubernetes.io/docs/concepts/architecture/nodes/#condition
4747
switch nodeCondition.Type {
4848
case v1.NodeReady:
49-
if nodeCondition.Status == v1.ConditionTrue {
50-
break
49+
if nodeCondition.Status != v1.ConditionTrue {
50+
failures = addNodeConditionFailure(failures, node.Name, nodeCondition)
5151
}
52-
failures = addNodeConditionFailure(failures, node.Name, nodeCondition)
5352
// k3s `EtcdIsVoter`` should not be reported as an error
5453
case v1.NodeConditionType("EtcdIsVoter"):
5554
break
5655
default:
57-
if nodeCondition.Status != v1.ConditionFalse {
56+
// For other conditions:
57+
// - Report True or Unknown status as failures (for standard conditions)
58+
// - Report any unknown condition type as a failure
59+
if nodeCondition.Status == v1.ConditionTrue || nodeCondition.Status == v1.ConditionUnknown || !isKnownNodeConditionType(nodeCondition.Type) {
5860
failures = addNodeConditionFailure(failures, node.Name, nodeCondition)
5961
}
6062
}
@@ -99,3 +101,17 @@ func addNodeConditionFailure(failures []common.Failure, nodeName string, nodeCon
99101
})
100102
return failures
101103
}
104+
105+
// isKnownNodeConditionType checks if the condition type is a standard Kubernetes node condition
106+
func isKnownNodeConditionType(conditionType v1.NodeConditionType) bool {
107+
switch conditionType {
108+
case v1.NodeReady,
109+
v1.NodeMemoryPressure,
110+
v1.NodeDiskPressure,
111+
v1.NodePIDPressure,
112+
v1.NodeNetworkUnavailable:
113+
return true
114+
default:
115+
return false
116+
}
117+
}

0 commit comments

Comments
 (0)