Skip to content

Commit dc86c0e

Browse files
committed
Create project fully works!!!
1 parent 79a56b6 commit dc86c0e

File tree

4 files changed

+162
-136
lines changed

4 files changed

+162
-136
lines changed

cli/projectcreate.go

Lines changed: 152 additions & 121 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,19 @@ import (
77
"io"
88
"os"
99
"path/filepath"
10+
"strings"
1011
"time"
1112

1213
"github.com/briandowns/spinner"
1314
"github.com/fatih/color"
1415
"github.com/google/uuid"
1516
"github.com/manifoldco/promptui"
1617
"github.com/spf13/cobra"
18+
"github.com/xlab/treeprint"
1719
"golang.org/x/xerrors"
1820

1921
"github.com/coder/coder/coderd"
22+
"github.com/coder/coder/coderd/parameter"
2023
"github.com/coder/coder/codersdk"
2124
"github.com/coder/coder/database"
2225
"github.com/coder/coder/provisionerd"
@@ -62,150 +65,178 @@ func projectCreate() *cobra.Command {
6265
return err
6366
}
6467

65-
spin := spinner.New(spinner.CharSets[0], 25*time.Millisecond)
66-
spin.Suffix = " Uploading current directory..."
67-
spin.Start()
68-
69-
defer spin.Stop()
70-
71-
bytes, err := tarDirectory(directory)
68+
job, err := doProjectLoop(cmd, client, organization, directory, []coderd.CreateParameterValueRequest{})
7269
if err != nil {
7370
return err
7471
}
75-
76-
resp, err := client.UploadFile(cmd.Context(), codersdk.ContentTypeTar, bytes)
72+
project, err := client.CreateProject(cmd.Context(), organization.Name, coderd.CreateProjectRequest{
73+
Name: name,
74+
VersionImportJobID: job.ID,
75+
})
7776
if err != nil {
7877
return err
7978
}
8079

81-
job, err := client.CreateProjectVersionImportProvisionerJob(cmd.Context(), organization.Name, coderd.CreateProjectImportJobRequest{
82-
StorageMethod: database.ProvisionerStorageMethodFile,
83-
StorageSource: resp.Hash,
84-
Provisioner: database.ProvisionerTypeTerraform,
80+
_, _ = fmt.Fprintf(cmd.OutOrStdout(), "%s The %s project has been created!\n", color.HiBlackString(">"), color.HiCyanString(project.Name))
81+
_, err = runPrompt(cmd, &promptui.Prompt{
82+
Label: "Create a new workspace?",
83+
IsConfirm: true,
84+
Default: "y",
8585
})
8686
if err != nil {
8787
return err
8888
}
89-
spin.Stop()
9089

91-
logs, err := client.FollowProvisionerJobLogsAfter(cmd.Context(), organization.Name, job.ID, time.Time{})
92-
if err != nil {
93-
return err
94-
}
95-
for {
96-
log, ok := <-logs
97-
if !ok {
98-
break
99-
}
100-
_, _ = fmt.Fprintf(cmd.OutOrStdout(), "%s %s\n", color.HiGreenString("[tf]"), log.Output)
101-
}
90+
fmt.Printf("Create a new workspace now!\n")
91+
return nil
92+
},
93+
}
94+
currentDirectory, _ := os.Getwd()
95+
cmd.Flags().StringVarP(&directory, "directory", "d", currentDirectory, "Specify the directory to create from")
10296

103-
job, err = client.ProvisionerJob(cmd.Context(), organization.Name, job.ID)
104-
if err != nil {
105-
return err
106-
}
97+
return cmd
98+
}
10799

