From 3c00fa8f987220f0376edd14682fc6f5ee15cf2e Mon Sep 17 00:00:00 2001 From: Tim Hess Date: Fri, 5 Jan 2024 17:33:54 -0600 Subject: [PATCH] remove some unused components --- .../Pages/DynamicLogging/GettingStarted.razor | 24 --- .../Pages/DynamicLogging/Index.razor | 59 +++---- .../Components/Pages/GetStarted/Basics.razor | 152 ------------------ .../Pages/Local/GettingStarted.razor | 45 ------ src/Client/Components/Pages/Local/Index.razor | 55 ------- .../Components/Pages/Management/Index.razor | 11 +- .../RunAppTab/AzureAppService.razor | 14 -- .../Components/RunAppTab/CloudFoundry.razor | 78 --------- src/Client/Components/RunAppTab/Docker.razor | 68 -------- .../Components/RunAppTab/DockerCompose.razor | 19 --- .../Components/RunAppTab/Kubernetes.razor | 105 ------------ src/Client/Components/RunAppTab/Local.razor | 43 ----- .../Components/StartInstanceTab/Azure.razor | 22 --- .../StartInstanceTab/CloudFoundry.razor | 27 ---- .../StartInstanceTab/Kubernetes.razor | 33 ---- .../Components/StartInstanceTab/Local.razor | 21 --- src/Client/Components/UIInterfaces/ITab.cs | 9 -- src/Client/Steeltoe.Client.csproj | 4 - ...oject-tye-are-your-path-to-productivity.md | 143 ---------------- 19 files changed, 26 insertions(+), 906 deletions(-) delete mode 100644 src/Client/Components/Pages/DynamicLogging/GettingStarted.razor delete mode 100644 src/Client/Components/Pages/GetStarted/Basics.razor delete mode 100644 src/Client/Components/Pages/Local/GettingStarted.razor delete mode 100644 src/Client/Components/Pages/Local/Index.razor delete mode 100644 src/Client/Components/RunAppTab/AzureAppService.razor delete mode 100644 src/Client/Components/RunAppTab/CloudFoundry.razor delete mode 100644 src/Client/Components/RunAppTab/Docker.razor delete mode 100644 src/Client/Components/RunAppTab/DockerCompose.razor delete mode 100644 src/Client/Components/RunAppTab/Kubernetes.razor delete mode 100644 src/Client/Components/RunAppTab/Local.razor delete mode 100644 src/Client/Components/StartInstanceTab/Azure.razor delete mode 100644 src/Client/Components/StartInstanceTab/CloudFoundry.razor delete mode 100644 src/Client/Components/StartInstanceTab/Kubernetes.razor delete mode 100644 src/Client/Components/StartInstanceTab/Local.razor delete mode 100644 src/Client/Components/UIInterfaces/ITab.cs delete mode 100644 src/Client/wwwroot/site-data/blog/tech-tutorial-use-kubernetes-for-modern-net-apps-steeltoe-and-project-tye-are-your-path-to-productivity.md diff --git a/src/Client/Components/Pages/DynamicLogging/GettingStarted.razor b/src/Client/Components/Pages/DynamicLogging/GettingStarted.razor deleted file mode 100644 index d1e772a..0000000 --- a/src/Client/Components/Pages/DynamicLogging/GettingStarted.razor +++ /dev/null @@ -1,24 +0,0 @@ -@page "/logging/get-started" -@inject IHttpContextAccessor HttpContextAccessor -@inject IOptionsSnapshot DocsSiteOptions - - - Logging - -

This page has moved, find the new location here

-
-
- -@code -{ - protected override void OnInitialized() - { - if (HttpContextAccessor.HttpContext != null) - { - var uri = new Uri(DocsSiteOptions.Value.BaseAddress + "/guides/").ToString(); - HttpContextAccessor.HttpContext.Response.Redirect(uri, true); - } - } -} diff --git a/src/Client/Components/Pages/DynamicLogging/Index.razor b/src/Client/Components/Pages/DynamicLogging/Index.razor index b515818..b30be1a 100644 --- a/src/Client/Components/Pages/DynamicLogging/Index.razor +++ b/src/Client/Components/Pages/DynamicLogging/Index.razor @@ -1,38 +1,27 @@ -@page "/dynamic-logging" +@page "/logging/get-started" +@page "/dynamic-logging" @page "/steeltoe-logging" - +@inject IHttpContextAccessor HttpContextAccessor +@inject IOptionsSnapshot DocsSiteOptions + + + Logging + +

This page has moved, find the new location here

