Commit e7c537cd by 据说甜蜜呢

添加项目文件。

parent 302ed7aa
Pipeline #4052 failed in 0 seconds
stages:
- build
- staging-release-major
- prod-release-major
build_job:
stage: build
script:
- echo "begin build..."
- dotnet build MicroService.AutoDevOpsPipeLines.sln
- echo "build successful."
tags:
- local
major-staging_job:
stage: major-staging
script:
# Continuous integration
- export RegistryHost='registry.geekbuying.com:8100'
- chmod +x ./build/CI.light.sh
- ./build/CI.light.sh
# Continuous delivery
# create config information
- export isCreateNamespace='1'
- export environment='Staging'
- export baseUrl='https://172.24.83.222:6443'
- export accessToken=''
- chmod +x ./build/CreateConfigMaps.sh
- ./build/CreateConfigMaps.sh
# create application component
- export kongServiceBaseUrl='http://127.0.0.1:81/services'
- export kongRouteBaseUrl='http://127.0.0.1:81/routes'
- export kongRouteDomain='staging-api.geekbuy.cn'
- chmod +x ./build/GrayRelease.sh
- ./build/GrayRelease.sh
only:
- rel/major
tags:
- staging
\ No newline at end of file

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.28307.136
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{0BF6F42B-B1A4-4E7A-BA32-A612F2F8A797}"
ProjectSection(SolutionItems) = preProject
devops\app.props = devops\app.props
devops\deploy.props = devops\deploy.props
devops\Gateways\kong.props = devops\Gateways\kong.props
devops\token.props = devops\token.props
devops\version.props = devops\version.props
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{779A24FC-0621-4085-AB80-9BD0BB6AF605}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{B7AEF66E-E1B9-4370-943F-E3573E58BACA}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Services", "Services", "{5267E5D9-2B87-4B75-92FD-111624A81E7D}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Basket", "Basket", "{C18FDD70-6D53-4007-8058-455DF6EA8C13}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Catalog", "Catalog", "{2B6EF9B0-35C8-469F-B241-F40C094F1B95}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Identity", "Identity", "{876548FD-6411-4833-906E-989C39386664}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Marketing", "Marketing", "{9FCEA7A6-0F43-4DF7-870F-3349F72CA0FA}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Ordering", "Ordering", "{45D19258-0B83-4FEA-99A9-346D5264EDF6}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Payment", "Payment", "{6FD53234-73B6-4A58-8CD8-7B5F4B575D34}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Basket.API", "src\Services\Basket\Basket.API\Basket.API.csproj", "{68DE6727-A0CB-4518-B8FD-016D5B841A09}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Catalog.API", "src\Services\Catalog\Catalog.API\Catalog.API.csproj", "{C901BCC7-4AE1-418C-8175-A72B74AC3584}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Identity.API", "src\Services\Identity\Identity.API\Identity.API.csproj", "{394FF665-294F-4847-8E7F-E58F1B142FAF}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Marketing.API", "src\Services\Marketing\Marketing.API\Marketing.API.csproj", "{CA029472-5637-4239-9168-AF282D96D859}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ordering.API", "src\Services\Ordering\Ordering.API\Ordering.API.csproj", "{7E09569A-D9D7-4B6B-8B34-DB3C832073E2}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Payment.API", "src\Services\Payment\Payment.API\Payment.API.csproj", "{0178BB26-8B37-4BFF-97AE-764D46593920}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ServicesTests", "ServicesTests", "{9F378944-D65E-4FA7-AA34-23BF342112F8}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IntegrationTest", "test\ServicesTests\IntegrationTest\IntegrationTest.csproj", "{94C559A6-82AA-4149-9616-E6EC78753766}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "BuildingBlocks", "BuildingBlocks", "{E53A0586-2FB1-4708-91A9-4D6814E02E3C}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Extensions", "Extensions", "{26EA0840-FACE-4F72-B7D0-64CA9443BD9F}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MvcExtensions", "src\BuildingBlocks\Extensions\MvcExtensions\MvcExtensions.csproj", "{8E88AA1F-8D4F-4FA6-9B94-03203BB5F739}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{68DE6727-A0CB-4518-B8FD-016D5B841A09}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{68DE6727-A0CB-4518-B8FD-016D5B841A09}.Debug|Any CPU.Build.0 = Debug|Any CPU
{68DE6727-A0CB-4518-B8FD-016D5B841A09}.Release|Any CPU.ActiveCfg = Release|Any CPU
{68DE6727-A0CB-4518-B8FD-016D5B841A09}.Release|Any CPU.Build.0 = Release|Any CPU
{C901BCC7-4AE1-418C-8175-A72B74AC3584}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C901BCC7-4AE1-418C-8175-A72B74AC3584}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C901BCC7-4AE1-418C-8175-A72B74AC3584}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C901BCC7-4AE1-418C-8175-A72B74AC3584}.Release|Any CPU.Build.0 = Release|Any CPU
{394FF665-294F-4847-8E7F-E58F1B142FAF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{394FF665-294F-4847-8E7F-E58F1B142FAF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{394FF665-294F-4847-8E7F-E58F1B142FAF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{394FF665-294F-4847-8E7F-E58F1B142FAF}.Release|Any CPU.Build.0 = Release|Any CPU
{CA029472-5637-4239-9168-AF282D96D859}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CA029472-5637-4239-9168-AF282D96D859}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CA029472-5637-4239-9168-AF282D96D859}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CA029472-5637-4239-9168-AF282D96D859}.Release|Any CPU.Build.0 = Release|Any CPU
{7E09569A-D9D7-4B6B-8B34-DB3C832073E2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7E09569A-D9D7-4B6B-8B34-DB3C832073E2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7E09569A-D9D7-4B6B-8B34-DB3C832073E2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7E09569A-D9D7-4B6B-8B34-DB3C832073E2}.Release|Any CPU.Build.0 = Release|Any CPU
{0178BB26-8B37-4BFF-97AE-764D46593920}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0178BB26-8B37-4BFF-97AE-764D46593920}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0178BB26-8B37-4BFF-97AE-764D46593920}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0178BB26-8B37-4BFF-97AE-764D46593920}.Release|Any CPU.Build.0 = Release|Any CPU
{94C559A6-82AA-4149-9616-E6EC78753766}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{94C559A6-82AA-4149-9616-E6EC78753766}.Debug|Any CPU.Build.0 = Debug|Any CPU
{94C559A6-82AA-4149-9616-E6EC78753766}.Release|Any CPU.ActiveCfg = Release|Any CPU
{94C559A6-82AA-4149-9616-E6EC78753766}.Release|Any CPU.Build.0 = Release|Any CPU
{8E88AA1F-8D4F-4FA6-9B94-03203BB5F739}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8E88AA1F-8D4F-4FA6-9B94-03203BB5F739}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8E88AA1F-8D4F-4FA6-9B94-03203BB5F739}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8E88AA1F-8D4F-4FA6-9B94-03203BB5F739}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{5267E5D9-2B87-4B75-92FD-111624A81E7D} = {779A24FC-0621-4085-AB80-9BD0BB6AF605}
{C18FDD70-6D53-4007-8058-455DF6EA8C13} = {5267E5D9-2B87-4B75-92FD-111624A81E7D}
{2B6EF9B0-35C8-469F-B241-F40C094F1B95} = {5267E5D9-2B87-4B75-92FD-111624A81E7D}
{876548FD-6411-4833-906E-989C39386664} = {5267E5D9-2B87-4B75-92FD-111624A81E7D}
{9FCEA7A6-0F43-4DF7-870F-3349F72CA0FA} = {5267E5D9-2B87-4B75-92FD-111624A81E7D}
{45D19258-0B83-4FEA-99A9-346D5264EDF6} = {5267E5D9-2B87-4B75-92FD-111624A81E7D}
{6FD53234-73B6-4A58-8CD8-7B5F4B575D34} = {5267E5D9-2B87-4B75-92FD-111624A81E7D}
{68DE6727-A0CB-4518-B8FD-016D5B841A09} = {C18FDD70-6D53-4007-8058-455DF6EA8C13}
{C901BCC7-4AE1-418C-8175-A72B74AC3584} = {2B6EF9B0-35C8-469F-B241-F40C094F1B95}
{394FF665-294F-4847-8E7F-E58F1B142FAF} = {876548FD-6411-4833-906E-989C39386664}
{CA029472-5637-4239-9168-AF282D96D859} = {9FCEA7A6-0F43-4DF7-870F-3349F72CA0FA}
{7E09569A-D9D7-4B6B-8B34-DB3C832073E2} = {45D19258-0B83-4FEA-99A9-346D5264EDF6}
{0178BB26-8B37-4BFF-97AE-764D46593920} = {6FD53234-73B6-4A58-8CD8-7B5F4B575D34}
{9F378944-D65E-4FA7-AA34-23BF342112F8} = {B7AEF66E-E1B9-4370-943F-E3573E58BACA}
{94C559A6-82AA-4149-9616-E6EC78753766} = {9F378944-D65E-4FA7-AA34-23BF342112F8}
{E53A0586-2FB1-4708-91A9-4D6814E02E3C} = {779A24FC-0621-4085-AB80-9BD0BB6AF605}
{26EA0840-FACE-4F72-B7D0-64CA9443BD9F} = {E53A0586-2FB1-4708-91A9-4D6814E02E3C}
{8E88AA1F-8D4F-4FA6-9B94-03203BB5F739} = {26EA0840-FACE-4F72-B7D0-64CA9443BD9F}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {94A499F2-8AA4-43FC-9824-F095E42D54AB}
EndGlobalSection
EndGlobal
# MicroService.AutoDevOpsPipeLines
Build a mature and stable automated DevOps pipeline with minimum learning cost, and continuously integrate/deploy AspnetCore micro-services to kubernetes.
以最小的学习成本搭建一套成熟稳定的自动化DevOps管道,持续集成/部署微服务(AspnetCore)到kubernetes。
<Project>
<PropertyGroup>
<ServiceUrl></ServiceUrl>
</PropertyGroup>
</Project>
#!/bin/bash
set -e
IFS=$'\n\n'
declare appName=($(grep -oP '(?<=AppName>)[^<]+' "devops/app.props"))
echo "Begin creating ${appName}'s settings to the configmap of k8s..."
function Create()
{
declare createUrl="$3/api/v1/namespaces/$2/configmaps?pretty=true"
echo "[environment: $1, namespace: $2]"
function send()
{
set +e
declare deleteUrl="${3}/api/v1/namespaces/${2}/configmaps/$5"
curl -X DELETE $deleteUrl -k \
--connect-timeout $2 --max-time $3 --retry $4 \
-H 'Authorization: Bearer '${AccessToken}''
set -e
declare configInfo=$(cat $1 | jq tostring)
curl -X POST $createUrl -k \
--connect-timeout $2 --max-time $3 --retry $4 \
-H 'Content-Type: application/json' \
-H 'cache-control: no-cache' \
-H 'Authorization: Bearer '${AccessToken}'' \
-d '{
"kind": "ConfigMap",
"apiVersion": "v1",
"metadata": {
"name": "'$5'",
"namespace": "'${namespace}'"
},
"data": {
"'$6'":'"$configInfo"'
}
}'
}
declare maxTime=30
declare maxConnectTime=20
declare retryCount=5
send "$4/appsettings.json" $maxConnectTime $maxTime $retryCount "$5.appsettings.json" "appsettings.json"
send "$4/appsettings.$1.json" $maxConnectTime $maxTime $retryCount "$(echo $5.appsettings.$1.json | tr 'A-Z' 'a-z')" "appsettings.$1.json"
}
declare major=($(grep -oP '(?<=VersionMajor>)[^<]+' "devops/version.props"))
declare namespace=($(grep -oP '(?<=Namespace>)[^<]+' "devops/app.props"))
declare namespaceOfK8s=$(echo "${namespace}-v${major}" | tr 'A-Z' 'a-z')
declare k8sApiServer=($(grep -oP '(?<=K8sApiServer>)[^<]+' "devops/deploy.props"))
kubectl create namespace ${namespaceOfK8s}
declare services=$(ls -l src/services | awk 'NR>1')
declare servicePrefix=""
for service in ${services}
do
servicePrefix=($(echo ${service} | awk '{print $9}'))
Create ${Environment} ${namespaceOfK8s} ${k8sApiServer} "./src/${servicePrefix}.API" "${servicePrefix}"
done
echo ""
echo "End creating app settings to the configmap of k8s..."
\ No newline at end of file
#!/bin/bash
set -e
IFS=$'\n\n'
declare appName=($(grep -oP '(?<=AppName>)[^<]+' "devops/app.props"))
echo "Release for ${appName} starting, dynamicly creating k8s environment..."
declare major=($(grep -oP '(?<=Major>)[^<]+' "devops/version.props"))
declare minor=($(grep -oP '(?<=Minor>)[^<]+' "devops/version.props"))
declare patch=($(grep -oP '(?<=Patch>)[^<]+' "devops/version.props"))
declare namespace=($(grep -oP '(?<=Namespace>)[^<]+' "devops/app.props"))
declare version=${major}.${minor}.${patch}
declare namespaceOfK8s=$(echo "${namespace}-v${major}" | tr 'A-Z' 'a-z')
declare releaseName="${appName}-v${major}"
echo ""
echo "Please check the image version of each microservice carefully !!!"
echo "kubernetes's namespace: ${namespaceOfK8s}"
declare services=$(ls -l src/services | awk 'NR>1')
declare servicePrefix=""
for service in ${services}
do
servicePrefix=($(echo ${service} | awk '{print $9}'))
echo "${servicePrefix}: ${version}"
done
echo ""
declare replicas=($(grep -oP '(?<=Replicas>)[^<]+' "devops/app.props"))
helm install /root/AutoDevOpsPipeLinesCharts \
--name=${releaseName} \
--set environment.upper=${Environment} \
--set environment.lower=$(echo ${Environment} | tr 'A-Z' 'a-z') \
--set namespace=${namespaceOfK8s} \
--set image.version=${version} \
--set replicas=${replicas}
echo ""
echo "Dynamicly creating k8s environment Successfully !!!"
\ No newline at end of file
#!/bin/bash
set -e
IFS=$'\n\n'
declare appName=($(grep -oP '(?<=AppName>)[^<]+' "devops/app.props"))
echo "Start building the gateway for ${appName} route dynamically..."
declare namespace=($(grep -oP '(?<=Namespace>)[^<]+' "devops/app.props"))
declare namespaceOfK8s=$(echo "${appName}-v${major}" | tr 'A-Z' 'a-z')
declare fdnOfK8s="${namespaceOfK8s}.svc.cluster.local"
declare kongServiceUrl=($(grep -oP '(?<=Namespace>)[^<]+' "devops/app.props"))
declare major=($(grep -oP '(?<=Major>)[^<]+' "devops/version.props"))
declare releaseVersion="v${major}"
# resilience handle
# Maximum time in seconds that you allow the whole operation to take.
declare maxTime=5
# Maximum time in seconds that you allow the connection to the server to take.
declare maxConnectTime=2
declare retryCount=5
## add services
function createService()
{
curl -X POST $1 \
--connect-timeout $2 \
--max-time $3 \
--retry $4 \
-H "accept: application/json" \
-H "Content-Type: application/json" \
-d "{ \"name\": \"$5\", \"url\": \"$6\"}";
}
## add routes
function createRoute()
{
declare svcResponse=$(curl -X GET ${kongServiceBaseUrl}/$5 --connect-timeout $2 --max-time $3 --retry $4)
declare JQ_EXEC=`which jq`
declare svcId=$(echo $svcResponse | ${JQ_EXEC} .id | sed 's/\"//g')
declare defMethods="[\"GET\",\"POST\"]"
set +e
if [ -n "$8" ]; then
defMethods=$8
fi
if [ -z "$svcId" ]; then
echo "Warnning, failed to get the service[$5] identifier, route cannot be created.";
else
# idempotent
declare routesAdded=$(curl -X GET ${kongServiceBaseUrl}/$5/routes)
declare routeid=$(echo $routesAdded | ${JQ_EXEC} .data[0].id | sed 's/\"//g')
if [ "$routeid" == "null" ]; then
curl -X POST $1 \
--connect-timeout $2 \
--max-time $3 \
--retry $4 \
-H "accept: application/json" \
-H "Content-Type: application/json" \
-d "{ \"service\": "{\"id\":\"$svcId\"}",\"paths\": "[\"$6\"]",\"methods\": "$defMethods",\"strip_path\":$7,\"hosts\": "[\"$kongRouteDomain\"]"}";
fi
fi
set -e
}
declare services=$(ls -l src/services | awk 'NR>1')
declare servicePrefix=""
declare serviceName=""
declare serviceNameWithVersion=""
declare serviceFullName=""
declare serviceUrl=""
declare serviceRouteUrl=""
for service in ${services}
do
servicePrefix=($(echo ${service} | awk '{print $9}'))
serviceName="${servicePrefix}-api"
serviceNameWithVersion="${serviceName}-${releaseVersion}"
serviceFullName="${serviceName}.${fdnOfK8s}"
serviceUrl="http://${serviceFullName}/api/${servicePrefix}"
echo "Begin creating service[${serviceNameWithVersion}]"
createService ${kongServiceUrl} ${maxConnectTime} ${maxTime} ${retryCount} ${serviceNameWithVersion} ${serviceUrl}
echo "Begin creating route of service[${serviceNameWithVersion}]"
serviceRouteUrl="/api/${releaseVersion}/${servicePrefix}"
createRoute ${kongServiceUrl} ${maxConnectTime} ${maxTime} ${retryCount} ${serviceNameWithVersion} ${serviceRouteUrl} true
done
echo ""
echo "Dynamicly building gateway route successfully !!!"
\ No newline at end of file
#!/bin/bash
set -e
IFS=$'\n\n'
function AddHeadConfig()
{
# sync config for later retries, not affected by cross-job.
echo "<Project>
<PropertyGroup>
<AllPublishable>${1}</AllPublishable>
<NoPublishable>${2}</NoPublishable>" > /tmp/cicd.props
}
function AddConfig()
{
# sync config for later retries, not affected by cross-job.
declare name=${1}
declare publishable=${2}
if [ "${publishable}" == "1" ]; then
echo "<${name}Publishable>${publishable}</${name}Publishable>" >> /tmp/cicd.props
fi
}
function AddTailConfig()
{
echo "</PropertyGroup>
</Project>" >> /tmp/cicd.props
}
if [ "${AllPublishable}" == "1" ];
then
AddHeadConfig "1","0"
AddTailConfig
echo "All micro-services will be released."
else
echo "Start analyzing the git difference log..."
echo ""
echo "the difference: "
git diff --name-only ORIG_HEAD
echo ""
declare changes=$(git diff --name-only ORIG_HEAD)
# Publishable by prefix
function IsPublishable()
{
if
echo $changes | grep "$1" > /dev/null
then
eval "$2='1'"
else
eval "$2='0'"
let count=$3+1
eval $3="${count}"
fi
}
declare services=$(ls -l src/services | awk 'NR>1')
declare servicePrefix=""
declare isPublishable
declare publishableCount=0;
AddHeadConfig "1","0"
for service in ${services}
do
servicePrefix=($(echo ${service} | awk '{print $9}'))
# Notes: manual control, mandatory release, will not analyzing changes
isPublishable=$(eval echo ${servicePrefix}Publishable)
if [ "${isPublishable}" == "1" ];
then
AddConfig "${servicePrefix}" "${isPublishable}"
echo "Tips[Hard Release]: ${servicePrefix} will be released."
else
# Analyzing git changes
IsPublishable "src/${servicePrefix}" isPublishable publishableCount
AddConfig "${servicePrefix}" "${isPublishable}"
echo "Tips[Soft Release]: ${servicePrefix} will be released."
fi
done
AddTailConfig
declare serviceCount=$(ls -l src/services | grep "^d" | wc -l)
if [ "${publishableCount}" == "${serviceCount}" ] ;
then
AddHeadConfig "0","1"
AddTailConfig
echo "Tips: No services need to be released."
fi
echo ""
echo "End analyzing the difference log..."
fi
\ No newline at end of file
#!/bin/bash
set -e
IFS=$'\n\n'
declare appName=($(grep -oP '(?<=AppName>)[^<]+' "devops/app.props"))
echo "Begin creating ${appName}'s settings to the configmap of k8s..."
declare noPublishable=($(grep -oP '(?<=NoPublishable>)[^<]+' "/tmp/cicd.props"))
if [ "${noPublishable}" == "1" ] ;
then
echo ""
echo "Tips: No services need to be synced config."
else
function create()
{
if [ "$6" == "1" ];
then
declare createUrl="$3/api/v1/namespaces/$2/configmaps?pretty=true"
echo "[environment: $1, namespace: $2]"
function send()
{
set +e
declare deleteUrl="$3/api/v1/namespaces/$2/configmaps/$5"
curl -X DELETE $deleteUrl -k \
--connect-timeout $2 --max-time $3 --retry $4 \
-H 'Authorization: Bearer '${AccessToken}''
set -e
declare configInfo=$(cat $1 | jq tostring)
curl -X POST $createUrl -k \
--connect-timeout $2 --max-time $3 --retry $4 \
-H 'Content-Type: application/json' \
-H 'cache-control: no-cache' \
-H 'Authorization: Bearer '${AccessToken}'' \
-d '{
"kind": "ConfigMap",
"apiVersion": "v1",
"metadata": {
"name": "'$5'",
"namespace": "'${namespace}'"
},
"data": {
"'$6'":'"$configInfo"'
}
}'
}
declare maxTime=30
declare maxConnectTime=20
declare retryCount=5
send "$4/appsettings.json" $maxConnectTime $maxTime $retryCount "$5.appsettings.json" "appsettings.json"
send "$4/appsettings.$1.json" $maxConnectTime $maxTime $retryCount "$(echo $5.appsettings.$1.json | tr 'A-Z' 'a-z')" "appsettings.$1.json"
else
echo ""
echo "Tips: $5 will not be synced config!!!"
fi
}
declare major=($(grep -oP '(?<=VersionMajor>)[^<]+' "devops/version.props"))
declare namespace=($(grep -oP '(?<=Namespace>)[^<]+' "devops/app.props"))
declare namespaceOfK8s=$(echo "${namespace}-v${major}" | tr 'A-Z' 'a-z')
declare k8sApiServer=($(grep -oP '(?<=K8sApiServer>)[^<]+' "devops/deploy.props"))
declare services=$(ls -l src/services | awk 'NR>1')
declare servicePrefix=""
for service in ${services}
do
servicePrefix=($(echo ${service} | awk '{print $9}'))
declare isPublishable=($(grep -oP "(?<=${servicePrefix}Publishable>)[^<]+" "/tmp/cicd.props"))
Create ${Environment} ${namespaceOfK8s} ${k8sApiServer} "./src/${servicePrefix}.API" "${servicePrefix}" ${isPublishable}
done
fi
echo ""
echo "End creating app settings to the configmap of k8s..."
\ No newline at end of file
#!/bin/bash
set -e
declare appName=($(grep -oP '(?<=AppName>)[^<]+' "devops/app.props"))
echo "Continuous integration for ${appName} starting..."
echo "build solution..."
declare noPublishable=($(grep -oP '(?<=NoPublishable>)[^<]+' "/tmp/cicd.props"))
if [ "${noPublishable}" == "1" ] ;
then
echo ""
echo "Tips: No services need to be cied."
else
declare solutionName=($(grep -oP '(?<=SolutionName>)[^<]+' "devops/app.props"))
dotnet build ${solutionName}
echo "Please check the version of each microservice carefully !!!"
declare major=($(grep -oP '(?<=VersionMajor>)[^<]+' "build/version.props"))
declare minor=($(grep -oP '(?<=VersionMinor>)[^<]+' "build/version.props"))
declare patch=($(grep -oP '(?<=VersionPatch>)[^<]+' "build/version.props"))
declare version=${major}.${minor}.${patch}
declare registryHost=($(grep -oP '(?<=ImageRegistryHost>)[^<]+' "build/deploy.props"))
declare registryUserName=($(grep -oP '(?<=ImageUserName>)[^<]+' "build/deploy.props"))
declare publishOutputDir=./publish
rm -fr ${publishOutputDir}
mkdir -p ${publishOutputDir}
function CI()
{
declare publishable=$1
declare imagename=$2
echo ""
if [ "${publishable}" == "1" ];
then
declare imagefullname=${registryHost}/${registryUserName}/${imagename}:${version}
declare publishFile=$3
echo "begin delivery of master branch for ${imagename}..."
mkdir -p ${publishOutputDir}/${imagename}
dotnet publish ${publishFile} -o ../../publish/${imagename} -c release --no-restore
docker build -t ${imagefullname} ${publishOutputDir}/${imagename}
docker push ${imagefullname}
echo "delivery of master branch for ${imagename}:${version} has been successful."
else
echo "Tips: master branch for ${imagename}:${version} will not be cied!!!"
fi
}
# Import external functions
chmod +x ./devops/PipeLines/functions.sh
sh functions.sh
declare services=$(ls -l src/services | awk 'NR>1')
declare servicePrefix=""
declare serviceName=""
declare isPublishable="0"
for service in ${services}
do
servicePrefix=($(echo ${service} | awk '{print $9}'))
isPublishable=($(grep -oP "(?<=${servicePrefix}Publishable>)[^<]+" "/tmp/cicd.props"))
GetServiceName "${servicePrefix}" serviceName
CI ${isPublishable} "${servicePrefix}" "./src/${servicePrefix}/${serviceName}.csproj"
done
fi
echo ""
echo "Continuous integration for ${appName} has been successful."
\ No newline at end of file
#!/bin/bash
set -e
# Import external functions
chmod +x ./devops/PipeLines/functions.sh
sh ./devops/PipeLines/functions.sh
GetAppName appName
echo "Continuous deployment of ${Environment} branch for ${appName} starting..."
GetCiCdSettings allPublishable noPublishable
if [ "${noPublishable}" == "1" ] ;
then
echo ""
echo "Tips: No services need to be cded."
else
echo "Please check the version of each microservice carefully !!!"
echo ""
GetVersion version
GetNameSpace namespace
GetImageRegistrySettings registryHost registryUserName
function CD()
{
declare publishable=$1
declare appName=$2
declare imageName=$3
echo ""
if [ "${publishable}" == "1" ];
then
kubectl -n ${namespace} set image deployments/${appName} "${appName}=${registryHost}/${registryUserName}/${imageName}:${version}";
if [ "${Environment}" == "Staging" ]; then
kubectl -n ${namespace} scale deploy ${appName} --replicas=0;
kubectl -n ${namespace} scale deploy ${appName} --replicas=1;
fi
echo "deployment of ${Environment} branch for ${appName}:${version} has been successful."
else
echo "Tips: ${Environment} branch for ${appName}:${version} will not be cded!!!"
fi
}
declare services=$(ls -l src/services | awk 'NR>1')
declare servicePrefix=""
declare serviceName=""
declare isPublishable="0"
for service in ${services}
do
servicePrefix=($(echo ${service} | awk '{print $9}'))
isPublishable=($(grep -oP "(?<=${servicePrefix}Publishable>)[^<]+" "/tmp/cicd.props"))
GetServiceName "${servicePrefix}" serviceName
CD ${apiPublishable} "${serviceName}" "${serviceName}"
done
fi
echo ""
echo "Continuous deployment of ${Environment} branch for ${appName} has been successful."
#!/bin/bash
IFS=$'\n\n'
# Import external functions
chmod +x ./devops/PipeLines/functions.sh
sh ./devops/PipeLines/functions.sh
#1: ready, 0: not ready.
declare ready=0
GetNameSpace namespace
while [ $((${ready})) == 0 ]
do
sleep 10s
echo ""
declare allIsReady=1
for row in $(kubectl -n ${namespace} get deployment)
do
echo ""
declare name=$(echo "${row}"|awk '{print $1}')
declare desired=$(echo "${row}"|awk '{print $2}')
declare current=$(echo "${row}"|awk '{print $3}')
declare uptodate=$(echo "${row}"|awk '{print $4}')
declare available=$(echo "${row}"|awk '{print $5}')
echo "deployment: ${name}, desired: ${desired}, current: ${current}, uptodate: ${uptodate}, available: ${available}"
if [ $((${desired})) == $((${current})) -a $((${current})) == $((${uptodate})) -a $((${uptodate})) == $((${available})) ]; then
echo "${name} has been ready.";
else
echo "${name} has been not ready.";
allIsReady=0
fi
done
if [ $((${allIsReady})) == 1 ]; then
ready=1
fi
done
\ No newline at end of file
#!/bin/bash
IFS=$'\n\n'
# Import external functions
chmod +x ./devops/PipeLines/functions.sh
sh ./devops/PipeLines/functions.sh
GetNameSpace namespace
declare replicas=$(kubectl -n ${namespace} get rs)
for row in $replicas
do
declare name=$(echo "${row}"|awk '{print $1}')
declare desired=$(echo "${row}"|awk '{print $2}')
declare current=$(echo "${row}"|awk '{print $3}')
declare ready=$(echo "${row}"|awk '{print $4}')
# echo "replica set: ${name}, desired: ${desired}"
if [ $((${desired})) == 0 -a $((${current})) == 0 -a $((${ready})) == 0 ]; then
# echo ${name}
kubectl -n ${namespace} delete rs ${name} --grace-period=0 --force
fi
done
echo 'clean successful...'
exit 0
\ No newline at end of file
#!/bin/bash
set -e
function GetServiceName()
{
declare servicePrefix=${1}
declare serviceName=$(ls ./src/services/${servicePrefix}|head -n 1|xargs -d '/' echo)
$2="${serviceName}"
}
function GetAppName()
{
declare appName=($(grep -oP '(?<=AppName>)[^<]+' "devops/app.props"))
$1="${appName}"
}
function GetCiCdSettings()
{
declare allPublishable=($(grep -oP '(?<=AllPublishable>)[^<]+' "/tmp/cicd.props"))
declare noPublishable=($(grep -oP '(?<=NoPublishable>)[^<]+' "/tmp/cicd.props"))
}
function GetMajor()
{
declare major=($(grep -oP '(?<=VersionMajor>)[^<]+' "devops/version.props"))
$1=${major}
}
function GetVersion()
{
declare major=($(grep -oP '(?<=VersionMajor>)[^<]+' "devops/version.props"))
declare minor=($(grep -oP '(?<=VersionMinor>)[^<]+' "devops/version.props"))
declare patch=($(grep -oP '(?<=VersionPatch>)[^<]+' "devops/version.props"))
declare version=${major}.${minor}.${patch}
$1=${version}
}
function GetImageRegistrySettings()
{
declare host=($(grep -oP '(?<=ImageRegistryHost>)[^<]+' "devops/deploy.props"))
declare username=($(grep -oP '(?<=ImageUserName>)[^<]+' "devops/deploy.props"))
$1=${host}
$2=${username}
}
\ No newline at end of file
<Project>
<PropertyGroup>
<NameSpace>microservice-autodevopspipeline</NameSpace>
<AppName>MicroService.AutoDevOpsPipeLine</AppName>
<SolutionName>MicroService.AutoDevOpsPipeLines.sln</SolutionName>
</PropertyGroup>
</Project>
<Project>
<PropertyGroup>
<Replicas>1</Replicas>
<ImageRegistryHost></ImageRegistryHost>
<ImageUserName></ImageUserName>
<K8sApiServer></K8sApiServer>
</PropertyGroup>
</Project>
<Project>
<PropertyGroup>
<Kubernetes>
<AccessToken>
<Staging></Staging>
<Production></Production>
</AccessToken>
</Kubernetes>
</PropertyGroup>
</Project>
<Project>
<PropertyGroup>
<Major>0</Major>
<Minor>0</Minor>
<Patch>1</Patch>
</PropertyGroup>
</Project>
apiVersion: v1
appVersion: "1.0"
description: A Helm chart for Kubernetes
name: light
version: 0.1.0
## 为我们的项目创建chart目录
helm create AutoDevOpsPipeLinesCharts
## 安装
## 渲染模板(调试)
```shell
helm install --debug --dry-run /root/AutoDevOpsPipeLinesCharts \
--set environment.upper=Production \
--set environment.lower=production \
--set namespace=geekbuying-light-v2 \
--set image.version=2.0.0
```
## 发布版本
```shell
helm install /root/AutoDevOpsPipeLinesCharts \
--name=geekbuying-light-v2 \
--set environment.upper=Production \
--set environment.lower=production \
--set namespace=geekbuying-light-v3 \
--set image.version=2.0.0
```
## 检视发布
helm get manifest [release name]
## 删除发布
helm delete [release name]
## 其他
helm ls
helm ls --deleted -d
helm del --purge $releaseName
\ No newline at end of file
apiVersion: apps/v1
kind: Deployment
metadata:
name: identity-api
namespace: {{ .Values.namespace }}
spec:
selector:
matchLabels:
app: auto-devops-pipelines
component: identity
type: webapi
replicas: {{ .Values.replicas }}
template:
metadata:
labels:
app: auto-devops-pipelines
component: identity
type: webapi
spec:
volumes:
- name: appsetting
configMap:
name: identity.appsettings.json
- name: appsetting-{{ .Values.environment.lower }}
configMap:
name: identity.appsettings.{{ .Values.environment.lower }}.json
containers:
- name: identity-api
image: {{ .Values.image.registryhost }}{{ .Values.image.username }}identity.api:{{ .Values.image.version }}
imagePullPolicy: Always
ports:
- containerPort: 80
readinessProbe:
httpGet:
path: /healthchecks
port: 80
scheme: HTTP
initialDelaySeconds: 5
periodSeconds: 60
volumeMounts:
- name: appsetting
mountPath: "/app/appsettings.json"
subPath: "appsettings.json"
- name: appsetting-{{ .Values.environment.lower }}
mountPath: "/app/appsettings.{{ .Values.environment.upper }}.json"
subPath: "appsettings.{{ .Values.environment.upper }}.json"
env:
- name: ASPNETCORE_ENVIRONMENT
value: "{{ .Values.environment.upper }}"
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: basket-api
namespace: {{ .Values.namespace }}
spec:
selector:
matchLabels:
app: auto-devops-pipelines
component: basket
type: webapi
replicas: {{ .Values.replicas }}
template:
metadata:
labels:
app: auto-devops-pipelines
component: basket
type: webapi
spec:
volumes:
- name: appsetting
configMap:
name: basket.appsettings.json
- name: appsetting-{{ .Values.environment.lower }}
configMap:
name: basket.appsettings.{{ .Values.environment.lower }}.json
containers:
- name: basket-api
image: {{ .Values.image.registryhost }}{{ .Values.image.username }}basket.api:{{ .Values.image.version }}
imagePullPolicy: Always
ports:
- containerPort: 80
readinessProbe:
httpGet:
path: /healthchecks
port: 80
scheme: HTTP
initialDelaySeconds: 5
periodSeconds: 60
volumeMounts:
- name: appsetting
mountPath: "/app/appsettings.json"
subPath: "appsettings.json"
- name: appsetting-{{ .Values.environment.lower }}
mountPath: "/app/appsettings.{{ .Values.environment.upper }}.json"
subPath: "appsettings.{{ .Values.environment.upper }}.json"
env:
- name: ASPNETCORE_ENVIRONMENT
value: "{{ .Values.environment.upper }}"
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: catalog-api
namespace: {{ .Values.namespace }}
spec:
selector:
matchLabels:
app: auto-devops-pipelines
component: catalog
type: webapi
replicas: {{ .Values.replicas }}
template:
metadata:
labels:
app: auto-devops-pipelines
component: catalog
type: webapi
spec:
volumes:
- name: appsetting
configMap:
name: catalog.appsettings.json
- name: appsetting-{{ .Values.environment.lower }}
configMap:
name: catalog.appsettings.{{ .Values.environment.lower }}.json
containers:
- name: catalog-api
image: {{ .Values.image.registryhost }}{{ .Values.image.username }}catalog.api:{{ .Values.image.version }}
imagePullPolicy: Always
ports:
- containerPort: 80
readinessProbe:
httpGet:
path: /healthchecks
port: 80
scheme: HTTP
initialDelaySeconds: 5
periodSeconds: 60
volumeMounts:
- name: appsetting
mountPath: "/app/appsettings.json"
subPath: "appsettings.json"
- name: appsetting-{{ .Values.environment.lower }}
mountPath: "/app/appsettings.{{ .Values.environment.upper }}.json"
subPath: "appsettings.{{ .Values.environment.upper }}.json"
env:
- name: ASPNETCORE_ENVIRONMENT
value: "{{ .Values.environment.upper }}"
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: marketing-api
namespace: {{ .Values.namespace }}
spec:
selector:
matchLabels:
app: auto-devops-pipelines
component: marketing
type: webapi
replicas: {{ .Values.replicas }}
template:
metadata:
labels:
app: auto-devops-pipelines
component: marketing
type: webapi
spec:
volumes:
- name: appsetting
configMap:
name: marketing.appsettings.json
- name: appsetting-{{ .Values.environment.lower }}
configMap:
name: marketing.appsettings.{{ .Values.environment.lower }}.json
containers:
- name: marketing-api
image: {{ .Values.image.registryhost }}{{ .Values.image.username }}marketing.api:{{ .Values.image.version }}
imagePullPolicy: Always
ports:
- containerPort: 80
readinessProbe:
httpGet:
path: /healthchecks
port: 80
scheme: HTTP
initialDelaySeconds: 5
periodSeconds: 60
volumeMounts:
- name: appsetting
mountPath: "/app/appsettings.json"
subPath: "appsettings.json"
- name: appsetting-{{ .Values.environment.lower }}
mountPath: "/app/appsettings.{{ .Values.environment.upper }}.json"
subPath: "appsettings.{{ .Values.environment.upper }}.json"
env:
- name: ASPNETCORE_ENVIRONMENT
value: "{{ .Values.environment.upper }}"
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: ordering-api
namespace: {{ .Values.namespace }}
spec:
selector:
matchLabels:
app: auto-devops-pipelines
component: ordering
type: webapi
replicas: {{ .Values.replicas }}
template:
metadata:
labels:
app: auto-devops-pipelines
component: ordering
type: webapi
spec:
volumes:
- name: appsetting
configMap:
name: ordering.appsettings.json
- name: appsetting-{{ .Values.environment.lower }}
configMap:
name: ordering.appsettings.{{ .Values.environment.lower }}.json
containers:
- name: ordering-api
image: {{ .Values.image.registryhost }}{{ .Values.image.username }}ordering.api:{{ .Values.image.version }}
imagePullPolicy: Always
ports:
- containerPort: 80
readinessProbe:
httpGet:
path: /healthchecks
port: 80
scheme: HTTP
initialDelaySeconds: 5
periodSeconds: 60
volumeMounts:
- name: appsetting
mountPath: "/app/appsettings.json"
subPath: "appsettings.json"
- name: appsetting-{{ .Values.environment.lower }}
mountPath: "/app/appsettings.{{ .Values.environment.upper }}.json"
subPath: "appsettings.{{ .Values.environment.upper }}.json"
env:
- name: ASPNETCORE_ENVIRONMENT
value: "{{ .Values.environment.upper }}"
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: payment-api
namespace: {{ .Values.namespace }}
spec:
selector:
matchLabels:
app: auto-devops-pipelines
component: payment
type: webapi
replicas: {{ .Values.replicas }}
template:
metadata:
labels:
app: auto-devops-pipelines
component: payment
type: webapi
spec:
volumes:
- name: appsetting
configMap:
name: payment.appsettings.json
- name: appsetting-{{ .Values.environment.lower }}
configMap:
name: payment.appsettings.{{ .Values.environment.lower }}.json
containers:
- name: payment-api
image: {{ .Values.image.registryhost }}{{ .Values.image.username }}payment.api:{{ .Values.image.version }}
imagePullPolicy: Always
ports:
- containerPort: 80
readinessProbe:
httpGet:
path: /healthchecks
port: 80
scheme: HTTP
initialDelaySeconds: 5
periodSeconds: 60
volumeMounts:
- name: appsetting
mountPath: "/app/appsettings.json"
subPath: "appsettings.json"
- name: appsetting-{{ .Values.environment.lower }}
mountPath: "/app/appsettings.{{ .Values.environment.upper }}.json"
subPath: "appsettings.{{ .Values.environment.upper }}.json"
env:
- name: ASPNETCORE_ENVIRONMENT
value: "{{ .Values.environment.upper }}"
\ No newline at end of file
apiVersion: v1
kind: Service
metadata:
labels:
app: light
component: common
name: common-api
namespace: {{ .Values.namespace }}
spec:
type: ClusterIP
ports:
- port: 80
selector:
app: light
component: common
type: webapi
---
apiVersion: v1
kind: Service
metadata:
labels:
app: light
component: basket
name: basket-api
namespace: {{ .Values.namespace }}
spec:
type: ClusterIP
ports:
- port: 80
selector:
app: light
component: basket
type: webapi
---
apiVersion: v1
kind: Service
metadata:
labels:
app: light
component: catalog
name: catalog-api
namespace: {{ .Values.namespace }}
spec:
type: ClusterIP
ports:
- port: 80
selector:
app: light
component: catalog
type: webapi
---
apiVersion: v1
kind: Service
metadata:
labels:
app: light
component: identity
name: identity-api
namespace: {{ .Values.namespace }}
spec:
type: ClusterIP
ports:
- port: 80
selector:
app: light
component: identity
type: webapi
---
apiVersion: v1
kind: Service
metadata:
labels:
app: light
component: marketing
name: marketing-api
namespace: {{ .Values.namespace }}
spec:
type: ClusterIP
ports:
- port: 80
selector:
app: light
component: marketing
type: webapi
---
apiVersion: v1
kind: Service
metadata:
labels:
app: light
component: ordering
name: ordering-api
namespace: {{ .Values.namespace }}
spec:
type: ClusterIP
ports:
- port: 80
selector:
app: light
component: ordering
type: webapi
---
apiVersion: v1
kind: Service
metadata:
labels:
app: light
component: payment
name: payment-api
namespace: {{ .Values.namespace }}
spec:
type: ClusterIP
ports:
- port: 80
selector:
app: light
component: payment
type: webapi
---
apiVersion: v1
kind: Service
metadata:
labels:
app: light
component: searching
name: searching-yu
namespace: {{ .Values.namespace }}
spec:
type: ClusterIP
ports:
- port: 80
selector:
app: light
component: searching
type: webapi
---
apiVersion: v1
kind: Service
metadata:
labels:
app: light
role: aggregation
component: light
name: aggregation-light
namespace: {{ .Values.namespace }}
spec:
type: ClusterIP
ports:
- port: 80
selector:
app: light
role: aggregation
component: light
type: webapi
namespace: microservice.autodevopspipeline-v0
replicas: 1
image:
registryhost: registry.justmine.com
username: justmine
environment:
upper: Production
lower: production
\ No newline at end of file
using Microsoft.AspNetCore.Mvc.ApplicationModels;
using Microsoft.AspNetCore.Mvc.Routing;
using System.Linq;
namespace MvcExtensions
{
public class GlobalRouteConvention : IApplicationModelConvention
{
private readonly AttributeRouteModel _centralPrefix;
public GlobalRouteConvention(IRouteTemplateProvider routeTemplateProvider)
{
_centralPrefix = new AttributeRouteModel(routeTemplateProvider);
}
public void Apply(ApplicationModel application)
{
//遍历所有的 Controller
foreach (var controller in application.Controllers)
{
// 已经标记了 RouteAttribute 的 Controller
var matchedSelectors = controller.Selectors.Where(x => x.AttributeRouteModel != null).ToList();
if (matchedSelectors.Any())
{
foreach (var selectorModel in matchedSelectors)
{
// 在 当前路由上 再 添加一个 路由前缀
selectorModel.AttributeRouteModel = AttributeRouteModel.CombineAttributeRouteModel(_centralPrefix,
selectorModel.AttributeRouteModel);
}
}
// 没有标记 RouteAttribute 的 Controller
var unmatchedSelectors = controller.Selectors.Where(x => x.AttributeRouteModel == null).ToList();
if (unmatchedSelectors.Any())
{
foreach (var selectorModel in unmatchedSelectors)
{
// 添加一个 路由前缀
selectorModel.AttributeRouteModel = _centralPrefix;
}
}
}
}
}
}
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.AspNetCore.Mvc.Core">
<HintPath>C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.aspnetcore.mvc.core\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Mvc.Core.dll</HintPath>
</Reference>
</ItemGroup>
</Project>
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ApplicationModels;
using Microsoft.AspNetCore.Mvc.Routing;
namespace MvcExtensions
{
public static class ServiceCollectionExtensions
{
/// <summary>扩展 MvcOption,注册统一的路由前缀到 RouteAttribute</summary>
public static void UseCentralRoutePrefix(this MvcOptions opts, string template)
{
if (string.IsNullOrEmpty(template))
return;
opts.Conventions.Insert(0, (IApplicationModelConvention)new GlobalRouteConvention((IRouteTemplateProvider)new RouteAttribute(template)));
}
}
}
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp2.2</TargetFramework>
<AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.App" />
<PackageReference Include="Microsoft.AspNetCore.Razor.Design" Version="2.2.0" PrivateAssets="All" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\BuildingBlocks\Extensions\MvcExtensions\MvcExtensions.csproj" />
</ItemGroup>
</Project>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
namespace Basket.API.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
// GET api/values
[HttpGet]
public ActionResult<IEnumerable<string>> Get()
{
return new string[] { "value1", "value2" };
}
// GET api/values/5
[HttpGet("{id}")]
public ActionResult<string> Get(int id)
{
return "value";
}
// POST api/values
[HttpPost]
public void Post([FromBody] string value)
{
}
// PUT api/values/5
[HttpPut("{id}")]
public void Put(int id, [FromBody] string value)
{
}
// DELETE api/values/5
[HttpDelete("{id}")]
public void Delete(int id)
{
}
}
}
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
namespace Basket.API
{
public class Program
{
public static void Main(string[] args)
{
CreateWebHostBuilder(args).Build().Run();
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>();
}
}
{
"$schema": "http://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:64719",
"sslPort": 0
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchUrl": "api/values",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"Basket.API": {
"commandName": "Project",
"launchBrowser": true,
"launchUrl": "api/values",
"applicationUrl": "http://localhost:5000",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
\ No newline at end of file
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using MvcExtensions;
namespace Basket.API
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(it => it.UseCentralRoutePrefix("/api/basket")).SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseMvc();
}
}
}
{
"Logging": {
"LogLevel": {
"Default": "Debug",
"System": "Information",
"Microsoft": "Information"
}
}
}
{
"Logging": {
"LogLevel": {
"Default": "Warning"
}
},
"AllowedHosts": "*"
}
{
"Logging": {
"LogLevel": {
"Default": "Warning"
}
},
"AllowedHosts": "*"
}
{
"Logging": {
"LogLevel": {
"Default": "Warning"
}
},
"AllowedHosts": "*"
}
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp2.2</TargetFramework>
<AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.App" />
<PackageReference Include="Microsoft.AspNetCore.Razor.Design" Version="2.2.0" PrivateAssets="All" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\BuildingBlocks\Extensions\MvcExtensions\MvcExtensions.csproj" />
</ItemGroup>
</Project>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
namespace Catalog.API.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
// GET api/values
[HttpGet]
public ActionResult<IEnumerable<string>> Get()
{
return new string[] { "value1", "value2" };
}
// GET api/values/5
[HttpGet("{id}")]
public ActionResult<string> Get(int id)
{
return "value";
}
// POST api/values
[HttpPost]
public void Post([FromBody] string value)
{
}
// PUT api/values/5
[HttpPut("{id}")]
public void Put(int id, [FromBody] string value)
{
}
// DELETE api/values/5
[HttpDelete("{id}")]
public void Delete(int id)
{
}
}
}
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
namespace Catalog.API
{
public class Program
{
public static void Main(string[] args)
{
CreateWebHostBuilder(args).Build().Run();
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>();
}
}
{
"$schema": "http://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:64741",
"sslPort": 0
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchUrl": "api/values",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"Catalog.API": {
"commandName": "Project",
"launchBrowser": true,
"launchUrl": "api/values",
"applicationUrl": "http://localhost:5000",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
\ No newline at end of file
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using MvcExtensions;
namespace Catalog.API
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(it => it.UseCentralRoutePrefix("/api/catalog")).SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseMvc();
}
}
}
{
"Logging": {
"LogLevel": {
"Default": "Debug",
"System": "Information",
"Microsoft": "Information"
}
}
}
{
"Logging": {
"LogLevel": {
"Default": "Warning"
}
},
"AllowedHosts": "*"
}
{
"Logging": {
"LogLevel": {
"Default": "Warning"
}
},
"AllowedHosts": "*"
}
{
"Logging": {
"LogLevel": {
"Default": "Warning"
}
},
"AllowedHosts": "*"
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
namespace Identity.API.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
// GET api/values
[HttpGet]
public ActionResult<IEnumerable<string>> Get()
{
return new string[] { "value1", "value2" };
}
// GET api/values/5
[HttpGet("{id}")]
public ActionResult<string> Get(int id)
{
return "value";
}
// POST api/values
[HttpPost]
public void Post([FromBody] string value)
{
}
// PUT api/values/5
[HttpPut("{id}")]
public void Put(int id, [FromBody] string value)
{
}
// DELETE api/values/5
[HttpDelete("{id}")]
public void Delete(int id)
{
}
}
}
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp2.2</TargetFramework>
<AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.App" />
<PackageReference Include="Microsoft.AspNetCore.Razor.Design" Version="2.2.0" PrivateAssets="All" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\BuildingBlocks\Extensions\MvcExtensions\MvcExtensions.csproj" />
</ItemGroup>
</Project>
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
namespace Identity.API
{
public class Program
{
public static void Main(string[] args)
{
CreateWebHostBuilder(args).Build().Run();
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>();
}
}
{
"$schema": "http://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:64770",
"sslPort": 0
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchUrl": "api/values",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"Identity.API": {
"commandName": "Project",
"launchBrowser": true,
"launchUrl": "api/values",
"applicationUrl": "http://localhost:5000",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
\ No newline at end of file
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using MvcExtensions;
namespace Identity.API
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(it => it.UseCentralRoutePrefix("/api/identity")).SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseMvc();
}
}
}
{
"Logging": {
"LogLevel": {
"Default": "Debug",
"System": "Information",
"Microsoft": "Information"
}
}
}
{
"Logging": {
"LogLevel": {
"Default": "Warning"
}
},
"AllowedHosts": "*"
}
{
"Logging": {
"LogLevel": {
"Default": "Warning"
}
},
"AllowedHosts": "*"
}
{
"Logging": {
"LogLevel": {
"Default": "Warning"
}
},
"AllowedHosts": "*"
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
namespace Marketing.API.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
// GET api/values
[HttpGet]
public ActionResult<IEnumerable<string>> Get()
{
return new string[] { "value1", "value2" };
}
// GET api/values/5
[HttpGet("{id}")]
public ActionResult<string> Get(int id)
{
return "value";
}
// POST api/values
[HttpPost]
public void Post([FromBody] string value)
{
}
// PUT api/values/5
[HttpPut("{id}")]
public void Put(int id, [FromBody] string value)
{
}
// DELETE api/values/5
[HttpDelete("{id}")]
public void Delete(int id)
{
}
}
}
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp2.2</TargetFramework>
<AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.App" />
<PackageReference Include="Microsoft.AspNetCore.Razor.Design" Version="2.2.0" PrivateAssets="All" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\BuildingBlocks\Extensions\MvcExtensions\MvcExtensions.csproj" />
</ItemGroup>
</Project>
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
namespace Marketing.API
{
public class Program
{
public static void Main(string[] args)
{
CreateWebHostBuilder(args).Build().Run();
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>();
}
}
{
"$schema": "http://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:64781",
"sslPort": 0
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchUrl": "api/values",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"Marketing.API": {
"commandName": "Project",
"launchBrowser": true,
"launchUrl": "api/values",
"applicationUrl": "http://localhost:5000",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
\ No newline at end of file
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using MvcExtensions;
namespace Marketing.API
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(it => it.UseCentralRoutePrefix("/api/marketing")).SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseMvc();
}
}
}
{
"Logging": {
"LogLevel": {
"Default": "Debug",
"System": "Information",
"Microsoft": "Information"
}
}
}
{
"Logging": {
"LogLevel": {
"Default": "Warning"
}
},
"AllowedHosts": "*"
}
{
"Logging": {
"LogLevel": {
"Default": "Warning"
}
},
"AllowedHosts": "*"
}
{
"Logging": {
"LogLevel": {
"Default": "Warning"
}
},
"AllowedHosts": "*"
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
namespace Ordering.API.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
// GET api/values
[HttpGet]
public ActionResult<IEnumerable<string>> Get()
{
return new string[] { "value1", "value2" };
}
// GET api/values/5
[HttpGet("{id}")]
public ActionResult<string> Get(int id)
{
return "value";
}
// POST api/values
[HttpPost]
public void Post([FromBody] string value)
{
}
// PUT api/values/5
[HttpPut("{id}")]
public void Put(int id, [FromBody] string value)
{
}
// DELETE api/values/5
[HttpDelete("{id}")]
public void Delete(int id)
{
}
}
}
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp2.2</TargetFramework>
<AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.App" />
<PackageReference Include="Microsoft.AspNetCore.Razor.Design" Version="2.2.0" PrivateAssets="All" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\BuildingBlocks\Extensions\MvcExtensions\MvcExtensions.csproj" />
</ItemGroup>
</Project>
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
namespace Ordering.API
{
public class Program
{
public static void Main(string[] args)
{
CreateWebHostBuilder(args).Build().Run();
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>();
}
}
{
"$schema": "http://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:64811",
"sslPort": 0
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchUrl": "api/values",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"Ordering.API": {
"commandName": "Project",
"launchBrowser": true,
"launchUrl": "api/values",
"applicationUrl": "http://localhost:5000",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
\ No newline at end of file
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using MvcExtensions;
namespace Ordering.API
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(it => it.UseCentralRoutePrefix("/api/ordering")).SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseMvc();
}
}
}
{
"Logging": {
"LogLevel": {
"Default": "Debug",
"System": "Information",
"Microsoft": "Information"
}
}
}
{
"Logging": {
"LogLevel": {
"Default": "Warning"
}
},
"AllowedHosts": "*"
}
{
"Logging": {
"LogLevel": {
"Default": "Warning"
}
},
"AllowedHosts": "*"
}
{
"Logging": {
"LogLevel": {
"Default": "Warning"
}
},
"AllowedHosts": "*"
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
namespace Payment.API.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
// GET api/values
[HttpGet]
public ActionResult<IEnumerable<string>> Get()
{
return new string[] { "value1", "value2" };
}
// GET api/values/5
[HttpGet("{id}")]
public ActionResult<string> Get(int id)
{
return "value";
}
// POST api/values
[HttpPost]
public void Post([FromBody] string value)
{
}
// PUT api/values/5
[HttpPut("{id}")]
public void Put(int id, [FromBody] string value)
{
}
// DELETE api/values/5
[HttpDelete("{id}")]
public void Delete(int id)
{
}
}
}
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp2.2</TargetFramework>
<AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.App" />
<PackageReference Include="Microsoft.AspNetCore.Razor.Design" Version="2.2.0" PrivateAssets="All" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\BuildingBlocks\Extensions\MvcExtensions\MvcExtensions.csproj" />
</ItemGroup>
</Project>
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
namespace Payment.API
{
public class Program
{
public static void Main(string[] args)
{
CreateWebHostBuilder(args).Build().Run();
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>();
}
}
{
"$schema": "http://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:64820",
"sslPort": 0
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchUrl": "api/values",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"Payment.API": {
"commandName": "Project",
"launchBrowser": true,
"launchUrl": "api/values",
"applicationUrl": "http://localhost:5000",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
\ No newline at end of file
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using MvcExtensions;
namespace Payment.API
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(it => it.UseCentralRoutePrefix("/api/payment")).SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseMvc();
}
}
}
{
"Logging": {
"LogLevel": {
"Default": "Debug",
"System": "Information",
"Microsoft": "Information"
}
}
}
{
"Logging": {
"LogLevel": {
"Default": "Warning"
}
},
"AllowedHosts": "*"
}
{
"Logging": {
"LogLevel": {
"Default": "Warning"
}
},
"AllowedHosts": "*"
}
{
"Logging": {
"LogLevel": {
"Default": "Warning"
}
},
"AllowedHosts": "*"
}
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.2</TargetFramework>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" />
<PackageReference Include="xunit" Version="2.4.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.0" />
</ItemGroup>
</Project>
using Xunit;
namespace IntegrationTest
{
public class UnitTest1
{
[Fact]
public void Test1()
{
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment