Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Go] Add Go API client generator #1747

Merged
merged 8 commits into from
Jan 22, 2016
Merged

Conversation

wing328
Copy link
Contributor

@wing328 wing328 commented Dec 21, 2015

This PR contains a functional Golang API client, which has been tested with Petstore (GET, POST form, POST JSON).

There are still some features pending to be added, e.g. authentication, default header, file upload, unit tests and more. I'll create some tasks for tracking shortly.

@wing328 wing328 added this to the v2.1.5 milestone Dec 21, 2015
@wing328 wing328 mentioned this pull request Dec 21, 2015
@fehguy
Copy link
Contributor

fehguy commented Dec 21, 2015

@casualjim want to look at this?

@casualjim
Copy link
Contributor

This is super optimistic and will only work for very simple models.
As soon as allof, additionalproperties, ... come into play the models will not work.

I'm very close to having something ready that makes all of it work properly. I have tickets on my backlog to submit integrations back to this project.

@wing328 would you like to help make go-swagger/go-swagger better? There are 3 open issues left wrt to generating models.

@wing328
Copy link
Contributor Author

wing328 commented Dec 22, 2015

@casualjim I agree with you that the go generator in this PR is very basic and won't work with allof, etc at at the moment.

I'm definitely aware of all the great work you've done with go-swagger and I've been referring people to your project when they're looking for a go api server/client generator based on swagger spec.

If I understand correctly, go-swagger client constructs the operations/methods dynamically based on a swagger spec during runtime, which means there's no static API files created for operations (similar to swagger-js, and now there's also a static API client for JS).

My intention was to create a static API client for Go and I'm still referring people to go-swagger for a more mature API client.

Can you share with us the URL to the remaining 3 open issues for go-swagger client so that anyone from the swagger community who is interested can potentially help on those?

@casualjim
Copy link
Contributor

There is no real dynamic aspect to the client that gets generated by go-swagger. There is a bit of content type inference that happens but other than that everything else is static.
There are structs generated for everything.

I have these 2 issues open:
go-swagger/go-swagger#110
go-swagger/go-swagger#109

The plan with those is to use a process builder and look in the path for the go swagger binary and map the required command line args. Perhaps that's an alternative implementation for this pull request? it will already support more features than this code.

You can see here how none of it is dynamic: https://github.com/go-swagger/go-swagger/blob/master/examples/todo-list/client/todos/find_parameters.go
https://github.com/go-swagger/go-swagger/blob/master/examples/todo-list/client/todos/todos_client.go#L62

Remaining issues: https://github.com/go-swagger/go-swagger/milestones/Minimal%20first%20release

@wing328
Copy link
Contributor Author

wing328 commented Dec 22, 2015

After I ran the command below, I got only Go model files under models folder:

./bin/swagger generate client -f /Users/williamcheng/Code/swagger-codegen/modules/swagger-codegen/src/test/resources/2_0/petstore.json

I checked the files but didn't find getPetById and other methods/operations. Am I doing anything wrong with the swagger generate client command?

I looked at the example in http://goswagger.io/generate/client/ and found the following example code:

  // load the swagger spec from URL or local file
  doc, err := spec.Load("https://raw.githubusercontent.com/go-swagger/go-swagger/master/examples/todo-list/swagger.yml")
  if err != nil {
    log.Fatal(err)
  }

  // create the transport
  transport := httptransport.New(doc)
  // configure the host
  if os.Getenv("TODOLIST_HOST") != "" {
    transport.Host = os.Getenv("TODOLIST_HOST")
  }

which seems to me it's loading the spec from a URL/file and construct the "transport" dynamically but as you've pointed out you're not really doing anything dynamic in the Go API client so my understanding is wrong.

@casualjim
Copy link
Contributor

That petstore spec doesn't validate:

git:(master) ✗ ! +? » swagger validate https://raw.githubusercontent.com/swagger-api/swagger-codegen/master/modules/swagger-codegen/src/test/resources/petstore.json

