<?xml version="1.0" encoding="UTF-8" standalone="no"?><rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
  <channel>
    <title>Admins Werk und Users Beitrag</title>
    <description>Tipps und Tricks für das tägliche Überleben im Dschungel der Netzwerke, Fehlermeldungen und Userwünsche. Anleitungen, Fehlerlösungen und vieles mehr.</description>
    <link>https://adminswerk.dehttps://adminswerk.de</link>
    <atom:link href="https://adminswerk.defeed.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Fri, 04 Aug 2023 10:14:25 +0000</pubDate>
    <lastBuildDate>Fri, 04 Aug 2023 10:14:25 +0000</lastBuildDate>
    <generator>Jekyll v3.9.3</generator>
    
      <item>
        <title>Nextcloud: Solving slow logins</title>
        <description>&lt;p&gt;My wife was complaining about slow logins for our Nextcloud instance. Indeed, while my logins were as fast as expected, her account took over 3 minutes logging in to seeing the Nextcloud Dashboard.&lt;/p&gt;

&lt;p&gt;After some internet research I found &lt;a href="https://help.nextcloud.com/t/very-slow-login-after-updating-to-21-0-3/113693/64"&gt;a thread on the Nextcloud board&lt;/a&gt; which recommended checking the auth tokens of the affected user.&lt;/p&gt;

&lt;p&gt;That was a good recommendation:&lt;/p&gt;

&lt;div class="language-sql highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;uid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;nbtokens&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;oc_authtoken&lt;/span&gt; &lt;span class="k"&gt;GROUP&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;uid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="c1"&gt;--------------------------------+----------+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;uid&lt;/span&gt;                            &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;nbtokens&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="c1"&gt;--------------------------------+----------+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;m3adows&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;nextcloud&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;acc&lt;/span&gt;          &lt;span class="o"&gt;|&lt;/span&gt;       &lt;span class="mi"&gt;22&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;my&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;wifes&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;nextcloud&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;acc&lt;/span&gt;         &lt;span class="o"&gt;|&lt;/span&gt;      &lt;span class="mi"&gt;412&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="c1"&gt;--------------------------------+----------+&lt;/span&gt;
&lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="k"&gt;rows&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt; &lt;span class="n"&gt;sec&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Whoops, that’s quite a lot! As the Nextcloud Board user MelwinKfr recommended, I also deleted all her authtokens, as I didn’t care if she had to reconnect her sessions. &lt;strong&gt;Beware: This will probably delete all App passwords!&lt;/strong&gt;&lt;/p&gt;

&lt;div class="language-sql highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="k"&gt;DELETE&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;authtoken&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;uid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'my-wifes-nextcloud-acc'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;Query&lt;/span&gt; &lt;span class="n"&gt;OK&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;412&lt;/span&gt; &lt;span class="k"&gt;rows&lt;/span&gt; &lt;span class="n"&gt;affected&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;08&lt;/span&gt; &lt;span class="n"&gt;sec&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Lo and behold, her login became blazing fast again.&lt;/p&gt;

&lt;p&gt;Now, I’m searching for the source of this problem, as it occured multiple times.
I suspect it to be Thunderbirds Lightning calendar, but we’ll see about that. 
I will follow MelwinKfrs advice of using App Passwords for one application after the other to
find out which one really was the problematic one.&lt;/p&gt;

</description>
        <pubDate>Fri, 04 Aug 2023 00:00:00 +0000</pubDate>
        <link>https://adminswerk.de/nextcloud-slow-logins/</link>
        <guid isPermaLink="true">https://adminswerk.de/nextcloud-slow-logins/</guid>
        
        
        <category>nextcloud</category>
        
      </item>
    
      <item>
        <title>Change SATA operation mode without Windows reinstallation</title>
        <description>&lt;p&gt;As I recently encountered this problem while exchaning the NVMe of a notebook, here’s a quick rundown on how to change the SATA operation 
mode for a Windows system without the requirement for a reinstallation or an OS repair:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Boot up Windows as normal&lt;/li&gt;
  &lt;li&gt;Start CMD as admin and run &lt;code class="language-plaintext highlighter-rouge"&gt;bcdedit /set safeboot minimal&lt;/code&gt; to enable safe mode on next boot&lt;/li&gt;
  &lt;li&gt;Restart the PC and enter UEFI&lt;/li&gt;
  &lt;li&gt;Now change the SATA Operation mode, in my case from RAID to AHCI&lt;/li&gt;
  &lt;li&gt;Save the UEFI changes and let Windows boot to Safe mode&lt;/li&gt;
  &lt;li&gt;Once again open CMD as admin  and run &lt;code class="language-plaintext highlighter-rouge"&gt;bcdedit /deletevalue safeboot&lt;/code&gt; to disable safe mode&lt;/li&gt;
  &lt;li&gt;After another reboot Windows will automatically start with the new drivers enabled&lt;/li&gt;
