My experience implementing a self service UI in ruby #1437
Replies: 1 comment 1 reply
-
Thank you for the feedback, we really appreciated it! I'll try to answer everything in detail below :)
Using wireshark to debug definitely sounds a bit frustrating. Do you remember what was the reason for the broken behaviour you experienced?
That also sounds quite frustrating :/ It's of course a good indicator if
So you mean the Ruby API here, correct? Unfortunately we currently do not have anyone proficient with Ruby. Since we're a small team (I'm actually maintaining Ory Kratos on my own) it is not possible to provide custom SDKs for other languages. Even the Go SDK is auto-generated and I had to create a long PR (still not merged) in OpenAPI Spec to resolve a lot of broken things: OpenAPITools/openapi-generator#8491 For Ruby, there might be a better generator template. I chose the one which looked like it was the default one: https://openapi-generator.tech/docs/generators/ruby/ I'm not sure if another library generator is better or not (e.g. faraday).
Yes, v0.6 was a major change in terms of the UI code. I tried to document it as good as possible, update all the respective documentation, but sometimes things can slip. What was the hardest for you here? Was it a lack of description, lack of details, or just the sheer volume of changes? In Ory Hydra I used to write an UPGRADE. At some point I changed the approach and released this high level description as part of the release notes, which you can find here for Ory Kratos 0.6. However, it appears that those are not included in the changelog itself. Did you find these high level release notes? Are you subscribed to the newsletter? We generally include them there. Not including them in the changelog is definitely a bug that we need to resolve. I've created an issue to track that here: #1442 Did you find that page with the release notes? Or is that you're missing? Would it have helped you during upgrading? Regarding maturity, in our docs we currently state that Ory Kratos is a sandbox project, which has implications on API stability. See Software Maturity. It's still frustrating though. I had an idea to label experimental / alpha APIs as such in the SDKs. What do you think about that? It would make it at least explicit that you're using unstable APIs?
Yeah, I gotta be honest here, with all the love I can give to the maintainers of openapi-generator, most of the generated code is terrible. I've looked into other options to auto-generate code from OpenAPI but all other options are even worse. The only thing I could find that generates better code is protobuf, but that's an entirely different protocol. My plan is to beef up our library team and have people dedicated to writing better OpenAPI generator templates for all the different languages. So if you're looking for a job... :)
So all Ory software runs with or without Docker. We just ship Docker with Docker Compose because it's easier to boot a database. You can use Ory on raw linux/mac/windows VMs. I'm not sure what difficulties you were facing here? In the simplest case you could SSH into a VM, download the binary, download the config, and go?
We have thought about that too. I think a solid approach would be to try and get maintainership and some people dedicated to improving the openapi generator templates so that they match the experience of e.g. the Google SDKs. In the end, the SDKs are still kinda fragile due to the way they are generated (from code docs...) so I'm not sure if writing wrappers wouldn't end up with more work. To follow up with your good feedback, here are some things we had planned before I saw this post, and some which we plan on doing following your post:
Do you have any other ideas? |
Beta Was this translation helpful? Give feedback.
-
My intent of this post is to document and share my experience of using the ruby client library. It is also my intent that this provides constructive feedback and to act as a discussion point. If I've failed in that please let me know and I'll try to clarify. With that in mind please excuse any hyperbolic language in it's born from the somewhat frustrating time during this process!
In October last year I wrote a self service UI app in ruby based on the Kratos ruby client library using the official typescript project as a template. I eventually got it working by comparing the wireshark output of the typescript version with my own. It took a while but I put it down to learning a new system. And even though it took me a while to sort it all out it has worked flawlessly since.
Cut forward 8 months and I decide to port my ruby app to the latest version of kratos, mainly because I want to use the hooks (and to not run old software). No problem! So I read the release notes from 0.4 → 0.5 and 0.5 → 0.6. Ok, so a lot had changed. I updated the Gemfile to reflect the new version, changed the URIs as outlined in the release notes. I looked at the gem documentation. Nothing. Oh well there's always the README.md, so I changed the existing methods to the updated methods and boom everything blow up.
There is a syntax problem with the library for which I've opened a but report for #1426 (which has been fixed). So I modified the gem to at least get around that immediate issue.
This is where it where it all starts to get a bit hazy. Nothing worked but I didn't know if the problem was with my kratos setup or with the ruby code. I compared the ruby code with the typescript code and it looks about right so maybe it's the kratos configuration. So I ran up docker-compose and eventually manage to extract a known good kratos configuration file which is virtually identical to the one I have. So kratos looks good. Next I did the same with the
kratos-selfservice-ui-node
and get that working. But the typescript code is very similar to my ruby code. This is where I start going round and round in circles! So I took a deep breath and started from scratch. I couldn't even getto_session
to work, it throws a stack trace seemingly in rack! This turned out to the kratos library trying to log something by iterating overnil
.This is pretty much the point at which I decided to write this post. As it stands I don't know what to do. In fact I think the only option is to use the typescript version which I'm really trying not to because I don't want to introduce another language (least of all one I have no knowledge of) into a project that already has too many languages.
Problem Areas
The points below summarise the major problems I had and I suspect will act as an impediment, at least in the short term, to people adopting the Ory suite of tools.
Automatically generated OpenAPI client libraries
The API is virtually unusable. I understand why you automatically generate the client code but it is almost unusable: the library documentation is useless and there is one very short example which, at the risk of repeating myself, is virtually useless. I had a look on github to see if anyone else had written something that I could use as an example but there was nothing.
Only the typescript kratos-selfservice-ui-node is documented
There is zero documentation (apart from the auto-generated documentation) for non-typescript kratos-selfservice-ui-node versions. I'm probably overstating this as I only looked at the ruby client library so I can't really comment on the other client libraries! Implementing the self service UI code is not a trivial thing; it's conceptually confusing with all the redirects and two different endpoints. The lack of good examples just makes it even harder. This is also exacerbated by the divergence between the typescript and ruby APIS (see the next point).
The upgrade process
The upgrade from 0.4 to 0.6 has been torturous; there is no other way of putting it. Yes I know it is early days, etc. but the release notes relating to breaking changes (they seem to be automatically generated) make it extremely difficult to actually work out what changes are required from a high level perspective.
Had I known what I know now three days ago I would have started from scratch rather than try to modify the existing code.
I think my code is falling over because the API has completely changed and using the typescript version to work out what I need to do in the ruby version is simply an exercise in futility.
Why do I think the API has completely changed? Because the only example in the README is quite different between version 0.4 and 0.6. Version 0.4 is quite similar to the typescript version whereas the 0.6 version is ... well, to be honest, I'm not really sure what it is.
In the example in the README I have to create an object called
OryHydraClient::CreateIdentity
add it to a hash where the key is calledcreate_identity
and then pass that into a method calledcreate_identity
. This is truly the most bizarre API I've ever seen and is as far from the principle of least surprise I think I've ever encountered. I also think this may be reason my code doesn't work but after spending three days working on this I don't want to spend any more time on conjecture.Converting from the Docker examples to a production environment
Extracting the various configurations from the docker images proved to be a lot trickier that I had expected. I don't use docker (I use LXD) so have no familiarity with it.
I ended up using a combination of the proc filesytem (environment) and general unix tools to extract the configs. I sure there is an easier way but my lack of docker knowledge just makes it hard.
I understand why you put everything in Docker containers but the lack of non-docker configuration examples makes things quite tricky for those of us who don't to/can't use docker.
Possible fix
I think the most of the problems could be fixed by writing a wrapper around the automatically generated library that provides a more idiomatic interface. I don't think it would be too much work and the maintenance burden would be relatively small.
Beta Was this translation helpful? Give feedback.
All reactions