Open Zombach opened 5 months ago
Can you show the entire log output?
If you enable VPN, it will be like this. And this is a project template out of the box
info: Aspire.Hosting.DistributedApplication[0]
Aspire version: 8.2.0+75fdcff28495bdd643f6323133a7d411df71ab70
info: Aspire.Hosting.DistributedApplication[0]
Distributed application starting.
info: Aspire.Hosting.DistributedApplication[0]
Application host directory is: Z:\Projects\AspireApp1\AspireApp1.AppHost
crit: Aspire.Hosting.Dcp.ApplicationExecutor[0]
Watch task over Kubernetes Endpoint resources terminated unexpectedly. Check to ensure dcpd process is running.
System.Net.Http.HttpRequestException: An attempt was made to access a socket using a method that is prohibited by access rights.([::1]:51899)
---> System.Net.Sockets.SocketException (10013): An attempt was made to access a socket using a method that is prohibited by access rights.
at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.ThrowException(SocketError error, CancellationToken cancellationToken)
at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.System.Threading.Tasks.Sources.IValueTaskSource.GetResult(Int16 token)
at System.Net.Sockets.Socket.1.WaitWithCancellationAsync(CancellationToken cancellationToken) at System.Net.Http.HttpConnectionPool.SendWithVersionDetectionAndRetryAsync(HttpRequestMessage request, Boolean async, Boolean doRequestAuth, CancellationToken cancellationToken) at System.Net.Http.DiagnosticsHandler.SendAsyncCore(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken) at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken) at System.Net.Http.HttpClient.<SendAsync>g__Core|83_0(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationTokenSource cts, Boolean disposeCts, CancellationTokenSource pendingRequestsCts, CancellationToken originalCancellationToken) at k8s.Kubernetes.SendRequestRaw(String requestContent, HttpRequestMessage httpRequest, CancellationToken cancellationToken) at k8s.AbstractKubernetes.ICustomObjectsOperations_ListClusterCustomObjectWithHttpMessagesAsync[T](String group, String version, String plural, Nullable
1 allowWatchBookmarks, String continueParameter, String fieldSelector, String labelSelector, Nullable1 limit, String resourceVersion, String resourceVersionMatch, Nullable
1 timeoutSeconds, Nullable1 watch, Nullable
1 pretty, IReadOnlyDictionary2 customHeaders, CancellationToken cancellationToken) at k8s.AbstractKubernetes.k8s.ICustomObjectsOperations.ListClusterCustomObjectWithHttpMessagesAsync(String group, String version, String plural, Nullable
1 allowWatchBookmarks, String continueParameter, String fieldSelector, String labelSelector, Nullable1 limit, String resourceVersion, String resourceVersionMatch, Nullable
1 timeoutSeconds, Nullable1 watch, Nullable
1 pretty, IReadOnlyDictionary2 customHeaders, CancellationToken cancellationToken) at k8s.WatcherExt.<>c__DisplayClass1_0
2.<1.<>c.<CreateWatchEventEnumerator>b__21_1[TR](Task
1 t)
at System.Threading.Tasks.ContinuationResultTaskFromResultTask2.InnerInvoke() at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state) --- End of stack trace from previous location --- at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state) at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot, Thread threadPoolThread) --- End of stack trace from previous location --- at k8s.Watcher
1.CreateWatchEventEnumerator(Func1 streamReaderCreator, Action
1 onError, CancellationToken cancellationToken)+MoveNext()
at k8s.Watcher1.CreateWatchEventEnumerator(Func
1 streamReaderCreator, Action1 onError, CancellationToken cancellationToken)+System.Threading.Tasks.Sources.IValueTaskSource<System.Boolean>.GetResult() at Aspire.Hosting.Dcp.KubernetesService.WatchAsync[T](String namespaceParameter, CancellationToken cancellationToken)+MoveNext() in /_/src/Aspire.Hosting/Dcp/KubernetesService.cs:line 216 at Aspire.Hosting.Dcp.KubernetesService.WatchAsync[T](String namespaceParameter, CancellationToken cancellationToken)+MoveNext() in /_/src/Aspire.Hosting/Dcp/KubernetesService.cs:line 216 at Aspire.Hosting.Dcp.KubernetesService.WatchAsync[T](String namespaceParameter, CancellationToken cancellationToken)+System.Threading.Tasks.Sources.IValueTaskSource<System.Boolean>.GetResult() at Aspire.Hosting.Dcp.ApplicationExecutor.<>c__DisplayClass39_1
1.<1.GetResultOrRethrow() at Polly.ResiliencePipeline.ExecuteAsync(Func
2 callback, CancellationToken cancellationToken)
at Aspire.Hosting.Dcp.ApplicationExecutor.<>c__DisplayClass39_0.<1.MoveNext() in /_/src/Aspire.Hosting/Dcp/ApplicationExecutor.cs:line 332 crit: Aspire.Hosting.Dcp.ApplicationExecutor[0] Watch task over Kubernetes Executable resources terminated unexpectedly. Check to ensure dcpd process is running. System.Net.Http.HttpRequestException: An attempt was made to access a socket using a method that is prohibited by access rights. ([::1]:51899) ---> System.Net.Sockets.SocketException (10013): An attempt was made to access a socket using a method that is prohibited by access rights. at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.ThrowException(SocketError error, CancellationToken cancellationToken) at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.System.Threading.Tasks.Sources.IValueTaskSource.GetResult(Int16 token) at System.Net.Sockets.Socket.<ConnectAsync>g__WaitForConnectWithCancellation|285_0(AwaitableSocketAsyncEventArgs saea, ValueTask connectTask, CancellationToken cancellationToken) at System.Net.Http.HttpConnectionPool.ConnectToTcpHostAsync(String host, Int32 port, HttpRequestMessage initialRequest, Boolean async, CancellationToken cancellationToken) --- End of inner exception stack trace --- at System.Net.Http.HttpConnectionPool.ConnectToTcpHostAsync(String host, Int32 port, HttpRequestMessage initialRequest, Boolean async, CancellationToken cancellationToken) at System.Net.Http.HttpConnectionPool.ConnectAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken) at System.Net.Http.HttpConnectionPool.AddHttp2ConnectionAsync(QueueItem queueItem) at System.Threading.Tasks.TaskCompletionSourceWithCancellation
1.WaitWithCancellationAsync(CancellationToken cancellationToken)
at System.Net.Http.HttpConnectionPool.SendWithVersionDetectionAndRetryAsync(HttpRequestMessage request, Boolean async, Boolean doRequestAuth, CancellationToken cancellationToken)
at System.Net.Http.DiagnosticsHandler.SendAsyncCore(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
at System.Net.Http.HttpClient.1 allowWatchBookmarks, String continueParameter, String fieldSelector, String labelSelector, Nullable
1 limit, String resourceVersion, String resourceVersionMatch, Nullable1 timeoutSeconds, Nullable
1 watch, Nullable1 pretty, IReadOnlyDictionary
2 customHeaders, CancellationToken cancellationToken)
at k8s.AbstractKubernetes.k8s.ICustomObjectsOperations.ListClusterCustomObjectWithHttpMessagesAsync(String group, String version, String plural, Nullable1 allowWatchBookmarks, String continueParameter, String fieldSelector, String labelSelector, Nullable
1 limit, String resourceVersion, String resourceVersionMatch, Nullable1 timeoutSeconds, Nullable
1 watch, Nullable1 pretty, IReadOnlyDictionary
2 customHeaders, CancellationToken cancellationToken)
at k8s.WatcherExt.<>cDisplayClass1_02.<<MakeStreamReaderCreator>b__0>d.MoveNext() --- End of stack trace from previous location --- at k8s.Watcher
1.<>c.1 t) at System.Threading.Tasks.ContinuationResultTaskFromResultTask
2.InnerInvoke()
at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state)
--- End of stack trace from previous location ---
at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot, Thread threadPoolThread)
--- End of stack trace from previous location ---
at k8s.Watcher1.CreateWatchEventEnumerator(Func
1 streamReaderCreator, Action1 onError, CancellationToken cancellationToken)+MoveNext() at k8s.Watcher
1.CreateWatchEventEnumerator(Func1 streamReaderCreator, Action
1 onError, CancellationToken cancellationToken)+System.Threading.Tasks.Sources.IValueTaskSource1.GetResultOrRethrow() at Polly.ResiliencePipeline.ExecuteAsync(Func
2 callback, CancellationToken cancellationToken)
at Aspire.Hosting.Dcp.ApplicationExecutor.<>cDisplayClass39_0.<1.WaitWithCancellationAsync(CancellationToken cancellationToken) at System.Net.Http.HttpConnectionPool.SendWithVersionDetectionAndRetryAsync(HttpRequestMessage request, Boolean async, Boolean doRequestAuth, CancellationToken cancellationToken) at System.Net.Http.DiagnosticsHandler.SendAsyncCore(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken) at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken) at System.Net.Http.HttpClient.<SendAsync>g__Core|83_0(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationTokenSource cts, Boolean disposeCts, CancellationTokenSource pendingRequestsCts, CancellationToken originalCancellationToken) at k8s.Kubernetes.SendRequestRaw(String requestContent, HttpRequestMessage httpRequest, CancellationToken cancellationToken) at k8s.AbstractKubernetes.ICustomObjectsOperations_ListClusterCustomObjectWithHttpMessagesAsync[T](String group, String version, String plural, Nullable
1 allowWatchBookmarks, String continueParameter, String fieldSelector, String labelSelector, Nullable1 limit, String resourceVersion, String resourceVersionMatch, Nullable
1 timeoutSeconds, Nullable1 watch, Nullable
1 pretty, IReadOnlyDictionary2 customHeaders, CancellationToken cancellationToken) at k8s.AbstractKubernetes.k8s.ICustomObjectsOperations.ListClusterCustomObjectWithHttpMessagesAsync(String group, String version, String plural, Nullable
1 allowWatchBookmarks, String continueParameter, String fieldSelector, String labelSelector, Nullable1 limit, String resourceVersion, String resourceVersionMatch, Nullable
1 timeoutSeconds, Nullable1 watch, Nullable
1 pretty, IReadOnlyDictionary2 customHeaders, CancellationToken cancellationToken) at k8s.WatcherExt.<>c__DisplayClass1_0
2.<1 t) at System.Threading.Tasks.ContinuationResultTaskFromResultTask
2.InnerInvoke()
at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state)
--- End of stack trace from previous location ---
at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot, Thread threadPoolThread)
--- End of stack trace from previous location ---
at k8s.Watcher1.CreateWatchEventEnumerator(Func
1 streamReaderCreator, Action1 onError, CancellationToken cancellationToken)+MoveNext() at k8s.Watcher
1.CreateWatchEventEnumerator(Func1 streamReaderCreator, Action
1 onError, CancellationToken cancellationToken)+System.Threading.Tasks.Sources.IValueTaskSource1.<<WatchResourceChanges>b__10>d.MoveNext() in /_/src/Aspire.Hosting/Dcp/ApplicationExecutor.cs:line 334 --- End of stack trace from previous location --- at Polly.ResiliencePipeline.<>c.<<ExecuteAsync>b__3_0>d.MoveNext() --- End of stack trace from previous location --- at Polly.Outcome
1.GetResultOrRethrow()
at Polly.ResiliencePipeline.ExecuteAsync(Func2 callback, CancellationToken cancellationToken) at Aspire.Hosting.Dcp.ApplicationExecutor.<>c__DisplayClass39_0.<<WatchResourceChanges>g__WatchKubernetesResourceAsync|3>d
1.MoveNext() in /_/src/Aspire.Hosting/Dcp/ApplicationExecutor.cs:line 332
crit: Aspire.Hosting.Dcp.ApplicationExecutor[0]
Watch task over Kubernetes Container resources terminated unexpectedly. Check to ensure dcpd process is running.
System.Net.Http.HttpRequestException: An attempt was made to access a socket using a method that is prohibited by access rights. ([::1]:51899)
---> System.Net.Sockets.SocketException (10013): An attempt was made to access a socket using a method that is prohibited by access rights.
at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.ThrowException(SocketError error, CancellationToken cancellationToken)
at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.System.Threading.Tasks.Sources.IValueTaskSource.GetResult(Int16 token)
at System.Net.Sockets.Socket.1.WaitWithCancellationAsync(CancellationToken cancellationToken) at System.Net.Http.HttpConnectionPool.SendWithVersionDetectionAndRetryAsync(HttpRequestMessage request, Boolean async, Boolean doRequestAuth, CancellationToken cancellationToken) at System.Net.Http.DiagnosticsHandler.SendAsyncCore(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken) at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken) at System.Net.Http.HttpClient.<SendAsync>g__Core|83_0(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationTokenSource cts, Boolean disposeCts, CancellationTokenSource pendingRequestsCts, CancellationToken originalCancellationToken) at k8s.Kubernetes.SendRequestRaw(String requestContent, HttpRequestMessage httpRequest, CancellationToken cancellationToken) at k8s.AbstractKubernetes.ICustomObjectsOperations_ListClusterCustomObjectWithHttpMessagesAsync[T](String group, String version, String plural, Nullable
1 allowWatchBookmarks, String continueParameter, String fieldSelector, String labelSelector, Nullable1 limit, String resourceVersion, String resourceVersionMatch, Nullable
1 timeoutSeconds, Nullable1 watch, Nullable
1 pretty, IReadOnlyDictionary2 customHeaders, CancellationToken cancellationToken) at k8s.AbstractKubernetes.k8s.ICustomObjectsOperations.ListClusterCustomObjectWithHttpMessagesAsync(String group, String version, String plural, Nullable
1 allowWatchBookmarks, String continueParameter, String fieldSelector, String labelSelector, Nullable1 limit, String resourceVersion, String resourceVersionMatch, Nullable
1 timeoutSeconds, Nullable1 watch, Nullable
1 pretty, IReadOnlyDictionary2 customHeaders, CancellationToken cancellationToken) at k8s.WatcherExt.<>c__DisplayClass1_0
2.<1.<>c.<CreateWatchEventEnumerator>b__21_1[TR](Task
1 t)
at System.Threading.Tasks.ContinuationResultTaskFromResultTask2.InnerInvoke() at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state) --- End of stack trace from previous location --- at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state) at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot, Thread threadPoolThread) --- End of stack trace from previous location --- at k8s.Watcher
1.CreateWatchEventEnumerator(Func1 streamReaderCreator, Action
1 onError, CancellationToken cancellationToken)+MoveNext()
at k8s.Watcher1.CreateWatchEventEnumerator(Func
1 streamReaderCreator, Action1 onError, CancellationToken cancellationToken)+System.Threading.Tasks.Sources.IValueTaskSource<System.Boolean>.GetResult() at Aspire.Hosting.Dcp.KubernetesService.WatchAsync[T](String namespaceParameter, CancellationToken cancellationToken)+MoveNext() in /_/src/Aspire.Hosting/Dcp/KubernetesService.cs:line 216 at Aspire.Hosting.Dcp.KubernetesService.WatchAsync[T](String namespaceParameter, CancellationToken cancellationToken)+MoveNext() in /_/src/Aspire.Hosting/Dcp/KubernetesService.cs:line 216 at Aspire.Hosting.Dcp.KubernetesService.WatchAsync[T](String namespaceParameter, CancellationToken cancellationToken)+System.Threading.Tasks.Sources.IValueTaskSource<System.Boolean>.GetResult() at Aspire.Hosting.Dcp.ApplicationExecutor.<>c__DisplayClass39_1
1.<1.GetResultOrRethrow() at Polly.ResiliencePipeline.ExecuteAsync(Func
2 callback, CancellationToken cancellationToken)
at Aspire.Hosting.Dcp.ApplicationExecutor.<>c__DisplayClass39_0.<1.MoveNext() in /_/src/Aspire.Hosting/Dcp/ApplicationExecutor.cs:line 332 fail: Aspire.Hosting.Dcp.dcpctrl[0] unable to confirm the API server is responding {"error": "failed to get API group resources: unable to retrieve the complete list of server APIs: usvc-dev.developer.microsoft.com/v1: Get \"https://[::1]:51899/apis/usvc-dev.developer.microsoft.com/v1\": dial tcp [::1]:51899: connectex: An attempt was made to access a socket in a way forbidden by its access permissions.\ncontext deadline exceeded"} fail: Microsoft.Extensions.Hosting.Internal.Host[11] Hosting failed to start System.Net.Http.HttpRequestException: An attempt was made to access a socket using a method that is prohibited by access rights.([::1]:51899) ---> System.Net.Sockets.SocketException (10013): An attempt was made to access a socket using a method that is prohibited by access rights. at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.ThrowException(SocketError error, CancellationToken cancellationToken) at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.System.Threading.Tasks.Sources.IValueTaskSource.GetResult(Int16 token) at System.Net.Sockets.Socket.<ConnectAsync>g__WaitForConnectWithCancellation|285_0(AwaitableSocketAsyncEventArgs saea, ValueTask connectTask, CancellationToken cancellationToken) at System.Net.Http.HttpConnectionPool.ConnectToTcpHostAsync(String host, Int32 port, HttpRequestMessage initialRequest, Boolean async, CancellationToken cancellationToken) --- End of inner exception stack trace --- at System.Net.Http.HttpConnectionPool.ConnectToTcpHostAsync(String host, Int32 port, HttpRequestMessage initialRequest, Boolean async, CancellationToken cancellationToken) at System.Net.Http.HttpConnectionPool.ConnectAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken) at System.Net.Http.HttpConnectionPool.AddHttp2ConnectionAsync(QueueItem queueItem) at System.Threading.Tasks.TaskCompletionSourceWithCancellation
1.WaitWithCancellationAsync(CancellationToken cancellationToken)
at System.Net.Http.HttpConnectionPool.SendWithVersionDetectionAndRetryAsync(HttpRequestMessage request, Boolean async, Boolean doRequestAuth, CancellationToken cancellationToken)
at System.Net.Http.DiagnosticsHandler.SendAsyncCore(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
at System.Net.Http.HttpClient.1 pretty, IReadOnlyDictionary
2 customHeaders, CancellationToken cancellationToken)
at k8s.AbstractKubernetes.k8s.ICustomObjectsOperations.CreateClusterCustomObjectWithHttpMessagesAsync(Object body, String group, String version, String plural, String dryRun, String fieldManager, String fieldValidation, Nullable1 pretty, IReadOnlyDictionary
2 customHeaders, CancellationToken cancellationToken)
at Aspire.Hosting.Dcp.KubernetesService.<>cDisplayClass16_01.<<CreateAsync>b__0>d.MoveNext() in /_/src/Aspire.Hosting/Dcp/KubernetesService.cs:line 105 --- End of stack trace from previous location --- at Aspire.Hosting.Dcp.KubernetesService.ExecuteWithRetry[TResult](DcpApiOperationType operationType, String resourceType, Func
2 operation, CancellationToken cancellationToken) in //src/Aspire.Hosting/Dcp/KubernetesService.cs:line 308
at Aspire.Hosting.Dcp.KubernetesService.ExecuteWithRetry[TResult](DcpApiOperationType operationType, String resourceType, Func`2 operation, CancellationToken cancellationToken) in //src/Aspire.Hosting/Dcp/KubernetesService.cs:line 315
at Aspire.Hosting.Dcp.ApplicationExecutor.CreateResourcesAsync[RT](CancellationToken cancellationToken) in //src/Aspire.Hosting/Dcp/ApplicationExecutor.cs:line 1740
at Aspire.Hosting.Dcp.ApplicationExecutor.CreateServicesAsync(CancellationToken cancellationToken) in //src/Aspire.Hosting/Dcp/ApplicationExecutor.cs:line 818
at Aspire.Hosting.Dcp.ApplicationExecutor.RunApplicationAsync(CancellationToken cancellationToken) in //src/Aspire.Hosting/Dcp/ApplicationExecutor.cs:line 132
at Aspire.Hosting.Dcp.DcpHostService.StartAsync(CancellationToken cancellationToken) in //src/Aspire.Hosting/Dcp/DcpHostService.cs:line 70
at Microsoft.Extensions.Hosting.Internal.Host.1 services, CancellationToken token, Boolean concurrent, Boolean abortOnFirstException, List
1 exceptions, Func`3 operation)
Can you show the entire log output?
If you turn off the VPN it will look like this.
info: Aspire.Hosting.DistributedApplication[0] Aspire version: 8.2.0+75fdcff28495bdd643f6323133a7d411df71ab70 info: Aspire.Hosting.DistributedApplication[0] Distributed application starting. info: Aspire.Hosting.DistributedApplication[0] Application host directory is: Z:\Projects\AspireApp1\AspireApp1.AppHost info: Aspire.Hosting.DistributedApplication[0] Now listening on: https://localhost:17018 info: Aspire.Hosting.DistributedApplication[0] Login to the dashboard at https://localhost:17018/login?t=68c6e2f59ad93c196f81089fda134520 info: Aspire.Hosting.DistributedApplication[0] Distributed application started. Press Ctrl+C to shut down.
So your VPN is blocking this localhost traffic for some reason. I'm not sure if there's anything we can do but thanks for the details.
What information do you have about this vpn and how it works?
This Avira phantom vpn pro
It forwards all traffic through itself. I can’t say more precisely, because I don’t know.
But with other VPNs, for example WireGuard/Cisco Any Connect/Open VPN, everything works without problems
If turn on VPN API server started {"Address": "::1", "Port": 63522} fail: Microsoft.Extensions.Hosting.Internal.Host[11] Hosting failed to start
If turn off VPN Everything is ok