&lt;/ol&gt;
</description>
        <pubDate>Sat, 31 Dec 2022 00:00:00 +0000</pubDate>
        <link>https://adminswerk.de/change-sata-operation-mode-windows/</link>
        <guid isPermaLink="true">https://adminswerk.de/change-sata-operation-mode-windows/</guid>
        
        
        <category>windows</category>
        
      </item>
    
      <item>
        <title>Starting applications before and after running a Steam game</title>
        <description>&lt;p&gt;Once in a while I’m rediscovering &lt;a href="https://www.humblebundle.com/store/stardew-valley?partner=m3adow"&gt;Stardew Valley&lt;/a&gt;&lt;em&gt;*&lt;/em&gt;, a very relaxing and charming Farming game. Occasionally, I decide to also play it on Android at the time. Sadly, there’s no inbuilt way of syncing the saves between my (Windows) PC and my Android device, although the file saves are compatible.&lt;/p&gt;

&lt;p&gt;There are a lot of tutorials online how to achieve that, so I won’t cover this. I more or less followed &lt;a href="https://www.reddit.com/r/StardewValley/comments/b5fb4d/tutorial_sync_saved_games_between_android_and_pc/"&gt;this tutorial&lt;/a&gt; on Reddit (&lt;a href="https://archive.is/yiLE0"&gt;archive.is link&lt;/a&gt;). In short: I symlinked my saves directory on the PC into my Dropbox folder and  then use an App, &lt;a href="https://play.google.com/store/apps/details?id=dk.tacit.android.foldersync.lite"&gt;FolderSync&lt;/a&gt;, to sync these saves to Android.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://adminswerk.de/assets/images/2020/2020-11-05-stardew-valley.jpg"&gt;&lt;img src="https://adminswerk.de/assets/images/2020/2020-11-05-stardew-valley.jpg" style="margin: 10px; max-width: 60%; max-height: auto; border-radius: 5%;" alt="Stardew Valley" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This worked nicely 90% of the time. Sadly, Stardew Valley on PC crashed every once in a while while saving. The error logs in the &lt;code class="language-plaintext highlighter-rouge"&gt;ErrorLogs&lt;/code&gt; directory made the problem very clear:&lt;/p&gt;

&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;Message: The process cannot access the file because it is being used by another process.
InnerException: 
Stack Trace:    at StardewValley.SaveGame.&amp;lt;Save&amp;gt;d__63.MoveNext() in C:\GitlabRunner\builds\Gq5qA5P4\0\ConcernedApe\stardewvalley\Farmer\Farmer\SaveGame.cs:line 344
   at StardewValley.Menus.SaveGameMenu.update(GameTime time) in C:\GitlabRunner\builds\Gq5qA5P4\0\ConcernedApe\stardewvalley\Farmer\Farmer\Menus\SaveGameMenu.cs:line 109
   at StardewValley.Menus.ShippingMenu.update(GameTime time) in C:\GitlabRunner\builds\Gq5qA5P4\0\ConcernedApe\stardewvalley\Farmer\Farmer\Menus\ShippingMenu.cs:line 333
   at StardewValley.Game1._update(GameTime gameTime) in C:\GitlabRunner\builds\Gq5qA5P4\0\ConcernedApe\stardewvalley\Farmer\Farmer\Game1.cs:line 3032
   at StardewValley.Game1.Update(GameTime gameTime) in C:\GitlabRunner\builds\Gq5qA5P4\0\ConcernedApe\stardewvalley\Farmer\Farmer\Game1.cs:line 2913
   at Microsoft.Xna.Framework.Game.Tick()
   at Microsoft.Xna.Framework.Game.HostIdle(Object sender, EventArgs e)
   at Microsoft.Xna.Framework.GameHost.OnIdle()
   at Microsoft.Xna.Framework.WindowsGameHost.RunOneFrame()
   at Microsoft.Xna.Framework.WindowsGameHost.ApplicationIdle(Object sender, EventArgs e)
   at System.Windows.Forms.Application.ThreadContext.System.Windows.Forms.UnsafeNativeMethods.IMsoComponent.FDoIdle(Int32 grfidlef)
   at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
   at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
   at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
   at System.Windows.Forms.Application.Run(Form mainForm)
   at Microsoft.Xna.Framework.WindowsGameHost.Run()
   at Microsoft.Xna.Framework.Game.RunGame(Boolean useBlockingRun)
   at StardewValley.Program.Main(String[] args) in C:\GitlabRunner\builds\Gq5qA5P4\0\ConcernedApe\stardewvalley\Farmer\Farmer\Program.cs:line 152
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Another process was accessing the save file, presumably Dropbox which wanted to sync the changed file. Therefore I searched for a solution to automatically stop Dropbox before starting Stardew Valley via Steam and resuming it after I was done playing. While this is pretty easy in Linux, due to Dropbox offering proper command line access, there’s no such CLI access on Windows.&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;Thusly, I had find another solution. I found it in the &lt;code class="language-plaintext highlighter-rouge"&gt;pssuspend&lt;/code&gt; command from Microsofts Sysinternals &lt;a href="https://docs.microsoft.com/en-us/sysinternals/downloads/pstools"&gt;PsTools&lt;/a&gt;. It suspends an application using Windows internal tools. When I exit Stardew Valley, &lt;code class="language-plaintext highlighter-rouge"&gt;pssuspend&lt;/code&gt; resumes Dropbox. This is the Batch I’m using, already prepared to being reused. ;-)&lt;/p&gt;