+
+
-@code{ - private Feature[] features = new[] { - new Feature() { - Title = (MarkupString)"", - Description = (b => { - b.AddMarkupContent(1,""); - }), - Img = "" - } - }; -} \ No newline at end of file +@code +{ + protected override void OnInitialized() + { + if (HttpContextAccessor.HttpContext != null) + { + var uri = new Uri(DocsSiteOptions.Value.BaseAddress + "/guides/").ToString(); + HttpContextAccessor.HttpContext.Response.Redirect(uri, true); + } + } +} diff --git a/src/Client/Components/Pages/GetStarted/Basics.razor b/src/Client/Components/Pages/GetStarted/Basics.razor deleted file mode 100644 index 18b799b..0000000 --- a/src/Client/Components/Pages/GetStarted/Basics.razor +++ /dev/null @@ -1,152 +0,0 @@ -@page "/get-started/basics" - - - - Building a basic ASP.NET Core app with Steeltoe - This tutorial takes you through setting up a .NET Core application that uses the essential Steeltoe packages, every microservice should have. - -
-
First, create a .NET Core WebAPI
-
-
-
-
    -
  1. - In Visual Studio (2019) choose to create a new project - -
  2. -
  3. - Configure the new project with the follow values - -
      -
    • Project Name: @ProjectName
    • -
    • Solution Name: @ProjectName
    • -
    • Framework: (>= 4.5)
    • -
    -
  4. -
  5. - Choose to create a new Web API project type - -
  6. -
  7. - Once created, the project should be loaded - -
  8. -
-
-
-
-
Next, install packages needed
-
-
-
-
    -
  1. - Open the package manager console - -
  2. -
  3. - Install NuGet distributed packages -
    Install-Package -Id Steeltoe.Security.Authentication.CloudFoundryOwin -Version @SteeltoeVersion
    -Install-Package -Id Steeltoe.Management.EndpointCore -Version @SteeltoeVersion
    -Install-Package -Id Steeltoe.Extensions.Logging.DynamicLogger -Version @SteeltoeVersion
    -Install-Package -Id Steeltoe.Management.TracingCore -Version @SteeltoeVersion
    -
  4. -
-
-
-
-
Then, add the management endpoints to the host builder, and run the app
-
-
-
    -
  1. - Set the endpoints in Program.cs -
    using Steeltoe.Management.Endpoint;
    -
    -...
    -
    -public class Startup {
    -
    -...
    -
    -	public static IHostBuilder CreateHostBuilder(string[] args) =>
    -		Host.CreateDefaultBuilder(args)
    -			.ConfigureWebHostDefaults(webBuilder => {
    -				webBuilder.UseStartup<Startup>();
    -			})
    -			.AddHealthActuator()
    -			.AddInfoActuator()
    -			.AddLoggersActuator();
    -}
    -
  2. -
  3. - Start distributed tracing in Startup.cs -
    using Steeltoe.Management.Tracing;
    -
    -...
    -
    -public class Startup {
    -
    -...
    -
    -	public void ConfigureServices(IServiceCollection services){
    -
    -		services.AddDistributedTracing(Configuration);
    -
    -		...
    -
    -	}
    -
    -...
    -
    -}
    -
  4. -
  5. - Open the Controllers\WeatherForecastController.cs file and test logging messages -
    using Microsoft.AspNetCore.Mvc;
    -using Microsoft.AspNetCore.Authorization;
    -
    -...
    -
    -[HttpGet]
    -public IEnumerable<WeatherForecast> Get() {
    -	_logger.LogInformation("Hi there from the logger!");
    -
    -		...
    -
    -}
    -
  6. -
  7. -
    Run the application
    -
    - - - -
    -
  8. -
  9. -
    Navigate to the health endpoint
    -
    - xxxxxx -
    -
  10. -
  11. -
    Observe the logs for trace and span information
    -
    - xxxxxx -
    -
  12. -