The swagger spec at "https://raw.githubusercontent.com/swagger-api/swagger-codegen/master/modules/swagger-codegen/src/test/resources/petstore.json" is invalid against swagger specification 2.0. see errors :
- status in query must be of type array: "string"

Go swagger also runs into a nil issue.

git:(master) ✗ ! +? » curl -sL -o swagger.json https://raw.githubusercontent.com/swagger-api/swagger-codegen/master/modules/swagger-codegen/src/test/resources/petstore.json && swagger generate client -f ./swagger.json
2015/12/21 19:36:09 rendered model template: User
2015/12/21 19:36:10 generated model User
2015/12/21 19:36:10 rendered model template: Category
2015/12/21 19:36:10 generated model Category
2015/12/21 19:36:10 rendered model template: Pet
2015/12/21 19:36:10 generated model Pet
2015/12/21 19:36:10 rendered model template: Tag
2015/12/21 19:36:10 generated model Tag
2015/12/21 19:36:10 rendered model template: Order
2015/12/21 19:36:10 generated model Order
2015/12/21 19:36:10 rendered client parameters template: pet.AddPetParameters
2015/12/21 19:36:10 rendered client responses template: pet.AddPetResponses
2015/12/21 19:36:10 rendered client parameters template: user.CreateUserParameters
2015/12/21 19:36:10 rendered client responses template: user.CreateUserResponses
template: parameter:85:14: executing "parameter" at <.Child.Formatter>: nil pointer evaluating *generator.GenItems.Formatter

but it does generate more stuff:

git:(master) ✗ ! +? » tree
.
├── client
│   ├── pet
│   │   ├── add_pet_parameters.go
│   │   └── add_pet_responses.go
│   └── user
│       ├── create_user_parameters.go
│       └── create_user_responses.go
├── models
│   ├── category.go
│   ├── order.go
│   ├── pet.go
│   ├── tag.go
│   └── user.go
└── swagger.json

@wing328
Copy link
Contributor Author

wing328 commented Dec 22, 2015

Here is the full output of the command I ran:

go-workspace-dir|⇒ ./bin/swagger generate client -f /Users/williamcheng/Code/swagger-codegen/modules/swagger-codegen/src/test/resources/2_0/petstore.json
2015/12/22 11:49:04 rendered model template: definitions
2015/12/22 11:49:04 generated model definitions
2015/12/22 11:49:04 rendered model template: User
2015/12/22 11:49:04 generated model User
2015/12/22 11:49:04 rendered model template: Category
2015/12/22 11:49:04 generated model Category
2015/12/22 11:49:05 rendered model template: Pet
2015/12/22 11:49:05 generated model Pet
2015/12/22 11:49:05 rendered model template: Tag
2015/12/22 11:49:05 generated model Tag
2015/12/22 11:49:05 rendered model template: Order
2015/12/22 11:49:05 generated model Order
2015/12/22 11:49:05 target must reside inside a location in the GOPATH
go-workspace-dir|⇒ echo $GOPATH
/Users/williamcheng/go-workspace-dir/
go-workspace-dir|⇒ pwd
/Users/williamcheng/go-workspace-dir

Does it mean I need to specify the target somehow?

@casualjim
Copy link
Contributor

I think it wants you to do this in a subdir of $GOPATH

mkdir -p $GOPATH/src/petstore
cd $GOPATH/src/petstore
$GOPATH/bin/swagger generate client -f /Users/williamcheng/Code/swagger-codegen/modules/swagger-codegen/src/test/resources/2_0/petstore.json

@wing328
Copy link
Contributor Author

wing328 commented Dec 22, 2015

Got the same result within a subfolder models:

