Do all the things like ++ or -- rants, post your own rants, comment on others' rants and build your customized dev avatarSign Up
From the creators of devRant, Pipeless lets you power real-time personalized recommendations and activity feeds using a simple APILearn More
Any one remember me talking about Covey (have a look at my rants from about 5 months ago)?
Well, it's finally (somewhat) usable!
For those who are wondering why it took so long, work (I got a job!) and some bugs in a core dependency of plugin system got in the way. I actually have to take a break right around now, for about 3 weeks to work on a project that has a deadline. But after that it should be smooth sailing to a proper alpha release!
You'll need to install upx for the build, and postgres for the actual function, and you want a few VMs to act as nodes, but have fun!
We have a bespoke management system that was developed in different times by different people, and hence each system acts like the others don't exist. Our current developer (not me) has been with us for around 15 years (he cares too much to leave, but does also have another primary occupation), and has been maintaining this old asp.Net codebase.
I've been slowly trying to plant the seeds of desire for something else, and we might possibly - by the end of the year - begin to use ERPNext to replace at least one of the systems, and then eventually more.
Today I'm ranting about Windows. No, it's not "WiNdOwS sUcKs!", it's more like "But why!?"
See, I'm an IT guy for the year, and in my office they use Windows. Now once upon a time, they had Active Directory and all that (well, actually, they still do) but then they got some new computers running Windows 10, and for some reason they just couldn't join them to the domain!
Why can't they, you ask? Well, Microsoft only allows Win 10 Pro and up to join a Domain, and since these computers came with Win 10 Home, that wasn't possible.
Long story short, I now have some 30 computers that need to be upgraded (possibly from 7) to Win 10 Pro, and joined to the Domain.
Thing is, I would like to do that all in one go, so I look into how to automatically setup Windows.
"Ah! Got it, provisioning packages!"
Lest you think they work let me spare you now: they don't. Just like real computers where everything is different, provisioning packages failed to work twice, and after wasting about a week trying to make it work, I gave up.
So now I realized that I need to try a different method, a custom windows image. Issue is, I've got no clue how to make one. See, microsoft decided to go all in on the provisioning packages thing (they do have advantages in certain use cases), and seemed to decide that making custom images was no longer necessary, so they documentation was nearly impossible to find.
But after a lot of searching, I figured out how to do it:
1. Install Windows in a VM.
2. Put it in audit mode.
3. Install your stuff.
4. Create an unattend.xml file with certain customizations.
5. Put the unattend in Windows\System32\Sysprep
6. Generalize the image.
7. Boot WinPE.
8. Open the console.
9. Capture the image.
10. Wait an hour or two.
I'm over simplifying, it was a huge PITA, and yet there were still issues.
Maybe another time I'll talk about those.27
Like I did before, I'm going to be live streaming development of Covey (https://github.com/chabad360/covey) again (or at least that's the plan): https://youtu.be/WHH8yBcmytU
Should be live at 9:30 ET4
Decided to start live coding the development of Covey because it helps me be productive.
Feel free to join in: https://youtu.be/Lnw4-NaHW4Y2
What you see in that screenshot, that was earned.
I'm on the plane and I want an hour of free Gogo (read: crappy) WiFi on my laptop (so I can push the code I'm probably the most proud of, more on that another time). The problem is that the free T-Mobile WiFi is apparently only available on mobile.
So after trying to just use responsive mode, and that still (almost obviously) not working. I realize it's time to bring in the big guns: A User Agent switcher. Small catch: I don't have an add-on for FF that can do that.
So on my phone I find an add-on that can and download the file. To send it to my computer, I initially thought to go through KDEConnect, but Gogo's network also isolates each system, so that doesn't work. So I try to send it over Bluetooth, except I can't. Why? Because Android's Bluetooth share "doesn't support" the .xpi extension, so I dump it in a zip (in retrospect, I should have just renamed it), and now I can share.
After a few tries, I successfully get the file over, extract the zip, and install the extension. Whew! Now I open up Gogo's page and proceed to try again, but this time I change the user-agent. Doesn't work... Ah! Cookies! I delete the cookies for Gogo (I had a cookie editor add-on already), but I had to try a few times because Gogo's scripts keep trying to, but I got it in the end.
Finally that stupid error saying it's for phones only went away, and I could write this rant for you.22
I've ranted about this before, but here we go again:
I was racking my brains trying to figure out how one could possibly implement plugins easily in Go.
I had a look at using RPC, which requires far to much boilerplate to be realistic. I looked at using Lua, but there doesn't seem to be a straight forward way of using it. I was even about to go with using WASM (yes, WASM). But then I came across Yaegi ("Yet another elegant Go interpreter", you heard right: "interpreter"), Yaegi is also very easy to use.
There are a few issues (including some I haven't solved yet), including flexibility (multiple types of plugins), module support, etc. Fortunately, Traefik just released their plugin system which is based on Yaegi (same company), and I got to learn a few tricks from them.
Here's how module loading works: The developer vendors their dependencies and pushes them to a repo. The user downloads the repo as a zip and saves it to the plugins folder. I hash the zip, unzip it to a cache, and set the the GOPATH for the interpreter to be that extracted folder. I then load the module (which is defined by a config file in the folder), and save it for later. This is the relatively easy part.
The hard part is allowing for different types of plugins. It looks easy, but Go has a strict typing system, makes things complicated. I'm in the process of solving this problem, and so far it should go like this: Check that the plugin fits an arbitrary interface, and if it does, we're good the go. I will just have to apply the returned plugin to that interface. I don't like this method for a few reasons, but hopefully with generics it will become a bit more clean.1
Building on yesterday's rant (https://devrant.com/rants/3110183/), after sleeping on it I realized that using groups was completely non-necessary, so I got rid of them and got a much more efficient (and faster) function:
Also, I've got these in a repo: https://github.com/chabad360/...15
I was bored, spent an half hour writing a non-recursive, relatively-high-allocations, somewhat slow Fibonacci function.
Here you go:17
So remember rant from yesterday about Go plugins? Well turns out that a new version of Traefik was just released with plugins based on Yaegi!
"It can't all be good news" you say, suddenly paying attention. You're right, their implementation is a bit weird and I don't fully understand it... So I've decided to try to ask for help from the guy who wrote the feature, let's see if he responds...
If you've ever tried using Go plugins raise your hand.
If you've ever tried doing plugins in Go, raise your hand.
If you think that the following rant will be interesting, raise your hand.
If you raised your hand, press [Read More]:
This is a tale of pain and sorrow, the sorrow of discovering that what could be a wonderful feature is woefully incomplete, and won't be for a very long time...
Go plugins are a cool feature: dynamically load pre-compiled code, and interact with it in a useful and relatively performant way (e.g. for dynamically extending the capabilities of your program). So far it sounds great, I know right?
Now let me list off some issues (in order of me remembering them):
1. You can't unload them (due to some bs about dlopen), so you need to restart the application...
2. They bundle the stdlib like a regular Go binary, despite the fact that they're meant to be dynamic!
3. #2 wouldn't be so bad if they didn't also require identical versions of all dependencies in both binaries (meaning you'd need to vendor the dependencies, and also hope you are using the right Go version).
4. You need to use -trimpath or everything dies...
All in all, they are broken and no one is rushing to fix it (literally, the Go team said they aren't really supporting it currently...).
So what other options are there for making plugins in Go?
There's the Hashicorp method of using RPC, where you have two separate applications one the plugin, one the plugin server, and they communicate over RPC. I don't like it. Why? Because it feels like a hack, it's not really efficient and it carries a fear of a limitation that I don't like...
Then we come to a somewhat more clever approach: using Lua (or any other scripting language), it's well known, it's what everyone uses (at least in games...). But, it simply is too hard to use, all the Go Lua VMs I could find were simply too hard to set up...
Now we come to the most creative option I've seen yet: WASM. Now you ask "WASM!? But that's a web thing, how are you gonna make that work?" Indeed, my son, it is a web thing, but that doesn't mean I can't use it! Someone made a WASM VM for Go, and the pros are that you can use any WASM supporting language (i.e. any/all of them). Problem inefficient, PITA to use, and also suffers from the same issues that were preventing me from using Lua.
Enter Yaegi, a Go interpreter created by the same guys who made (and named) Traefik. Yes, you heard me right, an INTERPRETER (i.e. like python) so while it's not super performant (and possibly suffering from large inefficiency issues), it's very easy to set up, and it means that my plugins can still be written in Go (yay)! However, don't think this method doesn't have its own issues, there's still the problem of effectively abstracting different types of plugins without requiring too much boilerplate (a hard problem that I'm actively working on, commits coming soon). However, this still feels to be the best option.
As you can see, doing plugins in Go is a very hard problem. In the coming weeks (hopefully), I'm going to (attempt to at least) benchmark all the different options, as well as publish a library that should help make using Yaegi based plugins easier. All of this stuff will go (see what I did there 😉) in a nice blog post that better explains the issues and solutions. But until then I have some coding to do...
Have a good night(/day)!13
Man, programs were fascinating, one day when I was (I think) seven years old, I googled how to make a program, I found something called neobook (anyone else?), and the rest was history.
Wow, yesterday was fun!
I had a rather buggy piece of code, it was bad when I first wrote it, and then I fixed it up, and it was still bad. Now I rewrote almost all of it, and it's much better.
Bad? How? Well, it was in Go, and it's basically an agent meant to execute tasks one at a time, and report the results back to home (live). Now while it worked, it was really flimsy, race conditions, way to much blocking, bad logic, and some very bad bugs.
So I had to rewrite it. Time for a quick primer on the design of this: you have a queue, a task gets add to the queue, the task manager runs the task. In the mean time, the agent is polling the host with the latest output from the task, and also receives new tasks to run (if there are any).
Seems like something that's for a messaging queue, you ask? Well, that would be true if each task was able to run on any random agent, but each task is only meant to run the agent it's tasked to (the tasks are of administrative nature al la apt-get), so having a whole separate service is a tad overkill.
So rewriting required rethinking how the tasks are executed by the task manager. I spent a day on this, it was fun, I ended up copying go contexts (very simple model, very useful). Why copy and not reuse? Because this is meant to be low memory code, so any extra parts are problematic, and I didn't really see a use for having a whole context, I just needed a way to announce that a task is done.
Anyways, if you're interested to see how the implementation worked out: https://github.com/chabad360/covey/...2
What the F#*@&$# %#@$!?!?!
This person has decided to skip using staging, because it doesn't correctly reflect prod!
If that's your problem, than why don't you try to fix it? Create a DB with fake data, make one based on anonymised customer data, or even do it on non-anonymised data (with permission of course), but fix the staging env so that it reflects prod!
This is a devops site (it's literally the name!), and instead of teaching you how to make staging exactly like prod, they tell you to do what caused the creation of the staging->prod system IN THE FIRST PLACE!!!
There's all these stuff like Vagrant that are literally designed to help you as a dev mimic prod, and you just throw it all out!?
"With feature flags, I can safely test in production without fear of breaking something or negatively affecting the customer experience."
Famous last words.12
Ah, strong motivation: get to 80% (or so) test coverage before my Goland trial expires today or tomorrow.
I've determined a simple formula for how to get people to stay in your app for long periods of time:
1. Infinity scrolling
2. OPTIMIZE BATTERY USAGE
Why? You can't infinitely scroll if your battery's dead.
Case Study: YouTube.2
I need to do a lot of refactoring and testing (%80 percent of which is integration) and ITS SO TEDIOUS!!!
Now, for anyone who says "oh, you write spaghetti code, your code shouldn't be so tedious to refactor". No. It's only tedious because it's a few thousand lines that I've been too lazy to refactor till now, and I need to go through it all.
Anybody have any advice for refactoring or testing in Go?17
GraphQL or REST?
I'm not really worried about boilerplate (my research reveals it's roughly the same), I currently have a (very incomplete) REST interface, but that was just for testing.
Also, the API has no real usage yet (I only use it for submissions) and it literally exists for the sake of having an API (so I don't need to write it later).11
How much should I try to cater to noscript users? Some situations are just not practical without some js (Ajax and friends can sometimes be the only practical option).3
Is anyone else having issues with animated gifs being clipped to their first frame? Or did I just miss something?21
Well, here it is finally, a first preview of the Covey Web UI.
It's powered by CoreUI (the only easy to use admin thing I could find).
If you want to look at the code, be warned: I don't do frontend...
Tried streaming a demo of a project I was working on...
A little while later my friend told me that it only showed the first frame... For the whole ten min...
At least now I don't have a potato PC...
A continuation to https://devrant.com/rants/2629107/...
Again the idea is bird/flock of birds.
Thanks to all the people who gave their opinion last time around.25