&lt;div class="language-batch highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="c"&gt;rem @echo off&lt;/span&gt;

&lt;span class="kd"&gt;set&lt;/span&gt; &lt;span class="kd"&gt;PssuspendPath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"C:\m3adow\apps\pstools\pssuspend.exe"&lt;/span&gt;
&lt;span class="kd"&gt;set&lt;/span&gt; &lt;span class="kd"&gt;SyncExe&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"Dropbox.exe"&lt;/span&gt;
&lt;span class="kd"&gt;set&lt;/span&gt; &lt;span class="kd"&gt;GamePath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"C:\m3adow\games\steam\steamapps\common\Stardew Valley"&lt;/span&gt;
&lt;span class="kd"&gt;set&lt;/span&gt; &lt;span class="kd"&gt;SteamId&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;413150&lt;/span&gt;
&lt;span class="c"&gt;rem Don't use ticks for the variable or the 'tasklist' line will not work properly&lt;/span&gt;
&lt;span class="kd"&gt;set&lt;/span&gt; &lt;span class="kd"&gt;GameExe&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kd"&gt;Stardew&lt;/span&gt; &lt;span class="kd"&gt;Valley&lt;/span&gt;&lt;span class="err"&gt;.exe&lt;/span&gt;
&lt;span class="c"&gt;rem The estimated additional time (to the LoopTime) the game needs to start up&lt;/span&gt;
&lt;span class="kd"&gt;set&lt;/span&gt; &lt;span class="na"&gt;/A &lt;/span&gt;&lt;span class="kd"&gt;StartupTimeAddition&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;15&lt;/span&gt;
&lt;span class="c"&gt;rem The time to sleep between game checks&lt;/span&gt;
&lt;span class="kd"&gt;set&lt;/span&gt; &lt;span class="na"&gt;/A &lt;/span&gt;&lt;span class="kd"&gt;LoopTime&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;

&lt;span class="nv"&gt;%PssuspendPath%&lt;/span&gt; &lt;span class="na"&gt;-nobanner &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;%SyncExe%&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="nb"&gt;cd&lt;/span&gt; &lt;span class="nv"&gt;%GamePath%&lt;/span&gt;
&lt;span class="nb"&gt;start&lt;/span&gt; &lt;span class="kd"&gt;steam&lt;/span&gt;://rungameid/&lt;span class="nv"&gt;%SteamId%&lt;/span&gt;
@ping &lt;span class="na"&gt;-n &lt;/span&gt;&lt;span class="nv"&gt;%StartupTimeAddition%&lt;/span&gt; &lt;span class="kd"&gt;localhost&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kr"&gt;nul&lt;/span&gt;

&lt;span class="nl"&gt;:GAMELOOP&lt;/span&gt;
@ping &lt;span class="na"&gt;-n &lt;/span&gt;&lt;span class="nv"&gt;%LoopTime%&lt;/span&gt; &lt;span class="kd"&gt;localhost&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kr"&gt;nul&lt;/span&gt;
&lt;span class="nb"&gt;tasklist&lt;/span&gt; &lt;span class="na"&gt;/FI &lt;/span&gt;&lt;span class="s2"&gt;"IMAGENAME eq &lt;/span&gt;&lt;span class="nv"&gt;%GameExe%&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="kd"&gt;NUL&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nb"&gt;find&lt;/span&gt; &lt;span class="na"&gt;/I /N &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;%GameExe%&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="kd"&gt;NUL&lt;/span&gt;
&lt;span class="c"&gt;rem if ERRORLEVEL is 0, the game is still running&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;%ERRORLEVEL%&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="s2"&gt;"0"&lt;/span&gt; &lt;span class="kd"&gt;GOTO&lt;/span&gt; &lt;span class="kd"&gt;GAMELOOP&lt;/span&gt;

&lt;span class="c"&gt;rem Do a double resume because Dropbox sometimes doesn't resume properly&lt;/span&gt;
&lt;span class="nv"&gt;%PssuspendPath%&lt;/span&gt; &lt;span class="na"&gt;-r -nobanner &lt;/span&gt;&lt;span class="nv"&gt;%SyncExe%&lt;/span&gt;
@ping &lt;span class="na"&gt;-n &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="kd"&gt;localhost&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kr"&gt;nul&lt;/span&gt;
&lt;span class="nv"&gt;%PssuspendPath%&lt;/span&gt; &lt;span class="na"&gt;-r -nobanner &lt;/span&gt;&lt;span class="nv"&gt;%SyncExe%&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;What does it do exactly?&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;The application &lt;code class="language-plaintext highlighter-rouge"&gt;%SyncExe%&lt;/code&gt; is suspended, &lt;code class="language-plaintext highlighter-rouge"&gt;Dropbox.exe&lt;/code&gt; in my case.&lt;/li&gt;
  &lt;li&gt;The game with the Steam ID &lt;code class="language-plaintext highlighter-rouge"&gt;%SteamId%&lt;/code&gt; is started, Stardew Valley does have the &lt;code class="language-plaintext highlighter-rouge"&gt;413150&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Before entering the &lt;code class="language-plaintext highlighter-rouge"&gt;GAMELOOP&lt;/code&gt; and waiting &lt;code class="language-plaintext highlighter-rouge"&gt;%LoopTime%&lt;/code&gt; seconds the batch waits an additional &lt;code class="language-plaintext highlighter-rouge"&gt;%StartupTimeAdditional%&lt;/code&gt; seconds to
ensure a proper game startup&lt;/li&gt;
  &lt;li&gt;In the &lt;code class="language-plaintext highlighter-rouge"&gt;GAMELOOP&lt;/code&gt; the batch wait &lt;code class="language-plaintext highlighter-rouge"&gt;%LoopTime%&lt;/code&gt; seconds, then checks if the &lt;code class="language-plaintext highlighter-rouge"&gt;%GameExe%&lt;/code&gt; exe file - &lt;code class="language-plaintext highlighter-rouge"&gt;Stardew Valley.exe&lt;/code&gt; in my case - is in the tasklist of Windows. If so, the
loop is started anew.&lt;/li&gt;
  &lt;li&gt;Otherwise the &lt;code class="language-plaintext highlighter-rouge"&gt;%SyncExe%&lt;/code&gt; is resumed twice. Dropbox oftentimes didn’t resume the first time, so I lazily added the resume twice which did the job for me.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I hope this helps other people trying something similarly.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;* = Affiliate Link&lt;/em&gt;&lt;/p&gt;

</description>
        <pubDate>Sun, 09 Oct 2022 00:00:00 +0000</pubDate>
        <link>https://adminswerk.de/start-application-before-after-steamgame/</link>
        <guid isPermaLink="true">https://adminswerk.de/start-application-before-after-steamgame/</guid>
        
        
        <category>Steam</category>
        
        <category>Gaming</category>
        
        <category>Windows</category>
        
      </item>
    
      <item>
        <title>Kustomize: Wildcard replace all items of a list</title>
        <description>&lt;p&gt;Most users of Kustomize know this problem: You have some kind of list and want to replace the same key in every item of the list in an overlay. Let’s say you have a list of &lt;code class="language-plaintext highlighter-rouge"&gt;ClusterRules&lt;/code&gt;:&lt;/p&gt;

&lt;div class="language-yaml highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;monitoring.googleapis.com/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ClusterRules&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pods&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;groups&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;main&lt;/span&gt;
      &lt;span class="na"&gt;interval&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;30s&lt;/span&gt;
      &lt;span class="na"&gt;rules&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;alert&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;PodCrashLooping&lt;/span&gt;
          &lt;span class="na"&gt;expr&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  &lt;span class="s"&gt;max_over_time(kube_pod_container_status_waiting_reason{reason="CrashLoopBackOff", job="kube-state-metrics"}[5m]) &amp;gt;= &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
          &lt;span class="na"&gt;for&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;5m&lt;/span&gt;
          &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;severity&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;warning&lt;/span&gt;
          &lt;span class="na"&gt;annotations&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;summary&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Pod&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;'{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;$labels.exported_pod&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}'&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;CrashLoopingPod"&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;alert&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;PodNotHealthy&lt;/span&gt;
          &lt;span class="na"&gt;expr&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;max_over_time(kube_pod_status_phase{phase!~"Running|Succeeded"}[5m]) &amp;gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;
          &lt;span class="na"&gt;for&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;5m&lt;/span&gt;
          &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;severity&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;critical&lt;/span&gt;
          &lt;span class="na"&gt;annotations&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;summary&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Pod&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;'{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;$labels.exported_pod&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}'&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;not&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;healthy"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;But you want to have a more lenient alerting time in the development environment, as the stuff there tends to break and isn’t as important as production. Thusly, we want to patch the &lt;code class="language-plaintext highlighter-rouge"&gt;spec.groups[].rules[].for&lt;/code&gt; path. Should be easy, targeting list items with Kustomize &lt;code class="language-plaintext highlighter-rouge"&gt;patchesJson6902&lt;/code&gt; method is simple. Sadly, wildcard replacement for list items are not implemented in the JSON Patch standard. To replace each value of the list above, we would need to use a dedicated JSON Patch for each list item:&lt;/p&gt;

&lt;div class="language-yaml highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="na"&gt;patchesJson6902&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;
    &lt;span class="na"&gt;group&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;monitoring.googleapis.com&lt;/span&gt;
    &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ClusterRules&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pods&lt;/span&gt;
  &lt;span class="na"&gt;patch&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|-&lt;/span&gt;
    &lt;span class="s"&gt;- op: replace&lt;/span&gt;
      &lt;span class="s"&gt;path: /spec/groups/0/rules/0/for&lt;/span&gt;
      &lt;span class="s"&gt;value: 15m&lt;/span&gt;
    &lt;span class="s"&gt;- op: replace&lt;/span&gt;
      &lt;span class="s"&gt;path:/spec/groups/0/rules/1/for&lt;/span&gt;
      &lt;span class="s"&gt;value: 15m&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;That’s okay for two list items like in this example, but becomes tedious if you have a list with many. You could use a Helm template, but depending on the rest of your code, that may be overkill.&lt;br /&gt;
That’s why I searched for a better way to programmatically patch all items in a list with Kustomize. And I found an - admittedly very hacky - solution. Entering Kustomize &lt;a href="https://kubectl.docs.kubernetes.io/references/kustomize/kustomization/replacements/"&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;replacements&lt;/code&gt;&lt;/a&gt;. Replacements are the destined successor of Kustomize deprecated &lt;code class="language-plaintext highlighter-rouge"&gt;vars&lt;/code&gt; feature which weren’t powerful enough in any scenario I wanted to use them for anyways. According to the documentation,&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Replacements are used to copy fields from one source into any number of specified targets.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That’s not exactly what we want, we don’t have a field…yet. But that’s not a problem, right? The simplest solution is to create a &lt;code class="language-plaintext highlighter-rouge"&gt;ConfigMap&lt;/code&gt; which contains the wanted key:&lt;/p&gt;

&lt;div class="language-yaml highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt; &lt;span class="c1"&gt;# This CM is only used for Kustomize replacements&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ConfigMap&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;alerting-time-replacement-dummy&lt;/span&gt;
&lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;for&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;15m&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Refering to that value in the &lt;code class="language-plaintext highlighter-rouge"&gt;kustomization.yaml&lt;/code&gt; is not difficult:&lt;/p&gt;

&lt;div class="language-yaml highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="na"&gt;replacements&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;source&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ConfigMap&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;alerting-time-replacement-dummy&lt;/span&gt;
      &lt;span class="na"&gt;fieldPath&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;data.for&lt;/span&gt;
    &lt;span class="na"&gt;targets&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;select&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ClusterRules&lt;/span&gt;
          &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pods&lt;/span&gt;
        &lt;span class="na"&gt;fieldPaths&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;spec.groups.*.rules.*.for&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;That properly replaces the values as we wanted:&lt;/p&gt;

&lt;div class="language-yaml highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;monitoring.googleapis.com/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ClusterRules&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pods&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;groups&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;main&lt;/span&gt;
      &lt;span class="na"&gt;interval&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;30s&lt;/span&gt;
      &lt;span class="na"&gt;rules&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;alert&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;PodCrashLooping&lt;/span&gt;
          &lt;span class="na"&gt;expr&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  &lt;span class="s"&gt;max_over_time(kube_pod_container_status_waiting_reason{reason="CrashLoopBackOff", job="kube-state-metrics"}[5m]) &amp;gt;= &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
          &lt;span class="na"&gt;for&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;15m&lt;/span&gt;
          &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;severity&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;warning&lt;/span&gt;
          &lt;span class="na"&gt;annotations&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;summary&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Pod&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;'{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;$labels.exported_pod&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}'&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;CrashLoopingPod"&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;alert&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;PodNotHealthy&lt;/span&gt;
          &lt;span class="na"&gt;expr&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;max_over_time(kube_pod_status_phase{phase!~"Running|Succeeded"}[5m]) &amp;gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;
          &lt;span class="na"&gt;for&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;15m&lt;/span&gt;
          &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;severity&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;critical&lt;/span&gt;
          &lt;span class="na"&gt;annotations&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;summary&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Pod&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;'{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;$labels.exported_pod&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}'&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;not&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;healthy"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If you dislike the need to have a permanent useless &lt;code class="language-plaintext highlighter-rouge"&gt;ConfigMap&lt;/code&gt; in your cluster, I have slightly bad news for you: Using &lt;code class="language-plaintext highlighter-rouge"&gt;patchesJson6902&lt;/code&gt; to delete the &lt;code class="language-plaintext highlighter-rouge"&gt;ConfigMap&lt;/code&gt; is not possible. Therefore, I recommend coupling this dirty hack with another small hack and using a “no-op” Job with a low `  ttlSecondsAfterFinished` value (available since Kubernetes 1.23) using an annotation as a replacement:&lt;/p&gt;

&lt;div class="language-yaml highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;batch/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Job&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;no-op&lt;/span&gt;
  &lt;span class="na"&gt;annotations&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# Refer to it via `fieldPath: metadata.annotations.my-replacement-value`&lt;/span&gt;
    &lt;span class="na"&gt;my-replacement-value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;15m&lt;/span&gt; 
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;ttlSecondsAfterFinished&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;containers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;no-op&lt;/span&gt;
        &lt;span class="c1"&gt;# Don't use dynamic tags in production kids, mkay!&lt;/span&gt;
        &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;busybox:stable&lt;/span&gt; 
        &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;:"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
      &lt;span class="na"&gt;restartPolicy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Never&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The job will be deleted nearly instantly, not leaving any trace in your cluster (although churning away some of your resources for a couple of seconds).&lt;/p&gt;

</description>
        <pubDate>Fri, 02 Sep 2022 00:00:00 +0000</pubDate>
        <link>https://adminswerk.de/kustomize-wildcard-replace-list/</link>
        <guid isPermaLink="true">https://adminswerk.de/kustomize-wildcard-replace-list/</guid>
        
        
        <category>Kubernetes</category>
        
        <category>Openshift</category>
        
      </item>
    
      <item>
        <title>Steam: Fix Software install on every Startup</title>
        <description>&lt;p&gt;While enjoying first playthrough of &lt;a href="https://www.humblebundle.com/store/borderlands-2-game-of-the-year?partner=m3adow"&gt;Borderlands 2&lt;/a&gt;, I encountered an annoyance. Every time I started the game, Steam tried a first-time setup by installing the Visual C++ 2010 Redistributable Package (vcredist). Additionally it also required me to confirm the install process every time, due to Windows UAC. I encountered similar annoyances a couple of weeks later when playing &lt;a href="https://www.humblebundle.com/store/dishonored?partner=m3adow"&gt;Dishonored&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Some research revealed that this is a very common issue with Steam games, especially older(ish) ones. For some reason the required program installations are not recognised which leads to this installation dialogue before each game start.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://adminswerk.de/assets/images/2021/2021-01-07-steam-first-time-setup.png"&gt;&lt;img src="https://adminswerk.de/assets/images/2021/2021-01-07-steam-first-time-setup.png" style="margin: 10px;" alt="League of Legends Steam properties" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I did some more digging and found out, that the source often times lies in a missing Windows Registry key. Therefore I created a Github Gist which contains all registry entries I could find: &lt;a href="https://gist.github.com/m3adow/721947cf076a0eec5bc2b194e16853d9"&gt;https://gist.github.com/m3adow/721947cf076a0eec5bc2b194e16853d9&lt;/a&gt;
Here’s a short instruction how to use the Registry Gist:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Get the Steam ID of the game which bugs you with the installation on every start. The easiest ways are by checking the desktop shortcut. Right-Click it, choose “Properties” and note down the number in the &lt;code class="language-plaintext highlighter-rouge"&gt;URL&lt;/code&gt; entry after &lt;code class="language-plaintext highlighter-rouge"&gt;steam://rungameid/&lt;/code&gt;. In the picture below that would be &lt;code class="language-plaintext highlighter-rouge"&gt;20590&lt;/code&gt;.&lt;br /&gt;
&lt;a href="https://adminswerk.de/assets/images/2021/2021-01-07-steam-league-of-legends.png"&gt;&lt;img src="https://adminswerk.de/assets/images/2021/2021-01-07-steam-league-of-legends.png" style="margin: 10px;" alt="League of Legends Steam properties" /&gt;&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Copy the Code from my &lt;a href="gist"&gt;Gist&lt;/a&gt; into a new text file. Save the text file with a &lt;code class="language-plaintext highlighter-rouge"&gt;.reg&lt;/code&gt; file extension, &lt;code class="language-plaintext highlighter-rouge"&gt;steamfix.reg&lt;/code&gt; for example.&lt;/li&gt;
  &lt;li&gt;Change the &lt;code class="language-plaintext highlighter-rouge"&gt;{{ INSERTYOURAPPIDHERE }}&lt;/code&gt; part to the Steam ID of your game and save the file. In my example the replacement would result in &lt;code class="language-plaintext highlighter-rouge"&gt;[HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Valve\Steam\Apps\20590]&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Double click the file and confirm you really want to apply these changes.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;BAM! You’re done. The installation of programs at each start of the game should be history.&lt;br /&gt;
If this is not the case please add a comment containing the game, its Steam ID and the software it tries to install every time, so others or I are able to invest more research into it.&lt;/p&gt;

</description>
        <pubDate>Thu, 07 Jan 2021 00:00:00 +0000</pubDate>
        <link>https://adminswerk.de/steam-software-install-on-game-startup/</link>
        <guid isPermaLink="true">https://adminswerk.de/steam-software-install-on-game-startup/</guid>
        
        
        <category>steam</category>
        
      </item>
    
      <item>
        <title>Extract ICS from Google Calendars</title>
        <description>&lt;p&gt;I wanted to import the &lt;a href="https://calendar.google.com/calendar/embed?src=redhatstreaming@gmail.com"&gt;Openshift.tv Google Calendar&lt;/a&gt; to my Nextcloud calendar app. The URL looks like this:&lt;/p&gt;

