Every time I see an integration with Spotify built for a single user to run themselves, it pains me that you have to setup an OAuth application and server to get a token for your own account. I just wish Spotify would let you generate tokens for your own account, so you can properly automate playlists etc.
I provided a proxy service[0] to do the oauth handling. It gives you a permanent token that let's you access your up to date oauth tokens, of course with the caveat that you have to trust me. This is not really a scalable solution.
I wanted to try and get the terraform provider to handle the oauth flow but it's tricky because of the way terraform providers run
Yes! Just last weekend I threw together a quick project to create a Discord bot that adds all spotify links to a playlist. It was smooth as butter until I got to the Spotify Auth flow. Decided it wasn't worth the time at that point.
Can't you just MITM a login and use the login token? The login flow never materially changes (it's always the same two credentials), that seems like way less of a pain than whatever this OAuth flow is supposed to be.
The example directive "spotify_search_track" runs a server-side search on Spotify and returns a list of results, which you can use to populate a playlist.
This is like … very cool, but also isn't it a little against the spirit of immutable infrastructure? Every time Spotify re-ranks their search results my terraform apply will populate different songs into my playlist, without anything changing in my main.tf in source control.
That's how data sources work for serious uses as well.
For example - get AWS AMI where we can pin it or let it be latest.
> the spirit of immutable infrastructure
Immutable means changes recreate the resources. Not that that there won't be any changes. Mutable infra is where we keep patching the same resource and potentially end up in a state where we are not able to recreate it.
Yeah on further reflection maybe the "immutable" part of this is that I never use the Spotify UI to modify my playlist - it only gets changed during terraform apply phases, which may change the playlist in random ways on each re-apply.
Indeed. If you don't like it, prepare to get into a lot of arguments. EKS/Helm providers in combination with controllers are wild. It forces you to understand every little facet your cluster if _anything_ goes wrong.
Maybe, but the official serious providers do stuff like this, too. Consider the feature that lets you automatically use the latest Linux or Windows AMI; it changes without you touching your .tf file.
There's nothing that says it has to be immutable. It's not uncommon to perform similar searches in e.g. AWS to select the latest version of some AMI or another resource that is subject to change, and applying with no changes to the Terraform code would update the resource. This isn't really "infrastructure" either. It's a neat use case.
Moreover, you can pair it with drift detection (available in i.e. Spacelift[0]), and have it automatically detect when a data source changes (and apply the resulting infra changes).
Very common scenario with lots of neat use cases around it. One of the more interesting ones - use a GitHub pull request listing data source to create an ephemeral environment for each PR.
I once demo'ed Terraform to one of my old teams using the Dominos Pizza provider as an example. I ended up inadvertently ordering a Hawaiian style pizza to my house. It was....fine.
> This is not a joke provider. Or, it kind of is a joke, but even though it's a joke it will still order you a pizza. You are going to get a pizza. You should be careful with this provider, if you don't want a pizza.
I use this to generate MiniDisc playlists to record using the SynchoRec feature to automatically add track markers. I wanted an automated way to add silence between tracks in an album and generate a easy-to-parse file to potentially write metadata from.
I just checked this out and it's fantastic, I wish this was exposed by default somewhere in Spotify, amazing app, thanks a ton for making this and sharing!!
Cool work! Good job - I love projects where asking "why?" a good response is "why not?", but I gotta ask... why? Also, how long did it take? What was the inspiration?
I've been using Swinsian on my desktop connected to a NAS. It has an sqlite DB that I backup with git to never lose my play counts. I save and sync playlists to a "playlists" folder in my music folder. When my NAS phone app (DS Audio) launches, it syncs all my playlists. I have scripts set up to make new smart playlists for me when a new artist is added, so I'll have an "unlistened" smart playlist, a listened one, and a bestof, for each artist. I downloaded a huge discography of Bach years ago and I'm still making my way through it. I have full control of all my tracks, playlists, playcounts, and any other metadata I want, all backed up to git. Spotify will never defeat this for me. I tried using Spotify and downloaded the free version, and was physically disgusted at the "6 free skips per day!" or something, not to mention random songs being unavailable.
I've made a service that scratches my own itch of wanting a way to sort a collection of playlists by the last time they were updated. I've got that running here, and I use it often.
Despite the incorrect labelling "Saving a spotify track" means liking it, not "downloading to your device". So you can add it to another Spotify playlist.
To get historical likes, cmd-a / ctrl-a (or equivalent) all Liked Songs tracks and drag them into the backup playlist.
Terraform is for specifying deterministic, idempotent results given a set of conditions and inputs.
Music apps like Spotify and Apple Music are about whimsical, serendipitous discovery independent of rational thought. At least, for me, anyway.
The two are wholly incompatible. I'm shocked that this exists. It calls into question how I think of music streaming platforms, what I think they provide, and how I interact with them.
Terraform is just an overcomplicated way to call APIs. It's not deterministic and idempotent, as if you're "doing it right" you don't even know what values it's going to apply until after it's applied them. It can't be idempotent because Terraform doesn't determine if an API call will succeed or fail or do the same thing or not, the SaaS API does. And if you change anything, it can trigger a destroy, a create-destroy, a destroy-create, a create, or a modify, all of which may fail if the provider's resource wasn't designed for that particular operation with those values, which you won't know until it actually happens. Debugging it is a nightmare, and the bizarre interaction with pretty shoddy and inconsistent providers makes it pretty lucky if your applies actually work.
It's basically an annoying version of curl that has a DAG that you can't even make good use of. I wouldn't call it whimsical, but getting anything to work in Terraform consistently definitely requires serendipity.
> as if you're "doing it right" you don't even know what values it's going to apply until after it's applied them. It can't be idempotent because Terraform
what do you mean by this? 'terraform apply' runs plan first, and tells me the diff from the expected state. Then it asks me if I want to reconcile it.
Not all values are known to you or terraform until after the apply. For example, on AWS, publishing a new version of lambda might have the ARN as known after apply since it includes the version # as part of the string. Or something like the calculated hash of an S3 object that would be known after apply. You can still reference these values in other parts of your terraform, and it will propagate the <
‘known after apply’ state there too. These dependencies are built into a graph to determine which items should be applied first, so all references to unknown data can be resolved in the correct order.
Have you seen it say "Old Value X" -> (known after apply) ? If you use most of Terraform's features, a good deal of the new values are (known after apply). If any of a value requires looking something up at apply time - say, from a backend, a data source, a local, the creation/modification/deletion of a different resource, a name_prefix, an internal function, etc - Terraform can't (or more precisely, won't) tell you what the new value is or could be. So often you have no idea what the result is going to be until it's done.
You’re correct in that it’s not deterministic or idempotent if the APIs are not, but this reads as very anti-terraform. The purpose is not to be easier than curl, but to express your infrastructure in code so you can check it into a project and automate the deployment process, keeping the code version of the infrastructure in line with what is deployed. Curl doesn’t do that in any way and isn’t at all a valid comparison to terraform. If you feel IaC as a whole is a pointless/useless endeavor, that’s a point to argue, but comparing terraform to curl in this way is ignoring the main value add of IaC.
Put that in Git; now you have Infrastructure as Code. IaC is not some holy scepter ordained to us by God. It's literally just a version-controlled list of commands that call SaaS APIs. It's not special or magical. And Terraform doesn't do it any better than a bunch of curls in a shell script.
The only reason to use Terraform is it's a standard way for a large group of people to make changes to the same thing. But if an entire team standardized on a shell script full of curls, that would work just as well. (Better, actually, because you could actually have error handling, auto-healing, importing existing resources, checking if they exist before trying to apply changes... you know, things that are useful for IaC that Terraform does not do)
> Terraform is for specifying deterministic, idempotent results given a set of conditions and inputs.
It’s not as reductive as that. Terraform can give you a consistent configuration experience. What exactly that configuration does is heavily context and provider dependent. As commenters elsewhere have pointed out there’s an especially common use case with pinning to an AWS AMI that meets a certain criteria. New AMI gets published and next time you apply it’ll get the new AMI. That’s not idempotent.
Similarly, this Spotify flow would let implement something like a playlist that was dynamic, but refreshed only on your terms. The plan phase of a run would let you assess any playlist changes, if they’re an improvement you can apply. If you don’t like the change you abandon it and leave things as they are. A provider for a different stream service starts to unlock the potential for playlist portability. It doesn’t magically happen. But if you were managing all your playlists this way it would significantly reduce the effort to switch platforms.
I've used Spotify since the invitation phase, in 2008 or so, and never have I used it for discovery. Not to say that there isn't value in it, but there's more than one way to swing a sword.
> Terraform is for specifying deterministic, idempotent results given a set of conditions and inputs.
No. Terraform is for manipulating state on the other side of an API, including orchestrating the state behind multiple different APIs such that those APIs will be "harmonious" for your use case.
> Music apps like Spotify and Apple Music are about whimsical, serendipitous discovery independent of rational thought. At least, for me, anyway. The two are wholly incompatible.
I beg to differ. If something changes, Terraform makes those changes visible to you, because it keeps notes on what it thought the state was on the other side of the API. For the right use case, being notified of those changes, and possibly deciding to do something else instead, is important.
Spotify makes me so, so sad. I say this as a premium customer since 2015.
They push out a mobile app update every week with either no changes, or changes to things I don't care about. They removed push-to-preview. They refuse to add custom song start and end times. They focus incessantly on podcasts. Their playlist management is a joke. They get the most embarrassing things wrong, like failing to understand that two artists with the same name are not the same artist, or that a song in my Discover Weekly is just a re-release of a song already in my library. Until recently, their random shuffle kept getting stuck in a loop of ~100 songs. There is no modification history, so if I accidentally remove a song from a playlist or my library, I get a snackbar saying "Removed from library" but it won't tell me what, and there's no way to find out. Their song queue system is utterly anemic. The "Home" button also serves as a kind of pseudo "back button" but with no obvious rules to understand exactly how navigation is going to occur.
The fact that so many third party Spotify integrations exists, each tackling a different deficiency in the Spotify app itself speaks volumes about what Spotify's priorities are. Spotify is lucky that their library is massive and that their recommendations are good (for me anyway. My friend and my mother separately have had astoundingly awful experiences with the recommendation system despite years of trying), or there's be no love lost in moving elsewhere.
My biggest UI annoyance is that you cannot sort by newest added when viewing a playlist on mobile (you can on desktop). So if you just added some songs to a playlist and want to listen to them first (I find myself doing this all the time when getting into my car), you have to spend 20 seconds scrolling frantically to the bottom of the list to find them. Let me know if I'm missing something.
I know this exists in Android: you can pull down at the top of a playlist to reveal the search bar and sorting options. The sorting options should include recently added.
It's really more about maintainable playlists, tbh. How are you going to scale your playlist management if you can't properly review changes and see history to avoid repeating mistakes of the past?
A lot of people like just managing playlists with a simple graphical console.
This works fine if you just want a playlist now, but you risk things like forgetting why the songs were added to a playlist; or forgetting which songs were in a playlist if the playlist accidentally got deleted.
Sure, describing it with Terraform may be more effort up front, but it saves effort in the long run.