-
-
-
-@code -{ - //private string ServiceName = "Place Holder"; - private const string ProjectName = "Steeltoe_Basics"; - private const string SteeltoeVersion = "3.0"; -} diff --git a/src/Client/Components/Pages/Local/GettingStarted.razor b/src/Client/Components/Pages/Local/GettingStarted.razor deleted file mode 100644 index 3ef5ef4..0000000 --- a/src/Client/Components/Pages/Local/GettingStarted.razor +++ /dev/null @@ -1,45 +0,0 @@ -@page "/local/get-started" - - - - Steeltoe Tooling CLI - This tutorial takes you through running a .NET Core microservice with 2 other backing services locally, using the CLI. - -
-
First, create a .NET Core WebAPI
-
-
-
-
    -
  1. - -
  2. -
  3. Extract the zipped project and open in your IDE of choice (we use Visual Studio)
  4. -
  5. -
    Run the application
    -
    - - - - - https://docs.microsoft.com/en-us/visualstudio/deployment/quickstart-deploy-to-azure?view=vs-2019 - - - -
    -
  6. -
  7. - That's it! You have generated a .NET Core microservice using all the latest patterns. Go back and try adding a dependency or try other tutorials -
  8. -
-
-
-
-
-@code -{ - private const string ProjectName = "Initializr_Example"; -} diff --git a/src/Client/Components/Pages/Local/Index.razor b/src/Client/Components/Pages/Local/Index.razor deleted file mode 100644 index 41116c6..0000000 --- a/src/Client/Components/Pages/Local/Index.razor +++ /dev/null @@ -1,55 +0,0 @@ -@page "/local" -@page "/steeltoe-local" - - - - -@code { -} \ No newline at end of file diff --git a/src/Client/Components/Pages/Management/Index.razor b/src/Client/Components/Pages/Management/Index.razor index c41c557..b0cae33 100644 --- a/src/Client/Components/Pages/Management/Index.razor +++ b/src/Client/Components/Pages/Management/Index.razor @@ -1,4 +1,4 @@ -@page "/cloud-management" +@page "/cloud-management" @page "/steeltoe-management" @page "/management" @@ -36,13 +36,6 @@ }), Img = "/images/Icon_connector.svg" }, - new Feature() { - Title = (MarkupString)"Distributed Tracing", - Description = (b => { - b.AddMarkupContent(1,"Use the OpenCensus project capture request tracing data and display it visually in the dashboard or send it to a remote collector."); - }), - Img = "/images/Icon_device-exchange.svg" - }, new Feature() { Title = (MarkupString)"Management Tasks", Description = (b => { @@ -51,4 +44,4 @@ Img = "/images/Icon_box.svg" } }; -} \ No newline at end of file +} diff --git a/src/Client/Components/RunAppTab/AzureAppService.razor b/src/Client/Components/RunAppTab/AzureAppService.razor deleted file mode 100644 index dcf548f..0000000 --- a/src/Client/Components/RunAppTab/AzureAppService.razor +++ /dev/null @@ -1,14 +0,0 @@ - - Follow Microsoft's guide to deploying on Azure App Service. Read more here. - -@ChildContent - -@code { - [Parameter] - public RenderFragment AzureDeployHowToUrl { get; set; } - //[Parameter] - //public string ServiceName { get; set; } = ""; - - [Parameter] - public RenderFragment ChildContent { get; set; } -} \ No newline at end of file diff --git a/src/Client/Components/RunAppTab/CloudFoundry.razor b/src/Client/Components/RunAppTab/CloudFoundry.razor deleted file mode 100644 index dcfeddc..0000000 --- a/src/Client/Components/RunAppTab/CloudFoundry.razor +++ /dev/null @@ -1,78 +0,0 @@ - -
    -
  1. - Open the package manager console - -
  2. -
  3. - Add the Cloud Foundry package to the project - PM> Install-Package Steeltoe.Extensions.Configuration.CloudFoundryCore -
  4. -
  5. - Add the Cloud Foundry configuration provider in Program.cs -
    using Steeltoe.Extensions.Configuration.CloudFoundry;
    -...
    -var builder = WebHost.CreateDefaultBuilder(args)
    - ...
    -
    - .AddCloudFoundry()
    - .UseStartup<Startup>();
    -
    -
  6. -
  7. - Publish the application locally using the .NET cli. The following command will create a publish folder automatically. -
    dotnet publish -o .\publish <PATH_TO>\@(ProjectName).csproj
    -
  8. -
  9. - Create manifest.yml in the same folder as @(ProjectName).csproj -
    ---
    -applications:
    -- name: @(ProjectName)
    -  buildpacks:
    -    - @if (AsDotNetFramework) {
    -hwc_buildpack
    -} else {
    -dotnet_core_buildpack
    -}  stack: @if (AsDotNetFramework) {
    -windows
    -} else {
    -cflinuxfs3
    -}
    - @if(!NoCFServices && !string.IsNullOrEmpty(InstanceName)){
    -  services:
    -    - @InstanceName
    - }
    -
  10. - With yaml files indention and line endings matter. Use an IDE like VS Code to confirm spacing and that line endings are set to LF (not the Windows default CR LF) -
  11. - Push the app to Cloud Foundry -
    cf push -f <PATH_TO>\manifest.yml -p .\publish
    -
  12. - @if (IncludeNavigateToApp) { -
  13. Navigate to the application endpoint https://<APP_ROUTE>/api/values
  14. - } - @AdditionalSteps -