&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;https://calendar.google.com/calendar/embed?src=redhatstreaming@gmail.com
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;A simple import in Nextclouds calendar app didn’t work, I figured I needed to get either an ICS or ICAL file, but couldn’t find any easy way. No button on the website, no knowledge base entries either.&lt;br /&gt;
By chance, I found &lt;a href="https://support.google.com/calendar/thread/7353749?msgid=17912822"&gt;a thread&lt;/a&gt; in Googles support forum which describes a way how to extract the ICS from a Google calendar:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;ol&gt;
    &lt;li&gt;
      &lt;p&gt;Go to the settings for the Other Calendar, and note down the Public URL to this calendar, for example: &lt;code class="language-plaintext highlighter-rouge"&gt;https://calendar.google.com/calendar/embed?src=en-gb.christian%23holiday%40group.v.calendar.google.com&amp;amp;ctz=Europe%2FParis&lt;/code&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li&gt;
      &lt;p&gt;Now take the part after ‘src=’ up to and including &lt;code class="language-plaintext highlighter-rouge"&gt;calendar.google.com&lt;/code&gt; so in this case our subscribed calendar ID is &lt;code class="language-plaintext highlighter-rouge"&gt;en-gb.christian%23holiday%40group.v.calendar.google.com&lt;/code&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li&gt;
      &lt;p&gt;Now replace the ********** here with that text: &lt;code class="language-plaintext highlighter-rouge"&gt;https://calendar.google.com/calendar/ical/**********/public/basic.ics&lt;/code&gt; to give the final feed URL which you can download directly in your browser: &lt;code class="language-plaintext highlighter-rouge"&gt;https://calendar.google.com/calendar/ical/en-gb.christian%23holiday%40group.v.calendar.google.com/public/basic.ics&lt;/code&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/blockquote&gt;

&lt;p&gt;For the Openshift.tv calendar, this lead to this ICAL URL: &lt;code class="language-plaintext highlighter-rouge"&gt;https://calendar.google.com/calendar/ical/redhatstreaming@gmail.com/public/basic.ics&lt;/code&gt;&lt;/p&gt;

</description>
        <pubDate>Thu, 05 Nov 2020 00:00:00 +0000</pubDate>
        <link>https://adminswerk.de/import-google-calendar-ics/</link>
        <guid isPermaLink="true">https://adminswerk.de/import-google-calendar-ics/</guid>
        
        
        <category>Google</category>
        
        <category>Nextcloud</category>
        
      </item>
    
      <item>
        <title>Finding Pump Express compatible chargers</title>
        <description>&lt;p&gt;&lt;a href="https://adminswerk.de/assets/images/2020/2020-08-mediatek-pump-express.jpg"&gt;&lt;img src="https://adminswerk.de/assets/images/2020/2020-08-mediatek-pump-express.jpg" style="margin: 10px;" alt="Mediatek Pump Express" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A friend of mine recently asked me to find Pump Express compatible chargers. I never heard that term, so I needed to research it. Apparently Pump Express is the fast charging solution of mid budget chip maker Mediatek. It’s the direct competitor to Quick Charge from Qualcomm or Oppos VOOC/OnePlus Dash Charge (they are using identical technology).&lt;br /&gt;
But in contrast to the formerly mentioned competing technologies where you can easily find chargers on Amazon (&lt;a href="https://smile.amazon.com/s?k=quick+charge+charger&amp;amp;ref=nb_sb_noss_2"&gt;Quick Charge&lt;/a&gt;/&lt;a href="https://smile.amazon.com/s?k=vooc+charger&amp;amp;ref=nb_sb_noss_2"&gt;VOOC&lt;/a&gt;), finding Pump Express compatible chargers wasn’t as easy.&lt;/p&gt;

&lt;p&gt;But that’s only because Mediatek did their charging technology the right way. To quote from Mediateks &lt;a href="https://www.mediatek.com/features/pump-express"&gt;Pump Express Marketing Site&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;The technology is compatible with the international standard of ‘USB PD 3.0 programmable power supplies’, allowing standard USB PD 3.0 fast chargers to boost Pump Express 4.0-enabled smartphones.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So instead of relying on a proprietary technique, they are utilizing USB Power Delivery. Therefore any USB PD 3.0 compatible charger should be able to “pump” the battery of your smartphone. I did some searches on &lt;strong&gt;&lt;a href="https://smile.amazon.com/s?k=usb+pd+charger&amp;amp;ref=nb_sb_noss_2"&gt;Amazon.com&lt;/a&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;a href="https://smile.amazon.co.uk/s?k=USB+PD+charger&amp;amp;ref=nb_sb_noss_2"&gt;Amazon.co.uk&lt;/a&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;a href="https://www.amazon.de/s/ref=as_li_ss_tl?k=usb+pd+ladeger%C3%A4t&amp;amp;crid=1HQDOZBWVFA2P&amp;amp;sprefix=USB+pd+,aps,170&amp;amp;ref=nb_sb_ss_i_1_7&amp;amp;linkCode=ll2&amp;amp;tag=admwer-21&amp;amp;linkId=c7cf3641b49d32fa97f959bbf37f7f46&amp;amp;language=en_GB"&gt;Amazon.de&lt;/a&gt;&lt;/strong&gt; so all of the less tech savy people can choose a device of their liking without the need of delving deeper. ;-)&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(Image source: &lt;a href="https://www.mediatek.com/features/pump-express"&gt;Mediatek&lt;/a&gt;)&lt;/em&gt;&lt;/p&gt;

</description>
        <pubDate>Sun, 16 Aug 2020 00:00:00 +0000</pubDate>
        <link>https://adminswerk.de/pump-express-chargers/</link>
        <guid isPermaLink="true">https://adminswerk.de/pump-express-chargers/</guid>
        
        
        <category>Android</category>
        
      </item>
    
      <item>
        <title>Openshift: Change Pull Secret</title>
        <description>&lt;p&gt;&lt;strong&gt;Warning: This procedure will lead to Node drains, node restarts and - as a result pod restarts! Prepare accordingly!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To change the pull secret of an Openshift cluster (e.g. because you switched Red Hat accounts), save your new pull secret you downloaded from &lt;a href="https://cloud.openshift.com"&gt;cloud.openshift.com&lt;/a&gt; in a file, lets call it &lt;code class="language-plaintext highlighter-rouge"&gt;my-pull.secret&lt;/code&gt;. Then execute this oc command:&lt;/p&gt;

&lt;div class="language-bash highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;oc &lt;span class="nb"&gt;set &lt;/span&gt;data secret/pull-secret &lt;span class="nt"&gt;-n&lt;/span&gt; openshift-config &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--from-file&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;.dockerconfigjson&lt;span class="o"&gt;=&lt;/span&gt;my-pull.secret
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Of course you’ll need the proper permissions, I assume it’s Cluster Admin, but I didn’t test the exact permission requirements.&lt;/p&gt;

</description>
        <pubDate>Thu, 23 Jul 2020 00:00:00 +0000</pubDate>
        <link>https://adminswerk.de/openshift-change-pull-secret/</link>
        <guid isPermaLink="true">https://adminswerk.de/openshift-change-pull-secret/</guid>
        
        
        <category>Openshift</category>
        
      </item>
    
      <item>
        <title>Openshift: Remove Zombie machines</title>
        <description>&lt;p&gt;When an Openshift MachineSet was created with a faulty configuration, Machines created from it may be undeletable by the Controller although the Machines are not existing at all. The status of the Machines will then stay in the “Deleting” state.&lt;/p&gt;

&lt;div class="language-bash highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;oc get machine &lt;span class="nt"&gt;-n&lt;/span&gt; openshift-machine-api
NAME                              PHASE      TYPE              REGION       ZONE   AGE
m3adow-infra-westeurope1-5asrt    Deleting                                         3d2h
m3adow-infra-westeurope1-ioq4z    Running    Standard_D2s_v3   westeurope   1      3d
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To manually remove the Machine from the API, remove its finalizers via patch:&lt;/p&gt;

&lt;div class="language-bash highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;oc patch machine &lt;span class="nt"&gt;-n&lt;/span&gt; openshift-machine-api &lt;span class="nt"&gt;--type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;merge &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="s1"&gt;'{"metadata":{"finalizers":null}}'&lt;/span&gt; m3adow-infra-westeurope1-5asrt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This will instantly remove it.&lt;/p&gt;

</description>
        <pubDate>Thu, 21 May 2020 00:00:00 +0000</pubDate>
        <link>https://adminswerk.de/openshift-remove-zombie-machines/</link>
        <guid isPermaLink="true">https://adminswerk.de/openshift-remove-zombie-machines/</guid>
        
        
        <category>Openshift</category>
        
        <category>Kubernetes</category>
        
      </item>
    
      <item>
        <title>Blog: Codebites removal announcement</title>
        <description>&lt;p&gt;I’ve been inactive for a long time and I won’t promise any more activity. I just wanted to inform all potential feed readers that I will remove Codebites as their own section soon. The plans I initially had with Codebites didn’t work well, Life and Work prevented me from writing more posts, so I don’t think having the few posts I write separated into different sections makes any sense. Therefore from now on all posts will be available in the one (and only) &lt;a href="/feed.xml"&gt;RSS feed (feed.xml)&lt;/a&gt; once again. This may lead to some old and/or already read posts reappearing in your feeds. Also, if you’re using one of the deprecated ones, you may encounter problems. While I tried redirecting the old RSS feeds to the new one (with Javascript, which surprisingly worked best for the three applications I tested with), I’m not certain all RSS readers support redirects.&lt;/p&gt;

</description>
        <pubDate>Tue, 19 May 2020 00:00:00 +0000</pubDate>
        <link>https://adminswerk.de/codebite-removal/</link>
        <guid isPermaLink="true">https://adminswerk.de/codebite-removal/</guid>
        
        
        <category>Blog</category>
        
      </item>
    
  </channel>
</rss>