Change WSLC container NetworkMode from enum to string (#40672)
beena352 committed
Jun 2, 2026 at 10:27 UTC
ed13e98779fa4119efb7a576e73b05a700fd44eb
32 files changed
+270
-703
localization/strings/cs-CZ/Resources.resw
-10
@@ -2111,17 +2111,10 @@ Využití:
2111
<value>Kontejner {} není spuštěný.</value>
2112
<comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2113
</data>
2114
- <data name="MessageWslcContainerIpAddressNotSupported" xml:space="preserve">
2115
- <value>ContainerIpAddress zatím není podporováno.</value>
2116
- <comment>{Locked="ContainerIpAddress"}Command line arguments, file names and string inserts should not be translated</comment>
2117
- </data>
2114
<data name="MessageWslcContainerIsRunning" xml:space="preserve">
2115
<value>Kontejner {} je spuštěný.</value>
2116
<comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2117
</data>
2122
- <data name="MessageWslcContainerModeNoAdditionalNetworks" xml:space="preserve">
2123
- <value>Další sítě se v režimu kontejnerové sítě nepovolují.</value>
2124
- </data>
2118
<data name="MessageWslcContainerModeNoPorts" xml:space="preserve">
2119
<value>Mapování portů režim sítě kontejneru nepodporuje; porty patří cílovému kontejneru.</value>
2120
</data>
@@ -2136,9 +2129,6 @@ Využití:
2129
<value>Kontejner {} se nenašel.</value>
2130
<comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2131
</data>
2139
- <data name="MessageWslcContainerNetworkNameRequired" xml:space="preserve">
2140
- <value>Pro vlastní typ sítě se vyžaduje název sítě kontejneru.</value>
2141
- </data>
2132
<data name="MessageWslcNetworkNameRequired" xml:space="preserve">
2133
<value>Název sítě nemůže být prázdný.</value>
2134
</data>
localization/strings/da-DK/Resources.resw
-10
@@ -2111,17 +2111,10 @@ Brug:
2111
<value>Objektbeholderen "{}" kører ikke.</value>
2112
<comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2113
</data>
2114
- <data name="MessageWslcContainerIpAddressNotSupported" xml:space="preserve">
2115
- <value>ContainerIpAddress understøttes endnu ikke.</value>
2116
- <comment>{Locked="ContainerIpAddress"}Command line arguments, file names and string inserts should not be translated</comment>
2117
- </data>
2114
<data name="MessageWslcContainerIsRunning" xml:space="preserve">
2115
<value>Objektbeholderen "{}" kører.</value>
2116
<comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2117
</data>
2122
- <data name="MessageWslcContainerModeNoAdditionalNetworks" xml:space="preserve">
2123
- <value>Yderligere netværk er ikke tilladt med objektbeholdernetværkstilstand.</value>
2124
- </data>
2118
<data name="MessageWslcContainerModeNoPorts" xml:space="preserve">
2119
<value>Porttilknytninger understøttes ikke med objektbeholdernetværkstilstand. Porte ejes af destinationsbeholderen.</value>
2120
</data>
@@ -2136,9 +2129,6 @@ Brug:
2129
<value>Objektbeholderen '{}' blev ikke fundet.</value>
2130
<comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2131
</data>
2139
- <data name="MessageWslcContainerNetworkNameRequired" xml:space="preserve">
2140
- <value>Navnet på objektbeholdernetværket er påkrævet for den brugerdefinerede netværkstype.</value>
2141
- </data>
2132
<data name="MessageWslcNetworkNameRequired" xml:space="preserve">
2133
<value>Netværksnavnet må ikke være tomt.</value>
2134
</data>
localization/strings/de-DE/Resources.resw
-10
@@ -2117,17 +2117,10 @@ Verwendung:
2117
<value>Container „{}“ wird nicht ausgeführt.</value>
2118
<comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2119
</data>
2120
- <data name="MessageWslcContainerIpAddressNotSupported" xml:space="preserve">
2121
- <value>ContainerIpAddress wird noch nicht unterstützt.</value>
2122
- <comment>{Locked="ContainerIpAddress"}Command line arguments, file names and string inserts should not be translated</comment>
2123
- </data>
2120
<data name="MessageWslcContainerIsRunning" xml:space="preserve">
2121
<value>Container „{}“ wird ausgeführt.</value>
2122
<comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2123
</data>
2128
- <data name="MessageWslcContainerModeNoAdditionalNetworks" xml:space="preserve">
2129
- <value>Zusätzliche Netzwerke sind im Containernetzwerkmodus nicht zulässig.</value>
2130
- </data>
2124
<data name="MessageWslcContainerModeNoPorts" xml:space="preserve">
2125
<value>Portzuordnungen werden im Containernetzwerkmodus nicht unterstützt. Ports befinden sich im Besitz des Zielcontainers.</value>
2126
</data>
@@ -2142,9 +2135,6 @@ Verwendung:
2135
<value>Der Container „{}“ wurde nicht gefunden.</value>
2136
<comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2137
</data>
2145
- <data name="MessageWslcContainerNetworkNameRequired" xml:space="preserve">
2146
- <value>Für den benutzerdefinierten Netzwerktyp ist ein Containernetzwerkname erforderlich.</value>
2147
- </data>
2138
<data name="MessageWslcNetworkNameRequired" xml:space="preserve">
2139
<value>Der Netzwerkname darf nicht leer sein.</value>
2140
</data>
localization/strings/en-GB/Resources.resw
-10
@@ -2111,17 +2111,10 @@ Usage:
2111
<value>Container '{}' is not running.</value>
2112
<comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2113
</data>
2114
- <data name="MessageWslcContainerIpAddressNotSupported" xml:space="preserve">
2115
- <value>ContainerIpAddress is not yet supported.</value>
2116
- <comment>{Locked="ContainerIpAddress"}Command line arguments, file names and string inserts should not be translated</comment>
2117
- </data>
2114
<data name="MessageWslcContainerIsRunning" xml:space="preserve">
2115
<value>Container '{}' is running.</value>
2116
<comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2117
</data>
2122
- <data name="MessageWslcContainerModeNoAdditionalNetworks" xml:space="preserve">
2123
- <value>Additional networks are not allowed with container network mode.</value>
2124
- </data>
2118
<data name="MessageWslcContainerModeNoPorts" xml:space="preserve">
2119
<value>Port mappings are not supported with container network mode; ports are owned by the target container.</value>
2120
</data>
@@ -2136,9 +2129,6 @@ Usage:
2129
<value>Container '{}' not found.</value>
2130
<comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2131
</data>
2139
- <data name="MessageWslcContainerNetworkNameRequired" xml:space="preserve">
2140
- <value>Container network name is required for custom network type.</value>
2141
- </data>
2132
<data name="MessageWslcNetworkNameRequired" xml:space="preserve">
2133
<value>Network name cannot be empty.</value>
2134
</data>
localization/strings/en-US/Resources.resw
+7
-13
@@ -2111,17 +2111,10 @@ Usage:
2111
<value>Container '{}' is not running.</value>
2112
<comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2113
</data>
2114
- <data name="MessageWslcContainerIpAddressNotSupported" xml:space="preserve">
2115
- <value>ContainerIpAddress is not yet supported.</value>
2116
- <comment>{Locked="ContainerIpAddress"}Command line arguments, file names and string inserts should not be translated</comment>
2117
- </data>
2114
<data name="MessageWslcContainerIsRunning" xml:space="preserve">
2115
<value>Container '{}' is running.</value>
2116
<comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2117
</data>
2122
- <data name="MessageWslcContainerModeNoAdditionalNetworks" xml:space="preserve">
2123
- <value>Additional networks are not allowed with container network mode.</value>
2124
- </data>
2118
<data name="MessageWslcContainerModeNoPorts" xml:space="preserve">
2119
<value>Port mappings are not supported with container network mode; ports are owned by the target container.</value>
2120
</data>
@@ -2136,9 +2129,6 @@ Usage:
2129
<value>Container '{}' not found.</value>
2130
<comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2131
</data>
2139
- <data name="MessageWslcContainerNetworkNameRequired" xml:space="preserve">
2140
- <value>Container network name is required for custom network type.</value>
2141
- </data>
2132
<data name="MessageWslcNetworkNameRequired" xml:space="preserve">
2133
<value>Network name cannot be empty.</value>
2134
</data>
@@ -2332,14 +2322,18 @@ For privacy information about this product please visit https://aka.ms/privacy.<
2322
<value>Network '{}' already exists.</value>
2323
<comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2324
</data>
2335
- <data name="MessageWslcAdditionalNetworksRequirePrimary" xml:space="preserve">
2336
- <value>Additional networks are not allowed when the primary network mode is 'host' or 'none'.</value>
2337
- <comment>{Locked="host"}{Locked="none"}Command line arguments, file names and string inserts should not be translated</comment>
2325
+ <data name="MessageWslcInvalidNetworkMode" xml:space="preserve">
2326
+ <value>Unsupported network mode: '{}'</value>
2327
+ <comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2328
</data>
2329
<data name="MessageWslcDuplicateNetwork" xml:space="preserve">
2330
<value>Duplicate network: '{}'</value>
2331
<comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2332
</data>
2333
+ <data name="MessageWslcEndpointSettingsNotSupported" xml:space="preserve">
2334
+ <value>Endpoint settings are not yet supported (network '{}').</value>
2335
+ <comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2336
+ </data>
2337
<data name = "MessageWslcFailedToMountVolume" xml:space = "preserve" >
2338
<value>Failed to create volume '{}': {}</value>
2339
<comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
localization/strings/es-ES/Resources.resw
-10
@@ -2117,17 +2117,10 @@ Uso:
2117
<value>El contenedor "{}" no se está ejecutando.</value>
2118
<comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2119
</data>
2120
- <data name="MessageWslcContainerIpAddressNotSupported" xml:space="preserve">
2121
- <value>ContainerIpAddress aún no se admite.</value>
2122
- <comment>{Locked="ContainerIpAddress"}Command line arguments, file names and string inserts should not be translated</comment>
2123
- </data>
2120
<data name="MessageWslcContainerIsRunning" xml:space="preserve">
2121
<value>El contenedor "{}" se está ejecutando.</value>
2122
<comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2123
</data>
2128
- <data name="MessageWslcContainerModeNoAdditionalNetworks" xml:space="preserve">
2129
- <value>No se permiten redes adicionales con el modo de red de contenedor.</value>
2130
- </data>
2124
<data name="MessageWslcContainerModeNoPorts" xml:space="preserve">
2125
<value>Las asignaciones de puerto no son compatibles con el modo de red de contenedor; Los puertos son propiedad del contenedor de destino.</value>
2126
</data>
@@ -2142,9 +2135,6 @@ Uso:
2135
<value>No se encontró el contenedor “{}”.</value>
2136
<comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2137
</data>
2145
- <data name="MessageWslcContainerNetworkNameRequired" xml:space="preserve">
2146
- <value>El nombre de red de contenedor es necesario para el tipo de red personalizado.</value>
2147
- </data>
2138
<data name="MessageWslcNetworkNameRequired" xml:space="preserve">
2139
<value>El nombre de red no puede estar vacío.</value>
2140
</data>
localization/strings/fi-FI/Resources.resw
-10
@@ -2111,17 +2111,10 @@ Käyttö:
2111
<value>Säilö '{}' ei ole käynnissä.</value>
2112
<comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2113
</data>
2114
- <data name="MessageWslcContainerIpAddressNotSupported" xml:space="preserve">
2115
- <value>ContainerIpAddress ei vielä tueta.</value>
2116
- <comment>{Locked="ContainerIpAddress"}Command line arguments, file names and string inserts should not be translated</comment>
2117
- </data>
2114
<data name="MessageWslcContainerIsRunning" xml:space="preserve">
2115
<value>Säilö '{}' on käynnissä.</value>
2116
<comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2117
</data>
2122
- <data name="MessageWslcContainerModeNoAdditionalNetworks" xml:space="preserve">
2123
- <value>Lisäverkkoja ei sallita säilön verkkotilassa.</value>
2124
- </data>
2118
<data name="MessageWslcContainerModeNoPorts" xml:space="preserve">
2119
<value>Porttimäärityksiä ei tueta säilön verkkotilassa; portit kuuluvat kohdesäilölle.</value>
2120
</data>
@@ -2136,9 +2129,6 @@ Käyttö:
2129
<value>Säilöä {} ei löydy.</value>
2130
<comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2131
</data>
2139
- <data name="MessageWslcContainerNetworkNameRequired" xml:space="preserve">
2140
- <value>Säilöverkon nimi vaaditaan mukautetulle verkkotyypille.</value>
2141
- </data>
2132
<data name="MessageWslcNetworkNameRequired" xml:space="preserve">
2133
<value>Verkon nimi ei voi olla tyhjä.</value>
2134
</data>
localization/strings/fr-FR/Resources.resw
-10
@@ -2118,17 +2118,10 @@ Utilisation :
2118
<value>Le conteneur « {} » ne fonctionne pas.</value>
2119
<comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2120
</data>
2121
- <data name="MessageWslcContainerIpAddressNotSupported" xml:space="preserve">
2122
- <value>ContainerIpAddress n’est pas encore pris en charge.</value>
2123
- <comment>{Locked="ContainerIpAddress"}Command line arguments, file names and string inserts should not be translated</comment>
2124
- </data>
2121
<data name="MessageWslcContainerIsRunning" xml:space="preserve">
2122
<value>Le conteneur « {} » est en cours d’exécution.</value>
2123
<comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2124
</data>
2129
- <data name="MessageWslcContainerModeNoAdditionalNetworks" xml:space="preserve">
2130
- <value>Les réseaux supplémentaires ne sont pas autorisés avec le mode réseau de conteneurs.</value>
2131
- </data>
2125
<data name="MessageWslcContainerModeNoPorts" xml:space="preserve">
2126
<value>Les mappages de ports ne sont pas pris en charge avec le mode réseau de conteneurs ; Les ports appartiennent au conteneur cible.</value>
2127
</data>
@@ -2143,9 +2136,6 @@ Utilisation :
2136
<value>Le conteneur '{}' est introuvable.</value>
2137
<comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2138
</data>
2146
- <data name="MessageWslcContainerNetworkNameRequired" xml:space="preserve">
2147
- <value>Le nom du réseau de conteneurs est obligatoire pour le type de réseau personnalisé.</value>
2148
- </data>
2139
<data name="MessageWslcNetworkNameRequired" xml:space="preserve">
2140
<value>Le nom de Mise en réseau ne peut pas être vide.</value>
2141
</data>
localization/strings/hu-HU/Resources.resw
-10
@@ -2111,17 +2111,10 @@ Usage:
2111
<value>A(z) {} tároló nem fut.</value>
2112
<comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2113
</data>
2114
- <data name="MessageWslcContainerIpAddressNotSupported" xml:space="preserve">
2115
- <value>A ContainerIpAddress még nem támogatott.</value>
2116
- <comment>{Locked="ContainerIpAddress"}Command line arguments, file names and string inserts should not be translated</comment>
2117
- </data>
2114
<data name="MessageWslcContainerIsRunning" xml:space="preserve">
2115
<value>A(z) {} tároló fut.</value>
2116
<comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2117
</data>
2122
- <data name="MessageWslcContainerModeNoAdditionalNetworks" xml:space="preserve">
2123
- <value>Tárolóhálózati módban nem engedélyezettek további hálózatok.</value>
2124
- </data>
2118
<data name="MessageWslcContainerModeNoPorts" xml:space="preserve">
2119
<value>A portleképezések nem támogatottak tárolóhálózati módban; a portok a céltárolóhoz tartoznak.</value>
2120
</data>
@@ -2136,9 +2129,6 @@ Usage:
2129
<value>A(z) {} tároló nem található.</value>
2130
<comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2131
</data>
2139
- <data name="MessageWslcContainerNetworkNameRequired" xml:space="preserve">
2140
- <value>Az egyéni hálózattípushoz meg kell adni a tárolóhálózat nevét.</value>
2141
- </data>
2132
<data name="MessageWslcNetworkNameRequired" xml:space="preserve">
2133
<value>A hálózat neve nem lehet üres.</value>
2134
</data>
localization/strings/it-IT/Resources.resw
-10
@@ -2117,17 +2117,10 @@ Utilizzo:
2117
<value>Il contenitore '{}' non è in esecuzione.</value>
2118
<comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2119
</data>
2120
- <data name="MessageWslcContainerIpAddressNotSupported" xml:space="preserve">
2121
- <value>ContainerIpAddress non è ancora supportato.</value>
2122
- <comment>{Locked="ContainerIpAddress"}Command line arguments, file names and string inserts should not be translated</comment>
2123
- </data>
2120
<data name="MessageWslcContainerIsRunning" xml:space="preserve">
2121
<value>Il contenitore '{}' è in esecuzione.</value>
2122
<comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2123
</data>
2128
- <data name="MessageWslcContainerModeNoAdditionalNetworks" xml:space="preserve">
2129
- <value>Le reti aggiuntive non sono consentite con la modalità di rete contenitori.</value>
2130
- </data>
2124
<data name="MessageWslcContainerModeNoPorts" xml:space="preserve">
2125
<value>I mapping delle porte non sono supportati con la modalità di rete dei contenitori; Le porte sono di proprietà del contenitore di destinazione.</value>
2126
</data>
@@ -2142,9 +2135,6 @@ Utilizzo:
2135
<value>Contenitore "{}" non trovato.</value>
2136
<comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2137
</data>
2145
- <data name="MessageWslcContainerNetworkNameRequired" xml:space="preserve">
2146
- <value>Il nome della rete del contenitore è obbligatorio per il tipo di rete personalizzato.</value>
2147
- </data>
2138
<data name="MessageWslcNetworkNameRequired" xml:space="preserve">
2139
<value>Il nome della rete non può essere vuoto.</value>
2140
</data>
localization/strings/ja-JP/Resources.resw
-10
@@ -2117,17 +2117,10 @@ VS Code 自体のコマンド パレットから、より多くの VS Code リ
2117
<value>コンテナー '{}' が実行されていません。</value>
2118
<comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2119
</data>
2120
- <data name="MessageWslcContainerIpAddressNotSupported" xml:space="preserve">
2121
- <value>ContainerIpAddress はまだサポートされていません。</value>
2122
- <comment>{Locked="ContainerIpAddress"}Command line arguments, file names and string inserts should not be translated</comment>
2123
- </data>
2120
<data name="MessageWslcContainerIsRunning" xml:space="preserve">
2121
<value>コンテナー '{}' は実行中です。</value>
2122
<comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2123
</data>
2128
- <data name="MessageWslcContainerModeNoAdditionalNetworks" xml:space="preserve">
2129
- <value>コンテナー ネットワーク モードでは、追加のネットワークは許可されていません。</value>
2130
- </data>
2124
<data name="MessageWslcContainerModeNoPorts" xml:space="preserve">
2125
<value>ポート マッピングは、コンテナー ネットワーク モードではサポートされていません。ポートはターゲット コンテナーによって所有されます。</value>
2126
</data>
@@ -2142,9 +2135,6 @@ VS Code 自体のコマンド パレットから、より多くの VS Code リ
2135
<value>コンテナー '{}' が見つかりません。</value>
2136
<comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2137
</data>
2145
- <data name="MessageWslcContainerNetworkNameRequired" xml:space="preserve">
2146
- <value>カスタム ネットワークの種類にはコンテナー ネットワーク名が必要です。</value>
2147
- </data>
2138
<data name="MessageWslcNetworkNameRequired" xml:space="preserve">
2139
<value>ネットワーク名を空にすることはできません。</value>
2140
</data>
localization/strings/ko-KR/Resources.resw
-10
@@ -2117,17 +2117,10 @@ VS Code 자체 내의 명령 팔레트를 통해 더 많은 VS Code 원격 옵
2117
<value>컨테이너 '{}'(이)가 실행되고 있지 않습니다.</value>
2118
<comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2119
</data>
2120
- <data name="MessageWslcContainerIpAddressNotSupported" xml:space="preserve">
2121
- <value>ContainerIpAddress는 아직 지원되지 않습니다.</value>
2122
- <comment>{Locked="ContainerIpAddress"}Command line arguments, file names and string inserts should not be translated</comment>
2123
- </data>
2120
<data name="MessageWslcContainerIsRunning" xml:space="preserve">
2121
<value>컨테이너 '{}'(이)가 실행 중입니다.</value>
2122
<comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2123
</data>
2128
- <data name="MessageWslcContainerModeNoAdditionalNetworks" xml:space="preserve">
2129
- <value>컨테이너 네트워크 모드에서는 추가 네트워크가 허용되지 않습니다.</value>
2130
- </data>
2124
<data name="MessageWslcContainerModeNoPorts" xml:space="preserve">
2125
<value>포트 매핑은 컨테이너 네트워크 모드에서 지원되지 않습니다. 포트는 대상 컨테이너에서 소유합니다.</value>
2126
</data>
@@ -2142,9 +2135,6 @@ VS Code 자체 내의 명령 팔레트를 통해 더 많은 VS Code 원격 옵
2135
<value>컨테이너 '{}'을(를) 찾을 수 없습니다.</value>
2136
<comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2137
</data>
2145
- <data name="MessageWslcContainerNetworkNameRequired" xml:space="preserve">
2146
- <value>사용자 지정 네트워크 유형에는 컨테이너 네트워크 이름이 필요합니다.</value>
2147
- </data>
2138
<data name="MessageWslcNetworkNameRequired" xml:space="preserve">
2139
<value>네트워크 이름은 비워 둘 수 없습니다.</value>
2140
</data>
localization/strings/nb-NO/Resources.resw
-10
@@ -2111,17 +2111,10 @@ Bruk:
2111
<value>Beholderen «{}» kjører ikke.</value>
2112
<comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2113
</data>
2114
- <data name="MessageWslcContainerIpAddressNotSupported" xml:space="preserve">
2115
- <value>ContainerIpAddress støttes ikke ennå.</value>
2116
- <comment>{Locked="ContainerIpAddress"}Command line arguments, file names and string inserts should not be translated</comment>
2117
- </data>
2114
<data name="MessageWslcContainerIsRunning" xml:space="preserve">
2115
<value>Beholderen «{}» kjører.</value>
2116
<comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2117
</data>
2122
- <data name="MessageWslcContainerModeNoAdditionalNetworks" xml:space="preserve">
2123
- <value>Tilleggsnettverk er ikke tillatt med beholdernettverksmodus.</value>
2124
- </data>
2118
<data name="MessageWslcContainerModeNoPorts" xml:space="preserve">
2119
<value>Porttilordninger støttes ikke med beholdernettverksmodus. porter eies av målbeholderen.</value>
2120
</data>
@@ -2136,9 +2129,6 @@ Bruk:
2129
<value>Beholder {} ikke funnet.</value>
2130
<comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2131
</data>
2139
- <data name="MessageWslcContainerNetworkNameRequired" xml:space="preserve">
2140
- <value>Navn på beholdernettverk kreves for egendefinert nettverkstype.</value>
2141
- </data>
2132
<data name="MessageWslcNetworkNameRequired" xml:space="preserve">
2133
<value>Nettverksnavnet kan ikke være tomt</value>
2134
</data>
localization/strings/nl-NL/Resources.resw
-10
@@ -2111,17 +2111,10 @@ Gebruik:
2111
<value>Container {} is niet actief.</value>
2112
<comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2113
</data>
2114
- <data name="MessageWslcContainerIpAddressNotSupported" xml:space="preserve">
2115
- <value>ContainerIpAddress wordt nog niet ondersteund.</value>
2116
- <comment>{Locked="ContainerIpAddress"}Command line arguments, file names and string inserts should not be translated</comment>
2117
- </data>
2114
<data name="MessageWslcContainerIsRunning" xml:space="preserve">
2115
<value>Container {} wordt uitgevoerd.</value>
2116
<comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2117
</data>
2122
- <data name="MessageWslcContainerModeNoAdditionalNetworks" xml:space="preserve">
2123
- <value>Aanvullende netwerken zijn niet toegestaan met de containernetwerkmodus.</value>
2124
- </data>
2118
<data name="MessageWslcContainerModeNoPorts" xml:space="preserve">
2119
<value>Poorttoewijzingen worden niet ondersteund met de containernetwerkmodus; poorten behoren toe aan de doelcontainer.</value>
2120
</data>
@@ -2136,9 +2129,6 @@ Gebruik:
2129
<value>Kan de container {} niet vinden.</value>
2130
<comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2131
</data>
2139
- <data name="MessageWslcContainerNetworkNameRequired" xml:space="preserve">
2140
- <value>De netwerknaam van de container is verplicht voor een aangepast netwerktype.</value>
2141
- </data>
2132
<data name="MessageWslcNetworkNameRequired" xml:space="preserve">
2133
<value>Netwerknaam mag niet leeg zijn.</value>
2134
</data>
localization/strings/pl-PL/Resources.resw
-10
@@ -2111,17 +2111,10 @@ Użycie:
2111
<value>Kontener „{}” nie jest uruchomiony.</value>
2112
<comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2113
</data>
2114
- <data name="MessageWslcContainerIpAddressNotSupported" xml:space="preserve">
2115
- <value>Adres ContainerIpAddress nie jest jeszcze obsługiwany.</value>
2116
- <comment>{Locked="ContainerIpAddress"}Command line arguments, file names and string inserts should not be translated</comment>
2117
- </data>
2114
<data name="MessageWslcContainerIsRunning" xml:space="preserve">
2115
<value>Kontener „{}” jest uruchomiony.</value>
2116
<comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2117
</data>
2122
- <data name="MessageWslcContainerModeNoAdditionalNetworks" xml:space="preserve">
2123
- <value>Dodatkowe sieci nie są dozwolone w trybie sieci kontenera.</value>
2124
- </data>
2118
<data name="MessageWslcContainerModeNoPorts" xml:space="preserve">
2119
<value>Mapowania portów nie są obsługiwane w trybie sieci kontenerów; porty są własnością kontenera docelowego.</value>
2120
</data>
@@ -2136,9 +2129,6 @@ Użycie:
2129
<value>Nie znaleziono kontenera „{}”.</value>
2130
<comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2131
</data>
2139
- <data name="MessageWslcContainerNetworkNameRequired" xml:space="preserve">
2140
- <value>Nazwa sieci kontenera jest wymagana dla niestandardowego typu sieci.</value>
2141
- </data>
2132
<data name="MessageWslcNetworkNameRequired" xml:space="preserve">
2133
<value>Nazwa sieci nie może być pusta.</value>
2134
</data>
localization/strings/pt-BR/Resources.resw
-10
@@ -2118,17 +2118,10 @@ Uso:
2118
<value>O contêiner '{}' não está em execução.</value>
2119
<comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2120
</data>
2121
- <data name="MessageWslcContainerIpAddressNotSupported" xml:space="preserve">
2122
- <value>ContainerIpAddress ainda não tem suporte.</value>
2123
- <comment>{Locked="ContainerIpAddress"}Command line arguments, file names and string inserts should not be translated</comment>
2124
- </data>
2121
<data name="MessageWslcContainerIsRunning" xml:space="preserve">
2122
<value>O contêiner '{}' está em execução.</value>
2123
<comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2124
</data>
2129
- <data name="MessageWslcContainerModeNoAdditionalNetworks" xml:space="preserve">
2130
- <value>Redes adicionais não são permitidas com o modo de rede de contêiner.</value>
2131
- </data>
2125
<data name="MessageWslcContainerModeNoPorts" xml:space="preserve">
2126
<value>Não há suporte para mapeamentos de porta com o modo de rede de contêineres; As portas são de propriedade do contêiner de destino.</value>
2127
</data>
@@ -2143,9 +2136,6 @@ Uso:
2136
<value>Contêiner '{}' não encontrado.</value>
2137
<comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2138
</data>
2146
- <data name="MessageWslcContainerNetworkNameRequired" xml:space="preserve">
2147
- <value>O nome da rede do contêiner é necessário para o tipo de rede personalizado.</value>
2148
- </data>
2139
<data name="MessageWslcNetworkNameRequired" xml:space="preserve">
2140
<value>O nome da rede não pode ficar vazio.</value>
2141
</data>
localization/strings/pt-PT/Resources.resw
-10
@@ -2111,17 +2111,10 @@ Utilização:
2111
<value>O contentor "{}" não está em execução.</value>
2112
<comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2113
</data>
2114
- <data name="MessageWslcContainerIpAddressNotSupported" xml:space="preserve">
2115
- <value>ContainerIpAddress ainda não é suportado.</value>
2116
- <comment>{Locked="ContainerIpAddress"}Command line arguments, file names and string inserts should not be translated</comment>
2117
- </data>
2114
<data name="MessageWslcContainerIsRunning" xml:space="preserve">
2115
<value>O contentor "{}" está em execução.</value>
2116
<comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2117
</data>
2122
- <data name="MessageWslcContainerModeNoAdditionalNetworks" xml:space="preserve">
2123
- <value>Não são permitidas redes adicionais com o modo de rede de contentor.</value>
2124
- </data>
2118
<data name="MessageWslcContainerModeNoPorts" xml:space="preserve">
2119
<value>Os mapeamentos de portas não são suportados com o modo de rede de contentores; As portas são propriedade do contentor de destino.</value>
2120
</data>
@@ -2136,9 +2129,6 @@ Utilização:
2129
<value>Contentor "{}" não encontrado.</value>
2130
<comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2131
</data>
2139
- <data name="MessageWslcContainerNetworkNameRequired" xml:space="preserve">
2140
- <value>O nome de rede do contentor é necessário para o tipo de rede personalizado.</value>
2141
- </data>
2132
<data name="MessageWslcNetworkNameRequired" xml:space="preserve">
2133
<value>O nome da rede não pode estar vazio.</value>
2134
</data>
localization/strings/ru-RU/Resources.resw
-10
@@ -2118,17 +2118,10 @@ wsl.exe --manage <DistributionName> --set-sparse true --allow-unsafe</valu
2118
<value>Контейнер "{}" не запущен.</value>
2119
<comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2120
</data>
2121
- <data name="MessageWslcContainerIpAddressNotSupported" xml:space="preserve">
2122
- <value>ContainerIpAddress пока не поддерживается.</value>
2123
- <comment>{Locked="ContainerIpAddress"}Command line arguments, file names and string inserts should not be translated</comment>
2124
- </data>
2121
<data name="MessageWslcContainerIsRunning" xml:space="preserve">
2122
<value>Контейнер "{}" запущен.</value>
2123
<comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2124
</data>
2129
- <data name="MessageWslcContainerModeNoAdditionalNetworks" xml:space="preserve">
2130
- <value>В режиме сети контейнера дополнительные сети не разрешены.</value>
2131
- </data>
2125
<data name="MessageWslcContainerModeNoPorts" xml:space="preserve">
2126
<value>В режиме сети контейнера сопоставление портов не поддерживается; права на порты принадлежат целевому контейнеру.</value>
2127
</data>
@@ -2143,9 +2136,6 @@ wsl.exe --manage <DistributionName> --set-sparse true --allow-unsafe</valu
2136
<value>Контейнер "{}" не найден.</value>
2137
<comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2138
</data>
2146
- <data name="MessageWslcContainerNetworkNameRequired" xml:space="preserve">
2147
- <value>Для пользовательского типа сети требуется имя сети контейнера.</value>
2148
- </data>
2139
<data name="MessageWslcNetworkNameRequired" xml:space="preserve">
2140
<value>Имя сети не может быть пустым.</value>
2141
</data>
localization/strings/sv-SE/Resources.resw
-10
@@ -2111,17 +2111,10 @@ Användning:
2111
<value>Containern {} körs inte.</value>
2112
<comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2113
</data>
2114
- <data name="MessageWslcContainerIpAddressNotSupported" xml:space="preserve">
2115
- <value>ContainerIpAddress stöds inte ännu.</value>
2116
- <comment>{Locked="ContainerIpAddress"}Command line arguments, file names and string inserts should not be translated</comment>
2117
- </data>
2114
<data name="MessageWslcContainerIsRunning" xml:space="preserve">
2115
<value>Containern {} körs.</value>
2116
<comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2117
</data>
2122
- <data name="MessageWslcContainerModeNoAdditionalNetworks" xml:space="preserve">
2123
- <value>Ytterligare nätverk tillåts inte i containernätverksläge.</value>
2124
- </data>
2118
<data name="MessageWslcContainerModeNoPorts" xml:space="preserve">
2119
<value>Portmappningar stöds inte med containernätverksläge. portar ägs av målcontainern.</value>
2120
</data>
@@ -2136,9 +2129,6 @@ Användning:
2129
<value>Containern '{}' hittades inte.</value>
2130
<comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2131
</data>
2139
- <data name="MessageWslcContainerNetworkNameRequired" xml:space="preserve">
2140
- <value>Containernätverksnamn krävs för anpassad nätverkstyp.</value>
2141
- </data>
2132
<data name="MessageWslcNetworkNameRequired" xml:space="preserve">
2133
<value>Nätverksnamnet får inte vara tomt.</value>
2134
</data>
localization/strings/tr-TR/Resources.resw
-10
@@ -2111,17 +2111,10 @@ Kullanım:
2111
<value>'{}' kapsayıcısı çalışmıyor.</value>
2112
<comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2113
</data>
2114
- <data name="MessageWslcContainerIpAddressNotSupported" xml:space="preserve">
2115
- <value>ContainerIpAddress henüz desteklenmiyor.</value>
2116
- <comment>{Locked="ContainerIpAddress"}Command line arguments, file names and string inserts should not be translated</comment>
2117
- </data>
2114
<data name="MessageWslcContainerIsRunning" xml:space="preserve">
2115
<value>'{}' kapsayıcısı çalışıyor.</value>
2116
<comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2117
</data>
2122
- <data name="MessageWslcContainerModeNoAdditionalNetworks" xml:space="preserve">
2123
- <value>Kapsayıcı ağ modunda ek ağlara izin verilmiyor.</value>
2124
- </data>
2118
<data name="MessageWslcContainerModeNoPorts" xml:space="preserve">
2119
<value>Bağlantı noktası eşlemeleri kapsayıcı ağ modunda desteklenmez; bağlantı noktalarının sahibi hedef kapsayıcıdır.</value>
2120
</data>
@@ -2136,9 +2129,6 @@ Kullanım:
2129
<value>'{}' kapsayıcısı bulunamadı.</value>
2130
<comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2131
</data>
2139
- <data name="MessageWslcContainerNetworkNameRequired" xml:space="preserve">
2140
- <value>Özel ağ türü için kapsayıcı ağ adı gereklidir.</value>
2141
- </data>
2132
<data name="MessageWslcNetworkNameRequired" xml:space="preserve">
2133
<value>Ağ adı boş olamaz.</value>
2134
</data>
localization/strings/zh-CN/Resources.resw
-10
@@ -2117,17 +2117,10 @@ wsl.exe --manage <DistributionName> --set-sparse true --allow-unsafe</valu
2117
<value>容器“{}”未运行。</value>
2118
<comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2119
</data>
2120
- <data name="MessageWslcContainerIpAddressNotSupported" xml:space="preserve">
2121
- <value>尚不支持 ContainerIpAddress。</value>
2122
- <comment>{Locked="ContainerIpAddress"}Command line arguments, file names and string inserts should not be translated</comment>
2123
- </data>
2120
<data name="MessageWslcContainerIsRunning" xml:space="preserve">
2121
<value>容器“{}”正在运行。</value>
2122
<comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2123
</data>
2128
- <data name="MessageWslcContainerModeNoAdditionalNetworks" xml:space="preserve">
2129
- <value>容器网络模式不允许使用其他网络。</value>
2130
- </data>
2124
<data name="MessageWslcContainerModeNoPorts" xml:space="preserve">
2125
<value>容器网络模式不支持端口映射;端口由目标容器拥有。</value>
2126
</data>
@@ -2142,9 +2135,6 @@ wsl.exe --manage <DistributionName> --set-sparse true --allow-unsafe</valu
2135
<value>找不到容器 '{}'。</value>
2136
<comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2137
</data>
2145
- <data name="MessageWslcContainerNetworkNameRequired" xml:space="preserve">
2146
- <value>自定义网络类型需要容器网络名称。</value>
2147
- </data>
2138
<data name="MessageWslcNetworkNameRequired" xml:space="preserve">
2139
<value>网络名称不可为空。</value>
2140
</data>
localization/strings/zh-TW/Resources.resw
-10
@@ -2117,17 +2117,10 @@ wsl.exe --manage <DistributionName> --set-sparse true --allow-unsafe</valu
2117
<value>容器 '{}' 未執行。</value>
2118
<comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2119
</data>
2120
- <data name="MessageWslcContainerIpAddressNotSupported" xml:space="preserve">
2121
- <value>ContainerIpAddress 尚未支援。</value>
2122
- <comment>{Locked="ContainerIpAddress"}Command line arguments, file names and string inserts should not be translated</comment>
2123
- </data>
2120
<data name="MessageWslcContainerIsRunning" xml:space="preserve">
2121
<value>容器 '{}' 正在執行。</value>
2122
<comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2123
</data>
2128
- <data name="MessageWslcContainerModeNoAdditionalNetworks" xml:space="preserve">
2129
- <value>容器網路模式不允許其他網路。</value>
2130
- </data>
2124
<data name="MessageWslcContainerModeNoPorts" xml:space="preserve">
2125
<value>容器網路模式不支援連接埠對應;連接埠由目標容器擁有。</value>
2126
</data>
@@ -2142,9 +2135,6 @@ wsl.exe --manage <DistributionName> --set-sparse true --allow-unsafe</valu
2135
<value>找不到容器 '{}'。</value>
2136
<comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2137
</data>
2145
- <data name="MessageWslcContainerNetworkNameRequired" xml:space="preserve">
2146
- <value>自訂網路類型需要容器網路名稱。</value>
2147
- </data>
2138
<data name="MessageWslcNetworkNameRequired" xml:space="preserve">
2139
<value>網路名稱不可為空白。</value>
2140
</data>
src/windows/WslcSDK/WslcsdkPrivate.h
+1
-1
@@ -87,7 +87,7 @@ typedef struct WslcContainerOptionsInternal
87
const WslcContainerNamedVolume* namedVolumes;
88
uint32_t namedVolumesCount;
89
const WslcContainerProcessOptionsInternal* initProcessOptions;
90
- WSLCContainerNetworkType networking;
90
+ PCSTR networkMode;
91
WslcContainerFlags containerFlags;
92
93
} WslcContainerOptionsInternal;
src/windows/WslcSDK/wslcsdk.cpp
+7
-6
@@ -99,14 +99,14 @@ WSLCSignal Convert(WslcSignal signal)
99
}
100
}
101
102
-WSLCContainerNetworkType Convert(WslcContainerNetworkingMode mode)
102
+PCSTR Convert(WslcContainerNetworkingMode mode)
103
{
104
switch (mode)
105
{
106
case WSLC_CONTAINER_NETWORKING_MODE_NONE:
107
- return WSLCContainerNetworkTypeNone;
107
+ return "none";
108
case WSLC_CONTAINER_NETWORKING_MODE_BRIDGED:
109
- return WSLCContainerNetworkTypeBridged;
109
+ return "bridge";
110
default:
111
THROW_HR_MSG(E_INVALIDARG, "Invalid WslcContainerNetworkingMode: %i", mode);
112
}
@@ -693,7 +693,7 @@ try
693
694
internalType->image = imageName;
695
// Default network configuration to WSLC SDK `0`, which is NONE.
696
- internalType->networking = WSLCContainerNetworkTypeNone;
696
+ internalType->networkMode = "none";
697
698
return S_OK;
699
}
@@ -822,7 +822,8 @@ try
822
containerOptions.PortsCount = static_cast<ULONG>(internalContainerSettings->portsCount);
823
}
824
825
- containerOptions.ContainerNetwork.ContainerNetworkType = internalContainerSettings->networking;
825
+ // SDK only exposes the network mode (no additional endpoints today).
826
+ containerOptions.ContainerNetwork.NetworkMode = internalContainerSettings->networkMode;
827
828
// TODO: No user access
829
// containerOptions.Labels;
@@ -933,7 +934,7 @@ try
934
{
935
auto internalType = CheckAndGetInternalType(containerSettings);
936
936
- internalType->networking = Convert(networkingMode);
937
+ internalType->networkMode = Convert(networkingMode);
938
939
return S_OK;
940
}
src/windows/WslcSDK/wslcsdk.h
+1
-1
@@ -53,7 +53,7 @@ typedef struct WslcSessionSettings
53
DECLARE_HANDLE(WslcSession);
54
55
// Container values
56
-#define WSLC_CONTAINER_OPTIONS_SIZE 96
56
+#define WSLC_CONTAINER_OPTIONS_SIZE 104
57
#define WSLC_CONTAINER_OPTIONS_ALIGNMENT 8
58
59
typedef struct WslcContainerSettings
src/windows/common/WSLCContainerLauncher.cpp
+10
-19
@@ -86,9 +86,9 @@ WSLCContainerLauncher::WSLCContainerLauncher(
86
const std::string& Name,
87
const std::vector<std::string>& Arguments,
88
const std::vector<std::string>& Environment,
89
- WSLCContainerNetworkType containerNetworkType,
89
+ std::string networkMode,
90
WSLCProcessFlags Flags) :
91
- WSLCProcessLauncher({}, Arguments, Environment, Flags), m_image(Image), m_name(Name), m_containerNetworkType(containerNetworkType)
91
+ WSLCProcessLauncher({}, Arguments, Environment, Flags), m_image(Image), m_name(Name), m_networkMode(std::move(networkMode))
92
{
93
}
94
@@ -144,11 +144,6 @@ void WSLCContainerLauncher::SetContainerFlags(WSLCContainerFlags Flags)
144
m_containerFlags = Flags;
145
}
146
147
-void WSLCContainerLauncher::SetContainerNetworkName(std::string&& Name)
148
-{
149
- m_containerNetworkName = std::move(Name);
150
-}
151
-
147
void WSLCContainerLauncher::SetHostname(std::string&& Hostname)
148
{
149
m_hostname = std::move(Hostname);
@@ -287,7 +282,6 @@ std::pair<HRESULT, std::optional<RunningWSLCContainer>> WSLCContainerLauncher::C
282
283
auto [processOptions, commandLinePtrs, environmentPtrs] = CreateProcessOptions();
284
options.InitProcessOptions = processOptions;
290
- options.ContainerNetwork.ContainerNetworkType = m_containerNetworkType;
285
options.Ports = m_ports.data();
286
options.PortsCount = static_cast<ULONG>(m_ports.size());
287
options.StopSignal = m_stopSignal;
@@ -359,21 +353,18 @@ std::pair<HRESULT, std::optional<RunningWSLCContainer>> WSLCContainerLauncher::C
353
options.TmpfsCount = static_cast<ULONG>(m_tmpfsMounts.size());
354
options.Tmpfs = m_tmpfsMounts.size() > 0 ? m_tmpfsMounts.data() : nullptr;
355
362
- std::vector<WSLCNetworkAttachment> networkAttachments;
363
- if (m_containerNetworkType == WSLCContainerNetworkTypeCustom)
364
- {
365
- networkAttachments.push_back({m_containerNetworkName.c_str(), nullptr});
366
- }
356
+ options.ContainerNetwork.NetworkMode = m_networkMode.c_str();
357
+
358
+ // Each additional network becomes an entry in NetworkingConfig.EndpointsConfig.
359
+ std::vector<WSLCNetworkConnection> connections;
360
+ connections.reserve(m_additionalNetworks.size());
361
for (const auto& e : m_additionalNetworks)
362
{
369
- networkAttachments.push_back({e.c_str(), nullptr});
363
+ connections.push_back({.NetworkName = e.c_str()});
364
}
365
372
- if (!networkAttachments.empty())
373
- {
374
- options.ContainerNetwork.Networks = networkAttachments.data();
375
- options.ContainerNetwork.NetworksCount = static_cast<ULONG>(networkAttachments.size());
376
- }
366
+ options.ContainerNetwork.Networks = connections.empty() ? nullptr : connections.data();
367
+ options.ContainerNetwork.NetworksCount = static_cast<ULONG>(connections.size());
368
369
options.MemoryBytes = m_memoryBytes;
370
options.NanoCpus = m_nanoCpus;
src/windows/common/WSLCContainerLauncher.h
+2
-4
@@ -54,7 +54,7 @@ public:
54
const std::string& Name = "",
55
const std::vector<std::string>& Arguments = {},
56
const std::vector<std::string>& Environment = {},
57
- WSLCContainerNetworkType containerNetworkType = WSLCContainerNetworkTypeHost,
57
+ std::string networkMode = "host",
58
WSLCProcessFlags Flags = WSLCProcessFlagsNone);
59
60
void AddVolume(const std::wstring& HostPath, const std::string& ContainerPath, bool ReadOnly);
@@ -75,7 +75,6 @@ public:
75
void SetDefaultStopSignal(WSLCSignal Signal);
76
void SetShmSize(int64_t ShmSize);
77
void SetContainerFlags(WSLCContainerFlags Flags);
78
- void SetContainerNetworkName(std::string&& Name);
78
void SetHostname(std::string&& Hostname);
79
void SetDomainname(std::string&& Domainame);
80
void SetDnsServers(std::vector<std::string>&& DnsServers);
@@ -98,8 +97,7 @@ private:
97
std::deque<std::wstring> m_hostPaths;
98
std::deque<std::string> m_volumeNames;
99
std::deque<std::string> m_containerPaths;
101
- WSLCContainerNetworkType m_containerNetworkType;
102
- std::string m_containerNetworkName;
100
+ std::string m_networkMode;
101
std::vector<std::string> m_entrypoint;
102
WSLCSignal m_stopSignal = WSLCSignalNone;
103
int64_t m_shmSize = 0;
src/windows/service/inc/wslc.idl
+8
-13
@@ -249,24 +249,19 @@ typedef struct _WSLCUlimit
249
LONGLONG Hard;
250
} WSLCUlimit;
251
252
-typedef enum _WSLCContainerNetworkType
252
+typedef struct _WSLCNetworkConnection
253
{
254
- WSLCContainerNetworkTypeNone = 0,
255
- WSLCContainerNetworkTypeHost = 1,
256
- WSLCContainerNetworkTypeBridged = 2,
257
- WSLCContainerNetworkTypeCustom = 3
258
-} WSLCContainerNetworkType;
254
+ [string] LPCSTR NetworkName;
255
260
-typedef struct _WSLCNetworkAttachment
261
-{
262
- [unique] LPCSTR NetworkName;
263
- [unique] LPCSTR ContainerIpAddress; // Reserved for future --ip support; must be NULL today.
264
-} WSLCNetworkAttachment;
256
+ [unique, size_is(SettingsCount)] const KeyValuePair* Settings;
257
+ ULONG SettingsCount;
258
+} WSLCNetworkConnection;
259
260
typedef struct _WSLCContainerNetwork
261
{
268
- WSLCContainerNetworkType ContainerNetworkType;
269
- [unique, size_is(NetworksCount)] const WSLCNetworkAttachment* Networks;
262
+ [unique, string] LPCSTR NetworkMode;
263
+
264
+ [unique, size_is(NetworksCount)] const WSLCNetworkConnection* Networks;
265
ULONG NetworksCount;
266
} WSLCContainerNetwork;
267
src/windows/wslc/services/ContainerService.cpp
+1
-1
@@ -50,7 +50,7 @@ static wsl::windows::common::RunningWSLCContainer CreateInternal(Session& sessio
50
WI_SetFlagIf(containerFlags, WSLCContainerFlagsGpu, options.Gpu);
51
52
wsl::windows::common::WSLCContainerLauncher containerLauncher(
53
- image, options.Name, options.Arguments, options.EnvironmentVariables, WSLCContainerNetworkTypeBridged, processFlags);
53
+ image, options.Name, options.Arguments, options.EnvironmentVariables, "bridge", processFlags);
54
55
// Set port options if provided
56
for (const auto& port : options.Ports)
src/windows/wslcsession/WSLCContainer.cpp
+124
-203
@@ -151,97 +151,115 @@ uint16_t AllocateEphemeralPort(int family, const char* address)
151
152
constexpr std::string_view c_containerNetworkPrefix = "container:";
153
154
-// Returns the target name after "container:" if present, std::nullopt otherwise.
155
-std::optional<std::string> ParseContainerTarget(std::string_view mode)
154
+bool NetworkModeAllocatesVmPorts(std::string_view mode) noexcept
155
{
157
- if (!mode.starts_with(c_containerNetworkPrefix))
156
+ return mode != "host" && mode != "none" && !mode.starts_with(c_containerNetworkPrefix);
157
+}
158
+
159
+// Reject `<prefix>:<value>` strings whose prefix isn't `container:`. Docker treats colon-prefixed
160
+// modes (`service:`, `ns:`, ...) as special, but WSLC only supports `container:`. Surface the
161
+// rejection here so both Create() and Open() recovery paths share the same gate.
162
+void RejectUnsupportedNetworkModes(std::string_view mode)
163
+{
164
+ if (mode.starts_with(c_containerNetworkPrefix))
165
{
159
- return std::nullopt;
166
+ return;
167
}
168
162
- return std::string{mode.substr(c_containerNetworkPrefix.size())};
169
+ const auto colon = mode.find(':');
170
+ THROW_HR_WITH_USER_ERROR_IF(E_INVALIDARG, Localization::MessageWslcInvalidNetworkMode(std::string{mode}), colon != std::string_view::npos);
171
}
172
165
-std::optional<std::string> ParseContainerTarget(LPCSTR mode)
173
+std::string ResolveNetworkMode(LPCSTR networkMode, bool hasRequestedPorts, const std::unordered_map<std::string, NetworkEntry>& sessionNetworks, DockerHTTPClient& dockerClient)
174
{
167
- return mode != nullptr ? ParseContainerTarget(std::string_view{mode}) : std::nullopt;
168
-}
175
+ const std::string_view mode = (networkMode == nullptr || *networkMode == '\0') ? std::string_view{"bridge"} : networkMode;
176
170
-// Builds port mapping list from container options and returns the network mode string.
171
-std::pair<std::vector<ContainerPortMapping>, std::string> ProcessPortMappings(
172
- std::vector<_WSLCPortMapping>& requestedPorts,
173
- WSLCContainerNetworkType networkType,
174
- WSLCVirtualMachine& virtualMachine,
175
- const std::unordered_map<std::string, NetworkEntry>& sessionNetworks,
176
- LPCSTR containerNetworkName,
177
- DockerHTTPClient& dockerClient)
178
-{
179
- THROW_HR_IF_MSG(
180
- E_INVALIDARG,
181
- containerNetworkName != nullptr && networkType != WSLCContainerNetworkTypeCustom,
182
- "ContainerNetworkName must be null when network type is not Custom");
177
+ // Reject `service:foo` and similar unsupported colon-prefixed modes before any further processing.
178
+ RejectUnsupportedNetworkModes(mode);
179
184
- // Determine network mode string.
185
- std::string networkMode;
186
- std::optional<std::string> containerTarget;
187
- if (networkType == WSLCContainerNetworkTypeBridged)
188
- {
189
- networkMode = "bridge";
190
- }
191
- else if (networkType == WSLCContainerNetworkTypeHost)
180
+ // N.B. Docker validates incompatible combinations (e.g. host/none/container: with additional networks)
181
+ // and returns clear error messages, so we don't duplicate that validation here.
182
+
183
+ if (mode == "host")
184
{
193
- networkMode = "host";
185
+ return "host";
186
}
195
- else if (networkType == WSLCContainerNetworkTypeNone)
187
+
188
+ if (mode == "none")
189
{
197
- networkMode = "none";
190
+ THROW_HR_IF_MSG(E_INVALIDARG, hasRequestedPorts, "Port mappings are not supported without networking");
191
+ return "none";
192
}
199
- else if (networkType == WSLCContainerNetworkTypeCustom)
193
+
194
+ if (mode.starts_with(c_containerNetworkPrefix))
195
{
201
- THROW_HR_WITH_USER_ERROR_IF(
202
- E_INVALIDARG, Localization::MessageWslcContainerNetworkNameRequired(), !containerNetworkName || strlen(containerNetworkName) == 0);
196
+ const std::string target{mode.substr(c_containerNetworkPrefix.size())};
197
+ THROW_HR_WITH_USER_ERROR_IF(E_INVALIDARG, Localization::MessageWslcContainerModeRequiresTarget(), target.empty());
198
+ THROW_HR_WITH_USER_ERROR_IF(E_INVALIDARG, Localization::MessageWslcContainerModeNoPorts(), hasRequestedPorts);
199
204
- containerTarget = ParseContainerTarget(containerNetworkName);
205
- if (containerTarget)
200
+ try
201
{
207
- THROW_HR_WITH_USER_ERROR_IF(E_INVALIDARG, Localization::MessageWslcContainerModeRequiresTarget(), containerTarget->empty());
208
-
209
- THROW_HR_WITH_USER_ERROR_IF(E_INVALIDARG, Localization::MessageWslcContainerModeNoPorts(), !requestedPorts.empty());
210
-
211
- try
212
- {
213
- auto targetInspect = dockerClient.InspectContainer(*containerTarget);
214
- networkMode = std::format("container:{}", targetInspect.Id);
215
- }
216
- catch (const DockerHTTPException& e)
217
- {
218
- THROW_HR_WITH_USER_ERROR_IF(
219
- WSLC_E_CONTAINER_NOT_FOUND, Localization::MessageWslcContainerModeTargetNotFound(*containerTarget), e.StatusCode() == 404);
220
- throw;
221
- }
202
+ return std::format("container:{}", dockerClient.InspectContainer(target).Id);
203
}
223
- else
204
+ catch (const DockerHTTPException& e)
205
{
206
THROW_HR_WITH_USER_ERROR_IF(
226
- WSLC_E_NETWORK_NOT_FOUND, Localization::MessageWslcNetworkNotFound(containerNetworkName), !sessionNetworks.contains(containerNetworkName));
227
-
228
- networkMode = containerNetworkName;
207
+ WSLC_E_CONTAINER_NOT_FOUND, Localization::MessageWslcContainerModeTargetNotFound(target), e.StatusCode() == 404);
208
+ throw;
209
}
210
}
231
- else
211
+
212
+ // User-defined network: bridge is the built-in one and bypasses the session lookup.
213
+ if (mode != "bridge")
214
{
233
- THROW_HR_MSG(E_INVALIDARG, "Invalid networking mode: %i", networkType);
215
+ THROW_HR_WITH_USER_ERROR_IF(
216
+ WSLC_E_NETWORK_NOT_FOUND, Localization::MessageWslcNetworkNotFound(std::string{mode}), !sessionNetworks.contains(std::string{mode}));
217
}
218
+ return std::string{mode};
219
+}
220
236
- // Validate port mappings.
237
- THROW_HR_IF_MSG(
238
- E_INVALIDARG,
239
- !requestedPorts.empty() && networkType == WSLCContainerNetworkTypeNone,
240
- "Port mappings are not supported without networking");
221
+std::map<std::string, EmptyObject> ResolveEndpoints(
222
+ const WSLCNetworkConnection* connections, ULONG count, std::string_view resolvedMode, const std::unordered_map<std::string, NetworkEntry>& sessionNetworks)
223
+{
224
+ std::map<std::string, EmptyObject> resolved;
225
+ if (count == 0)
226
+ {
227
+ return resolved;
228
+ }
229
+
230
+ THROW_HR_IF_MSG(E_INVALIDARG, connections == nullptr, "Networks is null with NetworksCount=%lu", count);
231
+
232
+ for (ULONG i = 0; i < count; i++)
233
+ {
234
+ const char* raw = connections[i].NetworkName;
235
+ THROW_HR_WITH_USER_ERROR_IF(E_INVALIDARG, Localization::MessageWslcNetworkNameRequired(), !raw || !*raw);
236
+
237
+ std::string name{raw};
238
+ THROW_HR_WITH_USER_ERROR_IF(E_INVALIDARG, Localization::MessageWslcDuplicateNetwork(name), name == resolvedMode);
239
+
240
+ auto [it, inserted] = resolved.try_emplace(name);
241
+ THROW_HR_WITH_USER_ERROR_IF(E_INVALIDARG, Localization::MessageWslcDuplicateNetwork(name), !inserted);
242
+
243
+ if (name != "bridge")
244
+ {
245
+ THROW_HR_WITH_USER_ERROR_IF(
246
+ WSLC_E_NETWORK_NOT_FOUND, Localization::MessageWslcNetworkNotFound(name), !sessionNetworks.contains(name));
247
+ }
248
249
+ // Per-endpoint Settings are reserved for future use (IPAddress, Aliases, ...). No keys
250
+ // are interpreted today, so reject any non-empty payload rather than silently dropping it.
251
+ THROW_HR_WITH_USER_ERROR_IF(E_NOTIMPL, Localization::MessageWslcEndpointSettingsNotSupported(name), connections[i].SettingsCount > 0);
252
+ }
253
+ return resolved;
254
+}
255
+
256
+// Builds the port-mapping list from caller-supplied requests.
257
+std::vector<ContainerPortMapping> BuildPortMappings(std::vector<_WSLCPortMapping>& requestedPorts, std::string_view primary, WSLCVirtualMachine& vm)
258
+{
259
std::vector<ContainerPortMapping> ports;
260
ports.reserve(requestedPorts.size());
261
262
+ const bool allocateVmPorts = NetworkModeAllocatesVmPorts(primary);
263
for (auto& e : requestedPorts)
264
{
265
if (e.HostPort == WSLC_EPHEMERAL_PORT)
@@ -250,15 +268,12 @@ std::pair<std::vector<ContainerPortMapping>, std::string> ProcessPortMappings(
268
}
269
270
auto& entry = ports.emplace_back(VMPortMapping::FromWSLCPortMapping(e), e.ContainerPort);
253
-
254
- // Allocate VM ports for bridged and custom networks. Host mode ports are allocated when the container starts.
255
- if (networkType == WSLCContainerNetworkTypeBridged || (networkType == WSLCContainerNetworkTypeCustom && !containerTarget))
271
+ if (allocateVmPorts)
272
{
257
- entry.VmMapping.AssignVmPort(virtualMachine.AllocatePort(e.Family, e.Protocol));
273
+ entry.VmMapping.AssignVmPort(vm.AllocatePort(e.Family, e.Protocol));
274
}
275
}
260
-
261
- return {std::move(ports), std::move(networkMode)};
276
+ return ports;
277
}
278
279
void UnmountVolumes(std::vector<WSLCVolumeMount>& volumes, WSLCVirtualMachine& parentVM)
@@ -319,46 +334,6 @@ WSLCContainerState DockerStateToWSLCState(ContainerState state)
334
}
335
}
336
322
-struct DockerNetworkMode
323
-{
324
- WSLCContainerNetworkType Type;
325
- std::optional<std::string> TargetId;
326
-};
327
-
328
-DockerNetworkMode ParseDockerNetworkMode(const std::string& mode)
329
-{
330
- if (mode == "bridge")
331
- {
332
- return {WSLCContainerNetworkTypeBridged, {}};
333
- }
334
- else if (mode == "host")
335
- {
336
- return {WSLCContainerNetworkTypeHost, {}};
337
- }
338
- else if (mode == "none")
339
- {
340
- return {WSLCContainerNetworkTypeNone, {}};
341
- }
342
-
343
- // Docker treats empty NetworkMode as the default (bridged).
344
- if (mode.empty())
345
- {
346
- return {WSLCContainerNetworkTypeBridged, {}};
347
- }
348
-
349
- if (auto target = ParseContainerTarget(mode))
350
- {
351
- THROW_HR_IF_MSG(E_INVALIDARG, target->empty(), "Invalid Docker network mode: missing container id/name in '%hs'", mode.c_str());
352
- return {WSLCContainerNetworkTypeCustom, std::move(*target)};
353
- }
354
-
355
- // Reject other Docker special syntaxes (service:<name>, etc.);
356
- // any plain name is treated as a user-defined custom network.
357
- THROW_HR_IF_MSG(E_INVALIDARG, mode.find(':') != std::string::npos, "Unsupported Docker network mode: %hs", mode.c_str());
358
-
359
- return {WSLCContainerNetworkTypeCustom, {}};
360
-}
361
-
337
std::uint64_t ParseDockerTimestamp(const std::string& timestamp)
338
{
339
// Docker timestamps are UTC ISO 8601, e.g. "2026-03-05T10:30:00.123456789Z".
@@ -437,75 +412,6 @@ void ProcessNamedVolumes(const WSLCContainerOptions& containerOptions, wsl::wind
412
}
413
}
414
440
-constexpr ULONG GetAdditionalStartIndex(WSLCContainerNetworkType type)
441
-{
442
- return (type == WSLCContainerNetworkTypeCustom) ? 1 : 0;
443
-}
444
-
445
-LPCSTR GetPrimaryNetworkName(const WSLCContainerNetwork& network)
446
-{
447
- const auto type = network.ContainerNetworkType;
448
- if (type != WSLCContainerNetworkTypeCustom || network.NetworksCount == 0)
449
- {
450
- return nullptr;
451
- }
452
- THROW_HR_IF_MSG(E_INVALIDARG, network.Networks == nullptr, "Networks pointer is null but NetworksCount=%lu", network.NetworksCount);
453
- return network.Networks[0].NetworkName;
454
-}
455
-
456
-void ProcessAdditionalNetworks(
457
- const WSLCContainerNetwork& network,
458
- const std::unordered_map<std::string, NetworkEntry>& sessionNetworks,
459
- const std::string& primaryNetworkMode,
460
- wsl::windows::common::docker_schema::CreateContainer& request)
461
-{
462
- // Validate pointer/count consistency and reject unsupported fields across all entries.
463
- if (network.NetworksCount > 0)
464
- {
465
- THROW_HR_IF_MSG(E_INVALIDARG, network.Networks == nullptr, "Networks pointer is null but NetworksCount=%lu", network.NetworksCount);
466
-
467
- for (ULONG i = 0; i < network.NetworksCount; i++)
468
- {
469
- THROW_HR_WITH_USER_ERROR_IF(
470
- E_NOTIMPL, Localization::MessageWslcContainerIpAddressNotSupported(), network.Networks[i].ContainerIpAddress != nullptr);
471
- }
472
- }
473
-
474
- const ULONG startIndex = GetAdditionalStartIndex(network.ContainerNetworkType);
475
- if (network.NetworksCount <= startIndex)
476
- {
477
- return;
478
- }
479
-
480
- THROW_HR_WITH_USER_ERROR_IF(
481
- E_INVALIDARG,
482
- Localization::MessageWslcContainerModeNoAdditionalNetworks(),
483
- ParseContainerTarget(GetPrimaryNetworkName(network)).has_value());
484
-
485
- THROW_HR_WITH_USER_ERROR_IF(
486
- E_INVALIDARG,
487
- Localization::MessageWslcAdditionalNetworksRequirePrimary(),
488
- primaryNetworkMode == "host" || primaryNetworkMode == "none");
489
-
490
- // Add the primary and all additional networks to EndpointsConfig so Docker attaches them all at create time.
491
- auto& endpointsConfig = request.NetworkingConfig.EndpointsConfig;
492
- endpointsConfig[primaryNetworkMode] = {};
493
-
494
- for (ULONG i = startIndex; i < network.NetworksCount; i++)
495
- {
496
- const char* rawName = network.Networks[i].NetworkName;
497
- THROW_HR_WITH_USER_ERROR_IF(E_INVALIDARG, Localization::MessageWslcNetworkNameRequired(), !rawName || strlen(rawName) == 0);
498
-
499
- const std::string networkName = rawName;
500
-
501
- auto [_, inserted] = endpointsConfig.insert({networkName, EmptyObject{}});
502
- THROW_HR_WITH_USER_ERROR_IF(E_INVALIDARG, Localization::MessageWslcDuplicateNetwork(networkName), !inserted);
503
-
504
- THROW_HR_WITH_USER_ERROR_IF(
505
- WSLC_E_NETWORK_NOT_FOUND, Localization::MessageWslcNetworkNotFound(networkName), !sessionNetworks.contains(networkName));
506
- }
507
-}
508
-
415
} // namespace
416
417
ContainerPortMapping::ContainerPortMapping(VMPortMapping&& VmMapping, uint16_t ContainerPort) :
@@ -572,7 +478,7 @@ WSLCContainerImpl::WSLCContainerImpl(
478
std::string&& Id,
479
std::string&& Name,
480
std::string&& Image,
575
- WSLCContainerNetworkType NetworkMode,
481
+ std::string NetworkMode,
482
std::vector<WSLCVolumeMount>&& volumes,
483
std::vector<ContainerPortMapping>&& ports,
484
std::map<std::string, std::string>&& labels,
@@ -589,7 +495,7 @@ WSLCContainerImpl::WSLCContainerImpl(
495
m_virtualMachine(virtualMachine),
496
m_name(std::move(Name)),
497
m_image(std::move(Image)),
592
- m_networkingMode(NetworkMode),
498
+ m_networkMode(std::move(NetworkMode)),
499
m_id(std::move(Id)),
500
m_mountedVolumes(std::move(volumes)),
501
m_mappedPorts(std::move(ports)),
@@ -1625,18 +1531,22 @@ std::unique_ptr<WSLCContainerImpl> WSLCContainerImpl::Create(
1531
}
1532
}
1533
1628
- // Process port mappings from container options.
1629
- auto [mappedPorts, networkMode] = ProcessPortMappings(
1630
- ports,
1631
- containerOptions.ContainerNetwork.ContainerNetworkType,
1632
- virtualMachine,
1633
- sessionNetworks,
1634
- GetPrimaryNetworkName(containerOptions.ContainerNetwork),
1635
- DockerClient);
1534
+ auto networkMode = ResolveNetworkMode(containerOptions.ContainerNetwork.NetworkMode, !ports.empty(), sessionNetworks, DockerClient);
1535
+
1536
+ auto endpoints = ResolveEndpoints(
1537
+ containerOptions.ContainerNetwork.Networks, containerOptions.ContainerNetwork.NetworksCount, networkMode, sessionNetworks);
1538
+
1539
+ auto mappedPorts = BuildPortMappings(ports, networkMode, virtualMachine);
1540
1541
request.HostConfig.NetworkMode = networkMode;
1542
+ request.NetworkingConfig.EndpointsConfig = std::move(endpoints);
1543
1639
- ProcessAdditionalNetworks(containerOptions.ContainerNetwork, sessionNetworks, networkMode, request);
1544
+ // Docker API v1.44 (Docker 25.x) requires the primary network to be present in EndpointsConfig
1545
+ // when EndpointsConfig is non-empty. Insert it so Docker attaches all networks at create time.
1546
+ if (!request.NetworkingConfig.EndpointsConfig.empty() && NetworkModeAllocatesVmPorts(networkMode))
1547
+ {
1548
+ request.NetworkingConfig.EndpointsConfig.try_emplace(networkMode);
1549
+ }
1550
1551
for (const auto& e : mappedPorts)
1552
{
@@ -1683,8 +1593,9 @@ std::unique_ptr<WSLCContainerImpl> WSLCContainerImpl::Create(
1593
1594
// Post-create verification: confirm every requested network is actually attached.
1595
// If Docker rejected any endpoint, throw here so deleteOnFailure cleans up the orphan container.
1686
- const ULONG verifyStartIndex = GetAdditionalStartIndex(containerOptions.ContainerNetwork.ContainerNetworkType);
1687
- if (containerOptions.ContainerNetwork.NetworksCount > verifyStartIndex)
1596
+ // container:<id> mode shares the target's netns, so the mode string is not a network name and
1597
+ // won't appear in NetworkSettings.Networks. Skip the check for that mode.
1598
+ if (!networkMode.starts_with(c_containerNetworkPrefix))
1599
{
1600
THROW_HR_IF_MSG(
1601
E_UNEXPECTED,
@@ -1693,15 +1604,20 @@ std::unique_ptr<WSLCContainerImpl> WSLCContainerImpl::Create(
1604
networkMode.c_str());
1605
}
1606
1696
- for (ULONG i = verifyStartIndex; i < containerOptions.ContainerNetwork.NetworksCount; i++)
1607
+ for (const auto& [name, _] : request.NetworkingConfig.EndpointsConfig)
1608
{
1698
- const char* rawName = containerOptions.ContainerNetwork.Networks[i].NetworkName;
1699
- const std::string networkName = rawName != nullptr ? rawName : "";
1609
+ // The primary network was auto-inserted into EndpointsConfig for Docker v1.44 compat
1610
+ // and is already verified above. Only check explicitly-requested additional networks here.
1611
+ if (name == networkMode)
1612
+ {
1613
+ continue;
1614
+ }
1615
+
1616
THROW_HR_IF_MSG(
1617
E_UNEXPECTED,
1702
- !inspectData.NetworkSettings.Networks.contains(networkName),
1703
- "Container was created but network '%hs' was not attached",
1704
- networkName.c_str());
1618
+ !inspectData.NetworkSettings.Networks.contains(name),
1619
+ "Container was created but requested network '%hs' was not attached",
1620
+ name.c_str());
1621
}
1622
1623
// Wait for the container create event to be delivered on the Docker event stream so that
@@ -1716,7 +1632,7 @@ std::unique_ptr<WSLCContainerImpl> WSLCContainerImpl::Create(
1632
std::move(result.Id),
1633
CleanContainerName(inspectData.Name),
1634
std::string(containerOptions.Image),
1719
- containerOptions.ContainerNetwork.ContainerNetworkType,
1635
+ std::move(networkMode),
1636
std::move(volumes),
1637
std::move(mappedPorts),
1638
std::move(labels),
@@ -1777,15 +1693,20 @@ std::unique_ptr<WSLCContainerImpl> WSLCContainerImpl::Open(
1693
auto metadata = ParseContainerMetadata(metadataIt->second.c_str());
1694
labels.erase(metadataIt);
1695
1780
- auto networkMode = ParseDockerNetworkMode(dockerContainer.HostConfig.NetworkMode);
1696
+ // Docker treats empty NetworkMode as the default (bridge).
1697
+ std::string networkMode = dockerContainer.HostConfig.NetworkMode.empty() ? std::string{"bridge"} : dockerContainer.HostConfig.NetworkMode;
1698
+
1699
+ RejectUnsupportedNetworkModes(networkMode);
1700
+
1701
+ const bool allocateVmPorts = NetworkModeAllocatesVmPorts(networkMode);
1702
+
1703
// Re-register recovered VM ports in the allocation pool to prevent conflicts.
1704
std::vector<ContainerPortMapping> ports;
1705
for (const auto& e : metadata.Ports)
1706
{
1707
auto& inserted = ports.emplace_back(ContainerPortMapping{VMPortMapping::FromContainerMetaData(e), e.ContainerPort});
1708
1787
- if (networkMode.Type == WSLCContainerNetworkTypeBridged ||
1788
- (networkMode.Type == WSLCContainerNetworkTypeCustom && !networkMode.TargetId.has_value()))
1709
+ if (allocateVmPorts)
1710
{
1711
auto allocation = virtualMachine.TryAllocatePort(e.VmPort, e.Family, e.Protocol);
1712
@@ -1807,7 +1728,7 @@ std::unique_ptr<WSLCContainerImpl> WSLCContainerImpl::Open(
1728
std::string(dockerContainer.Id),
1729
std::move(name),
1730
std::string(dockerContainer.Image),
1810
- networkMode.Type,
1731
+ std::move(networkMode),
1732
std::move(metadata.Volumes),
1733
std::move(ports),
1734
std::move(labels),
@@ -2022,7 +1943,7 @@ void WSLCContainerImpl::UnmapPorts()
1943
1944
try
1945
{
2025
- if (m_networkingMode == WSLCContainerNetworkTypeHost)
1946
+ if (m_networkMode == "host")
1947
{
1948
e.VmMapping.VmPort.reset();
1949
}
src/windows/wslcsession/WSLCContainer.h
+2
-2
@@ -76,7 +76,7 @@ public:
76
std::string&& Id,
77
std::string&& Name,
78
std::string&& Image,
79
- WSLCContainerNetworkType NetworkMode,
79
+ std::string NetworkMode,
80
std::vector<WSLCVolumeMount>&& volumes,
81
std::vector<ContainerPortMapping>&& ports,
82
std::map<std::string, std::string>&& labels,
@@ -211,7 +211,7 @@ private:
211
DockerEventTracker& m_eventTracker;
212
DockerEventTracker::EventTrackingReference m_containerEvents;
213
IORelay& m_ioRelay;
214
- WSLCContainerNetworkType m_networkingMode{};
214
+ std::string m_networkMode;
215
};
216
217
class DECLSPEC_UUID("B1F1C4E3-C225-4CAE-AD8A-34C004DE1AE4") WSLCContainer
test/windows/WSLCTests.cpp
+107
-230
@@ -1310,8 +1310,7 @@ class WSLCTests
1310
ExpectImagePresent(*m_defaultSession, "alpine:latest");
1311
1312
// Launch a container to ensure that image deletion fails when in use.
1313
- WSLCContainerLauncher launcher(
1314
- "alpine:latest", "test-delete-container-in-use", {"sleep", "99999"}, {}, WSLCContainerNetworkType::WSLCContainerNetworkTypeHost);
1313
+ WSLCContainerLauncher launcher("alpine:latest", "test-delete-container-in-use", {"sleep", "99999"}, {}, "host");
1314
1315
auto container = launcher.Launch(*m_defaultSession);
1316
@@ -4979,8 +4978,7 @@ class WSLCTests
4978
4979
// Validate that stdin is correctly wired
4980
{
4982
- WSLCContainerLauncher launcher(
4983
- "debian:latest", "test-default-entrypoint", {"/bin/cat"}, {}, WSLCContainerNetworkType::WSLCContainerNetworkTypeHost, WSLCProcessFlagsStdin);
4981
+ WSLCContainerLauncher launcher("debian:latest", "test-default-entrypoint", {"/bin/cat"}, {}, "host", WSLCProcessFlagsStdin);
4982
4983
auto container = launcher.Launch(*m_defaultSession);
4984
@@ -5647,8 +5645,7 @@ class WSLCTests
5645
5646
// Validate that container names are unique.
5647
{
5650
- WSLCContainerLauncher launcher(
5651
- "debian:latest", "test-unique-name", {"sleep", "99999"}, {}, WSLCContainerNetworkType::WSLCContainerNetworkTypeHost);
5648
+ WSLCContainerLauncher launcher("debian:latest", "test-unique-name", {"sleep", "99999"}, {}, "host");
5649
5650
auto container = launcher.Launch(*m_defaultSession);
5651
VERIFY_ARE_EQUAL(container.State(), WslcContainerStateRunning);
@@ -5695,8 +5692,7 @@ class WSLCTests
5692
expectContainerList({});
5693
5694
// Verify that the same name can be reused now that the container is deleted.
5698
- WSLCContainerLauncher otherLauncher(
5699
- "debian:latest", "test-unique-name", {"echo", "OK"}, {}, WSLCContainerNetworkType::WSLCContainerNetworkTypeHost);
5695
+ WSLCContainerLauncher otherLauncher("debian:latest", "test-unique-name", {"echo", "OK"}, {}, "host");
5696
5697
auto result = otherLauncher.Launch(*m_defaultSession).GetInitProcess().WaitAndCaptureOutput();
5698
VERIFY_ARE_EQUAL(result.Output[1], "OK\n");
@@ -5919,8 +5915,7 @@ class WSLCTests
5915
// TODO: Test bridge network container launch when VHD with bridge cni is ready
5916
// TODO: Add port mapping related tests when port mapping is implemented
5917
{
5922
- WSLCContainerLauncher launcher(
5923
- "debian:latest", "test-network", {"sleep", "99999"}, {}, WSLCContainerNetworkType::WSLCContainerNetworkTypeHost);
5918
+ WSLCContainerLauncher launcher("debian:latest", "test-network", {"sleep", "99999"}, {}, "host");
5919
5920
auto container = launcher.Launch(*m_defaultSession);
5921
VERIFY_ARE_EQUAL(container.State(), WslcContainerStateRunning);
@@ -5942,8 +5937,7 @@ class WSLCTests
5937
}
5938
5939
{
5945
- WSLCContainerLauncher launcher(
5946
- "debian:latest", "test-network", {"sleep", "99999"}, {}, WSLCContainerNetworkType::WSLCContainerNetworkTypeNone);
5940
+ WSLCContainerLauncher launcher("debian:latest", "test-network", {"sleep", "99999"}, {}, "none");
5941
5942
auto container = launcher.Launch(*m_defaultSession);
5943
VERIFY_ARE_EQUAL(container.State(), WslcContainerStateRunning);
@@ -5964,21 +5958,15 @@ class WSLCTests
5958
}
5959
5960
{
5967
- WSLCContainerLauncher launcher(
5968
- "debian:latest",
5969
- "test-network",
5970
- {"sleep", "99999"},
5971
- {},
5972
- (WSLCContainerNetworkType)6 // WSLCContainerNetworkType::WSLCContainerNetworkTypeNone
5973
- );
5961
+ // Unknown network names are rejected as "network not found".
5962
+ WSLCContainerLauncher launcher("debian:latest", "test-network", {"sleep", "99999"}, {}, "no-such-network");
5963
5964
auto retVal = launcher.LaunchNoThrow(*m_defaultSession);
5976
- VERIFY_ARE_EQUAL(retVal.first, E_INVALIDARG);
5965
+ VERIFY_ARE_EQUAL(retVal.first, WSLC_E_NETWORK_NOT_FOUND);
5966
}
5967
5968
{
5980
- WSLCContainerLauncher launcher(
5981
- "debian:latest", "test-network", {"sleep", "99999"}, {}, WSLCContainerNetworkType::WSLCContainerNetworkTypeBridged);
5969
+ WSLCContainerLauncher launcher("debian:latest", "test-network", {"sleep", "99999"}, {}, "bridge");
5970
5971
auto container = launcher.Launch(*m_defaultSession);
5972
VERIFY_ARE_EQUAL(container.State(), WslcContainerStateRunning);
@@ -6016,9 +6004,7 @@ class WSLCTests
6004
6005
auto networkCleanup = wil::scope_exit([&]() { LOG_IF_FAILED(m_defaultSession->DeleteNetwork(networkName.c_str())); });
6006
6019
- WSLCContainerLauncher launcher(
6020
- "debian:latest", "test-custom-network", {"sleep", "99999"}, {}, WSLCContainerNetworkType::WSLCContainerNetworkTypeCustom);
6021
- launcher.SetContainerNetworkName(std::string(networkName));
6007
+ WSLCContainerLauncher launcher("debian:latest", "test-custom-network", {"sleep", "99999"}, {}, std::string(networkName));
6008
6009
auto container = launcher.Launch(*m_defaultSession);
6010
VERIFY_ARE_EQUAL(container.State(), WslcContainerStateRunning);
@@ -6027,43 +6013,78 @@ class WSLCTests
6013
6014
WSLC_TEST_METHOD(ContainerCustomNetworkNotFoundTest)
6015
{
6030
- WSLCContainerLauncher launcher(
6031
- "debian:latest", "test-custom-network-notfound", {"sleep", "99999"}, {}, WSLCContainerNetworkType::WSLCContainerNetworkTypeCustom);
6032
- launcher.SetContainerNetworkName(std::string("nonexistent-net"));
6016
+ WSLCContainerLauncher launcher("debian:latest", "test-custom-network-notfound", {"sleep", "99999"}, {}, std::string("nonexistent-net"));
6017
6018
auto retVal = launcher.LaunchNoThrow(*m_defaultSession);
6019
VERIFY_ARE_EQUAL(WSLC_E_NETWORK_NOT_FOUND, retVal.first);
6020
ValidateCOMErrorMessageContains(L"nonexistent-net");
6021
}
6022
6039
- WSLC_TEST_METHOD(ContainerCustomNetworkMissingNameTest)
6023
+ WSLC_TEST_METHOD(ContainerCustomNetworkEmptyNameTest)
6024
{
6041
- WSLCContainerLauncher launcher(
6042
- "debian:latest", "test-custom-network-noname", {"sleep", "99999"}, {}, WSLCContainerNetworkType::WSLCContainerNetworkTypeCustom);
6025
+ // Empty entry in the Networks array must be rejected.
6026
+ LPCSTR args[] = {"sleep", "99999"};
6027
+ WSLCNetworkConnection emptyConnection{};
6028
+ emptyConnection.NetworkName = ""; // empty name — should be rejected
6029
6044
- auto retVal = launcher.LaunchNoThrow(*m_defaultSession);
6045
- VERIFY_ARE_EQUAL(E_INVALIDARG, retVal.first);
6046
- ValidateCOMErrorMessageContains(L"Container network name is required");
6030
+ WSLCContainerOptions options{};
6031
+ options.Image = "debian:latest";
6032
+ options.Name = "test-custom-network-empty";
6033
+ options.InitProcessOptions.CommandLine = {.Values = args, .Count = ARRAYSIZE(args)};
6034
+ options.ContainerNetwork.Networks = &emptyConnection;
6035
+ options.ContainerNetwork.NetworksCount = 1;
6036
+
6037
+ wil::com_ptr<IWSLCContainer> container;
6038
+ auto hr = m_defaultSession->CreateContainer(&options, &container);
6039
+ VERIFY_ARE_EQUAL(E_INVALIDARG, hr);
6040
+ ValidateCOMErrorMessageContains(L"Network name");
6041
}
6042
6049
- WSLC_TEST_METHOD(ContainerCustomNetworkEmptyNameTest)
6043
+ WSLC_TEST_METHOD(ContainerNetworkEndpointSettingsNotImplementedTest)
6044
{
6045
+ // Per-endpoint Settings (Aliases, IPAMConfig, etc.) are reserved for a future PR.
6046
+ // Until that lands, any non-empty Settings payload must be rejected with E_NOTIMPL
6047
+ // so callers don't silently lose data.
6048
+ const std::string networkName = "custom-net-settings";
6049
+ LOG_IF_FAILED(m_defaultSession->DeleteNetwork(networkName.c_str()));
6050
+
6051
+ WSLCNetworkOptions networkOptions{};
6052
+ networkOptions.Name = networkName.c_str();
6053
+ networkOptions.Driver = "bridge";
6054
+ VERIFY_SUCCEEDED(m_defaultSession->CreateNetwork(&networkOptions));
6055
+ auto networkCleanup = wil::scope_exit([&]() { LOG_IF_FAILED(m_defaultSession->DeleteNetwork(networkName.c_str())); });
6056
+
6057
LPCSTR args[] = {"sleep", "99999"};
6058
+ KeyValuePair settings[] = {{"Aliases", "my-alias"}};
6059
+ WSLCNetworkConnection connection{};
6060
+ connection.NetworkName = networkName.c_str();
6061
+ connection.Settings = settings;
6062
+ connection.SettingsCount = ARRAYSIZE(settings);
6063
6064
WSLCContainerOptions options{};
6065
options.Image = "debian:latest";
6055
- options.Name = "test-custom-network-empty";
6066
+ options.Name = "test-endpoint-settings";
6067
options.InitProcessOptions.CommandLine = {.Values = args, .Count = ARRAYSIZE(args)};
6057
- options.ContainerNetwork.ContainerNetworkType = WSLCContainerNetworkTypeCustom;
6058
- WSLCNetworkAttachment emptyNet{};
6059
- emptyNet.NetworkName = "";
6060
- options.ContainerNetwork.Networks = &emptyNet;
6068
+ options.ContainerNetwork.NetworkMode = "bridge";
6069
+ options.ContainerNetwork.Networks = &connection;
6070
options.ContainerNetwork.NetworksCount = 1;
6071
6072
wil::com_ptr<IWSLCContainer> container;
6073
auto hr = m_defaultSession->CreateContainer(&options, &container);
6065
- VERIFY_ARE_EQUAL(E_INVALIDARG, hr);
6066
- ValidateCOMErrorMessage(L"Container network name is required for custom network type.");
6074
+ VERIFY_ARE_EQUAL(E_NOTIMPL, hr);
6075
+ ValidateCOMErrorMessage(L"Endpoint settings are not yet supported (network 'custom-net-settings').");
6076
+ }
6077
+
6078
+ WSLC_TEST_METHOD(ContainerUnsupportedColonNetworkModeRejectedTest)
6079
+ {
6080
+ // Only `container:` is a recognized colon-prefixed mode. Anything else
6081
+ // (`service:foo`, `ns:bar`, ...) must be rejected at the WSLC layer rather
6082
+ // than being passed through to Docker or interpreted as a user-defined name.
6083
+ WSLCContainerLauncher launcher("debian:latest", "test-unsupported-colon", {"sleep", "99999"}, {}, std::string("service:foo"));
6084
+
6085
+ auto retVal = launcher.LaunchNoThrow(*m_defaultSession);
6086
+ VERIFY_ARE_EQUAL(E_INVALIDARG, retVal.first);
6087
+ ValidateCOMErrorMessageContains(L"service:foo");
6088
}
6089
6090
WSLC_TEST_METHOD(ContainerCustomNetworkMultipleContainersTest)
@@ -6084,13 +6105,9 @@ class WSLCTests
6105
6106
auto networkCleanup = wil::scope_exit([&]() { LOG_IF_FAILED(m_defaultSession->DeleteNetwork(networkName.c_str())); });
6107
6087
- WSLCContainerLauncher launcher1(
6088
- "debian:latest", "test-custom-multi-1", {"sleep", "99999"}, {}, WSLCContainerNetworkType::WSLCContainerNetworkTypeCustom);
6089
- launcher1.SetContainerNetworkName(std::string(networkName));
6108
+ WSLCContainerLauncher launcher1("debian:latest", "test-custom-multi-1", {"sleep", "99999"}, {}, std::string(networkName));
6109
6091
- WSLCContainerLauncher launcher2(
6092
- "debian:latest", "test-custom-multi-2", {"sleep", "99999"}, {}, WSLCContainerNetworkType::WSLCContainerNetworkTypeCustom);
6093
- launcher2.SetContainerNetworkName(std::string(networkName));
6110
+ WSLCContainerLauncher launcher2("debian:latest", "test-custom-multi-2", {"sleep", "99999"}, {}, std::string(networkName));
6111
6112
auto container1 = launcher1.Launch(*m_defaultSession);
6113
VERIFY_ARE_EQUAL(container1.State(), WslcContainerStateRunning);
@@ -6119,9 +6136,7 @@ class WSLCTests
6136
6137
auto networkCleanup = wil::scope_exit([&]() { LOG_IF_FAILED(m_defaultSession->DeleteNetwork(networkName.c_str())); });
6138
6122
- WSLCContainerLauncher launcher(
6123
- "debian:latest", "test-custom-net-inuse", {"sleep", "99999"}, {}, WSLCContainerNetworkType::WSLCContainerNetworkTypeCustom);
6124
- launcher.SetContainerNetworkName(std::string(networkName));
6139
+ WSLCContainerLauncher launcher("debian:latest", "test-custom-net-inuse", {"sleep", "99999"}, {}, std::string(networkName));
6140
6141
auto container = launcher.Launch(*m_defaultSession);
6142
VERIFY_ARE_EQUAL(container.State(), WslcContainerStateRunning);
@@ -6148,8 +6163,7 @@ class WSLCTests
6163
auto networkCleanup = wil::scope_exit([&]() { LOG_IF_FAILED(m_defaultSession->DeleteNetwork(networkName.c_str())); });
6164
6165
WSLCContainerLauncher launcher(
6151
- "python:3.12-alpine", "test-custom-net-ports", {"python3", "-m", "http.server"}, {"PYTHONUNBUFFERED=1"}, WSLCContainerNetworkType::WSLCContainerNetworkTypeCustom);
6152
- launcher.SetContainerNetworkName(std::string(networkName));
6166
+ "python:3.12-alpine", "test-custom-net-ports", {"python3", "-m", "http.server"}, {"PYTHONUNBUFFERED=1"}, std::string(networkName));
6167
launcher.AddPort(1251, 8000, AF_INET);
6168
6169
auto container = launcher.Launch(*m_defaultSession);
@@ -6178,8 +6192,7 @@ class WSLCTests
6192
6193
auto networkCleanup = wil::scope_exit([&]() { LOG_IF_FAILED(m_defaultSession->DeleteNetwork(networkName.c_str())); });
6194
6181
- WSLCContainerLauncher launcher("debian:latest", containerName, {"sleep", "99999"}, {}, WSLCContainerNetworkType::WSLCContainerNetworkTypeCustom);
6182
- launcher.SetContainerNetworkName(std::string(networkName));
6195
+ WSLCContainerLauncher launcher("debian:latest", containerName, {"sleep", "99999"}, {}, std::string(networkName));
6196
6197
{
6198
auto container = launcher.Create(*m_defaultSession);
@@ -6227,9 +6240,7 @@ class WSLCTests
6240
auto additionalCleanup =
6241
wil::scope_exit([&]() { LOG_IF_FAILED(m_defaultSession->DeleteNetwork(additionalNetwork.c_str())); });
6242
6230
- WSLCContainerLauncher launcher(
6231
- "debian:latest", "test-multi-net", {"sleep", "99999"}, {}, WSLCContainerNetworkType::WSLCContainerNetworkTypeCustom);
6232
- launcher.SetContainerNetworkName(std::string(primaryNetwork));
6243
+ WSLCContainerLauncher launcher("debian:latest", "test-multi-net", {"sleep", "99999"}, {}, std::string(primaryNetwork));
6244
launcher.AddAdditionalNetwork(additionalNetwork);
6245
6246
auto container = launcher.Launch(*m_defaultSession);
@@ -6243,32 +6254,6 @@ class WSLCTests
6254
VERIFY_IS_FALSE(inspect.NetworkSettings.Networks.at(additionalNetwork).IPAddress.empty());
6255
}
6256
6246
- WSLC_TEST_METHOD(ContainerAdditionalNetworksRejectedForHostAndNoneTest)
6247
- {
6248
- // This check runs before network existence is validated, so no real network needs to exist.
6249
- const std::string additionalNetwork = "any-additional-net";
6250
-
6251
- {
6252
- WSLCContainerLauncher launcher(
6253
- "debian:latest", "test-multi-net-host-reject", {"sleep", "99999"}, {}, WSLCContainerNetworkType::WSLCContainerNetworkTypeHost);
6254
- launcher.AddAdditionalNetwork(additionalNetwork);
6255
-
6256
- auto retVal = launcher.LaunchNoThrow(*m_defaultSession);
6257
- VERIFY_ARE_EQUAL(E_INVALIDARG, retVal.first);
6258
- ValidateCOMErrorMessage(L"Additional networks are not allowed when the primary network mode is 'host' or 'none'.");
6259
- }
6260
-
6261
- {
6262
- WSLCContainerLauncher launcher(
6263
- "debian:latest", "test-multi-net-none-reject", {"sleep", "99999"}, {}, WSLCContainerNetworkType::WSLCContainerNetworkTypeNone);
6264
- launcher.AddAdditionalNetwork(additionalNetwork);
6265
-
6266
- auto retVal = launcher.LaunchNoThrow(*m_defaultSession);
6267
- VERIFY_ARE_EQUAL(E_INVALIDARG, retVal.first);
6268
- ValidateCOMErrorMessage(L"Additional networks are not allowed when the primary network mode is 'host' or 'none'.");
6269
- }
6270
- }
6271
-
6257
WSLC_TEST_METHOD(ContainerDuplicateNetworkRejectedTest)
6258
{
6259
const std::string primaryNetwork = "multi-net-dup-primary";
@@ -6284,9 +6269,7 @@ class WSLCTests
6269
VERIFY_SUCCEEDED(m_defaultSession->CreateNetwork(&netOpts));
6270
auto cleanup = wil::scope_exit([&]() { LOG_IF_FAILED(m_defaultSession->DeleteNetwork(primaryNetwork.c_str())); });
6271
6287
- WSLCContainerLauncher launcher(
6288
- "debian:latest", "test-multi-net-dup-reject", {"sleep", "99999"}, {}, WSLCContainerNetworkType::WSLCContainerNetworkTypeCustom);
6289
- launcher.SetContainerNetworkName(std::string(primaryNetwork));
6272
+ WSLCContainerLauncher launcher("debian:latest", "test-multi-net-dup-reject", {"sleep", "99999"}, {}, std::string(primaryNetwork));
6273
launcher.AddAdditionalNetwork(primaryNetwork);
6274
6275
auto retVal = launcher.LaunchNoThrow(*m_defaultSession);
@@ -6312,9 +6295,7 @@ class WSLCTests
6295
VERIFY_SUCCEEDED(m_defaultSession->CreateNetwork(&netOpts));
6296
auto cleanup = wil::scope_exit([&]() { LOG_IF_FAILED(m_defaultSession->DeleteNetwork(primaryNetwork.c_str())); });
6297
6315
- WSLCContainerLauncher launcher(
6316
- "debian:latest", "test-multi-net-notfound-reject", {"sleep", "99999"}, {}, WSLCContainerNetworkType::WSLCContainerNetworkTypeCustom);
6317
- launcher.SetContainerNetworkName(std::string(primaryNetwork));
6298
+ WSLCContainerLauncher launcher("debian:latest", "test-multi-net-notfound-reject", {"sleep", "99999"}, {}, std::string(primaryNetwork));
6299
launcher.AddAdditionalNetwork(missingNetwork);
6300
6301
auto retVal = launcher.LaunchNoThrow(*m_defaultSession);
@@ -6326,8 +6307,7 @@ class WSLCTests
6307
WSLC_TEST_METHOD(ContainerBridgedPrimaryDuplicateNetworkRejectedTest)
6308
{
6309
// Verifies that passing the primary bridge network as an additional network is caught as a duplicate.
6329
- WSLCContainerLauncher launcher(
6330
- "debian:latest", "test-bridge-dup-reject", {"sleep", "99999"}, {}, WSLCContainerNetworkType::WSLCContainerNetworkTypeBridged);
6310
+ WSLCContainerLauncher launcher("debian:latest", "test-bridge-dup-reject", {"sleep", "99999"}, {}, "bridge");
6311
launcher.AddAdditionalNetwork("bridge");
6312
6313
auto retVal = launcher.LaunchNoThrow(*m_defaultSession);
@@ -6341,8 +6321,7 @@ class WSLCTests
6321
6322
// Invalid character.
6323
{
6344
- WSLCContainerLauncher launcher(
6345
- "debian:latest", "test-invalid-name-char", {"sleep", "99999"}, {}, WSLCContainerNetworkType::WSLCContainerNetworkTypeBridged);
6324
+ WSLCContainerLauncher launcher("debian:latest", "test-invalid-name-char", {"sleep", "99999"}, {}, "bridge");
6325
launcher.AddAdditionalNetwork("bad/name");
6326
6327
auto retVal = launcher.LaunchNoThrow(*m_defaultSession);
@@ -6352,8 +6331,7 @@ class WSLCTests
6331
6332
// Empty name.
6333
{
6355
- WSLCContainerLauncher launcher(
6356
- "debian:latest", "test-invalid-name-empty", {"sleep", "99999"}, {}, WSLCContainerNetworkType::WSLCContainerNetworkTypeBridged);
6334
+ WSLCContainerLauncher launcher("debian:latest", "test-invalid-name-empty", {"sleep", "99999"}, {}, "bridge");
6335
launcher.AddAdditionalNetwork("");
6336
6337
auto retVal = launcher.LaunchNoThrow(*m_defaultSession);
@@ -6365,8 +6343,7 @@ class WSLCTests
6343
{
6344
const std::string tooLongName(WSLC_MAX_NETWORK_NAME_LENGTH + 1, 'a');
6345
6368
- WSLCContainerLauncher launcher(
6369
- "debian:latest", "test-invalid-name-long", {"sleep", "99999"}, {}, WSLCContainerNetworkType::WSLCContainerNetworkTypeBridged);
6346
+ WSLCContainerLauncher launcher("debian:latest", "test-invalid-name-long", {"sleep", "99999"}, {}, "bridge");
6347
launcher.AddAdditionalNetwork(tooLongName);
6348
6349
auto retVal = launcher.LaunchNoThrow(*m_defaultSession);
@@ -6402,9 +6379,7 @@ class WSLCTests
6379
auto additionalCleanup =
6380
wil::scope_exit([&]() { LOG_IF_FAILED(m_defaultSession->DeleteNetwork(additionalNetwork.c_str())); });
6381
6405
- WSLCContainerLauncher launcher(
6406
- "debian:latest", "test-multi-net-del", {"sleep", "99999"}, {}, WSLCContainerNetworkType::WSLCContainerNetworkTypeCustom);
6407
- launcher.SetContainerNetworkName(std::string(primaryNetwork));
6382
+ WSLCContainerLauncher launcher("debian:latest", "test-multi-net-del", {"sleep", "99999"}, {}, std::string(primaryNetwork));
6383
launcher.AddAdditionalNetwork(additionalNetwork);
6384
6385
auto container = launcher.Launch(*m_defaultSession);
@@ -6413,41 +6388,6 @@ class WSLCTests
6388
VERIFY_ARE_EQUAL(HRESULT_FROM_WIN32(ERROR_SHARING_VIOLATION), m_defaultSession->DeleteNetwork(additionalNetwork.c_str()));
6389
}
6390
6416
- WSLC_TEST_METHOD(ContainerNetworkAttachmentIpAddressRejectedTest)
6417
- {
6418
- // ContainerIpAddress is reserved and must be null today.
6419
- LPCSTR args[] = {"sleep", "99999"};
6420
-
6421
- WSLCContainerOptions options{};
6422
- options.Image = "debian:latest";
6423
- options.Name = "test-network-ip-reserved";
6424
- options.InitProcessOptions.CommandLine = {.Values = args, .Count = ARRAYSIZE(args)};
6425
- options.ContainerNetwork.ContainerNetworkType = WSLCContainerNetworkTypeBridged;
6426
- WSLCNetworkAttachment netWithIp{};
6427
- netWithIp.NetworkName = "bridge";
6428
- netWithIp.ContainerIpAddress = "10.0.0.5";
6429
- options.ContainerNetwork.Networks = &netWithIp;
6430
- options.ContainerNetwork.NetworksCount = 1;
6431
-
6432
- wil::com_ptr<IWSLCContainer> container;
6433
- auto hr = m_defaultSession->CreateContainer(&options, &container);
6434
- VERIFY_ARE_EQUAL(E_NOTIMPL, hr);
6435
- ValidateCOMErrorMessage(L"ContainerIpAddress is not yet supported.");
6436
- }
6437
-
6438
- WSLC_TEST_METHOD(ContainerCustomNetworkMissingPrimaryWithAdditionalRejectedTest)
6439
- {
6440
- // Custom + additional networks without a primary network name must be rejected,
6441
- // not silently promote the first additional to primary.
6442
- WSLCContainerLauncher launcher(
6443
- "debian:latest", "test-custom-no-primary", {"sleep", "99999"}, {}, WSLCContainerNetworkType::WSLCContainerNetworkTypeCustom);
6444
- launcher.AddAdditionalNetwork("any-net");
6445
-
6446
- auto retVal = launcher.LaunchNoThrow(*m_defaultSession);
6447
- VERIFY_ARE_EQUAL(E_INVALIDARG, retVal.first);
6448
- ValidateCOMErrorMessage(L"Container network name is required for custom network type.");
6449
- }
6450
-
6391
WSLC_TEST_METHOD(ContainerNetworkModeHappyPathTest)
6392
{
6393
// Start container A on the default (bridged) network, then start container B sharing A's
@@ -6461,8 +6401,7 @@ class WSLCTests
6401
6402
const std::string containerAId = containerA.Id();
6403
6464
- WSLCContainerLauncher launcherB("debian:latest", containerBName, {"sleep", "99999"}, {}, WSLCContainerNetworkType::WSLCContainerNetworkTypeCustom);
6465
- launcherB.SetContainerNetworkName("container:" + containerAName);
6404
+ WSLCContainerLauncher launcherB("debian:latest", containerBName, {"sleep", "99999"}, {}, "container:" + containerAName);
6405
6406
auto containerB = launcherB.Launch(*m_defaultSession);
6407
VERIFY_ARE_EQUAL(containerB.State(), WslcContainerStateRunning);
@@ -6475,21 +6414,10 @@ class WSLCTests
6414
WSLC_TEST_METHOD(ContainerNetworkModeMissingTargetRejectedTest)
6415
{
6416
// Container mode with an empty target name must be rejected before any Docker call.
6478
- LPCSTR args[] = {"sleep", "99999"};
6479
-
6480
- WSLCContainerOptions options{};
6481
- options.Image = "debian:latest";
6482
- options.Name = "test-container-mode-no-target";
6483
- options.InitProcessOptions.CommandLine = {.Values = args, .Count = ARRAYSIZE(args)};
6484
- options.ContainerNetwork.ContainerNetworkType = WSLCContainerNetworkTypeCustom;
6485
- WSLCNetworkAttachment emptyTarget{};
6486
- emptyTarget.NetworkName = "container:";
6487
- options.ContainerNetwork.Networks = &emptyTarget;
6488
- options.ContainerNetwork.NetworksCount = 1;
6417
+ WSLCContainerLauncher launcher("debian:latest", "test-container-mode-no-target", {"sleep", "99999"}, {}, "container:");
6418
6490
- wil::com_ptr<IWSLCContainer> container;
6491
- auto hr = m_defaultSession->CreateContainer(&options, &container);
6492
- VERIFY_ARE_EQUAL(E_INVALIDARG, hr);
6419
+ auto retVal = launcher.LaunchNoThrow(*m_defaultSession);
6420
+ VERIFY_ARE_EQUAL(E_INVALIDARG, retVal.first);
6421
ValidateCOMErrorMessage(L"Target container name is required for container network mode.");
6422
}
6423
@@ -6499,9 +6427,7 @@ class WSLCTests
6427
// with a localized message naming the target.
6428
const std::string targetName = "does-not-exist-container-target";
6429
6502
- WSLCContainerLauncher launcher(
6503
- "debian:latest", "test-container-mode-notfound", {"sleep", "99999"}, {}, WSLCContainerNetworkType::WSLCContainerNetworkTypeCustom);
6504
- launcher.SetContainerNetworkName("container:" + targetName);
6430
+ WSLCContainerLauncher launcher("debian:latest", "test-container-mode-notfound", {"sleep", "99999"}, {}, "container:" + targetName);
6431
6432
auto retVal = launcher.LaunchNoThrow(*m_defaultSession);
6433
VERIFY_ARE_EQUAL(WSLC_E_CONTAINER_NOT_FOUND, retVal.first);
@@ -6517,9 +6443,7 @@ class WSLCTests
6443
auto containerA = launcherA.Launch(*m_defaultSession);
6444
VERIFY_ARE_EQUAL(containerA.State(), WslcContainerStateRunning);
6445
6520
- WSLCContainerLauncher launcherB(
6521
- "debian:latest", "test-container-mode-ports-b", {"sleep", "99999"}, {}, WSLCContainerNetworkType::WSLCContainerNetworkTypeCustom);
6522
- launcherB.SetContainerNetworkName("container:" + containerAName);
6446
+ WSLCContainerLauncher launcherB("debian:latest", "test-container-mode-ports-b", {"sleep", "99999"}, {}, "container:" + containerAName);
6447
launcherB.AddPort(8080, 80, AF_INET);
6448
6449
auto retVal = launcherB.LaunchNoThrow(*m_defaultSession);
@@ -6528,25 +6452,6 @@ class WSLCTests
6452
L"Port mappings are not supported with container network mode; ports are owned by the target container.");
6453
}
6454
6531
- WSLC_TEST_METHOD(ContainerNetworkModeAdditionalNetworkRejectedTest)
6532
- {
6533
- // Container mode does not support additional networks — the target owns the netns.
6534
- const std::string containerAName = "test-container-mode-addnet-a";
6535
-
6536
- WSLCContainerLauncher launcherA("debian:latest", containerAName, {"sleep", "99999"}, {});
6537
- auto containerA = launcherA.Launch(*m_defaultSession);
6538
- VERIFY_ARE_EQUAL(containerA.State(), WslcContainerStateRunning);
6539
-
6540
- WSLCContainerLauncher launcherB(
6541
- "debian:latest", "test-container-mode-addnet-b", {"sleep", "99999"}, {}, WSLCContainerNetworkType::WSLCContainerNetworkTypeCustom);
6542
- launcherB.SetContainerNetworkName("container:" + containerAName);
6543
- launcherB.AddAdditionalNetwork("bridge");
6544
-
6545
- auto retVal = launcherB.LaunchNoThrow(*m_defaultSession);
6546
- VERIFY_ARE_EQUAL(E_INVALIDARG, retVal.first);
6547
- ValidateCOMErrorMessage(L"Additional networks are not allowed with container network mode.");
6548
- }
6549
-
6455
WSLC_TEST_METHOD(ContainerNetworkModeInspectRoundTripTest)
6456
{
6457
// Verify that after a session reset (service restart), Inspect() on a recovered
@@ -6563,9 +6468,7 @@ class WSLCTests
6468
containerAId = containerA.Id();
6469
containerA.SetDeleteOnClose(false);
6470
6566
- WSLCContainerLauncher launcherB(
6567
- "debian:latest", containerBName, {"sleep", "99999"}, {}, WSLCContainerNetworkType::WSLCContainerNetworkTypeCustom);
6568
- launcherB.SetContainerNetworkName("container:" + containerAName);
6471
+ WSLCContainerLauncher launcherB("debian:latest", containerBName, {"sleep", "99999"}, {}, "container:" + containerAName);
6472
auto containerB = launcherB.Create(*m_defaultSession);
6473
VERIFY_ARE_EQUAL(containerB.State(), WslcContainerStateCreated);
6474
containerB.SetDeleteOnClose(false);
@@ -6582,35 +6485,6 @@ class WSLCTests
6485
VERIFY_ARE_EQUAL(recoveredContainerB.Inspect().HostConfig.NetworkMode, expectedNetworkMode);
6486
}
6487
6585
- WSLC_TEST_METHOD(ContainerNetworkModeIpAddressRejectedTest)
6586
- {
6587
- // ContainerIpAddress must be rejected for container network mode just as for other modes.
6588
- const std::string containerAName = "test-container-mode-ip-a";
6589
-
6590
- WSLCContainerLauncher launcherA("debian:latest", containerAName, {"sleep", "99999"}, {});
6591
- auto containerA = launcherA.Launch(*m_defaultSession);
6592
- VERIFY_ARE_EQUAL(containerA.State(), WslcContainerStateRunning);
6593
-
6594
- LPCSTR args[] = {"sleep", "99999"};
6595
-
6596
- WSLCContainerOptions options{};
6597
- options.Image = "debian:latest";
6598
- options.Name = "test-container-mode-ip-b";
6599
- options.InitProcessOptions.CommandLine = {.Values = args, .Count = ARRAYSIZE(args)};
6600
- options.ContainerNetwork.ContainerNetworkType = WSLCContainerNetworkTypeCustom;
6601
- const std::string containerNetName = "container:" + containerAName;
6602
- WSLCNetworkAttachment netWithIp{};
6603
- netWithIp.NetworkName = containerNetName.c_str();
6604
- netWithIp.ContainerIpAddress = "10.0.0.5";
6605
- options.ContainerNetwork.Networks = &netWithIp;
6606
- options.ContainerNetwork.NetworksCount = 1;
6607
-
6608
- wil::com_ptr<IWSLCContainer> container;
6609
- auto hr = m_defaultSession->CreateContainer(&options, &container);
6610
- VERIFY_ARE_EQUAL(E_NOTIMPL, hr);
6611
- ValidateCOMErrorMessage(L"ContainerIpAddress is not yet supported.");
6612
- }
6613
-
6488
WSLC_TEST_METHOD(ContainerInspect)
6489
{
6490
// Helper to verify port mappings.
@@ -6684,8 +6558,7 @@ class WSLCTests
6558
std::filesystem::remove_all(testFolderReadOnly, ec);
6559
});
6560
6687
- WSLCContainerLauncher launcher(
6688
- "debian:latest", "test-container-inspect", {"sleep", "99999"}, {}, WSLCContainerNetworkType::WSLCContainerNetworkTypeBridged);
6561
+ WSLCContainerLauncher launcher("debian:latest", "test-container-inspect", {"sleep", "99999"}, {}, "bridge");
6562
6563
launcher.AddPort(1234, 8000, AF_INET);
6564
launcher.AddPort(1235, 8000, AF_INET);
@@ -6786,8 +6659,7 @@ class WSLCTests
6659
WSLC_TEST_METHOD(Exec)
6660
{
6661
// Create a container.
6789
- WSLCContainerLauncher launcher(
6790
- "debian:latest", "test-container-exec", {"sleep", "99999"}, {}, WSLCContainerNetworkType::WSLCContainerNetworkTypeNone);
6662
+ WSLCContainerLauncher launcher("debian:latest", "test-container-exec", {"sleep", "99999"}, {}, "none");
6663
6664
auto container = launcher.Launch(*m_defaultSession);
6665
@@ -6932,7 +6804,7 @@ class WSLCTests
6804
6805
WSLC_TEST_METHOD(ExecContainerDelete)
6806
{
6935
- WSLCContainerLauncher launcher("debian:latest", "test-exec-dtor", {"sleep", "99999"}, {}, WSLCContainerNetworkType::WSLCContainerNetworkTypeNone);
6807
+ WSLCContainerLauncher launcher("debian:latest", "test-exec-dtor", {"sleep", "99999"}, {}, "none");
6808
6809
auto container = launcher.Launch(*m_defaultSession);
6810
@@ -6949,9 +6821,10 @@ class WSLCTests
6821
VERIFY_ARE_EQUAL(process.GetExitCode(), 128 + WSLCSignalSIGKILL);
6822
}
6823
6952
- void RunPortMappingsTest(IWSLCSession& session, WSLCContainerNetworkType containerNetworkType)
6824
+ void RunPortMappingsTest(IWSLCSession& session, std::string containerNetworkType)
6825
{
6954
- LogInfo("Container network type: %d", static_cast<int>(containerNetworkType));
6826
+ WEX::Logging::Log::Comment(
6827
+ std::format(L"Container network type: {}", wsl::shared::string::MultiByteToWide(containerNetworkType)).c_str());
6828
6829
auto expectBoundPorts = [&](RunningWSLCContainer& Container, const std::vector<std::string>& expectedBoundPorts) {
6830
auto ports = Container.Inspect().Ports;
@@ -7180,7 +7053,7 @@ class WSLCTests
7053
options.Image = "python:3.12-alpine";
7054
options.Ports = &port;
7055
options.PortsCount = 1;
7183
- options.ContainerNetwork.ContainerNetworkType = containerNetworkType;
7056
+ options.ContainerNetwork.NetworkMode = containerNetworkType.c_str();
7057
7058
wil::com_ptr<IWSLCContainer> container;
7059
VERIFY_ARE_EQUAL(session.CreateContainer(&options, &container), E_INVALIDARG);
@@ -7219,23 +7092,23 @@ class WSLCTests
7092
{
7093
auto [restore, session] = SetupPortMappingsTest(WSLCNetworkingModeNAT);
7094
7222
- RunPortMappingsTest(*session, WSLCContainerNetworkTypeBridged);
7223
- RunPortMappingsTest(*session, WSLCContainerNetworkTypeHost);
7095
+ RunPortMappingsTest(*session, "bridge");
7096
+ RunPortMappingsTest(*session, "host");
7097
}
7098
7099
WSLC_TEST_METHOD(PortMappingsVirtioProxy)
7100
{
7101
auto [restore, session] = SetupPortMappingsTest(WSLCNetworkingModeVirtioProxy);
7102
7230
- RunPortMappingsTest(*session, WSLCContainerNetworkTypeBridged);
7231
- RunPortMappingsTest(*session, WSLCContainerNetworkTypeHost);
7103
+ RunPortMappingsTest(*session, "bridge");
7104
+ RunPortMappingsTest(*session, "host");
7105
}
7106
7107
TEST_METHOD(PortMappingsNone)
7108
{
7109
// Validate that trying to map ports without network fails.
7110
WSLCContainerLauncher launcher(
7238
- "python:3.12-alpine", "test-ports-fail", {"python3", "-m", "http.server"}, {"PYTHONUNBUFFERED=1"}, WSLCContainerNetworkTypeNone);
7111
+ "python:3.12-alpine", "test-ports-fail", {"python3", "-m", "http.server"}, {"PYTHONUNBUFFERED=1"}, "none");
7112
7113
launcher.AddPort(1234, 8000, AF_INET);
7114
@@ -7271,7 +7144,7 @@ class WSLCTests
7144
"test-publish-all",
7145
{"python3", "-m", "http.server", "--bind", "::", "8080"},
7146
{"PYTHONUNBUFFERED=1"},
7274
- WSLCContainerNetworkTypeBridged);
7147
+ "bridge");
7148
7149
launcher.SetContainerFlags(WSLCContainerFlagsPublishAll);
7150
@@ -7307,7 +7180,7 @@ class WSLCTests
7180
WSLC_TEST_METHOD(PublishAllImageNotFound)
7181
{
7182
// Verify that using PublishAll with a nonexistent image still returns IMAGE_NOT_FOUND.
7310
- WSLCContainerLauncher launcher("invalid-image-name:nonexistent", "dummy-publish-all", {"/bin/cat"}, {}, WSLCContainerNetworkTypeBridged);
7183
+ WSLCContainerLauncher launcher("invalid-image-name:nonexistent", "dummy-publish-all", {"/bin/cat"}, {}, "bridge");
7184
launcher.SetContainerFlags(WSLCContainerFlagsPublishAll);
7185
7186
auto [hresult, container] = launcher.LaunchNoThrow(*m_defaultSession);
@@ -7993,7 +7866,11 @@ class WSLCTests
7866
auto session = CreateSession(GetDefaultSessionSettings(L"recovery-test-vp", true, WSLCNetworkingModeNAT));
7867
7868
WSLCContainerLauncher launcher(
7996
- "python:3.12-alpine", containerName, {"python3", "-m", "http.server", "--directory", "/volume"}, {"PYTHONUNBUFFERED=1"}, WSLCContainerNetworkTypeBridged);
7869
+ "python:3.12-alpine",
7870
+ containerName,
7871
+ {"python3", "-m", "http.server", "--directory", "/volume"},
7872
+ {"PYTHONUNBUFFERED=1"},
7873
+ "bridge");
7874
7875
launcher.AddPort(1250, 8000, AF_INET);
7876
launcher.AddVolume(hostFolder.wstring(), "/volume", false);
@@ -8725,7 +8602,7 @@ class WSLCTests
8602
WSLC_TEST_METHOD(ContainerStats_RunningContainer)
8603
{
8604
// Start a long-lived detached container on a bridged network so network stats are populated.
8728
- WSLCContainerLauncher launcher("debian:latest", "wslc-test-stats", {"sleep", "60"}, {}, WSLCContainerNetworkTypeBridged);
8605
+ WSLCContainerLauncher launcher("debian:latest", "wslc-test-stats", {"sleep", "60"}, {}, "bridge");
8606
8607
auto runningContainer = launcher.Launch(*m_defaultSession, WSLCContainerStartFlagsNone);
8608
@@ -8808,7 +8685,7 @@ class WSLCTests
8685
8686
WSLC_TEST_METHOD(ContainerStats_NullOutputPointer)
8687
{
8811
- WSLCContainerLauncher launcher("debian:latest", "wslc-test-stats-null", {"sleep", "60"}, {}, WSLCContainerNetworkTypeBridged);
8688
+ WSLCContainerLauncher launcher("debian:latest", "wslc-test-stats-null", {"sleep", "60"}, {}, "bridge");
8689
auto runningContainer = launcher.Launch(*m_defaultSession, WSLCContainerStartFlagsNone);
8690
8691
wil::com_ptr<IWSLCContainer> container;
@@ -8821,7 +8698,7 @@ class WSLCTests
8698
WSLC_TEST_METHOD(ContainerStats_CreatedContainer_ReturnsZeroedStats)
8699
{
8700
// A created-but-not-started container returns zeroed stats from Docker rather than an error.
8824
- WSLCContainerLauncher launcher("debian:latest", "wslc-test-stats-created", {}, {}, WSLCContainerNetworkTypeBridged);
8701
+ WSLCContainerLauncher launcher("debian:latest", "wslc-test-stats-created", {}, {}, "bridge");
8702
auto [result, runningContainer] = launcher.CreateNoThrow(*m_defaultSession);
8703
VERIFY_SUCCEEDED(result);
8704
@@ -9098,7 +8975,7 @@ class WSLCTests
8975
// Verify port mapping.
8976
// Two containers created with the same host port, only the first Start() succeeds.
8977
{
9101
- WSLCContainerLauncher launcher("debian:latest", "deferred-port", {"sleep", "99999"}, {}, WSLCContainerNetworkTypeBridged);
8978
+ WSLCContainerLauncher launcher("debian:latest", "deferred-port", {"sleep", "99999"}, {}, "bridge");
8979
launcher.AddPort(1240, 8000, AF_INET);
8980
8981
// Both Create() calls should succeed because ports are not reserved until Start().
@@ -9135,7 +9012,7 @@ class WSLCTests
9012
9013
auto baselineMountCount = getMountCount();
9014
9138
- WSLCContainerLauncher launcher("debian:latest", "deferred-volume", {"sleep", "99999"}, {}, WSLCContainerNetworkTypeHost);
9015
+ WSLCContainerLauncher launcher("debian:latest", "deferred-volume", {"sleep", "99999"}, {}, "host");
9016
launcher.AddVolume(hostFolder.wstring(), "/deferred-volume", false);
9017
9018
// Create the container — volume should NOT be mounted yet.