-
- -@code { - [Parameter] - public string ProjectName { get; set; } = ""; - [Parameter] - public string InstanceName { get; set; } = ""; - [Parameter] - public bool NoCFProvider { get; set; } = false; - [Parameter] - public bool NoCFServices { get; set; } = false; - [Parameter] - public string ServiceName { get; set; } = ""; - [Parameter] - public bool NoPackageManager { get; set; } = false; - [Parameter] - public bool IncludeNavigateToApp { get; set; } = true; - [Parameter] - public bool AsDotNetFramework { get; set; } = false; - - [Parameter] - public RenderFragment AdditionalSteps { get; set; } -} \ No newline at end of file diff --git a/src/Client/Components/RunAppTab/Docker.razor b/src/Client/Components/RunAppTab/Docker.razor deleted file mode 100644 index 334808a..0000000 --- a/src/Client/Components/RunAppTab/Docker.razor +++ /dev/null @@ -1,68 +0,0 @@ - -
    -
  1. - Create Dockerfile in the same folder as @(ProjectName).csproj -
    FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS build-env
    -WORKDIR /app
    -
    -# Copy csproj and restore as distinct layers
    -COPY *.csproj ./
    -RUN dotnet restore
    -
    -# Copy everything else and build
    -COPY . ./
    -RUN dotnet publish -c Release -o out
    -
    -# Build runtime image
    -FROM mcr.microsoft.com/dotnet/core/aspnet:3.1
    -WORKDIR /app
    -COPY --from=build-env /app/out .
    -ENTRYPOINT ["dotnet", "@(ProjectName).dll"]
    -
    -
  2. -
  3. Change into the folder that contains the project file (.csproj) -
    cd <PATH_TO_CSPROJ_FOLDER>
    -
  4. -
  5. Build the image using the Dockerfile and output of the publish -
    docker build -t @(ImageName) .
    -
  6. - @*With the container image built, you can test locally by running docker run -p 80:80 <YOUR_DOCKER_NAME>/@(ProjectName.ToLower()). Then navigate to http://localhost/api/values.*@ - @if(IncludeCreateNetworkStep == true){ -
  7. Create a docker network for all the containers to run within -
    docker network create "@NetworkName"
    -
  8. - } -
  9. Run the image as a container -
    docker run --name "@ContainerName" @(!string.IsNullOrEmpty(NetworkName) ? "--network \""+NetworkName+"\"" : "") -d -p @ContainerPort:@PublicPort @ImageName
    -
  10. - @AdditionalSteps -
-
- -@code { - [Parameter] - public string ProjectName { get; set; } - [Parameter] - public string ImageName { get; set; } - [Parameter] - public string ContainerName { get; set; } - [Parameter] - public string ContainerPort { get; set; } = "8080"; - [Parameter] - public string PublicPort { get; set; } = "8080"; - [Parameter] - public bool IncludeCreateNetworkStep { get; set; } = false; - [Parameter] - public string NetworkName { get; set; } = null; - - [Parameter] - public RenderFragment AdditionalSteps { get; set; } - - protected override void OnInitialized() - { - if(IncludeCreateNetworkStep == true) - NetworkName = "steeltoe"; - - base.OnInitializedAsync(); - } -} \ No newline at end of file diff --git a/src/Client/Components/RunAppTab/DockerCompose.razor b/src/Client/Components/RunAppTab/DockerCompose.razor deleted file mode 100644 index 30a9fe0..0000000 --- a/src/Client/Components/RunAppTab/DockerCompose.razor +++ /dev/null @@ -1,19 +0,0 @@ - -
    -
  1. Build the image using the provided docker-compose file - @if (string.IsNullOrEmpty(TerminalPromptPrefix)) { -
    docker-compose up -d
    - } else { -
    PS @(TerminalPromptPrefix)> docker-compose up -d
    - } -
  2. - @AdditionalSteps -
-
- -@code { - [Parameter] - public RenderFragment AdditionalSteps { get; set; } - [Parameter] - public string TerminalPromptPrefix { get; set; } -} \ No newline at end of file diff --git a/src/Client/Components/RunAppTab/Kubernetes.razor b/src/Client/Components/RunAppTab/Kubernetes.razor deleted file mode 100644 index d890a48..0000000 --- a/src/Client/Components/RunAppTab/Kubernetes.razor +++ /dev/null @@ -1,105 +0,0 @@ - -
    -
  1. - Create a DockerFile in the same folder as @(ProjectName).csproj. -
    FROM mcr.microsoft.com/dotnet/core/sdk:3.0 AS build-env
    -WORKDIR /app
    -
    -# Copy csproj and restore as distinct layers
    -COPY *.csproj ./
    -RUN dotnet restore
    -
    -# Copy everything else and build
    -COPY . ./
    -RUN dotnet publish -c Release -o out
    -
    -# Build runtime image
    -FROM mcr.microsoft.com/dotnet/core/aspnet:2.2
    -WORKDIR /app
    -COPY --from=build-env /app/out .
    -ENTRYPOINT ["dotnet", "@(ProjectName).dll"]
    -
    -
  2. -
  3. - Buld the Docker image -
    docker build -t <YOUR_DOCKER_NAME>/@(ProjectName.ToLower()) <PATH_TO_PROJECT_FOLDER>
    -
  4. - With the container image built, you can test locally by running docker run -p 80:80 <YOUR_DOCKER_NAME>/@(ProjectName.ToLower()). Then navigate to http://localhost/api/values. -
  5. - Push the new docker image to the Docker container registry hub -
    docker push <YOUR_DOCKER_NAME>/@(ProjectName.ToLower())
    -
  6. -
  7. - Create a Kubernetes manifest.yml in the same folder as @(ProjectName).csproj. -
    ---
    -apiVersion: extensions/v1beta1
    -kind: Deployment
    -metadata:
    -  labels:
    -    app: @(ProjectName.Replace("_","-").ToLower())
    -  name: @(ProjectName.Replace("_","-").ToLower())
    -spec:
    -  replicas: 1
    -  template:
    -    metadata:
    -      labels:
    -        app: @(ProjectName.Replace("_","-").ToLower())
    -      name: @(ProjectName.Replace("_","-").ToLower())
    -    spec:
    -      containers:
    -      - name: @(ProjectName.Replace("_","-").ToLower())
    -        imagePullPolicy: IfNotPresent
    -        image: <YOUR_DOCKER_NAME>/@(ProjectName.ToLower())
    ----
    -apiVersion: v1
    -kind: Service
    -metadata:
    -  name: @(ProjectName.Replace("_","-").ToLower())
    -  labels:
    -    app: @(ProjectName.Replace("_","-").ToLower())
    -spec:
    -  ports:
    -  - port: 80
    -    targetPort: 80
    -  selector:
    -    app: @(ProjectName.Replace("_","-").ToLower())
    -  type: NodePort
    -
    - This manifest is using a specific apiVersion. Your K8 cluster version might differ. Learn more about api versions here. -
  8. -
  9. - Using the manifest, create the pod deployment. -
    kubectl apply -f <PATH_TO>\manifest.yml
    -
  10. - @*
  11. - Expose the new app for access. -
    kubectl expose deployment @(ProjectName.Replace("_","-").ToLower()) --type=NodePort --name=@(ProjectName.Replace("_","-").ToLower()) --port 80
    -		
  12. *@ - @if (IncludeNavigateToApp) { -
  13. - Along with deploying the app, the manifest also exposed a port for accessing the app external of the customer. To retrieve the assigned port look up the service info. -
    kubectl get svc @(ProjectName.Replace("_", "-").ToLower()) -o jsonpath='{.spec.ports[0].nodePort}'
    -
  14. -
  15. - You'll also need any one of the node IP addresses. To look them up retrieve node details and note the EXTERNAL-IP of the first node. -
    kubectl get nodes -o wide
    -
  16. -
  17. - Using the IP address from https://<EXTERNAL_IP_ADDRESS>:<PORT>/api/values to run the app. -
  18. - } - @AdditionalSteps -
- Once finished, to remove the deployment simply run kubectl delete pod,service,deployment @(ProjectName.Replace("_", "-").ToLower()) -
- - -@code { - [Parameter] - public string ProjectName { get; set; } = ""; - [Parameter] - public bool IncludeNavigateToApp { get; set; } = true; - - [Parameter] - public RenderFragment AdditionalSteps { get; set; } -} \ No newline at end of file diff --git a/src/Client/Components/RunAppTab/Local.razor b/src/Client/Components/RunAppTab/Local.razor deleted file mode 100644 index 7119c63..0000000 --- a/src/Client/Components/RunAppTab/Local.razor +++ /dev/null @@ -1,43 +0,0 @@ - -
    - @if (!string.IsNullOrEmpty(ProjectName) && !string.IsNullOrEmpty(LocalEndpointAddress)) - { -
  1. - Using the .NET cli -
    dotnet run <PATH_TO>\@(ProjectName).csproj
    - - @if (IncludeNavigateToApp) { -
    Navigate to the endpoint (you may need to change the port number) @LocalEndpointAddress
    - } -
  2. - } - @if (!string.IsNullOrEmpty(ProjectName) && !string.IsNullOrWhiteSpace(VSEndpointAddress)) - { -
  3. - Using Visual Studio -
    Choose the top Debug menu, then choose Start Debugging (F5). This should bring up a browser with the app running.
    - - @if (IncludeNavigateToApp){ -
    Navigate to the endpoint (you may need to change the port number) @VSEndpointAddress
    - } -
  4. - } - - @AdditionalSteps -
-
- -@code { - [Parameter] - public string ProjectName { get; set; } = null; - [Parameter] - public string LocalEndpointAddress { get; set; } = "http://localhost:5000/api/values"; - [Parameter] - public string VSEndpointAddress { get; set; } = "http://localhost:8080/api/values"; - [Parameter] - public bool IncludeNavigateToApp { get; set; } = true; - - [Parameter] - public RenderFragment AdditionalSteps { get; set; } - -} \ No newline at end of file diff --git a/src/Client/Components/StartInstanceTab/Azure.razor b/src/Client/Components/StartInstanceTab/Azure.razor deleted file mode 100644 index 2359550..0000000 --- a/src/Client/Components/StartInstanceTab/Azure.razor +++ /dev/null @@ -1,22 +0,0 @@ - - -
    -
  1. - Follow the Azure getting started guide to get a @ServiceName instance started -
  2. -
  3. Name the instance @InstanceName
  4. -
  5. As you set up the instance, note the credentials and connection string created. You'll need this in the following steps.
  6. - @AdditionalSteps -
-
- -@code { - [Parameter] - public string InstanceName { get; set; } = ""; - [Parameter] - public string ServiceName { get; set; } = ""; - [Parameter] - public RenderFragment AzureGettingStartedUrl { get; set; } - [Parameter] - public RenderFragment AdditionalSteps { get; set; } -} diff --git a/src/Client/Components/StartInstanceTab/CloudFoundry.razor b/src/Client/Components/StartInstanceTab/CloudFoundry.razor deleted file mode 100644 index 41d4ad5..0000000 --- a/src/Client/Components/StartInstanceTab/CloudFoundry.razor +++ /dev/null @@ -1,27 +0,0 @@ - - -
    -
  1. - Start an instance of @ServiceName, named @InstanceName -
    @CfCreateServiceCmd
    -
  2. -
  3. - Wait for service to be ready -
    cf services
    -
  4. - @AdditionalSteps -
-
- -@code { - [Parameter] - public string InstanceName { get; set; } = ""; - [Parameter] - public string ServiceName { get; set; } = ""; - [Parameter] - public RenderFragment CfCreateServiceCmd { get; set; } - [Parameter] - public bool ShowServiceLookup { get; set; } = true; - [Parameter] - public RenderFragment AdditionalSteps { get; set; } -} diff --git a/src/Client/Components/StartInstanceTab/Kubernetes.razor b/src/Client/Components/StartInstanceTab/Kubernetes.razor deleted file mode 100644 index 6df00c0..0000000 --- a/src/Client/Components/StartInstanceTab/Kubernetes.razor +++ /dev/null @@ -1,33 +0,0 @@ - - -
    -
  1. - Using Helm Charts, start the @ServiceName chart providing connecting values. Learn more about using Helm here. -
    @HelmCmd
    -
  2. - @* -
  3. - Expose the port, for connecting outside the cluster -
    kubectl port-forward svc/@InstanceName @Portnumber
    -			
  4. -
    *@ -
  5. - Once deployed, Helm will give feedback how to "connect to your instance directly from outside the K8s cluster". You'll need the host IP and port # in the following steps. -
  6. - @AdditionalSteps -
- Once finished, to remove the deployment simply run helm del --purge @InstanceName -
- -@code { - [Parameter] - public string InstanceName { get; set; } = ""; - [Parameter] - public string ServiceName { get; set; } = ""; - [Parameter] - public RenderFragment HelmGettingStartedUrl { get; set; } - [Parameter] - public RenderFragment HelmCmd { get; set; } - [Parameter] - public RenderFragment AdditionalSteps { get; set; } -} diff --git a/src/Client/Components/StartInstanceTab/Local.razor b/src/Client/Components/StartInstanceTab/Local.razor deleted file mode 100644 index 13484bf..0000000 --- a/src/Client/Components/StartInstanceTab/Local.razor +++ /dev/null @@ -1,21 +0,0 @@ - - -
    -
  1. - Using the Steeltoe dockerfile, start a local instance of @ServiceName. The dockerfile will choose the correct image based on your OS. -
    @DockerCmd
    -
  2. - @AdditionalSteps -