models|⇒ ../bin/swagger generate client -f /Users/williamcheng/Code/swagger-codegen/modules/swagger-codegen/src/test/resources/2_0/petstore.json
2015/12/22 11:57:55 rendered model template: Tag
2015/12/22 11:57:55 generated model Tag
2015/12/22 11:57:55 rendered model template: Order
2015/12/22 11:57:55 generated model Order
2015/12/22 11:57:55 rendered model template: definitions
2015/12/22 11:57:55 generated model definitions
2015/12/22 11:57:55 rendered model template: User
2015/12/22 11:57:55 generated model User
2015/12/22 11:57:55 rendered model template: Category
2015/12/22 11:57:55 generated model Category
2015/12/22 11:57:55 rendered model template: Pet
2015/12/22 11:57:55 generated model Pet
2015/12/22 11:57:55 target must reside inside a location in the GOPATH
models|⇒ pwd
/Users/williamcheng/go-workspace-dir/models
models|⇒ echo $GOPATH
/Users/williamcheng/go-workspace-dir/
models|⇒ 

@casualjim
Copy link
Contributor

In this path: $GOPATH/src/random_dir

The src is important. the location for go sources in the GOPATH is $GOPATH/src
So it should really be a subdir of $GOPATH/src

@wing328
Copy link
Contributor Author

wing328 commented Dec 22, 2015

OK. Running the command inside a subfolder under src works for me.

If I might, I would suggest updating the error message target must reside inside a location in the GOPATH to target must reside inside a location in the $GOPATH/src

@casualjim
Copy link
Contributor

I've also fixed the issues that came from generating a client for an invalid spec, so if you do go get -u github.com/go-swagger/go-swagger/cmd/swagger it should generate a full client for that spec.

@wing328
Copy link
Contributor Author

wing328 commented Dec 22, 2015

Thanks for the quick turnaround. Confirmed that I no longer see the nil pointer exception after running go get to get the latest go-swagger/cmd/swagger

@fehguy fehguy modified the milestones: v2.1.5, v2.1.6 Jan 6, 2016
@wing328
Copy link
Contributor Author

wing328 commented Jan 13, 2016

@casualjim given that the Go API client generated by go-swagger is a lot more mature, do you mind if we update our Go API client to mimic yours?

We'll put down the following in each auto-generated files in the Go API client

This Go API client is based on the work done by go-swagger contributors.
Ref: https://github.com/go-swagger/go-swagger/graphs/contributors

@casualjim
Copy link
Contributor

If you want I can generate a release. Perhaps this could be embedded in swagger codegen, and it can shell out with process builder?

Which will allow us to close this ticket? go-swagger/go-swagger#109

@wing328
Copy link
Contributor Author

wing328 commented Jan 22, 2016

@casualjim I've discussed with @fehguy and decided to merge this PR into master so that the community can help contribute to make it better.

wing328 added a commit that referenced this pull request Jan 22, 2016
[Go] Add Go API client generator
@wing328 wing328 merged commit 5b6d224 into swagger-api:master Jan 22, 2016
@casualjim
Copy link
Contributor

the code this generates is invalid afaict
Have you tried to actualy use it in a go project ?

@wing328
Copy link
Contributor Author

wing328 commented Jan 22, 2016

@wing328 wing328 deleted the add_golang branch January 22, 2016 14:25
@casualjim
Copy link
Contributor

why aren't you just shelling out to go-swagger.
This will break down with all but the simplest specs.

  • no allOf support
  • no additionalItems support
  • no additionalProperties support
  • no discriminator support
  • no nested object support

because for all these things you'd require a custom deserializer/serializer.

So please I urge you guys to just integrate by shelling out to the go-swagger client. There are number of challenges that are unique to go which is why I didn't do it in this project. So instead of merging a janky client and starting all that work again, why not reuse mine?

That first import ./swagger is super invalid because it breaks everything that wants to depend on it.

@fehguy
Copy link
Contributor

fehguy commented Jan 22, 2016

We have to run non interactive and only in the jvm unfortunately

@jeetcontext
Copy link

jeetcontext commented Dec 22, 2016

hi, I am new to this tool. I am not able to generate the enum type with the present code. Does it support the enum generation within the GoClientCodegen.java and same within the mustache file? Please guide me what to do..

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants