@@ -3,6 +3,7 @@ package apply
33import (
44 "context"
55 "fmt"
6+ "sync"
67
78 "path/filepath"
89
@@ -28,14 +29,18 @@ type System struct {
2829 Deployments map [string ]Deployment `yaml:"deployments"`
2930}
3031
32+ type JobAgent struct {
33+ Id string `yaml:"id"`
34+ Config map [string ]any `yaml:"config"`
35+ }
36+
3137type Deployment struct {
32- Name string `yaml:"name"`
33- Description string `yaml:"description"`
34- SystemName string `yaml:"systemName"`
35- Metadata map [string ]string `yaml:"metadata"`
38+ Name string `yaml:"name"`
39+ Description * string `yaml:"description"`
40+ JobAgent * JobAgent `yaml:"jobAgent,omitempty"`
3641}
3742
38- // NewApplyCommand creates a new apply command
43+ // NewApplyCmd creates a new apply command
3944func NewApplyCmd () * cobra.Command {
4045 var filePath string
4146
@@ -56,7 +61,6 @@ func NewApplyCmd() *cobra.Command {
5661
5762func runApply (filePath string ) error {
5863 ctx := context .Background ()
59- logger := log .FromContext (ctx )
6064
6165 // Read and parse the YAML file
6266 config , err := readConfigFile (filePath )
@@ -65,45 +69,156 @@ func runApply(filePath string) error {
6569 }
6670
6771 // Create API client
72+ client , workspaceID , err := createAPIClient ()
73+ if err != nil {
74+ return err
75+ }
76+
77+ // Process systems and collect errors
78+ errors := processAllSystems (ctx , client , workspaceID , config .Systems )
79+
80+ if len (errors ) > 0 {
81+ return fmt .Errorf ("encountered %d errors during apply" , len (errors ))
82+ }
83+
84+ return nil
85+ }
86+
87+ func createAPIClient () (* api.ClientWithResponses , uuid.UUID , error ) {
6888 apiURL := viper .GetString ("url" )
6989 apiKey := viper .GetString ("api-key" )
7090 workspace := viper .GetString ("workspace" )
7191
7292 workspaceID , err := uuid .Parse (workspace )
7393 if err != nil {
74- return fmt .Errorf ("invalid workspace ID: %w" , err )
94+ return nil , uuid . Nil , fmt .Errorf ("invalid workspace ID: %w" , err )
7595 }
7696
7797 client , err := api .NewAPIKeyClientWithResponses (apiURL , apiKey )
7898 if err != nil {
79- return fmt .Errorf ("failed to create API client: %w" , err )
99+ return nil , uuid . Nil , fmt .Errorf ("failed to create API client: %w" , err )
80100 }
81101
82- for slug , system := range config . Systems {
83- logger . Info ( "Upserting system" , "name" , system . Name )
102+ return client , workspaceID , nil
103+ }
84104
85- systemID , err := upsertSystem (ctx , client , workspaceID , slug , system )
86- if err != nil {
87- logger .Error ("Failed to upsert system" , "name" , system .Name , "error" , err )
88- continue
89- }
90- logger .Info ("System created successfully" , "name" , system .Name , "id" , systemID )
105+ func processAllSystems (
106+ ctx context.Context ,
107+ client * api.ClientWithResponses ,
108+ workspaceID uuid.UUID ,
109+ systems map [string ]System ,
110+ ) []error {
111+ systemErrors := make (chan error , len (systems ))
112+ var systemWg sync.WaitGroup
113+
114+ for slug , system := range systems {
115+ systemWg .Add (1 )
116+ go processSystem (
117+ ctx ,
118+ client ,
119+ workspaceID ,
120+ slug ,
121+ system ,
122+ & systemWg ,
123+ )
124+ }
125+
126+ systemWg .Wait ()
127+ close (systemErrors )
128+
129+ // Collect all errors
130+ var errList []error
131+ for err := range systemErrors {
132+ errList = append (errList , err )
133+ }
134+
135+ return errList
136+ }
137+
138+ func processSystem (
139+ ctx context.Context ,
140+ client * api.ClientWithResponses ,
141+ workspaceID uuid.UUID ,
142+ slug string ,
143+ system System ,
144+ systemWg * sync.WaitGroup ,
145+ ) {
146+ defer systemWg .Done ()
147+
148+ log .Info ("Upserting system" , "name" , system .Name )
149+ systemID , err := upsertSystem (ctx , client , workspaceID , slug , system )
150+ if err != nil {
151+ log .Error ("Failed to upsert system" , "name" , system .Name , "error" , err )
152+ return
153+ }
154+ log .Info ("System created successfully" , "name" , system .Name , "id" , systemID )
155+
156+ systemIDUUID , err := uuid .Parse (systemID )
157+ if err != nil {
158+ log .Error ("Failed to parse system ID as UUID" , "id" , systemID , "error" , err )
159+ return
160+ }
161+
162+ processSystemDeployments (ctx , client , systemIDUUID , system )
163+ }
91164
92- systemIDUUID , err := uuid .Parse (systemID )
165+ func processSystemDeployments (
166+ ctx context.Context ,
167+ client * api.ClientWithResponses ,
168+ systemID uuid.UUID ,
169+ system System ,
170+ ) {
171+ var deploymentWg sync.WaitGroup
172+ for deploymentSlug , deployment := range system .Deployments {
173+ deploymentWg .Add (1 )
174+ log .Info ("Creating deployment" , "system" , system .Name , "name" , deployment .Name )
175+ go processDeployment (
176+ ctx ,
177+ client ,
178+ systemID ,
179+ deploymentSlug ,
180+ deployment ,
181+ & deploymentWg ,
182+ )
183+ }
184+ deploymentWg .Wait ()
185+ }
186+
187+ func processDeployment (
188+ ctx context.Context ,
189+ client * api.ClientWithResponses ,
190+ systemID uuid.UUID ,
191+ deploymentSlug string ,
192+ deployment Deployment ,
193+ deploymentWg * sync.WaitGroup ,
194+ ) {
195+ defer deploymentWg .Done ()
196+
197+ body := createDeploymentRequestBody (systemID , deploymentSlug , deployment )
198+
199+ if deployment .JobAgent != nil {
200+ jobAgentUUID , err := uuid .Parse (deployment .JobAgent .Id )
93201 if err != nil {
94- return fmt .Errorf ("invalid system ID: %w" , err )
202+ log .Error ("Failed to parse job agent ID as UUID" , "id" , deployment .JobAgent .Id , "error" , err )
203+ return
95204 }
205+ body .JobAgentId = & jobAgentUUID
206+ body .JobAgentConfig = & deployment .JobAgent .Config
207+ }
96208
97- for deploymentSlug , deployment := range system .Deployments {
98- logger .Info ("Creating deployment" , "name" , deployment .Name )
99- _ , err := upsertDeployment (ctx , client , systemIDUUID , deploymentSlug , deployment )
100- if err != nil {
101- logger .Error ("Failed to create deployment" , "name" , deployment .Name , "error" , err )
102- }
103- }
209+ _ , err := upsertDeployment (ctx , client , body )
210+ if err != nil {
211+ log .Error ("Failed to create deployment" , "name" , deployment .Name , "error" , err )
104212 }
213+ }
105214
106- return nil
215+ func createDeploymentRequestBody (systemID uuid.UUID , slug string , deployment Deployment ) api.CreateDeploymentJSONBody {
216+ return api.CreateDeploymentJSONBody {
217+ Slug : slug ,
218+ SystemId : systemID ,
219+ Name : deployment .Name ,
220+ Description : deployment .Description ,
221+ }
107222}
108223
109224func readConfigFile (filePath string ) (* Config , error ) {
@@ -164,21 +279,14 @@ func upsertSystem(
164279func upsertDeployment (
165280 ctx context.Context ,
166281 client * api.ClientWithResponses ,
167- systemID uuid.UUID ,
168- deploymentSlug string ,
169- deployment Deployment ,
282+ deployment api.CreateDeploymentJSONBody ,
170283) (string , error ) {
171- resp , err := client .CreateDeploymentWithResponse (ctx , api.CreateDeploymentJSONRequestBody {
172- SystemId : systemID ,
173- Slug : deploymentSlug ,
174- Name : deployment .Name ,
175- Description : & deployment .Description ,
176- })
284+ resp , err := client .CreateDeploymentWithResponse (ctx , api .CreateDeploymentJSONRequestBody (deployment ))
177285
178286 if err != nil {
179287 return "" , fmt .Errorf ("API request failed: %w" , err )
180288 }
181-
289+
182290 if resp .StatusCode () >= 400 {
183291 return "" , fmt .Errorf ("API returned error status: %d" , resp .StatusCode ())
184292 }
0 commit comments