Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -319,8 +319,7 @@ func convertFloat64ToFloat32(f64 *float64) *float32 {

// CreateHostedAgentAPIRequest creates a CreateAgentRequest for hosted agents
func CreateHostedAgentAPIRequest(hostedAgent ContainerAgent, buildConfig *AgentBuildConfig) (*agent_api.CreateAgentRequest, error) {
// Check if we have an image URL set via the build config
imageURL := ""
imageURL := hostedAgent.Image
cpu := "1" // Default CPU
memory := "2Gi" // Default memory
envVars := make(map[string]string)
Expand All @@ -341,7 +340,7 @@ func CreateHostedAgentAPIRequest(hostedAgent ContainerAgent, buildConfig *AgentB
}

if imageURL == "" {
return nil, fmt.Errorf("image URL is required for hosted agents - use WithImageURL build option or specify in container.image")
return nil, fmt.Errorf("image URL is required for hosted agents - specify image in agent.yaml or use WithImageURL")
}

// Map protocol versions from the hosted agent definition
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -961,6 +961,51 @@ func TestCreateHostedAgentAPIRequest_DefaultCPUAndMemory(t *testing.T) {
}
}

func TestCreateHostedAgentAPIRequest_UsesAgentImage(t *testing.T) {
t.Parallel()
agent := ContainerAgent{
AgentDefinition: AgentDefinition{
Kind: AgentKindHosted,
Name: "agent-image",
},
Image: "myregistry.azurecr.io/agent-image:v1",
}

req, err := CreateHostedAgentAPIRequest(agent, nil)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}

imgDef := req.Definition.(agent_api.ImageBasedHostedAgentDefinition)
if imgDef.Image != "myregistry.azurecr.io/agent-image:v1" {
t.Errorf("Image = %q", imgDef.Image)
}
}

func TestCreateHostedAgentAPIRequest_BuildConfigImageOverridesAgentImage(t *testing.T) {
t.Parallel()
agent := ContainerAgent{
AgentDefinition: AgentDefinition{
Kind: AgentKindHosted,
Name: "agent-image",
},
Image: "myregistry.azurecr.io/prebuilt:v1",
}

req, err := CreateHostedAgentAPIRequest(
agent,
&AgentBuildConfig{ImageURL: "myregistry.azurecr.io/published:v2"},
)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}

imgDef := req.Definition.(agent_api.ImageBasedHostedAgentDefinition)
if imgDef.Image != "myregistry.azurecr.io/published:v2" {
t.Errorf("Image = %q", imgDef.Image)
}
}

func TestCreateHostedAgentAPIRequest_MissingImageURL(t *testing.T) {
t.Parallel()
agent := ContainerAgent{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,43 @@ template:
}
}

// TestExtractAgentDefinition_WithImage tests that image is parsed and round-tripped.
func TestExtractAgentDefinition_WithImage(t *testing.T) {
yamlContent := []byte(`
name: image-agent
template:
kind: hosted
name: image-agent
image: myregistry.azurecr.io/myimage:v1
protocols:
- protocol: invocations
version: 1.0.0
`)

agent, err := ExtractAgentDefinition(yamlContent)
if err != nil {
t.Fatalf("ExtractAgentDefinition failed: %v", err)
}

containerAgent, ok := agent.(ContainerAgent)
if !ok {
t.Fatalf("Expected ContainerAgent, got %T", agent)
}

if containerAgent.Image != "myregistry.azurecr.io/myimage:v1" {
t.Errorf("Expected image 'myregistry.azurecr.io/myimage:v1', got '%s'", containerAgent.Image)
}

marshaled, err := yaml.Marshal(containerAgent)
if err != nil {
t.Fatalf("Failed to marshal ContainerAgent: %v", err)
}

if !strings.Contains(string(marshaled), "myregistry.azurecr.io/myimage:v1") {
t.Errorf("Marshaled YAML should contain image value, got:\n%s", string(marshaled))
}
}

// TestExtractAgentDefinition_WithoutResources tests that ContainerAgent without resources still parses
func TestExtractAgentDefinition_WithoutResources(t *testing.T) {
yamlContent := []byte(`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -172,8 +172,16 @@ type ContainerResources struct {
// ContainerAgent This represents a container based agent hosted by the provider/publisher.
// The intent is to represent a container application that the user wants to run
// in a hosted environment that the provider manages.
//
// When Image is set, deploy can use the pre-built container image instead of
// building from a Dockerfile:
// - Interactive mode: the user is prompted whether to use the configured
// image or build from a Dockerfile. The default is to build.
// - Non-interactive mode (`--no-prompt`): the default selection (build from
// Dockerfile) is used automatically.
type ContainerAgent struct {
AgentDefinition `json:",inline" yaml:",inline"`
Image string `json:"image,omitempty" yaml:"image,omitempty"`
Protocols []ProtocolVersionRecord `json:"protocols" yaml:"protocols"`
Resources *ContainerResources `json:"resources,omitempty" yaml:"resources,omitempty"`
EnvironmentVariables *[]EnvironmentVariable `json:"environmentVariables,omitempty" yaml:"environment_variables,omitempty"`
Expand Down
Loading
Loading