-
- -@code { - [Parameter] - public string InstanceName { get; set; } = ""; - [Parameter] - public string ServiceName { get; set; } = ""; - [Parameter] - public RenderFragment DockerCmd { get; set; } - [Parameter] - public RenderFragment AdditionalSteps { get; set; } -} diff --git a/src/Client/Components/UIInterfaces/ITab.cs b/src/Client/Components/UIInterfaces/ITab.cs deleted file mode 100644 index af3077f..0000000 --- a/src/Client/Components/UIInterfaces/ITab.cs +++ /dev/null @@ -1,9 +0,0 @@ -using Microsoft.AspNetCore.Components; - -namespace Steeltoe.Client.Components.UIInterfaces -{ - public interface ITab - { - RenderFragment ChildContent { get; } - } -} diff --git a/src/Client/Steeltoe.Client.csproj b/src/Client/Steeltoe.Client.csproj index 35b999a..7718a90 100644 --- a/src/Client/Steeltoe.Client.csproj +++ b/src/Client/Steeltoe.Client.csproj @@ -4,9 +4,5 @@ net8.0 enable - - - - diff --git a/src/Client/wwwroot/site-data/blog/tech-tutorial-use-kubernetes-for-modern-net-apps-steeltoe-and-project-tye-are-your-path-to-productivity.md b/src/Client/wwwroot/site-data/blog/tech-tutorial-use-kubernetes-for-modern-net-apps-steeltoe-and-project-tye-are-your-path-to-productivity.md deleted file mode 100644 index de353a2..0000000 --- a/src/Client/wwwroot/site-data/blog/tech-tutorial-use-kubernetes-for-modern-net-apps-steeltoe-and-project-tye-are-your-path-to-productivity.md +++ /dev/null @@ -1,143 +0,0 @@ -# Tech Tutorial: Use Kubernetes for Modern .NET Apps? Steeltoe and Project Tye are Your Path to Productivity - -I recently went through training to get my [Kubernetes Application Developer certification](https://www.cncf.io/certification/ckad/) (CKAD). I went into it with a decent amount of K8s knowledge and an even greater understanding of microservices. In fact my understanding of proper microservice architectures has raised my expectations for the tech I use. - -For example, I expect my selected platform to automatically provide some of the [12 factors](https://12factor.net/) I use in my design patterns. It should capture my streamed logs. It should allow me to autoscale app instances. It should allow for dynamic port binding. Everything should be immutable. And (the biggest one on my list) it should be architected in a way where I can recreate it locally while developing. Do these may seem like tall expectations? Perhaps, but any modern platform should do this. - -I (honestly) set my expectations of the training low. After all, Kubernetes is awesome for managing infrastructure. But it’s a little raw for developers. - -In an ideal world, a developer isn't interacting directly with infrastructure. They interact with GIT, which interacts with a CI/CD pipeline, which interacts with the runtime. But we live in the real world, and it's never going to be ideal. - -Having accepted an inevitable fate of yaml and dockerfile, my training taught me about all the developer tools in Kubernetes. Operators, controllers, namespaces, configmaps, secrets, and of course pods. My training took me through attaching disks and providing configurations to my app. It showed me how apps can interact with other apps in the same cluster through a DNS-like pattern. Powerful stuff! - -As I digested all this Kubernetes magic, a realization dawned on me. I don't want to follow Kubernetes patterns in my .NET application. I want to follow .NET patterns in my .NET application. How can I have a better developer experience using Kubernetes, and follow best practices for .NET? And how can I do it without having to create everything from scratch? - -Turns out, lots of other developers are wrestling with the same thing. But it gets better - the community has developed a project to deal with this exact scenario: [Steeltoe](https://steeltoe.io). - -Steeltoe 3.0 brings in Kubernetes goodies that abstract much of this toil away. When I coupled Steeltoe 3 with Microsoft’s [Project Tye](https://devblogs.microsoft.com/aspnet/introducing-project-tye/), my sky-high developer expectations are met. - -Let's look at how the combination of Steeltoe and Tye make consuming Kubernetes a whole lot easier. - -## Microservices should be given their configuration (and secrets) - -When you think of an application’s configuration value, a connection string is probably top of mind. It could really be anything. Typically microservices can't successfully start (or atleast run) without being fed proper values. - -As a microservice moves through its environments (local, staging, production) configuration values change, but the labels of the values are consistent. A microservice stays resilient to these changes by simply consuming the value it is fed. - -Further, configuration values come from different sources in different environments. A microservice should be smart enough to check every possible source and decide what value should be used. - -.NET Core introduced [configuration providers](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-3.1#configuration-providers) and a hierarchy to them. So it's natural that a Kubernetes configmap (which is just another key/value store) should be a config source in a .NET microservice. - -[Steeltoe offers a Kubernetes provider](https://steeltoe.io/docs/3/configuration/kubernetes-providers) to do just this! To add the client all you need to do is let the HostBuilder know about it. - -```csharp -public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) - .ConfigureWebHostDefaults(webBuilder => { - webBuilder.UseStartup(); - }) - .AddKubernetesConfiguration() -``` - -This little bit of code packs a powerful punch. Behind the scenes Steeltoe will use the key mappings to create a custom configuration provider and add it into the hierarchy. In turn all this will be added into the IConfiguration interface which is a part of dependency injection. This makes retrieving the values very straight forward. - -```csharp -private readonly IConfiguration config; - -public WeatherForecastController(IConfiguration config){ - _config = config; - - //To reference a specific value - //_config["my-setting"]; -} -``` - -Also included is the option to automatically refresh values. When enabled, your application will poll (or maintain an open connection) with the Kubernetes API server. Whenever a value in the ConfigMap is changed, your app’s values will also change -- no restart needed. Whenever a value is added or removed from the ConfigMap (or Secret) your app will automatically see those changes -- also no restart required. That's some cloud-native ninja action! - -Getting the value(s) of Kubernetes secrets to the application follows the same pattern as ConfigMaps. Additionally you can pick and choose which source should be made available to the application. [Learn more in the docs](https://steeltoe.io/docs/3/configuration/kubernetes-providers). - -## If all the services are in the same cluster... - -When your applications are running within the same Kubernetes cluster there is quite a bit to take advantage of. Load balancing, routing, and DNS services are a few. As it just so happens these are also the things needed for a very popular cloud-native pattern called service discovery. - -Things lined up even more for Steeltoe as it already has a discovery client that lets you abstract the provider away. So naturally including the option to use a Kubernetes cluster as a discovery provider was a quick and easy thing. - -To implement the Steeltoe discovery client, add the `Steeltoe.Discovery.Kubernetes` nuget package to the application and implement the general discovery client in program.cs… - -```csharp -using Steeltoe.Discovery.Client; - -public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) - .ConfigureWebHostDefaults(webBuilder => { - webBuilder.UseStartup(); - }) - .AddDiscoveryClient() -``` - -The combination of adding a specific discovery client’s package and generally implementing the discovery client tells Steeltoe exactly what the app wants to do. Under the covers Steeltoe will manage all the interactions with the Kubernetes API. - -> [TIP] You can also include the Eureka or Consul client package along with generally implementing the discovery client. Steeltoe will add in the appropriate provisions for the desired provider. - -Steeltoe actively discovers endpoints for all applications registered in the cluster. Because registration is automatic in Kubernetes there’s really no work to be done. That's a very nice cloud-native gimme! - -An example to discover a service named ‘fortuneService’ that has an endpoint prefix of ‘/api/fortunes’ we can follow .NET best practices using an HTTPClient factory... - -```csharp -public void ConfigureServices(IServiceCollection services) { - services.AddHttpClient("fortunes", c => { - c.BaseAddress = new Uri("http://fortuneService/api/fortunes/"); - }) - .AddServiceDiscovery() - .AddTypedClient(); -} -``` - -Steeltoe will take care of reading the registry behind the scenes. To use the client’s built in factory use constructor injection and get on with life! - -```csharp -private readonly HttpClient _httpClient; - -public FortuneService(HttpClient httpClient, ILoggerFactory logFactory){ - _httpClient = httpClient; - - //To then call the service using provided HTTPclient - //Fortune[] fortunes = await _httpClient.GetJsonAsync("random-fortunes"); -} -``` - -[Customizable load-balancing](https://steeltoe.io/docs/3/discovery/load-balancing) between multiple application instances of the same service? Done. Automatic service registration? Done. Steeltoe and Kubernetes are like peanut butter and jelly. They were made for one another. - -## Teach Kubernetes what a healthy application is - -Any proper platform running containers is going to have a concept of health reporting. An application reports its heartbeat (usually as an HTTP endpoint) and is checked on some interval by its platform. If there are complications then the platform acts accordingly. - -In Kubernetes, there are two deeper probes offered named `readiness` and `liveness`. Readiness is about ensuring the application is ready to start receiving traffic. While liveness is about making sure the application is still healthy over time. - -Fortunately, Steeltoe is here to help set up both of these probes. Using new IHealthContributors and support for grouping, Steeltoe’s [health actuator endpoint](https://steeltoe.io/docs/3/management/health) builds several different views of the app’s dependencies. - -A view is a collection of decisions that reflect the current state of the application. For example if an application depends on a service and it (for some reason) goes offline, then the view should return a negative state. When the service is back up, then the view’s state should update to positive. - -The current state of the views are a part of the response body in the health actuator endpoint. Kubernetes uses this to know how the app is doing. - -Learn more about Steeltoe’s health endpoint with documentation and code snippets, [here](https://steeltoe.io/docs/3/management/health). - -## Develop locally, as if you’re already in production - -Just like the old saying “dance as if no one is watching”, an application should not care who’s watching (ie: which environment). It should start and run exactly the same everywhere. The ability to run the same type cluster no matter the [physical] environment is definitely one of Kubernetes super powers. And you have all kinds of options to run local K8s clusters (like Docker Desktop or Kind). - -But the question I ask myself before going down this path is, what am I really accomplishing? It’s a natural instinct to want to develop on the same platform that the app will be using, but is it worth the time needed for setup? Under the covers there are really just a few primities that enable your application and its dependent services to do their job - container management and request routing with some sort of DNS. Yes there are all kinds of other fancy ingress, egress, service mesh, etc etc things going on in Kubernetes. And yes they are all a part of deciding if your app is actually going to work on the platform, but should they be a part of development? You’re never going to recreate all the firewalls, reverse proxies, certificates, and switches that requests have to traverse. And if we’re doing microservices the right way, the application shouldn’t care one bit about any of that stuff. - -The local development needs are: - -* The ability to build and run containers (ie: Docker) -* The ability to create a distinct container subnet and resolve names within -* The ability for an IDE running the application (in debugging mode) to interact with that subnet - -Say hello to [Project Tye](https://github.com/dotnet/tye). With Tye the environment is software defined as a manifest. Port assignment and container networking are done for you. You can run the application and all it’s services in individual containers. Or you could run the application from its IDE and just have Tye run the backing services. Most notably you can have Tye target Kubernetes as the intended platform. In fact you could switch between a local cluster and a hosted cluster with no change to the application! - -Project Tye solves a cloud-native developer’s biggest challenge, environment parity. It’s super friendly to all your existing .NET habits and doesn’t have much bias about an IDE. All you need is the [tool installed in the dotnet cli](https://github.com/dotnet/tye/blob/master/docs/getting_started.md) and Docker running… and maybe a little yaml skill. - -## Learn more and get started today - -To get started with any Steeltoe projects, head over to the [getting started guides](https://steeltoe.io/get-started). Combine this with the samples in the [Steeltoe GitHub repo](https://github.com/SteeltoeOSS/Samples), and you’ll have .NET microservices up and running before you know it! - -Want to get deeper into creating cloud-native .NET apps? Attend the VMware Pivotal Labs’s [4 -day .NET developer course](https://pivotal.io/platform-acceleration-lab/pal-for-developers-net). You’ll get hands-on cloud-native .NET training learn best practices when creating microservices and become a Steeltoe ninja!