108-
if provisionerd.IsMissingParameterError(job.Error) {
109-
fmt.Printf("Missing something!\n")
110-
return nil
111-
}
100+
func doProjectLoop(cmd *cobra.Command, client *codersdk.Client, organization coderd.Organization, directory string, params []coderd.CreateParameterValueRequest) (*coderd.ProvisionerJob, error) {
101+
spin := spinner.New(spinner.CharSets[5], 100*time.Millisecond)
102+
spin.Writer = cmd.OutOrStdout()
103+
spin.Suffix = " Uploading current directory..."
104+
spin.Color("fgHiGreen")
105+
spin.Start()
106+
defer spin.Stop()
112107

113-
resources, err := client.ProvisionerJobResources(cmd.Context(), organization.Name, job.ID)
114-
if err != nil {
115-
return err
116-
}
108+
bytes, err := tarDirectory(directory)
109+
if err != nil {
110+
return nil, err
111+
}
112+
113+
resp, err := client.UploadFile(cmd.Context(), codersdk.ContentTypeTar, bytes)
114+
if err != nil {
115+
return nil, err
116+
}
117117

118-
fmt.Printf("Resources: %+v\n", resources)
118+
job, err := client.CreateProjectVersionImportProvisionerJob(cmd.Context(), organization.Name, coderd.CreateProjectImportJobRequest{
119+
StorageMethod: database.ProvisionerStorageMethodFile,
120+
StorageSource: resp.Hash,
121+
Provisioner: database.ProvisionerTypeTerraform,
122+
ParameterValues: params,
123+
})
124+
if err != nil {
125+
return nil, err
126+
}
119127

120-
project, err := client.CreateProject(cmd.Context(), organization.Name, coderd.CreateProjectRequest{
121-
Name: name,
122-
VersionImportJobID: job.ID,
128+
spin.Suffix = " Waiting for the import to complete..."
129+
130+
logs, err := client.FollowProvisionerJobLogsAfter(cmd.Context(), organization.Name, job.ID, time.Time{})
131+
if err != nil {
132+
return nil, err
133+
}
134+
for {
135+
_, ok := <-logs
136+
if !ok {
137+
break
138+
}
139+
// _, _ = fmt.Fprintf(cmd.OutOrStdout(), "%s %s\n", color.HiGreenString("[tf]"), log.Output)
140+
}
141+
142+
job, err = client.ProvisionerJob(cmd.Context(), organization.Name, job.ID)
143+
if err != nil {
144+
return nil, err
145+
}
146+
147+
parameterSchemas, err := client.ProvisionerJobParameterSchemas(cmd.Context(), organization.Name, job.ID)
148+
if err != nil {
149+
return nil, err
150+
}
151+
parameterValues, err := client.ProvisionerJobParameterValues(cmd.Context(), organization.Name, job.ID)
152+
if err != nil {
153+
return nil, err
154+
}
155+
spin.Stop()
156+
157+
if provisionerd.IsMissingParameterError(job.Error) {
158+
valuesBySchemaID := map[string]coderd.ComputedParameterValue{}
159+
for _, parameterValue := range parameterValues {
160+
valuesBySchemaID[parameterValue.SchemaID.String()] = parameterValue
161+
}
162+
for _, parameterSchema := range parameterSchemas {
163+
_, ok := valuesBySchemaID[parameterSchema.ID.String()]
164+
if ok {
165+
continue
166+
}
167+
if parameterSchema.Name == parameter.CoderWorkspaceTransition {
168+
continue
169+
}
170+
value, err := runPrompt(cmd, &promptui.Prompt{
171+
Label: fmt.Sprintf("Enter value for %s:", color.HiCyanString(parameterSchema.Name)),
123172
})
124173
if err != nil {
125-
return err
174+
return nil, err
126175
}
176+
params = append(params, coderd.CreateParameterValueRequest{
177+
Name: parameterSchema.Name,
178+
SourceValue: value,
179+
SourceScheme: database.ParameterSourceSchemeData,
180+
DestinationScheme: parameterSchema.DefaultDestinationScheme,
181+
})
182+
}
183+
return doProjectLoop(cmd, client, organization, directory, params)
184+
}
127185

128-
fmt.Printf("Project: %+v\n", project)
129-
130-
// _, _ = fmt.Fprintf(cmd.OutOrStdout(), "Parsed project source... displaying parameters:")
131-
132-
// schemas, err := client.ProvisionerJobParameterSchemas(cmd.Context(), organization.Name, job.ID)
133-
// if err != nil {
134-
// return err
135-
// }
136-
137-
// values, err := client.ProvisionerJobParameterValues(cmd.Context(), organization.Name, job.ID)
138-
// if err != nil {
139-
// return err
140-
// }
141-
// valueBySchemaID := map[string]coderd.ComputedParameterValue{}
142-
// for _, value := range values {
143-
// valueBySchemaID[value.SchemaID.String()] = value
144-
// }
145-
146-
// for _, schema := range schemas {
147-
// if value, ok := valueBySchemaID[schema.ID.String()]; ok {
148-
// fmt.Printf("Value for: %s %s\n", value.Name, value.SourceValue)
149-
// continue
150-
// }
151-
// fmt.Printf("No value for: %s\n", schema.Name)
152-
// }
153-
154-
// schemas, err := client.ProvisionerJobParameterSchemas(cmd.Context(), organization.Name, job.ID)
155-
// if err != nil {
156-
// return err
157-
// }
158-
// _, _ = fmt.Fprintf(cmd.OutOrStdout(), "\n %s\n\n", color.HiBlackString("Parameters"))
159-
160-
// for _, param := range params {
161-
// if param.Value == nil {
162-
// _, _ = fmt.Fprintf(cmd.OutOrStdout(), " %s = must be set\n", color.HiRedString(param.Schema.Name))
163-
// continue
164-
// }
165-
// value := param.Value.DestinationValue
166-
// if !param.Schema.RedisplayValue {
167-
// value = "<redacted>"
168-
// }
169-
// output := fmt.Sprintf(" %s = %s", color.HiGreenString(param.Value.SourceValue), color.CyanString(value))
170-
// param.Value.DefaultSourceValue = false
171-
// param.Value.Scope = database.ParameterScopeOrganization
172-
// param.Value.ScopeID = organization.ID
173-
// if param.Value.DefaultSourceValue {
174-
// output += " (default value)"
175-
// } else {
176-
// output += fmt.Sprintf(" (inherited from %s)", param.Value.Scope)
177-
// }
178-
// root := treeprint.NewWithRoot(output)
179-
// root.AddNode(color.HiBlackString("Description") + "\n" + param.Schema.Description)
180-
// fmt.Fprintln(cmd.OutOrStdout(), strings.Join(strings.Split(root.String(), "\n"), "\n "))
181-
// }
182-
183-
// for _, param := range params {
184-
// if param.Value != nil {
185-
// continue
186-
// }
187-
188-
// value, err := runPrompt(cmd, &promptui.Prompt{
189-
// Label: "Specify value for " + color.HiCyanString(param.Schema.Name),
190-
// Validate: func(s string) error {
191-
// // param.Schema.Vali
192-
// return nil
193-
// },
194-
// })
195-
// if err != nil {
196-
// continue
197-
// }
198-
// fmt.Printf(": %s\n", value)
199-
// }
200-
201-
_, _ = fmt.Fprintf(cmd.OutOrStdout(), "Create project %q!\n", name)
202-
return nil
203-
},
186+
if job.Status != coderd.ProvisionerJobStatusSucceeded {
187+
return nil, xerrors.New(job.Error)
204188
}
205-
currentDirectory, _ := os.Getwd()
206-
cmd.Flags().StringVarP(&directory, "directory", "d", currentDirectory, "Specify the directory to create from")
207189

208-
return cmd
190+
_, _ = fmt.Fprintf(cmd.OutOrStdout(), "%s Successfully imported project source!\n", color.HiGreenString("✓"))
191+
192+
resources, err := client.ProvisionerJobResources(cmd.Context(), organization.Name, job.ID)
193+
if err != nil {
194+
return nil, err
195+
}
196+
return &job, outputProjectInformation(cmd, parameterSchemas, parameterValues, resources)
197+
}
198+
199+
func outputProjectInformation(cmd *cobra.Command, parameterSchemas []coderd.ParameterSchema, parameterValues []coderd.ComputedParameterValue, resources []coderd.ProjectImportJobResource) error {
200+
schemaByID := map[string]coderd.ParameterSchema{}
201+
for _, schema := range parameterSchemas {
202+
schemaByID[schema.ID.String()] = schema
203+
}
204+
205+
_, _ = fmt.Fprintf(cmd.OutOrStdout(), "\n %s\n\n", color.HiBlackString("Parameters"))
206+
for _, value := range parameterValues {
207+
schema, ok := schemaByID[value.SchemaID.String()]
208+
if !ok {
209+
return xerrors.Errorf("schema not found: %s", value.Name)
210+
}
211+
displayValue := value.SourceValue
212+
if !schema.RedisplayValue {
213+
displayValue = "<redacted>"
214+
}
215+
output := fmt.Sprintf("%s %s %s", color.HiCyanString(value.Name), color.HiBlackString("="), displayValue)
216+
if value.DefaultSourceValue {
217+
output += " (default value)"
218+
} else if value.Scope != database.ParameterScopeImportJob {
219+
output += fmt.Sprintf(" (inherited from %s)", value.Scope)
220+
}
221+
222+
root := treeprint.NewWithRoot(output)
223+
if schema.Description != "" {
224+
root.AddBranch(fmt.Sprintf("%s\n%s\n", color.HiBlackString("Description"), schema.Description))
225+
}
226+
if schema.AllowOverrideSource {
227+
root.AddBranch(fmt.Sprintf("%s Users can customize this value!", color.HiYellowString("+")))
228+
}
229+
_, _ = fmt.Fprintln(cmd.OutOrStdout(), " "+strings.Join(strings.Split(root.String(), "\n"), "\n "))
230+
}
231+
_, _ = fmt.Fprintf(cmd.OutOrStdout(), " %s\n\n", color.HiBlackString("Resources"))
232+
for _, resource := range resources {
233+
transition := color.HiGreenString("start")
234+
if resource.Transition == database.WorkspaceTransitionStop {
235+
transition = color.HiRedString("stop")
236+
}
237+
_, _ = fmt.Fprintf(cmd.OutOrStdout(), " %s %s on %s\n\n", color.HiCyanString(resource.Type), color.HiCyanString(resource.Name), transition)
238+
}
239+
return nil
209240
}
210241

211242
func tarDirectory(directory string) ([]byte, error) {

provisioner/terraform/parse.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ func convertVariableToParameter(variable *tfconfig.Variable) (*proto.ParameterSc
4646
Description: variable.Description,
4747
RedisplayValue: !variable.Sensitive,
4848
ValidationValueType: variable.Type,
49+
DefaultDestination: &proto.ParameterDestination{
50+
Scheme: proto.ParameterDestination_PROVISIONER_VARIABLE,
51+
},
4952
}
5053

5154
if variable.Default != nil {
@@ -57,9 +60,6 @@ func convertVariableToParameter(variable *tfconfig.Variable) (*proto.ParameterSc
5760
Scheme: proto.ParameterSource_DATA,
5861
Value: string(defaultData),
5962
}
60-
schema.DefaultDestination = &proto.ParameterDestination{
61-
Scheme: proto.ParameterDestination_PROVISIONER_VARIABLE,
62-
}
6363
}
6464

6565
if len(variable.Validations) > 0 && variable.Validations[0].Condition != nil {

provisioner/terraform/parse_test.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,9 @@ func TestParse(t *testing.T) {
5555
Name: "A",
5656
RedisplayValue: true,
5757
Description: "Testing!",
58+
DefaultDestination: &proto.ParameterDestination{
59+
Scheme: proto.ParameterDestination_PROVISIONER_VARIABLE,
60+
},
5861
}},
5962
},
6063
},
@@ -100,8 +103,10 @@ func TestParse(t *testing.T) {
100103
RedisplayValue: true,
101104
ValidationCondition: `var.A == "value"`,
102105
ValidationTypeSystem: proto.ParameterSchema_HCL,
103-
},
104-
},
106+
DefaultDestination: &proto.ParameterDestination{
107+
Scheme: proto.ParameterDestination_PROVISIONER_VARIABLE,
108+
},
109+
}},
105110
},
106111
},
107112
},

provisionerd/proto/provisionerd.proto

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -35,16 +35,6 @@ message CancelledJob {
3535
string error = 2;
3636
}
3737

38-
// TransitionedResource represents a resource that knows whether
39-
// it's existence is dependent on stop or not.
40-
//
41-
// This is used on import to display start + stopped resources
42-
// for the lifecycle of a workspace.
43-
message TransitionedResource {
44-
provisioner.Resource resource = 1;
45-
bool destroy_on_stop = 2;
46-
}
47-
4838
// CompletedJob is sent when the provisioner daemon completes a job.
4939
message CompletedJob {
5040
message WorkspaceProvision {

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy