├── .gitignore ├── .mvn └── wrapper │ ├── maven-wrapper.jar │ └── maven-wrapper.properties ├── README.md ├── mvnw ├── mvnw.cmd ├── pom.xml ├── postman_collection └── Kubernetes Java Client API Example.postman_collection.json ├── screenshots ├── 1.PNG ├── 2.PNG ├── 3.PNG └── springboot-kubernetes-java-client-api-main-image.png └── src ├── main ├── java │ └── com │ │ └── example │ │ └── kubernetesjavaclientapi │ │ ├── KubernetesJavaClientApiApplication.java │ │ ├── config │ │ └── KubernetesConfig.java │ │ ├── controller │ │ ├── DeploymentController.java │ │ ├── NamespaceController.java │ │ ├── PodController.java │ │ └── ServiceController.java │ │ ├── dto │ │ ├── deployment │ │ │ └── DeploymentDto.java │ │ ├── namespace │ │ │ └── NameSpaceDto.java │ │ ├── pod │ │ │ ├── PodDto.java │ │ │ ├── V1ManagedFieldsEntryDto.java │ │ │ └── V1OwnerReferenceDto.java │ │ └── service │ │ │ └── ServiceDto.java │ │ ├── mapper │ │ ├── BaseMapper.java │ │ ├── V1ManagedFieldsEntryToV1ManagedFieldsEntryDtoMapper.java │ │ └── V1OwnerReferenceToV1OwnerReferenceDtoMapper.java │ │ ├── payload │ │ └── request │ │ │ ├── deployment │ │ │ ├── CreateDeploymentRequest.java │ │ │ ├── DeleteDeploymentRequest.java │ │ │ └── EditDeploymentRequest.java │ │ │ ├── namespace │ │ │ ├── CreateNamespaceRequest.java │ │ │ ├── DeleteNamespaceRequest.java │ │ │ └── EditNamespaceRequest.java │ │ │ ├── pods │ │ │ ├── CreatePodRequest.java │ │ │ ├── DeletePodRequest.java │ │ │ └── EditPodRequest.java │ │ │ └── service │ │ │ ├── CreateServiceRequest.java │ │ │ ├── DeleteServiceRequest.java │ │ │ └── EditServiceRequest.java │ │ └── service │ │ ├── DeploymentService.java │ │ ├── KubeServiceService.java │ │ ├── NamespaceService.java │ │ └── PodService.java └── resources │ └── application.yaml └── test └── java └── com └── example └── kubernetesjavaclientapi ├── KubernetesjavaclientapiApplicationTests.java ├── base ├── BaseControllerTest.java └── BaseServiceTest.java ├── controller ├── DeploymentControllerTest.java ├── NamespaceControllerTest.java ├── PodControllerTest.java └── ServiceControllerTest.java └── service ├── DeploymentServiceTest.java ├── KubeServiceServiceTest.java ├── NamespaceServiceTest.java └── PodServiceTest.java /.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rapter1990/kubernetesjavaclientapi/64be9d35d5f876ce109bb3791d608156a4c3750b/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.5/apache-maven-3.9.5-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Spring Boot Kubernetes Java Client Api Example 2 | 3 |

4 | Main Information 5 |

6 | 7 | ### 📖 Information 8 | 9 | 19 | 20 | ### Explore Rest APIs 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 |
MethodUrlDescriptionRequest BodyHeaderValid Path VariableNo Path Variable
GET/api/v1/kubernetes/deployments/listDeploymentsList Deployments
POST/api/v1/kubernetes/deployments/createDeploymentCreate DeploymentCreateDeploymentRequest
PUT/api/v1/kubernetes/deployments/editDeploymentEdit DeploymentEditDeploymentRequest
DELETE/api/v1/kubernetes/deployments/deleteDeploymentDelete DeploymentDeleteDeploymentRequest
GET/api/v1/kubernetes/namespaces/listNamespacesList Namespaces
POST/api/v1/kubernetes/namespaces/createNamespaceCreate NamespaceCreateNamespaceRequest
PUT/api/v1/kubernetes/namespaces/editNamespaceEdit NamespaceEditNamespaceRequest
DELETE/api/v1/kubernetes/namespaces/deleteNamespaceDelete NamespaceDeleteNamespaceRequest
GET/api/v1/kubernetes/pods/listPodsList Pods
POST/api/v1/kubernetes/pods/createPodCreate PodCreatePodRequest
PUT/api/v1/kubernetes/pods/editPodEdit PodEditPodRequest
DELETE/api/v1/kubernetes/pods/deletePodDelete PodDeletePodRequest
GET/api/v1/kubernetes/services/listServicesList Services
POST/api/v1/kubernetes/services/createServiceCreate ServiceCreateServiceRequest
PUT/api/v1/kubernetes/services/editServiceEdit ServiceEditServiceRequest
DELETE/api/v1/kubernetes/services/deleteServiceDelete ServiceDeleteServiceRequest
177 | 178 | 179 | 180 | ### Technologies 181 | 182 | --- 183 | - Java 17 184 | - Spring Boot 3.0 185 | - Restful API 186 | - Lombok 187 | - Maven 188 | - Junit5 189 | - Mockito 190 | - Integration Tests 191 | - Postman 192 | 193 | ### Prerequisites to Run the App 194 | 195 | 1 ) Install minikube to access this link https://minikube.sigs.k8s.io/docs/start/ 196 | 197 | 2 ) Open command prompt and install kubectl through this command shown below 198 | ``` 199 | minikube kubectl -- 200 | ``` 201 | 202 | 3 ) Start minikube through this command shown below. 203 | ``` 204 | minikube start 205 | ``` 206 | 207 | ### Maven Run 208 | To build and run the application with `Maven`, please follow the directions shown below; 209 | 210 | ```sh 211 | $ cd kubernetesjavaclientapi 212 | $ mvn clean install 213 | $ mvn spring-boot:run 214 | ``` 215 | 216 | ### Screenshots 217 | 218 |
219 | Click here to show the screenshots of project 220 |

Figure 1

221 | 222 |

Figure 2

223 | 224 |

Figure 3

225 | 226 |
227 | 228 | ### Contributors 229 | 230 | - [Sercan Noyan Germiyanoğlu](https://github.com/Rapter1990) -------------------------------------------------------------------------------- /mvnw: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # ---------------------------------------------------------------------------- 3 | # Licensed to the Apache Software Foundation (ASF) under one 4 | # or more contributor license agreements. See the NOTICE file 5 | # distributed with this work for additional information 6 | # regarding copyright ownership. The ASF licenses this file 7 | # to you under the Apache License, Version 2.0 (the 8 | # "License"); you may not use this file except in compliance 9 | # with the License. You may obtain a copy of the License at 10 | # 11 | # https://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, 14 | # software distributed under the License is distributed on an 15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | # KIND, either express or implied. See the License for the 17 | # specific language governing permissions and limitations 18 | # under the License. 19 | # ---------------------------------------------------------------------------- 20 | 21 | # ---------------------------------------------------------------------------- 22 | # Apache Maven Wrapper startup batch script, version 3.2.0 23 | # 24 | # Required ENV vars: 25 | # ------------------ 26 | # JAVA_HOME - location of a JDK home dir 27 | # 28 | # Optional ENV vars 29 | # ----------------- 30 | # MAVEN_OPTS - parameters passed to the Java VM when running Maven 31 | # e.g. to debug Maven itself, use 32 | # set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 33 | # MAVEN_SKIP_RC - flag to disable loading of mavenrc files 34 | # ---------------------------------------------------------------------------- 35 | 36 | if [ -z "$MAVEN_SKIP_RC" ] ; then 37 | 38 | if [ -f /usr/local/etc/mavenrc ] ; then 39 | . /usr/local/etc/mavenrc 40 | fi 41 | 42 | if [ -f /etc/mavenrc ] ; then 43 | . /etc/mavenrc 44 | fi 45 | 46 | if [ -f "$HOME/.mavenrc" ] ; then 47 | . "$HOME/.mavenrc" 48 | fi 49 | 50 | fi 51 | 52 | # OS specific support. $var _must_ be set to either true or false. 53 | cygwin=false; 54 | darwin=false; 55 | mingw=false 56 | case "$(uname)" in 57 | CYGWIN*) cygwin=true ;; 58 | MINGW*) mingw=true;; 59 | Darwin*) darwin=true 60 | # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home 61 | # See https://developer.apple.com/library/mac/qa/qa1170/_index.html 62 | if [ -z "$JAVA_HOME" ]; then 63 | if [ -x "/usr/libexec/java_home" ]; then 64 | JAVA_HOME="$(/usr/libexec/java_home)"; export JAVA_HOME 65 | else 66 | JAVA_HOME="/Library/Java/Home"; export JAVA_HOME 67 | fi 68 | fi 69 | ;; 70 | esac 71 | 72 | if [ -z "$JAVA_HOME" ] ; then 73 | if [ -r /etc/gentoo-release ] ; then 74 | JAVA_HOME=$(java-config --jre-home) 75 | fi 76 | fi 77 | 78 | # For Cygwin, ensure paths are in UNIX format before anything is touched 79 | if $cygwin ; then 80 | [ -n "$JAVA_HOME" ] && 81 | JAVA_HOME=$(cygpath --unix "$JAVA_HOME") 82 | [ -n "$CLASSPATH" ] && 83 | CLASSPATH=$(cygpath --path --unix "$CLASSPATH") 84 | fi 85 | 86 | # For Mingw, ensure paths are in UNIX format before anything is touched 87 | if $mingw ; then 88 | [ -n "$JAVA_HOME" ] && [ -d "$JAVA_HOME" ] && 89 | JAVA_HOME="$(cd "$JAVA_HOME" || (echo "cannot cd into $JAVA_HOME."; exit 1); pwd)" 90 | fi 91 | 92 | if [ -z "$JAVA_HOME" ]; then 93 | javaExecutable="$(which javac)" 94 | if [ -n "$javaExecutable" ] && ! [ "$(expr "\"$javaExecutable\"" : '\([^ ]*\)')" = "no" ]; then 95 | # readlink(1) is not available as standard on Solaris 10. 96 | readLink=$(which readlink) 97 | if [ ! "$(expr "$readLink" : '\([^ ]*\)')" = "no" ]; then 98 | if $darwin ; then 99 | javaHome="$(dirname "\"$javaExecutable\"")" 100 | javaExecutable="$(cd "\"$javaHome\"" && pwd -P)/javac" 101 | else 102 | javaExecutable="$(readlink -f "\"$javaExecutable\"")" 103 | fi 104 | javaHome="$(dirname "\"$javaExecutable\"")" 105 | javaHome=$(expr "$javaHome" : '\(.*\)/bin') 106 | JAVA_HOME="$javaHome" 107 | export JAVA_HOME 108 | fi 109 | fi 110 | fi 111 | 112 | if [ -z "$JAVACMD" ] ; then 113 | if [ -n "$JAVA_HOME" ] ; then 114 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 115 | # IBM's JDK on AIX uses strange locations for the executables 116 | JAVACMD="$JAVA_HOME/jre/sh/java" 117 | else 118 | JAVACMD="$JAVA_HOME/bin/java" 119 | fi 120 | else 121 | JAVACMD="$(\unset -f command 2>/dev/null; \command -v java)" 122 | fi 123 | fi 124 | 125 | if [ ! -x "$JAVACMD" ] ; then 126 | echo "Error: JAVA_HOME is not defined correctly." >&2 127 | echo " We cannot execute $JAVACMD" >&2 128 | exit 1 129 | fi 130 | 131 | if [ -z "$JAVA_HOME" ] ; then 132 | echo "Warning: JAVA_HOME environment variable is not set." 133 | fi 134 | 135 | # traverses directory structure from process work directory to filesystem root 136 | # first directory with .mvn subdirectory is considered project base directory 137 | find_maven_basedir() { 138 | if [ -z "$1" ] 139 | then 140 | echo "Path not specified to find_maven_basedir" 141 | return 1 142 | fi 143 | 144 | basedir="$1" 145 | wdir="$1" 146 | while [ "$wdir" != '/' ] ; do 147 | if [ -d "$wdir"/.mvn ] ; then 148 | basedir=$wdir 149 | break 150 | fi 151 | # workaround for JBEAP-8937 (on Solaris 10/Sparc) 152 | if [ -d "${wdir}" ]; then 153 | wdir=$(cd "$wdir/.." || exit 1; pwd) 154 | fi 155 | # end of workaround 156 | done 157 | printf '%s' "$(cd "$basedir" || exit 1; pwd)" 158 | } 159 | 160 | # concatenates all lines of a file 161 | concat_lines() { 162 | if [ -f "$1" ]; then 163 | # Remove \r in case we run on Windows within Git Bash 164 | # and check out the repository with auto CRLF management 165 | # enabled. Otherwise, we may read lines that are delimited with 166 | # \r\n and produce $'-Xarg\r' rather than -Xarg due to word 167 | # splitting rules. 168 | tr -s '\r\n' ' ' < "$1" 169 | fi 170 | } 171 | 172 | log() { 173 | if [ "$MVNW_VERBOSE" = true ]; then 174 | printf '%s\n' "$1" 175 | fi 176 | } 177 | 178 | BASE_DIR=$(find_maven_basedir "$(dirname "$0")") 179 | if [ -z "$BASE_DIR" ]; then 180 | exit 1; 181 | fi 182 | 183 | MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}; export MAVEN_PROJECTBASEDIR 184 | log "$MAVEN_PROJECTBASEDIR" 185 | 186 | ########################################################################################## 187 | # Extension to allow automatically downloading the maven-wrapper.jar from Maven-central 188 | # This allows using the maven wrapper in projects that prohibit checking in binary data. 189 | ########################################################################################## 190 | wrapperJarPath="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" 191 | if [ -r "$wrapperJarPath" ]; then 192 | log "Found $wrapperJarPath" 193 | else 194 | log "Couldn't find $wrapperJarPath, downloading it ..." 195 | 196 | if [ -n "$MVNW_REPOURL" ]; then 197 | wrapperUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" 198 | else 199 | wrapperUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" 200 | fi 201 | while IFS="=" read -r key value; do 202 | # Remove '\r' from value to allow usage on windows as IFS does not consider '\r' as a separator ( considers space, tab, new line ('\n'), and custom '=' ) 203 | safeValue=$(echo "$value" | tr -d '\r') 204 | case "$key" in (wrapperUrl) wrapperUrl="$safeValue"; break ;; 205 | esac 206 | done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties" 207 | log "Downloading from: $wrapperUrl" 208 | 209 | if $cygwin; then 210 | wrapperJarPath=$(cygpath --path --windows "$wrapperJarPath") 211 | fi 212 | 213 | if command -v wget > /dev/null; then 214 | log "Found wget ... using wget" 215 | [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--quiet" 216 | if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then 217 | wget $QUIET "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" 218 | else 219 | wget $QUIET --http-user="$MVNW_USERNAME" --http-password="$MVNW_PASSWORD" "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" 220 | fi 221 | elif command -v curl > /dev/null; then 222 | log "Found curl ... using curl" 223 | [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--silent" 224 | if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then 225 | curl $QUIET -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath" 226 | else 227 | curl $QUIET --user "$MVNW_USERNAME:$MVNW_PASSWORD" -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath" 228 | fi 229 | else 230 | log "Falling back to using Java to download" 231 | javaSource="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.java" 232 | javaClass="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.class" 233 | # For Cygwin, switch paths to Windows format before running javac 234 | if $cygwin; then 235 | javaSource=$(cygpath --path --windows "$javaSource") 236 | javaClass=$(cygpath --path --windows "$javaClass") 237 | fi 238 | if [ -e "$javaSource" ]; then 239 | if [ ! -e "$javaClass" ]; then 240 | log " - Compiling MavenWrapperDownloader.java ..." 241 | ("$JAVA_HOME/bin/javac" "$javaSource") 242 | fi 243 | if [ -e "$javaClass" ]; then 244 | log " - Running MavenWrapperDownloader.java ..." 245 | ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$wrapperUrl" "$wrapperJarPath") || rm -f "$wrapperJarPath" 246 | fi 247 | fi 248 | fi 249 | fi 250 | ########################################################################################## 251 | # End of extension 252 | ########################################################################################## 253 | 254 | # If specified, validate the SHA-256 sum of the Maven wrapper jar file 255 | wrapperSha256Sum="" 256 | while IFS="=" read -r key value; do 257 | case "$key" in (wrapperSha256Sum) wrapperSha256Sum=$value; break ;; 258 | esac 259 | done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties" 260 | if [ -n "$wrapperSha256Sum" ]; then 261 | wrapperSha256Result=false 262 | if command -v sha256sum > /dev/null; then 263 | if echo "$wrapperSha256Sum $wrapperJarPath" | sha256sum -c > /dev/null 2>&1; then 264 | wrapperSha256Result=true 265 | fi 266 | elif command -v shasum > /dev/null; then 267 | if echo "$wrapperSha256Sum $wrapperJarPath" | shasum -a 256 -c > /dev/null 2>&1; then 268 | wrapperSha256Result=true 269 | fi 270 | else 271 | echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." 272 | echo "Please install either command, or disable validation by removing 'wrapperSha256Sum' from your maven-wrapper.properties." 273 | exit 1 274 | fi 275 | if [ $wrapperSha256Result = false ]; then 276 | echo "Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised." >&2 277 | echo "Investigate or delete $wrapperJarPath to attempt a clean download." >&2 278 | echo "If you updated your Maven version, you need to update the specified wrapperSha256Sum property." >&2 279 | exit 1 280 | fi 281 | fi 282 | 283 | MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" 284 | 285 | # For Cygwin, switch paths to Windows format before running java 286 | if $cygwin; then 287 | [ -n "$JAVA_HOME" ] && 288 | JAVA_HOME=$(cygpath --path --windows "$JAVA_HOME") 289 | [ -n "$CLASSPATH" ] && 290 | CLASSPATH=$(cygpath --path --windows "$CLASSPATH") 291 | [ -n "$MAVEN_PROJECTBASEDIR" ] && 292 | MAVEN_PROJECTBASEDIR=$(cygpath --path --windows "$MAVEN_PROJECTBASEDIR") 293 | fi 294 | 295 | # Provide a "standardized" way to retrieve the CLI args that will 296 | # work with both Windows and non-Windows executions. 297 | MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $*" 298 | export MAVEN_CMD_LINE_ARGS 299 | 300 | WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 301 | 302 | # shellcheck disable=SC2086 # safe args 303 | exec "$JAVACMD" \ 304 | $MAVEN_OPTS \ 305 | $MAVEN_DEBUG_OPTS \ 306 | -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ 307 | "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ 308 | ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" 309 | -------------------------------------------------------------------------------- /mvnw.cmd: -------------------------------------------------------------------------------- 1 | @REM ---------------------------------------------------------------------------- 2 | @REM Licensed to the Apache Software Foundation (ASF) under one 3 | @REM or more contributor license agreements. See the NOTICE file 4 | @REM distributed with this work for additional information 5 | @REM regarding copyright ownership. The ASF licenses this file 6 | @REM to you under the Apache License, Version 2.0 (the 7 | @REM "License"); you may not use this file except in compliance 8 | @REM with the License. You may obtain a copy of the License at 9 | @REM 10 | @REM https://www.apache.org/licenses/LICENSE-2.0 11 | @REM 12 | @REM Unless required by applicable law or agreed to in writing, 13 | @REM software distributed under the License is distributed on an 14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | @REM KIND, either express or implied. See the License for the 16 | @REM specific language governing permissions and limitations 17 | @REM under the License. 18 | @REM ---------------------------------------------------------------------------- 19 | 20 | @REM ---------------------------------------------------------------------------- 21 | @REM Apache Maven Wrapper startup batch script, version 3.2.0 22 | @REM 23 | @REM Required ENV vars: 24 | @REM JAVA_HOME - location of a JDK home dir 25 | @REM 26 | @REM Optional ENV vars 27 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands 28 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending 29 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven 30 | @REM e.g. to debug Maven itself, use 31 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 32 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files 33 | @REM ---------------------------------------------------------------------------- 34 | 35 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' 36 | @echo off 37 | @REM set title of command window 38 | title %0 39 | @REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' 40 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% 41 | 42 | @REM set %HOME% to equivalent of $HOME 43 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") 44 | 45 | @REM Execute a user defined script before this one 46 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre 47 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending 48 | if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %* 49 | if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %* 50 | :skipRcPre 51 | 52 | @setlocal 53 | 54 | set ERROR_CODE=0 55 | 56 | @REM To isolate internal variables from possible post scripts, we use another setlocal 57 | @setlocal 58 | 59 | @REM ==== START VALIDATION ==== 60 | if not "%JAVA_HOME%" == "" goto OkJHome 61 | 62 | echo. 63 | echo Error: JAVA_HOME not found in your environment. >&2 64 | echo Please set the JAVA_HOME variable in your environment to match the >&2 65 | echo location of your Java installation. >&2 66 | echo. 67 | goto error 68 | 69 | :OkJHome 70 | if exist "%JAVA_HOME%\bin\java.exe" goto init 71 | 72 | echo. 73 | echo Error: JAVA_HOME is set to an invalid directory. >&2 74 | echo JAVA_HOME = "%JAVA_HOME%" >&2 75 | echo Please set the JAVA_HOME variable in your environment to match the >&2 76 | echo location of your Java installation. >&2 77 | echo. 78 | goto error 79 | 80 | @REM ==== END VALIDATION ==== 81 | 82 | :init 83 | 84 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn". 85 | @REM Fallback to current working directory if not found. 86 | 87 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% 88 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir 89 | 90 | set EXEC_DIR=%CD% 91 | set WDIR=%EXEC_DIR% 92 | :findBaseDir 93 | IF EXIST "%WDIR%"\.mvn goto baseDirFound 94 | cd .. 95 | IF "%WDIR%"=="%CD%" goto baseDirNotFound 96 | set WDIR=%CD% 97 | goto findBaseDir 98 | 99 | :baseDirFound 100 | set MAVEN_PROJECTBASEDIR=%WDIR% 101 | cd "%EXEC_DIR%" 102 | goto endDetectBaseDir 103 | 104 | :baseDirNotFound 105 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR% 106 | cd "%EXEC_DIR%" 107 | 108 | :endDetectBaseDir 109 | 110 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig 111 | 112 | @setlocal EnableExtensions EnableDelayedExpansion 113 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a 114 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% 115 | 116 | :endReadAdditionalConfig 117 | 118 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" 119 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" 120 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 121 | 122 | set WRAPPER_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" 123 | 124 | FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( 125 | IF "%%A"=="wrapperUrl" SET WRAPPER_URL=%%B 126 | ) 127 | 128 | @REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central 129 | @REM This allows using the maven wrapper in projects that prohibit checking in binary data. 130 | if exist %WRAPPER_JAR% ( 131 | if "%MVNW_VERBOSE%" == "true" ( 132 | echo Found %WRAPPER_JAR% 133 | ) 134 | ) else ( 135 | if not "%MVNW_REPOURL%" == "" ( 136 | SET WRAPPER_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" 137 | ) 138 | if "%MVNW_VERBOSE%" == "true" ( 139 | echo Couldn't find %WRAPPER_JAR%, downloading it ... 140 | echo Downloading from: %WRAPPER_URL% 141 | ) 142 | 143 | powershell -Command "&{"^ 144 | "$webclient = new-object System.Net.WebClient;"^ 145 | "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ 146 | "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ 147 | "}"^ 148 | "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%WRAPPER_URL%', '%WRAPPER_JAR%')"^ 149 | "}" 150 | if "%MVNW_VERBOSE%" == "true" ( 151 | echo Finished downloading %WRAPPER_JAR% 152 | ) 153 | ) 154 | @REM End of extension 155 | 156 | @REM If specified, validate the SHA-256 sum of the Maven wrapper jar file 157 | SET WRAPPER_SHA_256_SUM="" 158 | FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( 159 | IF "%%A"=="wrapperSha256Sum" SET WRAPPER_SHA_256_SUM=%%B 160 | ) 161 | IF NOT %WRAPPER_SHA_256_SUM%=="" ( 162 | powershell -Command "&{"^ 163 | "$hash = (Get-FileHash \"%WRAPPER_JAR%\" -Algorithm SHA256).Hash.ToLower();"^ 164 | "If('%WRAPPER_SHA_256_SUM%' -ne $hash){"^ 165 | " Write-Output 'Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised.';"^ 166 | " Write-Output 'Investigate or delete %WRAPPER_JAR% to attempt a clean download.';"^ 167 | " Write-Output 'If you updated your Maven version, you need to update the specified wrapperSha256Sum property.';"^ 168 | " exit 1;"^ 169 | "}"^ 170 | "}" 171 | if ERRORLEVEL 1 goto error 172 | ) 173 | 174 | @REM Provide a "standardized" way to retrieve the CLI args that will 175 | @REM work with both Windows and non-Windows executions. 176 | set MAVEN_CMD_LINE_ARGS=%* 177 | 178 | %MAVEN_JAVA_EXE% ^ 179 | %JVM_CONFIG_MAVEN_PROPS% ^ 180 | %MAVEN_OPTS% ^ 181 | %MAVEN_DEBUG_OPTS% ^ 182 | -classpath %WRAPPER_JAR% ^ 183 | "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^ 184 | %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* 185 | if ERRORLEVEL 1 goto error 186 | goto end 187 | 188 | :error 189 | set ERROR_CODE=1 190 | 191 | :end 192 | @endlocal & set ERROR_CODE=%ERROR_CODE% 193 | 194 | if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost 195 | @REM check for post script, once with legacy .bat ending and once with .cmd ending 196 | if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat" 197 | if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd" 198 | :skipRcPost 199 | 200 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' 201 | if "%MAVEN_BATCH_PAUSE%"=="on" pause 202 | 203 | if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE% 204 | 205 | cmd /C exit /B %ERROR_CODE% 206 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | org.springframework.boot 7 | spring-boot-starter-parent 8 | 3.1.5 9 | 10 | 11 | com.example 12 | kubernetesjavaclientapi 13 | 0.0.1-SNAPSHOT 14 | kubernetesjavaclientapi 15 | Kubernetes Java Client API for Spring Boot 16 | 17 | 17 18 | 17 19 | 17 20 | 3.11.0 21 | 3.11.0 22 | 1.5.5.Final 23 | 0.2.0 24 | 15.0.1 25 | 26 | 27 | 28 | org.springframework.boot 29 | spring-boot-starter-web 30 | 31 | 32 | 33 | org.projectlombok 34 | lombok 35 | true 36 | 37 | 38 | org.springframework.boot 39 | spring-boot-starter-test 40 | test 41 | 42 | 43 | 44 | io.kubernetes 45 | client-java 46 | ${kubernetes.client.java.version} 47 | 48 | 49 | 50 | org.mapstruct 51 | mapstruct 52 | ${mapstruct.version} 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | org.springframework.boot 62 | spring-boot-maven-plugin 63 | 64 | 65 | paketobuildpacks/builder-jammy-base:latest 66 | 67 | 68 | 69 | org.projectlombok 70 | lombok 71 | 72 | 73 | 74 | 75 | 76 | org.apache.maven.plugins 77 | maven-compiler-plugin 78 | ${maven-compiler-plugin.version} 79 | 80 | 17 81 | 17 82 | 83 | 84 | org.mapstruct 85 | mapstruct-processor 86 | ${mapstruct.version} 87 | 88 | 89 | org.projectlombok 90 | lombok 91 | ${lombok.version} 92 | 93 | 94 | org.projectlombok 95 | lombok-mapstruct-binding 96 | ${lombok-mapstruct-binding.version} 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | -------------------------------------------------------------------------------- /postman_collection/Kubernetes Java Client API Example.postman_collection.json: -------------------------------------------------------------------------------- 1 | { 2 | "info": { 3 | "_postman_id": "fc8b2ee1-71ba-420f-8c85-8ea4aee8ff9f", 4 | "name": "Kubernetes Java Client API Example", 5 | "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", 6 | "_exporter_id": "5570426" 7 | }, 8 | "item": [ 9 | { 10 | "name": "Pods", 11 | "item": [ 12 | { 13 | "name": "Get pods", 14 | "request": { 15 | "method": "GET", 16 | "header": [] 17 | }, 18 | "response": [] 19 | }, 20 | { 21 | "name": "Delete Pod", 22 | "request": { 23 | "method": "DELETE", 24 | "header": [], 25 | "body": { 26 | "mode": "raw", 27 | "raw": "{\r\n \"namespace\": \"default\",\r\n \"podName\": \"example-pod\"\r\n}", 28 | "options": { 29 | "raw": { 30 | "language": "json" 31 | } 32 | } 33 | }, 34 | "url": { 35 | "raw": "http://localhost:1010/api/v1/kubernetes/pods/deletePod", 36 | "protocol": "http", 37 | "host": [ 38 | "localhost" 39 | ], 40 | "port": "1010", 41 | "path": [ 42 | "api", 43 | "v1", 44 | "kubernetes", 45 | "pods", 46 | "deletePod" 47 | ] 48 | } 49 | }, 50 | "response": [] 51 | }, 52 | { 53 | "name": "Create Pod", 54 | "request": { 55 | "method": "POST", 56 | "header": [], 57 | "body": { 58 | "mode": "raw", 59 | "raw": "{\r\n \"namespace\": \"default\",\r\n \"podName\": \"example-pod\"\r\n}", 60 | "options": { 61 | "raw": { 62 | "language": "json" 63 | } 64 | } 65 | }, 66 | "url": { 67 | "raw": "http://localhost:1010/api/v1/kubernetes/pods/createPod", 68 | "protocol": "http", 69 | "host": [ 70 | "localhost" 71 | ], 72 | "port": "1010", 73 | "path": [ 74 | "api", 75 | "v1", 76 | "kubernetes", 77 | "pods", 78 | "createPod" 79 | ] 80 | } 81 | }, 82 | "response": [] 83 | }, 84 | { 85 | "name": "Edit Pod", 86 | "request": { 87 | "method": "PUT", 88 | "header": [], 89 | "body": { 90 | "mode": "raw", 91 | "raw": "{\r\n \"namespace\": \"default\",\r\n \"podName\": \"example-pod\",\r\n \"updatedLabels\": {\r\n \"key1\": \"value1\",\r\n \"key2\": \"value2\"\r\n }\r\n}", 92 | "options": { 93 | "raw": { 94 | "language": "json" 95 | } 96 | } 97 | }, 98 | "url": { 99 | "raw": "http://localhost:1010/api/v1/kubernetes/pods/editPod", 100 | "protocol": "http", 101 | "host": [ 102 | "localhost" 103 | ], 104 | "port": "1010", 105 | "path": [ 106 | "api", 107 | "v1", 108 | "kubernetes", 109 | "pods", 110 | "editPod" 111 | ] 112 | } 113 | }, 114 | "response": [] 115 | } 116 | ] 117 | }, 118 | { 119 | "name": "Namespaces", 120 | "item": [ 121 | { 122 | "name": "Get Namespaces", 123 | "request": { 124 | "method": "GET", 125 | "header": [], 126 | "url": { 127 | "raw": "http://localhost:1010/api/v1/kubernetes/namespaces/listNamespaces", 128 | "protocol": "http", 129 | "host": [ 130 | "localhost" 131 | ], 132 | "port": "1010", 133 | "path": [ 134 | "api", 135 | "v1", 136 | "kubernetes", 137 | "namespaces", 138 | "listNamespaces" 139 | ] 140 | } 141 | }, 142 | "response": [] 143 | }, 144 | { 145 | "name": "Create Namespace", 146 | "request": { 147 | "method": "POST", 148 | "header": [], 149 | "body": { 150 | "mode": "raw", 151 | "raw": "{\r\n \"name\": \"new-namespace-name\"\r\n}", 152 | "options": { 153 | "raw": { 154 | "language": "json" 155 | } 156 | } 157 | }, 158 | "url": { 159 | "raw": "http://localhost:1010/api/v1/kubernetes/namespaces/createNamespace", 160 | "protocol": "http", 161 | "host": [ 162 | "localhost" 163 | ], 164 | "port": "1010", 165 | "path": [ 166 | "api", 167 | "v1", 168 | "kubernetes", 169 | "namespaces", 170 | "createNamespace" 171 | ] 172 | } 173 | }, 174 | "response": [] 175 | }, 176 | { 177 | "name": "Edit Namespace", 178 | "request": { 179 | "method": "PUT", 180 | "header": [], 181 | "body": { 182 | "mode": "raw", 183 | "raw": "{\r\n \"existingName\": \"new-namespace-name\",\r\n \"updatedName\" : \"updated-namespace-name\"\r\n}", 184 | "options": { 185 | "raw": { 186 | "language": "json" 187 | } 188 | } 189 | }, 190 | "url": { 191 | "raw": "http://localhost:1010/api/v1/kubernetes/namespaces/editNamespace", 192 | "protocol": "http", 193 | "host": [ 194 | "localhost" 195 | ], 196 | "port": "1010", 197 | "path": [ 198 | "api", 199 | "v1", 200 | "kubernetes", 201 | "namespaces", 202 | "editNamespace" 203 | ] 204 | } 205 | }, 206 | "response": [] 207 | }, 208 | { 209 | "name": "Delete Namespace", 210 | "request": { 211 | "method": "DELETE", 212 | "header": [], 213 | "body": { 214 | "mode": "raw", 215 | "raw": "{\r\n \"name\": \"updated-namespace-name\"\r\n}", 216 | "options": { 217 | "raw": { 218 | "language": "json" 219 | } 220 | } 221 | }, 222 | "url": { 223 | "raw": "http://localhost:1010/api/v1/kubernetes/namespaces/deleteNamespace", 224 | "protocol": "http", 225 | "host": [ 226 | "localhost" 227 | ], 228 | "port": "1010", 229 | "path": [ 230 | "api", 231 | "v1", 232 | "kubernetes", 233 | "namespaces", 234 | "deleteNamespace" 235 | ] 236 | } 237 | }, 238 | "response": [] 239 | } 240 | ] 241 | }, 242 | { 243 | "name": "Services", 244 | "item": [ 245 | { 246 | "name": "Get Services", 247 | "request": { 248 | "method": "GET", 249 | "header": [], 250 | "url": { 251 | "raw": "http://localhost:1010/api/v1/kubernetes/services/listServices", 252 | "protocol": "http", 253 | "host": [ 254 | "localhost" 255 | ], 256 | "port": "1010", 257 | "path": [ 258 | "api", 259 | "v1", 260 | "kubernetes", 261 | "services", 262 | "listServices" 263 | ] 264 | } 265 | }, 266 | "response": [] 267 | }, 268 | { 269 | "name": "Create Service", 270 | "request": { 271 | "method": "POST", 272 | "header": [], 273 | "body": { 274 | "mode": "raw", 275 | "raw": "{\r\n \"name\" : \"new-kubernetes-service\"\r\n}", 276 | "options": { 277 | "raw": { 278 | "language": "json" 279 | } 280 | } 281 | }, 282 | "url": { 283 | "raw": "http://localhost:1010/api/v1/kubernetes/services/createService", 284 | "protocol": "http", 285 | "host": [ 286 | "localhost" 287 | ], 288 | "port": "1010", 289 | "path": [ 290 | "api", 291 | "v1", 292 | "kubernetes", 293 | "services", 294 | "createService" 295 | ] 296 | } 297 | }, 298 | "response": [] 299 | }, 300 | { 301 | "name": "Edit Service", 302 | "request": { 303 | "method": "PUT", 304 | "header": [], 305 | "body": { 306 | "mode": "raw", 307 | "raw": "{\r\n \"existingName\" : \"new-kubernetes-service\",\r\n \"updatedName\" : \"updated-kubernetes-service\"\r\n}", 308 | "options": { 309 | "raw": { 310 | "language": "json" 311 | } 312 | } 313 | }, 314 | "url": { 315 | "raw": "http://localhost:1010/api/v1/kubernetes/services/editService", 316 | "protocol": "http", 317 | "host": [ 318 | "localhost" 319 | ], 320 | "port": "1010", 321 | "path": [ 322 | "api", 323 | "v1", 324 | "kubernetes", 325 | "services", 326 | "editService" 327 | ] 328 | } 329 | }, 330 | "response": [] 331 | }, 332 | { 333 | "name": "Delete Service", 334 | "request": { 335 | "method": "DELETE", 336 | "header": [], 337 | "body": { 338 | "mode": "raw", 339 | "raw": "{\r\n \"name\" : \"updated-kubernetes-service\"\r\n}", 340 | "options": { 341 | "raw": { 342 | "language": "json" 343 | } 344 | } 345 | }, 346 | "url": { 347 | "raw": "http://localhost:1010/api/v1/kubernetes/services/deleteService", 348 | "protocol": "http", 349 | "host": [ 350 | "localhost" 351 | ], 352 | "port": "1010", 353 | "path": [ 354 | "api", 355 | "v1", 356 | "kubernetes", 357 | "services", 358 | "deleteService" 359 | ] 360 | } 361 | }, 362 | "response": [] 363 | } 364 | ] 365 | }, 366 | { 367 | "name": "Deployments", 368 | "item": [ 369 | { 370 | "name": "Get Deployments", 371 | "request": { 372 | "method": "GET", 373 | "header": [], 374 | "url": { 375 | "raw": "http://localhost:1010/api/v1/kubernetes/deployments/listDeployments", 376 | "protocol": "http", 377 | "host": [ 378 | "localhost" 379 | ], 380 | "port": "1010", 381 | "path": [ 382 | "api", 383 | "v1", 384 | "kubernetes", 385 | "deployments", 386 | "listDeployments" 387 | ] 388 | } 389 | }, 390 | "response": [] 391 | }, 392 | { 393 | "name": "Create Deployment", 394 | "request": { 395 | "method": "POST", 396 | "header": [], 397 | "body": { 398 | "mode": "raw", 399 | "raw": "{\r\n \"name\": \"new-kubernetes-deployment\",\r\n \"replicas\": 3,\r\n \"labels\": {\r\n \"app\": \"example-app\",\r\n \"tier\": \"backend\"\r\n },\r\n \"containerName\": \"example-container\",\r\n \"image\": \"your-docker-image:latest\",\r\n \"containerPort\": 1234\r\n}", 400 | "options": { 401 | "raw": { 402 | "language": "json" 403 | } 404 | } 405 | }, 406 | "url": { 407 | "raw": "http://localhost:1010/api/v1/kubernetes/deployments/createDeployment", 408 | "protocol": "http", 409 | "host": [ 410 | "localhost" 411 | ], 412 | "port": "1010", 413 | "path": [ 414 | "api", 415 | "v1", 416 | "kubernetes", 417 | "deployments", 418 | "createDeployment" 419 | ] 420 | } 421 | }, 422 | "response": [] 423 | }, 424 | { 425 | "name": "Edit Deployment", 426 | "request": { 427 | "method": "PUT", 428 | "header": [], 429 | "body": { 430 | "mode": "raw", 431 | "raw": "{\r\n \"name\": \"new-kubernetes-deployment\",\r\n \"replicas\": 5,\r\n \"labels\": {\r\n \"app\": \"edited-app\",\r\n \"environment\": \"production\"\r\n },\r\n \"containerName\": \"edited-container\",\r\n \"image\": \"edited-docker-image:latest\",\r\n \"containerPort\": 2121\r\n}", 432 | "options": { 433 | "raw": { 434 | "language": "json" 435 | } 436 | } 437 | }, 438 | "url": { 439 | "raw": "http://localhost:1010/api/v1/kubernetes/deployments/editDeployment", 440 | "protocol": "http", 441 | "host": [ 442 | "localhost" 443 | ], 444 | "port": "1010", 445 | "path": [ 446 | "api", 447 | "v1", 448 | "kubernetes", 449 | "deployments", 450 | "editDeployment" 451 | ] 452 | } 453 | }, 454 | "response": [] 455 | }, 456 | { 457 | "name": "Delete Deployment", 458 | "request": { 459 | "method": "DELETE", 460 | "header": [], 461 | "body": { 462 | "mode": "raw", 463 | "raw": "{\r\n \"name\": \"new-kubernetes-deployment\"\r\n}", 464 | "options": { 465 | "raw": { 466 | "language": "json" 467 | } 468 | } 469 | }, 470 | "url": { 471 | "raw": "http://localhost:1010/api/v1/kubernetes/deployments/deleteDeployment", 472 | "protocol": "http", 473 | "host": [ 474 | "localhost" 475 | ], 476 | "port": "1010", 477 | "path": [ 478 | "api", 479 | "v1", 480 | "kubernetes", 481 | "deployments", 482 | "deleteDeployment" 483 | ] 484 | } 485 | }, 486 | "response": [] 487 | } 488 | ] 489 | } 490 | ] 491 | } -------------------------------------------------------------------------------- /screenshots/1.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rapter1990/kubernetesjavaclientapi/64be9d35d5f876ce109bb3791d608156a4c3750b/screenshots/1.PNG -------------------------------------------------------------------------------- /screenshots/2.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rapter1990/kubernetesjavaclientapi/64be9d35d5f876ce109bb3791d608156a4c3750b/screenshots/2.PNG -------------------------------------------------------------------------------- /screenshots/3.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rapter1990/kubernetesjavaclientapi/64be9d35d5f876ce109bb3791d608156a4c3750b/screenshots/3.PNG -------------------------------------------------------------------------------- /screenshots/springboot-kubernetes-java-client-api-main-image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rapter1990/kubernetesjavaclientapi/64be9d35d5f876ce109bb3791d608156a4c3750b/screenshots/springboot-kubernetes-java-client-api-main-image.png -------------------------------------------------------------------------------- /src/main/java/com/example/kubernetesjavaclientapi/KubernetesJavaClientApiApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.kubernetesjavaclientapi; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | /** 7 | * Main application class {@link KubernetesJavaClientApiApplication} for the Kubernetes Java Client API demo. 8 | */ 9 | @SpringBootApplication 10 | public class KubernetesJavaClientApiApplication { 11 | 12 | /** 13 | * The main method that starts the Spring Boot application. 14 | * 15 | * @param args Command-line arguments passed to the application. 16 | */ 17 | public static void main(String[] args) { 18 | SpringApplication.run(KubernetesJavaClientApiApplication.class, args); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/example/kubernetesjavaclientapi/config/KubernetesConfig.java: -------------------------------------------------------------------------------- 1 | package com.example.kubernetesjavaclientapi.config; 2 | 3 | import io.kubernetes.client.openapi.ApiClient; 4 | import io.kubernetes.client.openapi.apis.AppsV1Api; 5 | import io.kubernetes.client.openapi.apis.CoreV1Api; 6 | import io.kubernetes.client.util.Config; 7 | import org.springframework.context.annotation.Bean; 8 | import org.springframework.context.annotation.Configuration; 9 | 10 | /** 11 | * Configuration class {@link KubernetesConfig} for setting up Kubernetes-related beans. 12 | */ 13 | @Configuration 14 | public class KubernetesConfig { 15 | 16 | /** 17 | * Creates and configures an instance of {@link ApiClient} using default settings. 18 | * 19 | * @return An initialized {@link ApiClient} instance. 20 | * @throws Exception if an error occurs during configuration. 21 | */ 22 | @Bean 23 | public ApiClient apiClient() throws Exception { 24 | return Config.defaultClient(); 25 | } 26 | 27 | /** 28 | * Creates and configures an instance of {@link CoreV1Api} using the provided {@link ApiClient}. 29 | * 30 | * @param apiClient The {@link ApiClient} to use for the {@link CoreV1Api} instance. 31 | * @return An initialized {@link CoreV1Api} instance. 32 | */ 33 | @Bean 34 | public CoreV1Api coreV1Api(ApiClient apiClient) { 35 | return new CoreV1Api(apiClient); 36 | } 37 | 38 | /** 39 | * Creates and configures an instance of {@link AppsV1Api} using the provided {@link ApiClient}. 40 | * 41 | * @param apiClient The {@link ApiClient} to use for the {@link AppsV1Api} instance. 42 | * @return An initialized {@link AppsV1Api} instance. 43 | */ 44 | @Bean 45 | public AppsV1Api appsV1Api(ApiClient apiClient) { 46 | return new AppsV1Api(apiClient); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/com/example/kubernetesjavaclientapi/controller/DeploymentController.java: -------------------------------------------------------------------------------- 1 | package com.example.kubernetesjavaclientapi.controller; 2 | 3 | import com.example.kubernetesjavaclientapi.dto.deployment.DeploymentDto; 4 | import com.example.kubernetesjavaclientapi.payload.request.deployment.CreateDeploymentRequest; 5 | import com.example.kubernetesjavaclientapi.payload.request.deployment.DeleteDeploymentRequest; 6 | import com.example.kubernetesjavaclientapi.payload.request.deployment.EditDeploymentRequest; 7 | import com.example.kubernetesjavaclientapi.service.DeploymentService; 8 | import io.kubernetes.client.openapi.ApiException; 9 | import io.kubernetes.client.openapi.models.V1Deployment; 10 | import io.kubernetes.client.openapi.models.V1Status; 11 | import lombok.RequiredArgsConstructor; 12 | import lombok.extern.slf4j.Slf4j; 13 | import org.springframework.http.HttpStatus; 14 | import org.springframework.http.ResponseEntity; 15 | import org.springframework.web.bind.annotation.*; 16 | 17 | import java.util.List; 18 | 19 | /** 20 | * Controller class {@link DeploymentController} for handling Kubernetes deployment-related operations. 21 | */ 22 | @RestController 23 | @RequestMapping("/api/v1/kubernetes/deployments") 24 | @RequiredArgsConstructor 25 | @Slf4j 26 | public class DeploymentController { 27 | 28 | private final DeploymentService deploymentService; 29 | 30 | /** 31 | * Retrieves a list of Deployments. 32 | * 33 | * @return List of DeploymentDto containing deployment information. 34 | * @throws Exception if an error occurs while retrieving the deployments. 35 | */ 36 | @GetMapping("/listDeployments") 37 | public List listDeployments() throws Exception { 38 | return deploymentService.listDeployments(); 39 | } 40 | 41 | /** 42 | * Creates a new Deployment based on the provided request. 43 | * 44 | * @param request CreateDeploymentRequest containing deployment creation parameters. 45 | * @return ResponseEntity indicating the status of the creation operation. 46 | */ 47 | @PostMapping("/createDeployment") 48 | public ResponseEntity createDeployment(@RequestBody CreateDeploymentRequest request) { 49 | try { 50 | V1Deployment deployment = deploymentService.createDeployment(request); 51 | 52 | return ResponseEntity.status(HttpStatus.CREATED).body("Deployment created successfully: " + deployment.getMetadata().getName()); 53 | } catch (ApiException e) { 54 | log.error("Error creating deployment", e); 55 | return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Error creating deployment: " + e.getResponseBody()); 56 | } 57 | } 58 | 59 | /** 60 | * Edits an existing Deployment based on the provided request. 61 | * 62 | * @param request EditDeploymentRequest containing deployment modification parameters. 63 | * @return ResponseEntity indicating the status of the edit operation. 64 | */ 65 | @PutMapping("/editDeployment") 66 | public ResponseEntity editDeployment(@RequestBody EditDeploymentRequest request){ 67 | try { 68 | V1Deployment editDeployment = deploymentService.editDeployment(request); 69 | return ResponseEntity.status(HttpStatus.OK).body("Service edited successfully: " + editDeployment.getMetadata().getName()); 70 | } catch (ApiException e) { 71 | log.error("Error editing deployment", e); 72 | return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Error editing deployment: " + e.getResponseBody()); 73 | } 74 | } 75 | 76 | /** 77 | * Deletes an existing Deployment based on the provided request. 78 | * 79 | * @param request DeleteDeploymentRequest containing deployment deletion parameters. 80 | * @return ResponseEntity indicating the status of the deletion operation. 81 | */ 82 | @DeleteMapping("/deleteDeployment") 83 | public ResponseEntity deleteDeployment(@RequestBody DeleteDeploymentRequest request){ 84 | 85 | try { 86 | V1Status deletionStatus = deploymentService.deleteDeployment(request); 87 | 88 | // Check the deletion status or use it in the response if needed 89 | log.info("Namespace deletion status: {}", deletionStatus.getMessage()); 90 | 91 | return ResponseEntity.status(HttpStatus.OK).body("Deployment deleted successfully: " + request.getName()); 92 | } catch (ApiException e) { 93 | // Handle the exception appropriately 94 | log.error("Error deleting deployment: {}", e.getMessage()); 95 | return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Error deleting deployment: " + e.getResponseBody()); 96 | } 97 | 98 | } 99 | 100 | } 101 | -------------------------------------------------------------------------------- /src/main/java/com/example/kubernetesjavaclientapi/controller/NamespaceController.java: -------------------------------------------------------------------------------- 1 | package com.example.kubernetesjavaclientapi.controller; 2 | 3 | import com.example.kubernetesjavaclientapi.dto.namespace.NameSpaceDto; 4 | import com.example.kubernetesjavaclientapi.payload.request.namespace.CreateNamespaceRequest; 5 | import com.example.kubernetesjavaclientapi.payload.request.namespace.DeleteNamespaceRequest; 6 | import com.example.kubernetesjavaclientapi.payload.request.namespace.EditNamespaceRequest; 7 | import com.example.kubernetesjavaclientapi.service.NamespaceService; 8 | import io.kubernetes.client.openapi.ApiException; 9 | import io.kubernetes.client.openapi.models.V1Namespace; 10 | import io.kubernetes.client.openapi.models.V1Status; 11 | import lombok.RequiredArgsConstructor; 12 | import lombok.extern.slf4j.Slf4j; 13 | import org.springframework.http.HttpStatus; 14 | import org.springframework.http.ResponseEntity; 15 | import org.springframework.web.bind.annotation.*; 16 | 17 | import java.util.List; 18 | 19 | /** 20 | * Controller class {@link NamespaceController} for handling Kubernetes namespace-related operations. 21 | */ 22 | @RestController 23 | @RequestMapping("/api/v1/kubernetes/namespaces") 24 | @RequiredArgsConstructor 25 | @Slf4j 26 | public class NamespaceController { 27 | 28 | private final NamespaceService namespaceService; 29 | 30 | /** 31 | * Retrieves a list of namespaces. 32 | * 33 | * @return List of NameSpaceDto objects representing the namespaces. 34 | * @throws Exception if there is an error while retrieving the namespaces. 35 | */ 36 | @GetMapping("/listNamespaces") 37 | public List listNamespaces() throws Exception { 38 | return namespaceService.listNameSpaces(); 39 | } 40 | 41 | /** 42 | * Creates a new namespace based on the provided request. 43 | * 44 | * @param request The CreateNamespaceRequest containing information for creating the namespace. 45 | * @return ResponseEntity with a success message if the namespace is created successfully, 46 | * or an error message if the creation fails. 47 | */ 48 | @PostMapping("/createNamespace") 49 | public ResponseEntity createNamespace(@RequestBody CreateNamespaceRequest request) { 50 | try { 51 | V1Namespace namespace = namespaceService.createNamespace(request); 52 | // Optionally, you can return more information about the created Namespace. 53 | return ResponseEntity.status(HttpStatus.CREATED).body("Namespace created successfully: " + namespace.getMetadata().getName()); 54 | } catch (ApiException e) { 55 | log.error("Error creating namespace", e); 56 | return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Error creating Namespace: " + e.getResponseBody()); 57 | } 58 | } 59 | 60 | /** 61 | * Edits an existing namespace based on the provided request. 62 | * 63 | * @param request The EditNamespaceRequest containing information for editing the namespace. 64 | * @return ResponseEntity with a success message if the namespace is edited successfully, 65 | * or an error message if the editing fails. 66 | */ 67 | @PutMapping("/editNamespace") 68 | public ResponseEntity editNamespace(@RequestBody EditNamespaceRequest request){ 69 | try { 70 | V1Namespace editedNamespace = namespaceService.editNamespace(request); 71 | // Optionally, you can return more information about the edited pod. 72 | return ResponseEntity.status(HttpStatus.OK).body("Namespace edited successfully: " + editedNamespace.getMetadata().getName()); 73 | } catch (ApiException e) { 74 | log.error("Error editing namespace", e); 75 | return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Error editing namespace: " + e.getResponseBody()); 76 | } 77 | } 78 | 79 | /** 80 | * Deletes an existing namespace based on the provided request. 81 | * 82 | * @param request The DeleteNamespaceRequest containing information for deleting the namespace. 83 | * @return ResponseEntity with a success message if the namespace is deleted successfully, 84 | * or an error message if the deletion fails. 85 | */ 86 | @DeleteMapping("/deleteNamespace") 87 | public ResponseEntity deleteNamespace(@RequestBody DeleteNamespaceRequest request){ 88 | 89 | try { 90 | V1Status deletionStatus = namespaceService.deleteNamespace(request); 91 | 92 | // Check the deletion status or use it in the response if needed 93 | log.info("Namespace deletion status: {}", deletionStatus.getMessage()); 94 | 95 | return ResponseEntity.status(HttpStatus.OK).body("Namespace deleted successfully: " + request.getName()); 96 | } catch (ApiException e) { 97 | // Handle the exception appropriately 98 | log.error("Error deleting namespace: {}", e.getMessage()); 99 | return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Error deleting namespace: " + e.getResponseBody()); 100 | } 101 | 102 | } 103 | 104 | } 105 | -------------------------------------------------------------------------------- /src/main/java/com/example/kubernetesjavaclientapi/controller/PodController.java: -------------------------------------------------------------------------------- 1 | package com.example.kubernetesjavaclientapi.controller; 2 | 3 | import com.example.kubernetesjavaclientapi.dto.pod.PodDto; 4 | import com.example.kubernetesjavaclientapi.payload.request.pods.CreatePodRequest; 5 | import com.example.kubernetesjavaclientapi.payload.request.pods.DeletePodRequest; 6 | import com.example.kubernetesjavaclientapi.payload.request.pods.EditPodRequest; 7 | import com.example.kubernetesjavaclientapi.service.PodService; 8 | import io.kubernetes.client.openapi.ApiException; 9 | import io.kubernetes.client.openapi.models.V1Pod; 10 | import lombok.RequiredArgsConstructor; 11 | import lombok.extern.slf4j.Slf4j; 12 | import org.springframework.http.HttpStatus; 13 | import org.springframework.http.ResponseEntity; 14 | import org.springframework.web.bind.annotation.*; 15 | 16 | import java.util.List; 17 | 18 | /** 19 | * Controller class {@link PodController} for handling Kubernetes pod-related operations. 20 | */ 21 | @RestController 22 | @RequestMapping("/api/v1/kubernetes/pods") 23 | @RequiredArgsConstructor 24 | @Slf4j 25 | public class PodController { 26 | 27 | private final PodService podService; 28 | 29 | /** 30 | * Retrieves a list of Kubernetes pods. 31 | * 32 | * @return A list of {@link PodDto} representing Kubernetes pods. 33 | * @throws Exception if an error occurs during pod retrieval. 34 | */ 35 | @GetMapping("/listPods") 36 | public List listPods() throws Exception { 37 | return podService.listPods(); 38 | } 39 | 40 | /** 41 | * Creates a new Kubernetes pod based on the provided request. 42 | * 43 | * @param request The {@link CreatePodRequest} containing pod creation details. 44 | * @return A {@link ResponseEntity} indicating the status of the pod creation operation. 45 | */ 46 | @PostMapping("/createPod") 47 | public ResponseEntity createPod(@RequestBody CreatePodRequest request) { 48 | try { 49 | V1Pod createdPod = podService.createPod(request); 50 | // Optionally, you can return more information about the created pod. 51 | return ResponseEntity.status(HttpStatus.CREATED).body("Pod created successfully: " + createdPod.getMetadata().getName()); 52 | } catch (ApiException e) { 53 | log.error("Error creating pod", e); 54 | return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Error creating pod: " + e.getResponseBody()); 55 | } 56 | } 57 | 58 | /** 59 | * Creates a new Kubernetes pod based on the provided request. 60 | * 61 | * @param request The {@link CreatePodRequest} containing pod creation details. 62 | * @return A {@link ResponseEntity} indicating the status of the pod creation operation. 63 | */ 64 | @PutMapping("/editPod") 65 | public ResponseEntity editPod(@RequestBody EditPodRequest request){ 66 | try { 67 | V1Pod editedPod = podService.editPod(request); 68 | // Optionally, you can return more information about the edited pod. 69 | return ResponseEntity.status(HttpStatus.OK).body("Pod edited successfully: " + editedPod.getMetadata().getName()); 70 | } catch (ApiException e) { 71 | log.error("Error editing pod", e); 72 | return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Error editing pod: " + e.getResponseBody()); 73 | } 74 | } 75 | 76 | /** 77 | * Deletes an existing Kubernetes pod based on the provided request. 78 | * 79 | * @param request The {@link DeletePodRequest} containing pod deletion details. 80 | * @return A {@link ResponseEntity} indicating the status of the pod deletion operation. 81 | */ 82 | @DeleteMapping("/deletePod") 83 | public ResponseEntity deletePod(@RequestBody DeletePodRequest request){ 84 | try { 85 | podService.deletePod(request); 86 | // Optionally, you can return more information about the deleted pod. 87 | return ResponseEntity.status(HttpStatus.OK).body("Pod deleted successfully: " + request.getPodName()); 88 | } catch (ApiException e) { 89 | log.error("Error deleting pod", e); 90 | return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Error deleting pod: " + e.getResponseBody()); 91 | } 92 | } 93 | 94 | } 95 | -------------------------------------------------------------------------------- /src/main/java/com/example/kubernetesjavaclientapi/controller/ServiceController.java: -------------------------------------------------------------------------------- 1 | package com.example.kubernetesjavaclientapi.controller; 2 | 3 | import com.example.kubernetesjavaclientapi.dto.service.ServiceDto; 4 | import com.example.kubernetesjavaclientapi.payload.request.service.CreateServiceRequest; 5 | import com.example.kubernetesjavaclientapi.payload.request.service.DeleteServiceRequest; 6 | import com.example.kubernetesjavaclientapi.payload.request.service.EditServiceRequest; 7 | import com.example.kubernetesjavaclientapi.service.KubeServiceService; 8 | import io.kubernetes.client.openapi.ApiException; 9 | import io.kubernetes.client.openapi.models.V1Service; 10 | import lombok.RequiredArgsConstructor; 11 | import lombok.extern.slf4j.Slf4j; 12 | import org.springframework.http.HttpStatus; 13 | import org.springframework.http.ResponseEntity; 14 | import org.springframework.web.bind.annotation.*; 15 | 16 | import java.util.List; 17 | 18 | /** 19 | * Controller class {@link ServiceController} for handling Kubernetes service-related operations. 20 | */ 21 | @RestController 22 | @RequestMapping("/api/v1/kubernetes/services") 23 | @RequiredArgsConstructor 24 | @Slf4j 25 | public class ServiceController { 26 | 27 | private final KubeServiceService kubeServiceService; 28 | 29 | /** 30 | * Endpoint to retrieve a list of all Kubernetes services. 31 | * 32 | * @return A list of {@link ServiceDto} representing the Kubernetes services. 33 | * @throws Exception If an error occurs while fetching the services. 34 | */ 35 | @GetMapping("/listServices") 36 | public List listServices() throws Exception { 37 | return kubeServiceService.listServices(); 38 | } 39 | 40 | /** 41 | * Endpoint to create a new Kubernetes service. 42 | * 43 | * @param request The request body containing the details for creating the service. 44 | * @return A ResponseEntity indicating the result of the service creation. 45 | */ 46 | @PostMapping("/createService") 47 | public ResponseEntity createService(@RequestBody CreateServiceRequest request) { 48 | try { 49 | V1Service service = kubeServiceService.createService(request); 50 | // Optionally, you can return more information about the created Namespace. 51 | return ResponseEntity.status(HttpStatus.CREATED).body("Service created successfully: " + service.getMetadata().getName()); 52 | } catch (ApiException e) { 53 | log.error("Error creating service", e); 54 | return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Error creating Service: " + e.getResponseBody()); 55 | } 56 | } 57 | 58 | /** 59 | * Endpoint to edit an existing Kubernetes service. 60 | * 61 | * @param request The request body containing the details for editing the service. 62 | * @return A ResponseEntity indicating the result of the service editing. 63 | */ 64 | @PutMapping("/editService") 65 | public ResponseEntity editService(@RequestBody EditServiceRequest request){ 66 | try { 67 | V1Service editedService = kubeServiceService.editService(request); 68 | return ResponseEntity.status(HttpStatus.OK).body("Service edited successfully: " + request.getUpdatedName()); 69 | } catch (ApiException e) { 70 | log.error("Error editing service", e); 71 | return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Error editing Service: " + e.getResponseBody()); 72 | } 73 | } 74 | 75 | /** 76 | * Endpoint to delete a Kubernetes service. 77 | * 78 | * @param request The request body containing the details for deleting the service. 79 | * @return A ResponseEntity indicating the result of the service deletion. 80 | */ 81 | @DeleteMapping("/deleteService") 82 | public ResponseEntity deletePod(@RequestBody DeleteServiceRequest request){ 83 | try { 84 | V1Service v1Service = kubeServiceService.deleteService(request); 85 | 86 | return ResponseEntity.status(HttpStatus.OK).body("Service deleted successfully: " + v1Service.getMetadata().getName()); 87 | } catch (ApiException e) { 88 | log.error("Error deleting service", e); 89 | return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Error deleting service: " + e.getResponseBody()); 90 | } 91 | } 92 | 93 | } 94 | -------------------------------------------------------------------------------- /src/main/java/com/example/kubernetesjavaclientapi/dto/deployment/DeploymentDto.java: -------------------------------------------------------------------------------- 1 | package com.example.kubernetesjavaclientapi.dto.deployment; 2 | 3 | import lombok.Builder; 4 | import lombok.Getter; 5 | 6 | @Builder 7 | @Getter 8 | public class DeploymentDto { 9 | 10 | private String uid; 11 | private String name; 12 | 13 | private String namespace; 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/example/kubernetesjavaclientapi/dto/namespace/NameSpaceDto.java: -------------------------------------------------------------------------------- 1 | package com.example.kubernetesjavaclientapi.dto.namespace; 2 | 3 | import io.micrometer.common.lang.Nullable; 4 | import lombok.Builder; 5 | import lombok.Getter; 6 | 7 | @Builder 8 | @Getter 9 | public class NameSpaceDto { 10 | private String uid; 11 | 12 | private String namespace; 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/example/kubernetesjavaclientapi/dto/pod/PodDto.java: -------------------------------------------------------------------------------- 1 | package com.example.kubernetesjavaclientapi.dto.pod; 2 | 3 | import io.kubernetes.client.openapi.models.V1ManagedFieldsEntry; 4 | import io.kubernetes.client.openapi.models.V1OwnerReference; 5 | import io.micrometer.common.lang.Nullable; 6 | import lombok.Builder; 7 | import lombok.Data; 8 | import lombok.Getter; 9 | 10 | import java.time.OffsetDateTime; 11 | import java.util.ArrayList; 12 | import java.util.HashMap; 13 | import java.util.List; 14 | import java.util.Map; 15 | 16 | /** 17 | * Data Transfer Object (DTO) {@link PodDto} representing information about a Kubernetes Pod. 18 | */ 19 | @Builder 20 | @Getter 21 | public class PodDto { 22 | private String uid; 23 | 24 | @Nullable 25 | private String name; 26 | 27 | @Nullable 28 | private Map annotations = new HashMap(); 29 | 30 | @Nullable 31 | private String clusterName; 32 | private OffsetDateTime creationTimestamp; 33 | 34 | @Nullable 35 | private Long deletionGracePeriodSeconds; 36 | 37 | @Nullable 38 | private OffsetDateTime deletionTimestamp; 39 | 40 | @Nullable 41 | private List finalizers = new ArrayList<>(); 42 | private String generateName; 43 | 44 | @Nullable 45 | private Long generation; 46 | private Map labels = new HashMap(); 47 | private List managedFields = new ArrayList<>(); 48 | private String namespace; 49 | private List ownerReferences; 50 | private String resourceVersion; 51 | 52 | @Nullable 53 | private String selfLink; 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/com/example/kubernetesjavaclientapi/dto/pod/V1ManagedFieldsEntryDto.java: -------------------------------------------------------------------------------- 1 | package com.example.kubernetesjavaclientapi.dto.pod; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | import lombok.Builder; 5 | import lombok.Getter; 6 | 7 | import javax.annotation.Nullable; 8 | import java.time.OffsetDateTime; 9 | 10 | /** 11 | * Data Transfer Object (DTO) {@link V1ManagedFieldsEntryDto} representing Kubernetes V1ManagedFieldsEntry information. 12 | */ 13 | @Builder 14 | @Getter 15 | public class V1ManagedFieldsEntryDto { 16 | private String apiVersion; 17 | private String fieldsType; 18 | private Object fieldsV1; 19 | private String manager; 20 | private String operation; 21 | 22 | @Nullable 23 | private String subresource; 24 | private OffsetDateTime time; 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/com/example/kubernetesjavaclientapi/dto/pod/V1OwnerReferenceDto.java: -------------------------------------------------------------------------------- 1 | package com.example.kubernetesjavaclientapi.dto.pod; 2 | 3 | import lombok.Builder; 4 | import lombok.Getter; 5 | 6 | /** 7 | * Data Transfer Object (DTO) {@link V1OwnerReferenceDto} representing Kubernetes V1OwnerReference information. 8 | */ 9 | @Builder 10 | @Getter 11 | public class V1OwnerReferenceDto { 12 | private String apiVersion; 13 | private Boolean blockOwnerDeletion; 14 | private Boolean controller; 15 | private String kind; 16 | private String name; 17 | private String uid; 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/example/kubernetesjavaclientapi/dto/service/ServiceDto.java: -------------------------------------------------------------------------------- 1 | package com.example.kubernetesjavaclientapi.dto.service; 2 | 3 | import lombok.Builder; 4 | import lombok.Getter; 5 | 6 | /** 7 | * Data Transfer Object (DTO) {@link ServiceDto} representing information about a Kubernetes Service. 8 | */ 9 | @Builder 10 | @Getter 11 | public class ServiceDto { 12 | private String uid; 13 | private String name; 14 | 15 | private String namespace; 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/example/kubernetesjavaclientapi/mapper/BaseMapper.java: -------------------------------------------------------------------------------- 1 | package com.example.kubernetesjavaclientapi.mapper; 2 | 3 | import java.util.Collection; 4 | import java.util.List; 5 | 6 | /** 7 | * Base interface for object mapping between two types. 8 | * 9 | * @param the source type 10 | * @param the target type 11 | */ 12 | public interface BaseMapper { 13 | 14 | /** 15 | * Maps the specified source object to an object of type {@code T}. 16 | * 17 | * @param source the source object to be mapped 18 | * @return the resulting object of type {@code T} 19 | */ 20 | T map(S source); 21 | 22 | /** 23 | * Maps the specified collection of source objects to a list of objects of type {@code T}. 24 | * 25 | * @param sources the collection of source objects to be mapped 26 | * @return the list of resulting objects of type {@code T} 27 | */ 28 | List map(Collection sources); 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/com/example/kubernetesjavaclientapi/mapper/V1ManagedFieldsEntryToV1ManagedFieldsEntryDtoMapper.java: -------------------------------------------------------------------------------- 1 | package com.example.kubernetesjavaclientapi.mapper; 2 | 3 | import com.example.kubernetesjavaclientapi.dto.pod.V1ManagedFieldsEntryDto; 4 | import io.kubernetes.client.openapi.models.V1ManagedFieldsEntry; 5 | import org.mapstruct.Mapper; 6 | import org.mapstruct.factory.Mappers; 7 | 8 | /** 9 | * Mapper interface {@link V1ManagedFieldsEntryToV1ManagedFieldsEntryDtoMapper} for mapping Kubernetes V1ManagedFieldsEntry objects to V1ManagedFieldsEntryDto objects. 10 | */ 11 | @Mapper 12 | public interface V1ManagedFieldsEntryToV1ManagedFieldsEntryDtoMapper extends BaseMapper { 13 | 14 | /** 15 | * Initializes the mapper. 16 | * 17 | * @return the initialized mapper object. 18 | */ 19 | static V1ManagedFieldsEntryToV1ManagedFieldsEntryDtoMapper initialize() { 20 | return Mappers.getMapper(V1ManagedFieldsEntryToV1ManagedFieldsEntryDtoMapper.class); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/com/example/kubernetesjavaclientapi/mapper/V1OwnerReferenceToV1OwnerReferenceDtoMapper.java: -------------------------------------------------------------------------------- 1 | package com.example.kubernetesjavaclientapi.mapper; 2 | 3 | import com.example.kubernetesjavaclientapi.dto.pod.V1OwnerReferenceDto; 4 | import io.kubernetes.client.openapi.models.V1OwnerReference; 5 | import org.mapstruct.Mapper; 6 | import org.mapstruct.factory.Mappers; 7 | 8 | /** 9 | * Mapper interface {@link V1OwnerReferenceToV1OwnerReferenceDtoMapper} for mapping Kubernetes V1OwnerReference objects to V1OwnerReferenceDto objects. 10 | */ 11 | @Mapper 12 | public interface V1OwnerReferenceToV1OwnerReferenceDtoMapper extends BaseMapper { 13 | 14 | /** 15 | * Initializes the mapper. 16 | * 17 | * @return the initialized mapper object. 18 | */ 19 | static V1OwnerReferenceToV1OwnerReferenceDtoMapper initialize() { 20 | return Mappers.getMapper(V1OwnerReferenceToV1OwnerReferenceDtoMapper.class); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/example/kubernetesjavaclientapi/payload/request/deployment/CreateDeploymentRequest.java: -------------------------------------------------------------------------------- 1 | package com.example.kubernetesjavaclientapi.payload.request.deployment; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | import java.util.Map; 10 | 11 | /** 12 | * Represents a request {@link CreateDeploymentRequest} for creating a Kubernetes deployment. 13 | */ 14 | @Data 15 | @Builder 16 | @NoArgsConstructor 17 | @AllArgsConstructor 18 | @JsonIgnoreProperties(ignoreUnknown = true) 19 | public class CreateDeploymentRequest { 20 | 21 | private String name; 22 | private int replicas; 23 | private Map labels; 24 | private String containerName; 25 | private String image; 26 | private int containerPort; 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/example/kubernetesjavaclientapi/payload/request/deployment/DeleteDeploymentRequest.java: -------------------------------------------------------------------------------- 1 | package com.example.kubernetesjavaclientapi.payload.request.deployment; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | /** 10 | * Represents a request {@link DeleteDeploymentRequest} for deleting a Kubernetes deployment. 11 | */ 12 | @Data 13 | @Builder 14 | @NoArgsConstructor 15 | @AllArgsConstructor 16 | @JsonIgnoreProperties(ignoreUnknown = true) 17 | public class DeleteDeploymentRequest { 18 | 19 | private String name; 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/example/kubernetesjavaclientapi/payload/request/deployment/EditDeploymentRequest.java: -------------------------------------------------------------------------------- 1 | package com.example.kubernetesjavaclientapi.payload.request.deployment; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | import java.util.Map; 10 | 11 | /** 12 | * Represents a request {@link CreateDeploymentRequest} for editing a Kubernetes deployment. 13 | */ 14 | @Data 15 | @Builder 16 | @NoArgsConstructor 17 | @AllArgsConstructor 18 | @JsonIgnoreProperties(ignoreUnknown = true) 19 | public class EditDeploymentRequest { 20 | 21 | private String name; 22 | private int replicas; 23 | private Map labels; 24 | private String containerName; 25 | private String image; 26 | private int containerPort; 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/example/kubernetesjavaclientapi/payload/request/namespace/CreateNamespaceRequest.java: -------------------------------------------------------------------------------- 1 | package com.example.kubernetesjavaclientapi.payload.request.namespace; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | /** 10 | * A request class {@link CreateNamespaceRequest} representing the information needed to create a new Kubernetes namespace. 11 | */ 12 | @Data 13 | @Builder 14 | @NoArgsConstructor 15 | @AllArgsConstructor 16 | @JsonIgnoreProperties(ignoreUnknown = true) 17 | public class CreateNamespaceRequest { 18 | private String name; 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/com/example/kubernetesjavaclientapi/payload/request/namespace/DeleteNamespaceRequest.java: -------------------------------------------------------------------------------- 1 | package com.example.kubernetesjavaclientapi.payload.request.namespace; 2 | 3 | 4 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Builder; 7 | import lombok.Data; 8 | import lombok.NoArgsConstructor; 9 | 10 | /** 11 | * A request class {@link DeleteNamespaceRequest} representing the information needed to delete a Kubernetes namespace. 12 | */ 13 | @Data 14 | @Builder 15 | @NoArgsConstructor 16 | @AllArgsConstructor 17 | @JsonIgnoreProperties(ignoreUnknown = true) 18 | public class DeleteNamespaceRequest { 19 | private String name; 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/example/kubernetesjavaclientapi/payload/request/namespace/EditNamespaceRequest.java: -------------------------------------------------------------------------------- 1 | package com.example.kubernetesjavaclientapi.payload.request.namespace; 2 | 3 | import lombok.Builder; 4 | import lombok.Data; 5 | 6 | /** 7 | * A request class {@link EditNamespaceRequest} representing the information needed to edit a Kubernetes namespace. 8 | */ 9 | @Data 10 | @Builder 11 | public class EditNamespaceRequest { 12 | private String existingName; 13 | private String updatedName; 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/example/kubernetesjavaclientapi/payload/request/pods/CreatePodRequest.java: -------------------------------------------------------------------------------- 1 | package com.example.kubernetesjavaclientapi.payload.request.pods; 2 | 3 | import lombok.Builder; 4 | import lombok.Data; 5 | 6 | /** 7 | * A request class {@link CreatePodRequest} representing the information needed to create a new Kubernetes Pod. 8 | */ 9 | @Data 10 | @Builder 11 | public class CreatePodRequest { 12 | private String namespace; 13 | private String podName; 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/example/kubernetesjavaclientapi/payload/request/pods/DeletePodRequest.java: -------------------------------------------------------------------------------- 1 | package com.example.kubernetesjavaclientapi.payload.request.pods; 2 | 3 | import lombok.Builder; 4 | import lombok.Data; 5 | 6 | /** 7 | * A request class {@link DeletePodRequest} representing the information needed to delete a Kubernetes Pod. 8 | */ 9 | @Data 10 | @Builder 11 | public class DeletePodRequest { 12 | private String namespace; 13 | private String podName; 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/example/kubernetesjavaclientapi/payload/request/pods/EditPodRequest.java: -------------------------------------------------------------------------------- 1 | package com.example.kubernetesjavaclientapi.payload.request.pods; 2 | 3 | import lombok.Builder; 4 | import lombok.Data; 5 | 6 | import java.util.Map; 7 | 8 | /** 9 | * A request class {@link EditPodRequest} representing the information needed to edit a Kubernetes Pod. 10 | */ 11 | @Data 12 | @Builder 13 | public class EditPodRequest { 14 | private String namespace; 15 | private String podName; 16 | Map updatedLabels; 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/example/kubernetesjavaclientapi/payload/request/service/CreateServiceRequest.java: -------------------------------------------------------------------------------- 1 | package com.example.kubernetesjavaclientapi.payload.request.service; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | /** 10 | * Represents a request {@link CreateServiceRequest} for creating a Kubernetes service. 11 | */ 12 | @Data 13 | @Builder 14 | @NoArgsConstructor 15 | @AllArgsConstructor 16 | @JsonIgnoreProperties(ignoreUnknown = true) 17 | public class CreateServiceRequest { 18 | 19 | private String name; 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/example/kubernetesjavaclientapi/payload/request/service/DeleteServiceRequest.java: -------------------------------------------------------------------------------- 1 | package com.example.kubernetesjavaclientapi.payload.request.service; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | /** 10 | * Represents a request {@link DeleteServiceRequest} for deleting a Kubernetes service. 11 | */ 12 | @Data 13 | @Builder 14 | @NoArgsConstructor 15 | @AllArgsConstructor 16 | @JsonIgnoreProperties(ignoreUnknown = true) 17 | public class DeleteServiceRequest { 18 | 19 | private String name; 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/example/kubernetesjavaclientapi/payload/request/service/EditServiceRequest.java: -------------------------------------------------------------------------------- 1 | package com.example.kubernetesjavaclientapi.payload.request.service; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | /** 10 | * Represents a request {@link EditServiceRequest} for editing a Kubernetes service. 11 | */ 12 | @Data 13 | @Builder 14 | @NoArgsConstructor 15 | @AllArgsConstructor 16 | @JsonIgnoreProperties(ignoreUnknown = true) 17 | public class EditServiceRequest { 18 | 19 | private String existingName; 20 | private String updatedName; 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/example/kubernetesjavaclientapi/service/DeploymentService.java: -------------------------------------------------------------------------------- 1 | package com.example.kubernetesjavaclientapi.service; 2 | 3 | import com.example.kubernetesjavaclientapi.dto.deployment.DeploymentDto; 4 | import com.example.kubernetesjavaclientapi.payload.request.deployment.CreateDeploymentRequest; 5 | import com.example.kubernetesjavaclientapi.payload.request.deployment.DeleteDeploymentRequest; 6 | import com.example.kubernetesjavaclientapi.payload.request.deployment.EditDeploymentRequest; 7 | import io.kubernetes.client.openapi.ApiException; 8 | import io.kubernetes.client.openapi.apis.AppsV1Api; 9 | import io.kubernetes.client.openapi.models.*; 10 | import lombok.RequiredArgsConstructor; 11 | import lombok.extern.slf4j.Slf4j; 12 | import org.springframework.stereotype.Service; 13 | 14 | import java.util.ArrayList; 15 | import java.util.Collections; 16 | import java.util.List; 17 | import java.util.stream.Collectors; 18 | 19 | /** 20 | * Service class {@link DeploymentService} for managing Kubernetes deployment and related operations. 21 | */ 22 | @Service 23 | @RequiredArgsConstructor 24 | @Slf4j 25 | public class DeploymentService { 26 | 27 | private final AppsV1Api appsV1Api; 28 | 29 | 30 | /** 31 | * Lists Deployments in the "default" namespace. 32 | * 33 | * @return List of DeploymentDto containing deployment information. 34 | * @throws ApiException if an error occurs while interacting with the Kubernetes API. 35 | */ 36 | public List listDeployments() throws ApiException { 37 | 38 | V1DeploymentList deploymentList = appsV1Api.listNamespacedDeployment( 39 | "default", 40 | null, 41 | null, 42 | null, 43 | null, 44 | null, 45 | null, 46 | null, 47 | null, 48 | null, 49 | null); 50 | 51 | return deploymentList.getItems().stream() 52 | .map(deployment -> 53 | DeploymentDto.builder() 54 | .uid(deployment.getMetadata().getUid()) 55 | .name(deployment.getMetadata().getName()) 56 | .namespace(deployment.getMetadata().getNamespace()) 57 | .build()) 58 | .collect(Collectors.toList()); 59 | 60 | } 61 | 62 | /** 63 | * Creates a new Deployment based on the provided CreateDeploymentRequest. 64 | * 65 | * @param request CreateDeploymentRequest containing deployment creation parameters. 66 | * @return The created Deployment. 67 | * @throws ApiException if an error occurs while interacting with the Kubernetes API. 68 | */ 69 | public V1Deployment createDeployment(CreateDeploymentRequest request) throws ApiException { 70 | 71 | // Create a basic deployment 72 | V1Deployment deployment = new V1Deployment(); 73 | V1ObjectMeta metadata = new V1ObjectMeta(); 74 | metadata.setName(request.getName()); 75 | 76 | // Set the selector to match the labels in the template 77 | V1LabelSelector selector = new V1LabelSelector(); 78 | selector.setMatchLabels(request.getLabels()); 79 | V1DeploymentSpec spec = new V1DeploymentSpec(); 80 | spec.setSelector(selector); 81 | 82 | // Set the template with metadata and containers 83 | V1PodTemplateSpec template = new V1PodTemplateSpec(); 84 | V1ObjectMeta templateMetadata = new V1ObjectMeta(); 85 | templateMetadata.setLabels(request.getLabels()); 86 | template.setMetadata(templateMetadata); 87 | 88 | // Add a container to the template 89 | V1Container container = new V1Container(); 90 | container.setName(request.getContainerName()); 91 | container.setImage(request.getImage()); 92 | container.setPorts(Collections.singletonList(new V1ContainerPort().containerPort(request.getContainerPort()))); 93 | // Set other container properties as needed 94 | template.setSpec(new V1PodSpec().containers(Collections.singletonList(container))); 95 | spec.setTemplate(template); 96 | 97 | // Set the deployment's metadata and spec 98 | deployment.metadata(metadata); 99 | deployment.spec(spec); 100 | 101 | // Set the number of replicas 102 | deployment.getSpec().setReplicas(request.getReplicas()); 103 | 104 | return appsV1Api.createNamespacedDeployment("default", 105 | deployment, 106 | null, 107 | null, 108 | null, 109 | null); 110 | } 111 | 112 | /** 113 | * Edits an existing Deployment based on the provided EditDeploymentRequest. 114 | * 115 | * @param request EditDeploymentRequest containing deployment modification parameters. 116 | * @return The edited Deployment. 117 | * @throws ApiException if an error occurs while interacting with the Kubernetes API. 118 | */ 119 | public V1Deployment editDeployment(EditDeploymentRequest request) throws ApiException { 120 | 121 | // Retrieve the existing deployment 122 | V1Deployment existingDeployment = appsV1Api.readNamespacedDeployment(request.getName(), "default", null); 123 | 124 | // Ensure that spec is initialized 125 | if (existingDeployment.getSpec() == null) { 126 | existingDeployment.setSpec(new V1DeploymentSpec()); 127 | } 128 | 129 | // Modify the deployment based on the request 130 | existingDeployment.getMetadata().setLabels(request.getLabels()); 131 | 132 | // Ensure that template is initialized 133 | if (existingDeployment.getSpec().getTemplate() == null) { 134 | existingDeployment.getSpec().setTemplate(new V1PodTemplateSpec()); 135 | } 136 | 137 | // Ensure that spec is initialized inside the template 138 | if (existingDeployment.getSpec().getTemplate().getSpec() == null) { 139 | existingDeployment.getSpec().getTemplate().setSpec(new V1PodSpec()); 140 | } 141 | 142 | // Ensure that containers list is initialized 143 | if (existingDeployment.getSpec().getTemplate().getSpec().getContainers() == null) { 144 | existingDeployment.getSpec().getTemplate().getSpec().setContainers(new ArrayList<>()); 145 | } 146 | 147 | // Ensure that there is at least one container in the list 148 | if (existingDeployment.getSpec().getTemplate().getSpec().getContainers().isEmpty()) { 149 | existingDeployment.getSpec().getTemplate().getSpec().getContainers().add(new V1Container()); 150 | } 151 | 152 | // Modify the number of replicas 153 | existingDeployment.getSpec().setReplicas(request.getReplicas()); 154 | 155 | // Modify the container details 156 | V1Container container = existingDeployment.getSpec().getTemplate().getSpec().getContainers().get(0); 157 | container.setName(request.getContainerName()); 158 | container.setImage(request.getImage()); 159 | 160 | // Ensure that ports list is initialized 161 | if (container.getPorts() == null) { 162 | container.setPorts(new ArrayList<>()); 163 | } 164 | 165 | // Ensure that there is at least one port in the list 166 | if (container.getPorts().isEmpty()) { 167 | container.getPorts().add(new V1ContainerPort()); 168 | } 169 | 170 | // Modify the container port 171 | container.getPorts().get(0).setContainerPort(request.getContainerPort()); 172 | 173 | // Use the Kubernetes client to update the deployment 174 | return appsV1Api.replaceNamespacedDeployment(request.getName(), "default", existingDeployment, null, null, null,null); 175 | } 176 | 177 | /** 178 | * Deletes an existing Deployment based on the provided DeleteDeploymentRequest. 179 | * 180 | * @param request DeleteDeploymentRequest containing deployment deletion parameters. 181 | * @return The status of the deletion operation. 182 | * @throws ApiException if an error occurs while interacting with the Kubernetes API. 183 | */ 184 | public V1Status deleteDeployment(DeleteDeploymentRequest request) throws ApiException { 185 | 186 | return appsV1Api.deleteNamespacedDeployment(request.getName(), 187 | "default", 188 | null, 189 | null, 190 | null, 191 | null, 192 | null, 193 | null); 194 | } 195 | 196 | } 197 | -------------------------------------------------------------------------------- /src/main/java/com/example/kubernetesjavaclientapi/service/KubeServiceService.java: -------------------------------------------------------------------------------- 1 | package com.example.kubernetesjavaclientapi.service; 2 | 3 | import com.example.kubernetesjavaclientapi.dto.service.ServiceDto; 4 | import com.example.kubernetesjavaclientapi.payload.request.service.CreateServiceRequest; 5 | import com.example.kubernetesjavaclientapi.payload.request.service.DeleteServiceRequest; 6 | import com.example.kubernetesjavaclientapi.payload.request.service.EditServiceRequest; 7 | import io.kubernetes.client.openapi.ApiException; 8 | import io.kubernetes.client.openapi.apis.AppsV1Api; 9 | import io.kubernetes.client.openapi.apis.CoreV1Api; 10 | import io.kubernetes.client.openapi.models.*; 11 | import lombok.RequiredArgsConstructor; 12 | import lombok.extern.slf4j.Slf4j; 13 | import org.springframework.stereotype.Service; 14 | 15 | import java.util.Collections; 16 | import java.util.HashMap; 17 | import java.util.List; 18 | import java.util.stream.Collectors; 19 | 20 | /** 21 | * Service class {@link KubeServiceService} for managing Kubernetes namespaces and related operations. 22 | */ 23 | @Service 24 | @RequiredArgsConstructor 25 | @Slf4j 26 | public class KubeServiceService { 27 | 28 | private final CoreV1Api coreV1Api; 29 | 30 | private final AppsV1Api appsV1Api; 31 | 32 | /** 33 | * Retrieves a list of Kubernetes services. 34 | * 35 | * @return A list of {@link ServiceDto} representing the Kubernetes services. 36 | * @throws ApiException If an error occurs while fetching the services. 37 | */ 38 | public List listServices() throws ApiException { 39 | 40 | V1ServiceList serviceList = coreV1Api.listNamespacedService("default", 41 | null, 42 | null, 43 | null, 44 | null, 45 | null, 46 | null, 47 | null, 48 | null, 49 | null, 50 | null); 51 | 52 | return serviceList.getItems().stream() 53 | .map(service -> 54 | ServiceDto.builder() 55 | .name(service.getMetadata().getName()) 56 | .uid(service.getMetadata().getUid()) 57 | .namespace(service.getMetadata().getNamespace()) 58 | .build()) 59 | .collect(Collectors.toList()); 60 | } 61 | 62 | /** 63 | * Creates a new Kubernetes service. 64 | * 65 | * @param request The request object containing the details for creating the service. 66 | * @return The created {@link V1Service} object. 67 | * @throws ApiException If an error occurs while creating the service. 68 | */ 69 | public V1Service createService(CreateServiceRequest request) throws ApiException { 70 | 71 | V1Service service = new V1Service(); 72 | V1ObjectMeta metadata = new V1ObjectMeta(); 73 | metadata.setName(request.getName()); 74 | service.setMetadata(metadata); 75 | 76 | // Set the port information 77 | V1ServiceSpec serviceSpec = new V1ServiceSpec(); 78 | V1ServicePort servicePort = new V1ServicePort(); 79 | servicePort.setPort(80); // Set your desired port number 80 | serviceSpec.setPorts(Collections.singletonList(servicePort)); 81 | service.setSpec(serviceSpec); 82 | 83 | return coreV1Api.createNamespacedService("default", 84 | service, 85 | null, 86 | null, 87 | null, 88 | null); 89 | } 90 | 91 | /** 92 | * Edits an existing Kubernetes service. 93 | * 94 | * @param request The request object containing the details for editing the service. 95 | * @return The edited {@link V1Service} object. 96 | * @throws ApiException If an error occurs while editing the service. 97 | */ 98 | public V1Service editService(EditServiceRequest request) throws ApiException { 99 | 100 | // Retrieve the existing service 101 | V1Service existingService = coreV1Api.readNamespacedService(request.getExistingName(), "default", null); 102 | 103 | // Create a new service with the updated name 104 | V1Service updatedService = new V1Service() 105 | .metadata(new V1ObjectMeta().name(request.getUpdatedName())) 106 | .spec(new V1ServiceSpec().ports(existingService.getSpec().getPorts())); 107 | 108 | // Create the new service 109 | coreV1Api.createNamespacedService("default", updatedService, null, null, null, null); 110 | 111 | moveServiceResources(request.getExistingName(), request.getUpdatedName()); 112 | 113 | return updatedService; 114 | } 115 | 116 | /** 117 | * Deletes a Kubernetes service. 118 | * 119 | * @param request The request object containing the details for deleting the service. 120 | * @return The deleted {@link V1Service} object. 121 | * @throws ApiException If an error occurs while deleting the service. 122 | */ 123 | public V1Service deleteService(DeleteServiceRequest request) throws ApiException { 124 | V1DeleteOptions deleteOptions = new V1DeleteOptions(); 125 | return coreV1Api.deleteNamespacedService(request.getName(), 126 | "default", 127 | null, 128 | null, 129 | null, 130 | null, 131 | null, deleteOptions); 132 | } 133 | 134 | /** 135 | * Moves resources associated with a service to reference the updated service name. 136 | * 137 | * @param existingServiceName The name of the existing service. 138 | * @param updatedServiceName The updated name of the service. 139 | * @throws ApiException If an error occurs while moving the resources. 140 | */ 141 | private void moveServiceResources(String existingServiceName, String updatedServiceName) throws ApiException { 142 | // Retrieve deployments in the default namespace associated with the existing service 143 | V1DeploymentList deploymentList = appsV1Api.listNamespacedDeployment("default", 144 | null, 145 | null, 146 | null, 147 | null, 148 | "app=" + existingServiceName, 149 | null, 150 | null, 151 | null, 152 | null, 153 | null); 154 | 155 | // Update selector labels in each deployment to reference the updated service name 156 | for (V1Deployment deployment : deploymentList.getItems()) { 157 | // Ensure that the spec and selector are initialized 158 | if (deployment.getSpec() == null) { 159 | deployment.setSpec(new V1DeploymentSpec()); 160 | } 161 | 162 | if (deployment.getSpec().getSelector() == null) { 163 | deployment.getSpec().setSelector(new V1LabelSelector()); 164 | } 165 | 166 | // Ensure that the matchLabels is initialized 167 | if (deployment.getSpec().getSelector().getMatchLabels() == null) { 168 | deployment.getSpec().getSelector().setMatchLabels(new HashMap<>()); 169 | } 170 | 171 | // Update selector labels 172 | deployment.getSpec().getSelector().getMatchLabels().put("app", updatedServiceName); 173 | 174 | // Update the deployment 175 | appsV1Api.replaceNamespacedDeployment(deployment.getMetadata().getName(), "default", deployment, null, null, null,null); 176 | } 177 | } 178 | 179 | } 180 | -------------------------------------------------------------------------------- /src/main/java/com/example/kubernetesjavaclientapi/service/NamespaceService.java: -------------------------------------------------------------------------------- 1 | package com.example.kubernetesjavaclientapi.service; 2 | 3 | import com.example.kubernetesjavaclientapi.dto.namespace.NameSpaceDto; 4 | import com.example.kubernetesjavaclientapi.payload.request.namespace.CreateNamespaceRequest; 5 | import com.example.kubernetesjavaclientapi.payload.request.namespace.DeleteNamespaceRequest; 6 | import com.example.kubernetesjavaclientapi.payload.request.namespace.EditNamespaceRequest; 7 | import io.kubernetes.client.openapi.ApiException; 8 | import io.kubernetes.client.openapi.apis.AppsV1Api; 9 | import io.kubernetes.client.openapi.apis.CoreV1Api; 10 | import io.kubernetes.client.openapi.models.*; 11 | import lombok.RequiredArgsConstructor; 12 | import lombok.extern.slf4j.Slf4j; 13 | import org.springframework.stereotype.Service; 14 | 15 | import java.util.List; 16 | import java.util.stream.Collectors; 17 | 18 | /** 19 | * Service class {@link NamespaceService} for managing Kubernetes namespaces and related operations. 20 | */ 21 | @Service 22 | @RequiredArgsConstructor 23 | @Slf4j 24 | public class NamespaceService { 25 | 26 | private final CoreV1Api coreV1Api; 27 | 28 | private final AppsV1Api appsV1Api; 29 | 30 | /** 31 | * Retrieves a list of namespaces and maps them to NameSpaceDto objects. 32 | * 33 | * @return List of NameSpaceDto objects representing the namespaces. 34 | * @throws ApiException if there is an error while retrieving the namespaces. 35 | */ 36 | public List listNameSpaces() throws ApiException { 37 | 38 | V1NamespaceList list = coreV1Api.listNamespace( 39 | null, 40 | null, 41 | null, 42 | null, 43 | null, 44 | null, 45 | null, 46 | null, 47 | null, 48 | null); 49 | 50 | return list.getItems().stream() 51 | .map(item -> { 52 | V1ObjectMeta data = item.getMetadata(); 53 | return NameSpaceDto.builder() 54 | .uid(data.getUid()) 55 | .namespace(data.getName()) 56 | .build(); 57 | 58 | }).collect(Collectors.toList()); 59 | 60 | } 61 | 62 | /** 63 | * Creates a new namespace based on the provided request. 64 | * 65 | * @param request The CreateNamespaceRequest containing information for creating the namespace. 66 | * @return The created V1Namespace object. 67 | * @throws ApiException if there is an error while creating the namespace. 68 | */ 69 | public V1Namespace createNamespace(CreateNamespaceRequest request) throws ApiException { 70 | 71 | V1Namespace namespace = new V1Namespace(); 72 | namespace.metadata(new V1ObjectMeta().name(request.getName())); 73 | 74 | return coreV1Api.createNamespace(namespace, 75 | null, 76 | null, 77 | null, 78 | null); 79 | } 80 | 81 | /** 82 | * Edits an existing namespace based on the provided request. 83 | * 84 | * @param request The EditNamespaceRequest containing information for editing the namespace. 85 | * @return The edited V1Namespace object. 86 | * @throws ApiException if there is an error while editing the namespace. 87 | */ 88 | public V1Namespace editNamespace(EditNamespaceRequest request) throws ApiException { 89 | 90 | // Read the existing namespace 91 | V1Namespace existingNamespace = coreV1Api.readNamespace(request.getExistingName(), null); 92 | 93 | // Create a new namespace with the updated name 94 | V1Namespace updatedNamespace = new V1Namespace() 95 | .metadata(new V1ObjectMeta().name(request.getUpdatedName())); 96 | 97 | // Create the new namespace 98 | coreV1Api.createNamespace(updatedNamespace, null, null, null, null); 99 | 100 | // Move resources from the existing namespace to the updated one 101 | moveDeployments(request.getExistingName(), request.getUpdatedName()); 102 | 103 | // Optionally, delete the existing namespace 104 | coreV1Api.deleteNamespace(request.getExistingName(), null, null, null, null, null, null); 105 | 106 | return updatedNamespace; 107 | } 108 | 109 | /** 110 | * Deletes an existing namespace based on the provided request. 111 | * 112 | * @param request The DeleteNamespaceRequest containing information for deleting the namespace. 113 | * @return The V1Status object representing the deletion status. 114 | * @throws ApiException if there is an error while deleting the namespace. 115 | */ 116 | public V1Status deleteNamespace(DeleteNamespaceRequest request) throws ApiException { 117 | 118 | V1DeleteOptions deleteOptions = new V1DeleteOptions(); 119 | return coreV1Api.deleteNamespace(request.getName(), 120 | null, 121 | null, 122 | null, 123 | null, 124 | null, 125 | deleteOptions); 126 | } 127 | 128 | /** 129 | * Moves deployments from the existing namespace to the updated namespace. 130 | * 131 | * @param existingNamespace The current namespace. 132 | * @param updatedNamespace The updated namespace. 133 | * @throws ApiException if there is an error while moving deployments. 134 | */ 135 | private void moveDeployments(String existingNamespace, String updatedNamespace) throws ApiException { 136 | V1DeploymentList deploymentList = appsV1Api.listNamespacedDeployment(existingNamespace, 137 | null, 138 | null, 139 | null, 140 | null, 141 | null, 142 | null, 143 | null, 144 | null, 145 | null, 146 | null); 147 | 148 | for (V1Deployment deployment : deploymentList.getItems()) { 149 | // Update the namespace in metadata 150 | deployment.getMetadata().setNamespace(updatedNamespace); 151 | 152 | // Create the deployment in the updated namespace 153 | appsV1Api.createNamespacedDeployment(updatedNamespace, deployment, null, null, null, null); 154 | 155 | // Delete the deployment in the existing namespace 156 | appsV1Api.deleteNamespacedDeployment(deployment.getMetadata().getName(), existingNamespace, null, null, null, null, null, null); 157 | } 158 | 159 | } 160 | 161 | } 162 | -------------------------------------------------------------------------------- /src/main/java/com/example/kubernetesjavaclientapi/service/PodService.java: -------------------------------------------------------------------------------- 1 | package com.example.kubernetesjavaclientapi.service; 2 | 3 | import com.example.kubernetesjavaclientapi.dto.pod.PodDto; 4 | import com.example.kubernetesjavaclientapi.dto.pod.V1ManagedFieldsEntryDto; 5 | import com.example.kubernetesjavaclientapi.dto.pod.V1OwnerReferenceDto; 6 | import com.example.kubernetesjavaclientapi.mapper.V1ManagedFieldsEntryToV1ManagedFieldsEntryDtoMapper; 7 | import com.example.kubernetesjavaclientapi.mapper.V1OwnerReferenceToV1OwnerReferenceDtoMapper; 8 | import com.example.kubernetesjavaclientapi.payload.request.pods.CreatePodRequest; 9 | import com.example.kubernetesjavaclientapi.payload.request.pods.DeletePodRequest; 10 | import com.example.kubernetesjavaclientapi.payload.request.pods.EditPodRequest; 11 | import io.kubernetes.client.openapi.ApiException; 12 | import io.kubernetes.client.openapi.apis.CoreV1Api; 13 | import io.kubernetes.client.openapi.models.*; 14 | import lombok.RequiredArgsConstructor; 15 | import lombok.extern.slf4j.Slf4j; 16 | import org.springframework.stereotype.Service; 17 | 18 | import java.util.Collections; 19 | import java.util.HashMap; 20 | import java.util.List; 21 | import java.util.stream.Collectors; 22 | 23 | /** 24 | * Service class {@link PodService} for managing Kubernetes Pods. 25 | * Provides methods for listing, creating, editing, and deleting Pods. 26 | */ 27 | @Service 28 | @RequiredArgsConstructor 29 | @Slf4j 30 | public class PodService { 31 | 32 | private final CoreV1Api coreV1Api; 33 | 34 | private final V1ManagedFieldsEntryToV1ManagedFieldsEntryDtoMapper v1ManagedFieldsEntryToV1ManagedFieldsEntryDtoMapper = V1ManagedFieldsEntryToV1ManagedFieldsEntryDtoMapper.initialize(); 35 | private final V1OwnerReferenceToV1OwnerReferenceDtoMapper v1OwnerReferenceToV1OwnerReferenceDtoMapper = V1OwnerReferenceToV1OwnerReferenceDtoMapper.initialize(); 36 | 37 | /** 38 | * Retrieves a list of PodDto objects representing Pods from all namespaces. 39 | * 40 | * @return A list of PodDto objects. 41 | * @throws Exception If an error occurs while fetching the list of Pods. 42 | */ 43 | public List listPods() throws Exception { 44 | 45 | V1PodList list = coreV1Api.listPodForAllNamespaces(null, 46 | null, 47 | null, 48 | null, 49 | null, 50 | null, 51 | null, 52 | null, 53 | null, 54 | null); 55 | 56 | 57 | return list.getItems().stream() 58 | .map(item -> { 59 | V1ObjectMeta data = item.getMetadata(); 60 | log.info("listPods | data | name :" + data.getName()); 61 | 62 | List v1ManagedFieldsEntryDtos = v1ManagedFieldsEntryToV1ManagedFieldsEntryDtoMapper.map(data.getManagedFields()); 63 | List v1OwnerReferenceDtos = v1OwnerReferenceToV1OwnerReferenceDtoMapper.map(data.getOwnerReferences()); 64 | 65 | return PodDto.builder() 66 | .uid(data.getUid()) 67 | .name(data.getName()) 68 | .annotations(data.getAnnotations()) 69 | .clusterName(data.getClusterName()) 70 | .creationTimestamp(data.getCreationTimestamp()) 71 | .deletionGracePeriodSeconds(data.getDeletionGracePeriodSeconds()) 72 | .deletionTimestamp(data.getDeletionTimestamp()) 73 | .finalizers(data.getFinalizers()) 74 | .generateName(data.getGenerateName()) 75 | .generation(data.getGeneration()) 76 | .labels(data.getLabels()) 77 | .managedFields(v1ManagedFieldsEntryDtos) 78 | .namespace(data.getNamespace()) 79 | .ownerReferences(v1OwnerReferenceDtos) 80 | .selfLink(data.getSelfLink()) 81 | .build(); 82 | }) 83 | .collect(Collectors.toList()); 84 | } 85 | 86 | /** 87 | * Creates a new Pod based on the provided request. 88 | * 89 | * @param request The request containing information to create the Pod. 90 | * @return The created Pod. 91 | * @throws ApiException If an error occurs while creating the Pod. 92 | */ 93 | public V1Pod createPod(CreatePodRequest request) throws ApiException { 94 | V1Pod pod = new V1Pod(); 95 | V1ObjectMeta metadata = new V1ObjectMeta(); 96 | metadata.setName(request.getPodName()); 97 | pod.setMetadata(metadata); 98 | 99 | V1PodSpec podSpec = new V1PodSpec(); 100 | 101 | // Define container 102 | V1Container container = new V1Container(); 103 | container.setName("example-container"); 104 | container.setImage("nginx:latest"); 105 | 106 | podSpec.setContainers(Collections.singletonList(container)); 107 | podSpec.setRestartPolicy("Always"); 108 | 109 | pod.setSpec(podSpec); 110 | 111 | return coreV1Api.createNamespacedPod( 112 | request.getNamespace(), 113 | pod, 114 | null, 115 | null, 116 | null, 117 | null); 118 | } 119 | 120 | /** 121 | * Edits an existing Pod based on the provided request. 122 | * 123 | * @param request The request containing information to edit the Pod. 124 | * @return The edited Pod. 125 | * @throws ApiException If an error occurs while editing the Pod. 126 | */ 127 | public V1Pod editPod(EditPodRequest request) throws ApiException { 128 | 129 | // Retrieve the existing pod 130 | V1Pod existingPod = coreV1Api.readNamespacedPod(request.getPodName(), request.getNamespace(),null); 131 | 132 | // Update pod metadata (labels in this example) 133 | V1ObjectMeta metadata = existingPod.getMetadata(); 134 | if (metadata.getLabels() == null) { 135 | metadata.setLabels(new HashMap<>()); 136 | } 137 | metadata.getLabels().putAll(request.getUpdatedLabels()); 138 | 139 | // Update the pod 140 | return coreV1Api.replaceNamespacedPod( 141 | request.getPodName(), 142 | request.getNamespace(), 143 | existingPod, 144 | null, 145 | null, 146 | null, 147 | null); 148 | } 149 | 150 | /** 151 | * Deletes an existing Pod based on the provided request. 152 | * 153 | * @param request The request containing information to delete the Pod. 154 | * @return The deleted Pod. 155 | * @throws ApiException If an error occurs while deleting the Pod. 156 | */ 157 | public V1Pod deletePod(DeletePodRequest request) throws ApiException { 158 | return coreV1Api.deleteNamespacedPod(request.getPodName(), request.getNamespace(), null, null, null, null, null, null); 159 | } 160 | 161 | } 162 | -------------------------------------------------------------------------------- /src/main/resources/application.yaml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 1010 3 | -------------------------------------------------------------------------------- /src/test/java/com/example/kubernetesjavaclientapi/KubernetesjavaclientapiApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.example.kubernetesjavaclientapi; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class KubernetesjavaclientapiApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/test/java/com/example/kubernetesjavaclientapi/base/BaseControllerTest.java: -------------------------------------------------------------------------------- 1 | package com.example.kubernetesjavaclientapi.base; 2 | 3 | import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | @AutoConfigureMockMvc 8 | public abstract class BaseControllerTest { 9 | 10 | } 11 | -------------------------------------------------------------------------------- /src/test/java/com/example/kubernetesjavaclientapi/base/BaseServiceTest.java: -------------------------------------------------------------------------------- 1 | package com.example.kubernetesjavaclientapi.base; 2 | 3 | import org.junit.jupiter.api.extension.ExtendWith; 4 | import org.mockito.junit.jupiter.MockitoExtension; 5 | 6 | @ExtendWith(MockitoExtension.class) 7 | public abstract class BaseServiceTest { 8 | 9 | } 10 | -------------------------------------------------------------------------------- /src/test/java/com/example/kubernetesjavaclientapi/controller/DeploymentControllerTest.java: -------------------------------------------------------------------------------- 1 | package com.example.kubernetesjavaclientapi.controller; 2 | 3 | import com.example.kubernetesjavaclientapi.base.BaseControllerTest; 4 | import com.example.kubernetesjavaclientapi.dto.deployment.DeploymentDto; 5 | import com.example.kubernetesjavaclientapi.payload.request.deployment.CreateDeploymentRequest; 6 | import com.example.kubernetesjavaclientapi.payload.request.deployment.DeleteDeploymentRequest; 7 | import com.example.kubernetesjavaclientapi.payload.request.deployment.EditDeploymentRequest; 8 | import com.example.kubernetesjavaclientapi.service.DeploymentService; 9 | import com.fasterxml.jackson.databind.ObjectMapper; 10 | import io.kubernetes.client.openapi.models.V1Deployment; 11 | import io.kubernetes.client.openapi.models.V1ObjectMeta; 12 | import io.kubernetes.client.openapi.models.V1Status; 13 | import org.junit.jupiter.api.Test; 14 | import org.springframework.beans.factory.annotation.Autowired; 15 | import org.springframework.boot.test.mock.mockito.MockBean; 16 | import org.springframework.http.MediaType; 17 | import org.springframework.test.web.servlet.MockMvc; 18 | import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; 19 | 20 | import java.util.Arrays; 21 | import java.util.Collections; 22 | import java.util.List; 23 | 24 | import static org.junit.jupiter.api.Assertions.*; 25 | import static org.mockito.ArgumentMatchers.any; 26 | import static org.mockito.Mockito.when; 27 | import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; 28 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; 29 | 30 | class DeploymentControllerTest extends BaseControllerTest { 31 | 32 | @Autowired 33 | private MockMvc mockMvc; 34 | 35 | @Autowired 36 | private ObjectMapper objectMapper; 37 | 38 | @MockBean 39 | private DeploymentService deploymentService; 40 | 41 | private static final String BASE_PATH = "/api/v1/kubernetes/deployments"; 42 | 43 | @Test 44 | void testListDeployments() throws Exception { 45 | 46 | List mockDeploymentDtoList = Arrays.asList( 47 | DeploymentDto.builder().name("deployment1").build(), 48 | DeploymentDto.builder().name("deployment2").build() 49 | ); 50 | 51 | when(deploymentService.listDeployments()).thenReturn(mockDeploymentDtoList); 52 | 53 | mockMvc.perform(MockMvcRequestBuilders.get(BASE_PATH + "/listDeployments") 54 | .contentType(MediaType.APPLICATION_JSON)) 55 | .andExpect(status().isOk()) 56 | .andDo(print()) 57 | .andExpect(content().contentType(MediaType.APPLICATION_JSON)) 58 | .andExpect(jsonPath("$[0].name").value("deployment1")) 59 | .andExpect(jsonPath("$[1].name").value("deployment2")); 60 | 61 | } 62 | 63 | @Test 64 | void testCreateDeployment() throws Exception { 65 | 66 | // Given 67 | CreateDeploymentRequest request = CreateDeploymentRequest.builder() 68 | .name("example-deployment") 69 | .replicas(3) 70 | .labels(Collections.singletonMap("app", "example-app")) 71 | .containerName("example-container") 72 | .image("your-docker-image:latest") 73 | .containerPort(8080) 74 | .build(); 75 | 76 | V1Deployment createdDeployment = new V1Deployment(); 77 | V1ObjectMeta metadata = new V1ObjectMeta(); 78 | metadata.setName(request.getName()); 79 | createdDeployment.metadata(metadata); 80 | 81 | // When 82 | when(deploymentService.createDeployment(any())).thenReturn(createdDeployment); 83 | 84 | // Then 85 | mockMvc.perform(MockMvcRequestBuilders.post(BASE_PATH + "/createDeployment") 86 | .contentType(MediaType.APPLICATION_JSON) 87 | .content(objectMapper.writeValueAsString(request))) 88 | .andDo(print()) 89 | .andExpect(content().contentType(MediaType.valueOf(MediaType.TEXT_PLAIN_VALUE + ";charset=UTF-8"))) 90 | .andExpect(status().isCreated()) 91 | .andExpect(content().string("Deployment created successfully: " + request.getName())); 92 | 93 | } 94 | 95 | @Test 96 | void testEditDeployment() throws Exception { 97 | 98 | // Given 99 | EditDeploymentRequest request = EditDeploymentRequest.builder() 100 | .name("example-deployment") 101 | .replicas(5) 102 | .labels(Collections.singletonMap("app", "edited-app")) 103 | .containerName("edited-container") 104 | .image("edited-docker-image:latest") 105 | .containerPort(8081) 106 | .build(); 107 | 108 | V1Deployment editedDeployment = new V1Deployment(); 109 | V1ObjectMeta metadata = new V1ObjectMeta(); 110 | metadata.setName(request.getName()); 111 | editedDeployment.metadata(metadata); 112 | 113 | // When 114 | when(deploymentService.editDeployment(any())).thenReturn(editedDeployment); 115 | 116 | // Then 117 | mockMvc.perform(MockMvcRequestBuilders.put(BASE_PATH + "/editDeployment") 118 | .contentType(MediaType.APPLICATION_JSON) 119 | .content(objectMapper.writeValueAsString(request))) 120 | .andDo(print()) 121 | .andExpect(content().contentType(MediaType.valueOf(MediaType.TEXT_PLAIN_VALUE + ";charset=UTF-8"))) 122 | .andExpect(status().isOk()) 123 | .andExpect(content().string("Service edited successfully: " + request.getName())); 124 | 125 | } 126 | 127 | @Test 128 | void testDeleteDeployment() throws Exception { 129 | 130 | // Given 131 | DeleteDeploymentRequest request = DeleteDeploymentRequest.builder() 132 | .name("example-deployment") 133 | .build(); 134 | 135 | V1Status deletionStatus = new V1Status(); 136 | deletionStatus.setMessage("Deployment deleted successfully"); 137 | 138 | // When 139 | when(deploymentService.deleteDeployment(any())).thenReturn(deletionStatus); 140 | 141 | // Then 142 | mockMvc.perform(MockMvcRequestBuilders.delete("/api/v1/kubernetes/deployments/deleteDeployment") 143 | .contentType(MediaType.APPLICATION_JSON) 144 | .content(objectMapper.writeValueAsString(request))) 145 | .andDo(print()) 146 | .andExpect(content().contentType(MediaType.valueOf(MediaType.TEXT_PLAIN_VALUE + ";charset=UTF-8"))) 147 | .andExpect(status().isOk()) 148 | .andExpect(content().string("Deployment deleted successfully: " + request.getName())); 149 | 150 | } 151 | 152 | } 153 | -------------------------------------------------------------------------------- /src/test/java/com/example/kubernetesjavaclientapi/controller/NamespaceControllerTest.java: -------------------------------------------------------------------------------- 1 | package com.example.kubernetesjavaclientapi.controller; 2 | 3 | import com.example.kubernetesjavaclientapi.base.BaseControllerTest; 4 | import com.example.kubernetesjavaclientapi.dto.namespace.NameSpaceDto; 5 | import com.example.kubernetesjavaclientapi.payload.request.namespace.CreateNamespaceRequest; 6 | import com.example.kubernetesjavaclientapi.payload.request.namespace.DeleteNamespaceRequest; 7 | import com.example.kubernetesjavaclientapi.payload.request.namespace.EditNamespaceRequest; 8 | import com.example.kubernetesjavaclientapi.service.NamespaceService; 9 | import com.fasterxml.jackson.databind.ObjectMapper; 10 | import io.kubernetes.client.openapi.models.V1Namespace; 11 | import io.kubernetes.client.openapi.models.V1ObjectMeta; 12 | import io.kubernetes.client.openapi.models.V1Status; 13 | import org.hamcrest.Matchers; 14 | import org.junit.jupiter.api.Test; 15 | import org.springframework.beans.factory.annotation.Autowired; 16 | import org.springframework.boot.test.mock.mockito.MockBean; 17 | import org.springframework.http.MediaType; 18 | import org.springframework.test.web.servlet.MockMvc; 19 | import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; 20 | 21 | import java.util.Arrays; 22 | import java.util.List; 23 | 24 | import static org.junit.jupiter.api.Assertions.*; 25 | import static org.mockito.ArgumentMatchers.any; 26 | import static org.mockito.Mockito.when; 27 | import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; 28 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; 29 | 30 | class NamespaceControllerTest extends BaseControllerTest { 31 | 32 | @Autowired 33 | private MockMvc mockMvc; 34 | 35 | @MockBean 36 | private NamespaceService namespaceService; 37 | 38 | @Autowired 39 | private ObjectMapper objectMapper; 40 | 41 | private static final String BASE_PATH = "/api/v1/kubernetes/namespaces"; 42 | 43 | @Test 44 | public void testListNamespaces() throws Exception { 45 | 46 | // Given 47 | List expectedNamespaces = Arrays.asList( 48 | NameSpaceDto.builder().uid("uid1").namespace("namespace1").build(), 49 | NameSpaceDto.builder().uid("uid2").namespace("namespace2").build() 50 | ); 51 | 52 | // When 53 | when(namespaceService.listNameSpaces()).thenReturn(expectedNamespaces); 54 | 55 | // Then 56 | mockMvc.perform(MockMvcRequestBuilders.get(BASE_PATH + "/listNamespaces")) 57 | .andExpect(status().isOk()) 58 | .andDo(print()) 59 | .andExpect(content().contentType(MediaType.APPLICATION_JSON)) 60 | .andExpect(jsonPath("$", Matchers.hasSize(expectedNamespaces.size()))) 61 | .andExpect(jsonPath("$[0].uid", Matchers.is("uid1"))) 62 | .andExpect(jsonPath("$[0].namespace", Matchers.is("namespace1"))) 63 | .andExpect(jsonPath("$[1].uid", Matchers.is("uid2"))) 64 | .andExpect(jsonPath("$[1].namespace", Matchers.is("namespace2"))); 65 | 66 | } 67 | 68 | @Test 69 | public void testCreateNamespace() throws Exception { 70 | 71 | // Given 72 | CreateNamespaceRequest createNamespaceRequest = CreateNamespaceRequest.builder() 73 | .name("test-namespace") 74 | .build(); 75 | 76 | V1Namespace createdNamespace = new V1Namespace(); 77 | createdNamespace.setMetadata(new V1ObjectMeta()); 78 | createdNamespace.getMetadata().setName(createNamespaceRequest.getName()); 79 | 80 | // When 81 | when(namespaceService.createNamespace(any())).thenReturn(createdNamespace); 82 | 83 | // Then 84 | mockMvc.perform(MockMvcRequestBuilders.post(BASE_PATH + "/createNamespace") 85 | .contentType(MediaType.APPLICATION_JSON) 86 | .content(objectMapper.writeValueAsString(createNamespaceRequest))) 87 | .andDo(print()) 88 | .andExpect(content().contentType(MediaType.valueOf(MediaType.TEXT_PLAIN_VALUE + ";charset=UTF-8"))) 89 | .andExpect(status().isCreated()) 90 | .andExpect(content().string("Namespace created successfully: " + createNamespaceRequest.getName())); 91 | } 92 | 93 | @Test 94 | public void testEditNamespace() throws Exception { 95 | 96 | // Given 97 | EditNamespaceRequest editNamespaceRequest = EditNamespaceRequest.builder() 98 | .existingName("old-namespace") 99 | .updatedName("new-namespace") 100 | .build(); 101 | 102 | V1Namespace editedNamespace = new V1Namespace(); 103 | editedNamespace.setMetadata(new V1ObjectMeta()); 104 | editedNamespace.getMetadata().setName(editNamespaceRequest.getUpdatedName()); 105 | 106 | // When 107 | when(namespaceService.editNamespace(any())).thenReturn(editedNamespace); 108 | 109 | // Then 110 | mockMvc.perform(MockMvcRequestBuilders.put(BASE_PATH + "/editNamespace") 111 | .contentType(MediaType.APPLICATION_JSON) 112 | .content(objectMapper.writeValueAsString(editNamespaceRequest))) 113 | .andDo(print()) 114 | .andExpect(status().isOk()) 115 | .andExpect(content().contentType(MediaType.TEXT_PLAIN_VALUE + ";charset=UTF-8")) 116 | .andExpect(content().string("Namespace edited successfully: " + editNamespaceRequest.getUpdatedName())); 117 | } 118 | 119 | @Test 120 | public void testDeleteNamespace() throws Exception { 121 | 122 | // Given 123 | DeleteNamespaceRequest deleteNamespaceRequest = DeleteNamespaceRequest.builder() 124 | .name("namespace-to-delete") 125 | .build(); 126 | 127 | V1Status deletionStatus = new V1Status(); 128 | deletionStatus.setStatus("Success"); 129 | deletionStatus.setMessage("Namespace deleted successfully"); 130 | 131 | // When 132 | when(namespaceService.deleteNamespace(any())).thenReturn(deletionStatus); 133 | 134 | // Then 135 | mockMvc.perform(MockMvcRequestBuilders.delete(BASE_PATH + "/deleteNamespace") 136 | .contentType(MediaType.APPLICATION_JSON) 137 | .content(objectMapper.writeValueAsString(deleteNamespaceRequest))) 138 | .andExpect(status().isOk()) 139 | .andExpect(content().contentType(MediaType.TEXT_PLAIN_VALUE + ";charset=UTF-8")) 140 | .andExpect(content().string("Namespace deleted successfully: " + deleteNamespaceRequest.getName())); 141 | 142 | } 143 | 144 | } -------------------------------------------------------------------------------- /src/test/java/com/example/kubernetesjavaclientapi/controller/PodControllerTest.java: -------------------------------------------------------------------------------- 1 | package com.example.kubernetesjavaclientapi.controller; 2 | 3 | import com.example.kubernetesjavaclientapi.base.BaseControllerTest; 4 | import com.example.kubernetesjavaclientapi.dto.pod.PodDto; 5 | import com.example.kubernetesjavaclientapi.payload.request.pods.CreatePodRequest; 6 | import com.example.kubernetesjavaclientapi.payload.request.pods.DeletePodRequest; 7 | import com.example.kubernetesjavaclientapi.payload.request.pods.EditPodRequest; 8 | import com.example.kubernetesjavaclientapi.service.PodService; 9 | import com.fasterxml.jackson.databind.ObjectMapper; 10 | import io.kubernetes.client.openapi.models.V1ObjectMeta; 11 | import io.kubernetes.client.openapi.models.V1Pod; 12 | import org.junit.jupiter.api.Test; 13 | import org.springframework.beans.factory.annotation.Autowired; 14 | import org.springframework.boot.test.mock.mockito.MockBean; 15 | import org.springframework.http.MediaType; 16 | import org.springframework.test.web.servlet.MockMvc; 17 | import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; 18 | import org.springframework.test.web.servlet.result.MockMvcResultMatchers; 19 | 20 | import java.util.Collections; 21 | import java.util.Map; 22 | 23 | import static org.hamcrest.Matchers.hasSize; 24 | import static org.mockito.ArgumentMatchers.any; 25 | import static org.mockito.Mockito.*; 26 | import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; 27 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; 28 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; 29 | 30 | class PodControllerTest extends BaseControllerTest { 31 | 32 | @Autowired 33 | private MockMvc mockMvc; 34 | 35 | @Autowired 36 | private ObjectMapper objectMapper; 37 | 38 | @MockBean 39 | private PodService podService; 40 | 41 | private static final String BASE_PATH = "/api/v1/kubernetes/pods"; 42 | 43 | @Test 44 | public void testListPods() throws Exception { 45 | // Given 46 | PodDto podDto = PodDto.builder() 47 | .uid("TestUid") 48 | .name("TestPod") 49 | .build(); 50 | 51 | // When 52 | when(podService.listPods()).thenReturn(Collections.singletonList(podDto)); 53 | 54 | // sng mockServiceList = Arrays.asList( 52 | ServiceDto.builder().uid("1").name("Service1").namespace("Namespace1").build(), 53 | ServiceDto.builder().uid("2").name("Service2").namespace("Namespace2").build() 54 | ); 55 | 56 | // When 57 | when(kubeServiceService.listServices()).thenReturn(mockServiceList); 58 | 59 | // Then 60 | mockMvc.perform(MockMvcRequestBuilders.get(BASE_PATH + "/listServices")) 61 | .andExpect(status().isOk()) 62 | .andDo(print()) 63 | .andExpect(MockMvcResultMatchers.content().contentType(MediaType.APPLICATION_JSON)) 64 | .andExpect(jsonPath("$", hasSize(2))); 65 | } 66 | 67 | @Test 68 | void testCreateService() throws Exception { 69 | 70 | // Given 71 | CreateServiceRequest createServiceRequest = CreateServiceRequest.builder() 72 | .name("SampleService") 73 | .build(); 74 | 75 | // Create a mock V1Service 76 | V1Service mockService = new V1Service(); 77 | mockService.setMetadata(new V1ObjectMeta().name(createServiceRequest.getName())); 78 | V1ServiceSpec serviceSpec = new V1ServiceSpec(); 79 | V1ServicePort servicePort = new V1ServicePort(); 80 | servicePort.setPort(80); // Set your desired port number 81 | serviceSpec.setPorts(Collections.singletonList(servicePort)); 82 | mockService.setSpec(serviceSpec); 83 | 84 | // When 85 | when(kubeServiceService.createService(createServiceRequest)).thenReturn(mockService); 86 | 87 | // Then 88 | mockMvc.perform(MockMvcRequestBuilders.post(BASE_PATH + "/createService") 89 | .content(objectMapper.writeValueAsString(createServiceRequest)) 90 | .contentType(MediaType.APPLICATION_JSON)) 91 | .andDo(print()) 92 | .andExpect(status().isCreated()) 93 | .andExpect(content().contentType(MediaType.valueOf(MediaType.TEXT_PLAIN_VALUE + ";charset=UTF-8"))) 94 | .andExpect(MockMvcResultMatchers.content().string("Service created successfully: " + createServiceRequest.getName())); 95 | 96 | } 97 | 98 | @Test 99 | void testEditService() throws Exception { 100 | 101 | EditServiceRequest editServiceRequest = EditServiceRequest.builder() 102 | .existingName("new-kubernetes-service") 103 | .updatedName("updated-kubernetes-service") 104 | .build(); 105 | 106 | // Create a mock V1Service 107 | V1Service mockService = new V1Service(); 108 | mockService.setMetadata(new V1ObjectMeta().name(editServiceRequest.getUpdatedName())); 109 | V1ServiceSpec serviceSpec = new V1ServiceSpec(); 110 | V1ServicePort servicePort = new V1ServicePort(); 111 | servicePort.setPort(80); // Set your desired port number 112 | serviceSpec.setPorts(Collections.singletonList(servicePort)); 113 | mockService.setSpec(serviceSpec); 114 | 115 | when(kubeServiceService.editService(any())).thenReturn(mockService); 116 | 117 | mockMvc.perform(MockMvcRequestBuilders.put(BASE_PATH + "/editService") 118 | .content(objectMapper.writeValueAsString(editServiceRequest)) 119 | .contentType(MediaType.APPLICATION_JSON)) 120 | .andDo(print()) 121 | .andExpect(content().contentType(MediaType.valueOf(MediaType.TEXT_PLAIN_VALUE + ";charset=UTF-8"))) 122 | .andExpect(status().isOk()) 123 | .andExpect(MockMvcResultMatchers.content().string("Service edited successfully: " + editServiceRequest.getUpdatedName())); 124 | 125 | } 126 | 127 | @Test 128 | void testDeleteService() throws Exception { 129 | DeleteServiceRequest deleteServiceRequest = DeleteServiceRequest.builder() 130 | .name("test-kubernetes-service") 131 | .build(); 132 | 133 | // Create a mock V1Service 134 | V1Service mockService = new V1Service(); 135 | mockService.setMetadata(new V1ObjectMeta().name(deleteServiceRequest.getName())); 136 | V1ServiceSpec serviceSpec = new V1ServiceSpec(); 137 | V1ServicePort servicePort = new V1ServicePort(); 138 | servicePort.setPort(80); // Set your desired port number 139 | serviceSpec.setPorts(Collections.singletonList(servicePort)); 140 | mockService.setSpec(serviceSpec); 141 | 142 | when(kubeServiceService.deleteService(deleteServiceRequest)).thenReturn(mockService); 143 | 144 | mockMvc.perform(MockMvcRequestBuilders.delete(BASE_PATH + "/deleteService") 145 | .content(objectMapper.writeValueAsString(deleteServiceRequest)) 146 | .contentType(MediaType.APPLICATION_JSON)) 147 | .andDo(print()) 148 | .andExpect(content().contentType(MediaType.valueOf(MediaType.TEXT_PLAIN_VALUE + ";charset=UTF-8"))) 149 | .andExpect(status().isOk()) 150 | .andExpect(MockMvcResultMatchers.content().string("Service deleted successfully: " + mockService.getMetadata().getName())); 151 | } 152 | 153 | } -------------------------------------------------------------------------------- /src/test/java/com/example/kubernetesjavaclientapi/service/DeploymentServiceTest.java: -------------------------------------------------------------------------------- 1 | package com.example.kubernetesjavaclientapi.service; 2 | 3 | import com.example.kubernetesjavaclientapi.base.BaseServiceTest; 4 | import com.example.kubernetesjavaclientapi.dto.deployment.DeploymentDto; 5 | import com.example.kubernetesjavaclientapi.payload.request.deployment.CreateDeploymentRequest; 6 | import com.example.kubernetesjavaclientapi.payload.request.deployment.DeleteDeploymentRequest; 7 | import com.example.kubernetesjavaclientapi.payload.request.deployment.EditDeploymentRequest; 8 | import io.kubernetes.client.openapi.ApiException; 9 | import io.kubernetes.client.openapi.apis.AppsV1Api; 10 | import io.kubernetes.client.openapi.models.V1Deployment; 11 | import io.kubernetes.client.openapi.models.V1DeploymentList; 12 | import io.kubernetes.client.openapi.models.V1ObjectMeta; 13 | import io.kubernetes.client.openapi.models.V1Status; 14 | import org.junit.jupiter.api.Test; 15 | import org.mockito.InjectMocks; 16 | import org.mockito.Mock; 17 | 18 | import java.util.Collections; 19 | import java.util.List; 20 | import java.util.stream.Collectors; 21 | 22 | import static org.junit.jupiter.api.Assertions.*; 23 | import static org.mockito.ArgumentMatchers.any; 24 | import static org.mockito.Mockito.*; 25 | 26 | class DeploymentServiceTest extends BaseServiceTest { 27 | 28 | @InjectMocks 29 | private DeploymentService deploymentService; 30 | 31 | @Mock 32 | private AppsV1Api appsV1Api; 33 | 34 | 35 | @Test 36 | void testListDeployments() throws ApiException { 37 | // Given 38 | V1Deployment deployment = new V1Deployment(); 39 | V1ObjectMeta metadata = new V1ObjectMeta(); 40 | metadata.setUid("1"); 41 | metadata.setName("example-deployment"); 42 | metadata.setNamespace("default"); 43 | deployment.metadata(metadata); 44 | 45 | V1DeploymentList deploymentList = new V1DeploymentList(); 46 | deploymentList.setItems(Collections.singletonList(deployment)); 47 | 48 | List mockDeploymentDtoList = deploymentList.getItems().stream() 49 | .map(deploymentInfo -> 50 | DeploymentDto.builder() 51 | .uid(deploymentInfo.getMetadata().getUid()) 52 | .name(deploymentInfo.getMetadata().getName()) 53 | .namespace(deploymentInfo.getMetadata().getNamespace()) 54 | .build()) 55 | .collect(Collectors.toList()); 56 | 57 | when(appsV1Api.listNamespacedDeployment( 58 | any(), 59 | any(), 60 | any(), 61 | any(), 62 | any(), 63 | any(), 64 | any(), 65 | any(), 66 | any(), 67 | any(), 68 | any())) 69 | .thenReturn(deploymentList); 70 | 71 | // When 72 | List result = deploymentService.listDeployments(); 73 | 74 | assertEquals(mockDeploymentDtoList.size(), result.size()); 75 | assertEquals(mockDeploymentDtoList.get(0).getUid(), result.get(0).getUid()); 76 | assertEquals(mockDeploymentDtoList.get(0).getName(), result.get(0).getName()); 77 | assertEquals(mockDeploymentDtoList.get(0).getNamespace(), result.get(0).getNamespace()); 78 | 79 | // Verify that the appsV1Api.listNamespacedDeployment method was called with the expected parameters 80 | verify(appsV1Api, times(1)).listNamespacedDeployment( 81 | any(), 82 | any(), 83 | any(), 84 | any(), 85 | any(), 86 | any(), 87 | any(), 88 | any(), 89 | any(), 90 | any(), 91 | any()); 92 | 93 | } 94 | 95 | @Test 96 | void testCreateDeployment() throws ApiException { 97 | 98 | // Given 99 | CreateDeploymentRequest request = CreateDeploymentRequest.builder() 100 | .name("example-deployment") 101 | .replicas(3) 102 | .labels(Collections.singletonMap("app", "example-app")) 103 | .containerName("example-container") 104 | .image("your-docker-image:latest") 105 | .containerPort(8080) 106 | .build(); 107 | 108 | V1Deployment createdDeployment = new V1Deployment(); 109 | V1ObjectMeta metadata = new V1ObjectMeta(); 110 | metadata.setName(request.getName()); 111 | createdDeployment.metadata(metadata); 112 | 113 | when(appsV1Api.createNamespacedDeployment( 114 | any(), 115 | any(), 116 | any(), 117 | any(), 118 | any(), 119 | any())) 120 | .thenReturn(createdDeployment); 121 | 122 | // When 123 | V1Deployment result = deploymentService.createDeployment(request); 124 | 125 | // Then 126 | assertNotNull(result); 127 | assertNotNull(result.getMetadata()); 128 | assertEquals(request.getName(), result.getMetadata().getName()); 129 | 130 | // Verify that the appsV1Api.createNamespacedDeployment method was called with the expected parameters 131 | verify(appsV1Api, times(1)).createNamespacedDeployment( 132 | any(), 133 | any(), 134 | any(), 135 | any(), 136 | any(), 137 | any()); 138 | } 139 | 140 | 141 | @Test 142 | void editDeployment_ShouldReturnV1Deployment() throws ApiException { 143 | 144 | // Given 145 | EditDeploymentRequest request = EditDeploymentRequest.builder() 146 | .name("example-deployment") 147 | .replicas(5) 148 | .labels(Collections.singletonMap("app", "edited-app")) 149 | .containerName("edited-container") 150 | .image("edited-docker-image:latest") 151 | .containerPort(8081) 152 | .build(); 153 | 154 | V1Deployment existingDeployment = new V1Deployment(); 155 | V1ObjectMeta metadata = new V1ObjectMeta(); 156 | metadata.setName(request.getName()); 157 | existingDeployment.metadata(metadata); 158 | 159 | // When 160 | when(appsV1Api.readNamespacedDeployment(anyString(), anyString(), any())) 161 | .thenReturn(existingDeployment); 162 | 163 | 164 | when(appsV1Api.replaceNamespacedDeployment(anyString(), anyString(), any(), any(), any(), any(), any())) 165 | .thenReturn(existingDeployment); 166 | 167 | // Then 168 | V1Deployment result = deploymentService.editDeployment(request); 169 | 170 | 171 | assertNotNull(result); 172 | assertNotNull(result.getMetadata()); 173 | assertEquals(request.getName(), result.getMetadata().getName()); 174 | 175 | // Verify 176 | verify(appsV1Api, times(1)).readNamespacedDeployment( 177 | anyString(), 178 | anyString(), 179 | any()); 180 | 181 | verify(appsV1Api, times(1)).replaceNamespacedDeployment( 182 | anyString(), 183 | anyString(), 184 | any(), 185 | any(), 186 | any(), 187 | any(), 188 | any()); 189 | } 190 | 191 | @Test 192 | void testDeleteDeployment() throws ApiException { 193 | 194 | // Given 195 | DeleteDeploymentRequest request = DeleteDeploymentRequest.builder() 196 | .name("example-deployment") 197 | .build(); 198 | 199 | V1Status deletionStatus = new V1Status(); 200 | deletionStatus.setMessage("Deployment deleted successfully"); 201 | 202 | // When 203 | when(appsV1Api.deleteNamespacedDeployment(anyString(), anyString(), any(), any(), any(), any(), any(), any())) 204 | .thenReturn(deletionStatus); 205 | 206 | // Then 207 | V1Status result = deploymentService.deleteDeployment(request); 208 | 209 | assertNotNull(result); 210 | assertEquals("Deployment deleted successfully", result.getMessage()); 211 | 212 | // Verify 213 | verify(appsV1Api, times(1)).deleteNamespacedDeployment( 214 | anyString(), 215 | anyString(), 216 | any(), 217 | any(), 218 | any(), 219 | any(), 220 | any(), 221 | any()); 222 | } 223 | 224 | } -------------------------------------------------------------------------------- /src/test/java/com/example/kubernetesjavaclientapi/service/KubeServiceServiceTest.java: -------------------------------------------------------------------------------- 1 | package com.example.kubernetesjavaclientapi.service; 2 | 3 | import com.example.kubernetesjavaclientapi.base.BaseServiceTest; 4 | import com.example.kubernetesjavaclientapi.dto.service.ServiceDto; 5 | import com.example.kubernetesjavaclientapi.payload.request.service.CreateServiceRequest; 6 | import com.example.kubernetesjavaclientapi.payload.request.service.DeleteServiceRequest; 7 | import com.example.kubernetesjavaclientapi.payload.request.service.EditServiceRequest; 8 | import io.kubernetes.client.openapi.ApiException; 9 | import io.kubernetes.client.openapi.apis.AppsV1Api; 10 | import io.kubernetes.client.openapi.apis.CoreV1Api; 11 | import io.kubernetes.client.openapi.models.*; 12 | import org.junit.jupiter.api.Test; 13 | import org.mockito.InjectMocks; 14 | import org.mockito.Mock; 15 | 16 | import java.util.Arrays; 17 | import java.util.Collections; 18 | import java.util.List; 19 | import java.util.stream.Collectors; 20 | 21 | import static org.junit.jupiter.api.Assertions.*; 22 | import static org.mockito.ArgumentMatchers.any; 23 | import static org.mockito.BDDMockito.willReturn; 24 | import static org.mockito.Mockito.*; 25 | 26 | class KubeServiceServiceTest extends BaseServiceTest { 27 | 28 | @InjectMocks 29 | private KubeServiceService kubeServiceService; 30 | 31 | @Mock 32 | private CoreV1Api coreV1Api; 33 | 34 | @Mock 35 | private AppsV1Api appsV1Api; 36 | 37 | @Test 38 | void testListServices() throws ApiException { 39 | 40 | // Given 41 | V1Service service1 = new V1Service() 42 | .metadata(new V1ObjectMeta().name("Service1").uid("1").namespace("Namespace1")) 43 | .spec(new V1ServiceSpec()) 44 | .status(new V1ServiceStatus()); 45 | V1Service service2 = new V1Service() 46 | .metadata(new V1ObjectMeta().name("Service2").uid("2").namespace("Namespace1")) 47 | .spec(new V1ServiceSpec()) 48 | .status(new V1ServiceStatus()); 49 | 50 | V1ServiceList serviceList = new V1ServiceList().items(Arrays.asList(service1, service2)); 51 | 52 | List collect = serviceList.getItems().stream() 53 | .map(service -> 54 | ServiceDto.builder() 55 | .name(service.getMetadata().getName()) 56 | .uid(service.getMetadata().getUid()) 57 | .namespace(service.getMetadata().getNamespace()) 58 | .build()) 59 | .collect(Collectors.toList()); 60 | 61 | // When 62 | when(coreV1Api.listNamespacedService(any(), any(), any(), any(), any(), any(), any(), any(), any(), any(), any())) 63 | .thenReturn(serviceList); 64 | 65 | 66 | // Then 67 | List result = kubeServiceService.listServices(); 68 | 69 | // Validate the result 70 | assertEquals(2, result.size()); 71 | 72 | // Validate the content of the result based on your actual implementation 73 | assertEquals("Service1", result.get(0).getName()); 74 | assertEquals("1", result.get(0).getUid()); 75 | assertEquals("Namespace1", result.get(0).getNamespace()); 76 | 77 | assertEquals("Service2", result.get(1).getName()); 78 | assertEquals("2", result.get(1).getUid()); 79 | assertEquals("Namespace1", result.get(1).getNamespace()); 80 | 81 | verify(coreV1Api, times(1)) 82 | .listNamespacedService(any(), any(), any(), any(), any(), any(), any(), any(), any(), any(), any()); 83 | 84 | } 85 | 86 | @Test 87 | void testCreateService() throws ApiException { 88 | // Given 89 | CreateServiceRequest createServiceRequest = CreateServiceRequest.builder().name("SampleService").build(); 90 | 91 | V1Service expectedService = new V1Service(); 92 | V1ObjectMeta expectedMetadata = new V1ObjectMeta(); 93 | expectedMetadata.setName(createServiceRequest.getName()); 94 | expectedService.setMetadata(expectedMetadata); 95 | 96 | V1ServiceSpec expectedSpec = new V1ServiceSpec(); 97 | V1ServicePort expectedServicePort = new V1ServicePort(); 98 | expectedServicePort.setPort(80); 99 | expectedSpec.setPorts(Collections.singletonList(expectedServicePort)); 100 | expectedService.setSpec(expectedSpec); 101 | 102 | // When 103 | when(coreV1Api.createNamespacedService(any(), any(), any(), any(), any(), any())) 104 | .thenReturn(expectedService); 105 | 106 | // Then 107 | V1Service resultService = kubeServiceService.createService(createServiceRequest); 108 | 109 | assertEquals(expectedService.getMetadata().getName(), resultService.getMetadata().getName()); 110 | 111 | // Verify 112 | verify(coreV1Api, times(1)) 113 | .createNamespacedService("default", expectedService, null, null, null, null); 114 | 115 | } 116 | 117 | @Test 118 | void testEditService() throws ApiException { 119 | 120 | // Given 121 | EditServiceRequest editServiceRequest = new EditServiceRequest("ExistingService", "UpdatedService"); 122 | 123 | V1Service existingService = new V1Service() 124 | .metadata(new V1ObjectMeta().name(editServiceRequest.getExistingName())) 125 | .spec(new V1ServiceSpec() 126 | .ports(Arrays.asList( 127 | new V1ServicePort().port(80).name("http").protocol("TCP"), 128 | new V1ServicePort().port(443).name("https").protocol("TCP") 129 | ))); 130 | 131 | V1Service updatedService = new V1Service() 132 | .metadata(new V1ObjectMeta().name(editServiceRequest.getUpdatedName())) 133 | .spec(new V1ServiceSpec().ports(existingService.getSpec().getPorts())); 134 | 135 | V1DeploymentList deploymentList = new V1DeploymentList(); 136 | V1Deployment deployment = new V1Deployment(); 137 | deployment.setMetadata(new V1ObjectMeta()); 138 | deployment.getMetadata().setName("test-deployment"); 139 | deploymentList.setItems(Collections.singletonList(deployment)); 140 | 141 | // When 142 | when(coreV1Api.readNamespacedService(any(), any(), any())) 143 | .thenReturn(existingService); 144 | 145 | when(coreV1Api.createNamespacedService(any(), any(), any(), any(), any(), any())) 146 | .thenReturn(updatedService); 147 | 148 | when(appsV1Api.listNamespacedDeployment(any(), 149 | any(), 150 | any(), 151 | any(), 152 | any(), 153 | any(), 154 | any(), 155 | any(), 156 | any(), 157 | any(), 158 | any())) 159 | .thenReturn(deploymentList); 160 | 161 | // Then 162 | V1Service resultService = kubeServiceService.editService(editServiceRequest); 163 | 164 | assertNotNull(resultService); 165 | assertEquals(editServiceRequest.getUpdatedName(), resultService.getMetadata().getName()); 166 | 167 | // Then 168 | verify(coreV1Api, times(1)) 169 | .readNamespacedService(any(), any(), any()); 170 | verify(coreV1Api, times(1)) 171 | .createNamespacedService(any(), any(), any(), any(), any(), any()); 172 | verify(appsV1Api, times(1)) 173 | .listNamespacedDeployment(any(), any(), any(), any(), any(), 174 | any(), any(), any(), any(), any(), any()); 175 | 176 | } 177 | 178 | @Test 179 | void testDeleteService() throws ApiException { 180 | 181 | // Given 182 | DeleteServiceRequest deleteServiceRequest = DeleteServiceRequest.builder() 183 | .name("ServiceToDelete") 184 | .build(); 185 | 186 | V1Service deletedService = new V1Service(); 187 | V1ObjectMeta metadata = new V1ObjectMeta(); 188 | metadata.setName(deleteServiceRequest.getName()); 189 | deletedService.setMetadata(metadata); 190 | 191 | // When 192 | when(coreV1Api.deleteNamespacedService(any(), any(), any(), any(), any(), any(), any(), any())) 193 | .thenReturn(deletedService); 194 | 195 | // Then 196 | V1Service resultService = kubeServiceService.deleteService(deleteServiceRequest); 197 | 198 | assertNotNull(resultService); 199 | assertEquals(deleteServiceRequest.getName(), resultService.getMetadata().getName()); 200 | 201 | // Verify 202 | verify(coreV1Api, times(1)) 203 | .deleteNamespacedService(any(), any(), any(), any(), any(), any(), any(), any()); 204 | } 205 | 206 | } -------------------------------------------------------------------------------- /src/test/java/com/example/kubernetesjavaclientapi/service/NamespaceServiceTest.java: -------------------------------------------------------------------------------- 1 | package com.example.kubernetesjavaclientapi.service; 2 | 3 | import com.example.kubernetesjavaclientapi.base.BaseServiceTest; 4 | import com.example.kubernetesjavaclientapi.payload.request.namespace.CreateNamespaceRequest; 5 | import com.example.kubernetesjavaclientapi.payload.request.namespace.DeleteNamespaceRequest; 6 | import com.example.kubernetesjavaclientapi.payload.request.namespace.EditNamespaceRequest; 7 | import io.kubernetes.client.openapi.ApiException; 8 | import io.kubernetes.client.openapi.apis.AppsV1Api; 9 | import io.kubernetes.client.openapi.apis.CoreV1Api; 10 | import io.kubernetes.client.openapi.models.*; 11 | import org.junit.jupiter.api.Test; 12 | import org.mockito.InjectMocks; 13 | import org.mockito.Mock; 14 | 15 | import java.util.Collections; 16 | 17 | import static org.junit.jupiter.api.Assertions.*; 18 | import static org.mockito.ArgumentMatchers.any; 19 | import static org.mockito.Mockito.*; 20 | 21 | class NamespaceServiceTest extends BaseServiceTest { 22 | 23 | @InjectMocks 24 | private NamespaceService namespaceService; 25 | 26 | @Mock 27 | private CoreV1Api coreV1Api; 28 | 29 | @Mock 30 | private AppsV1Api appsV1Api; 31 | 32 | @Test 33 | void testListNameSpaces() throws ApiException { 34 | // Given 35 | V1NamespaceList namespaceList = new V1NamespaceList(); 36 | V1Namespace namespace = new V1Namespace(); 37 | V1ObjectMeta metadata = new V1ObjectMeta(); 38 | metadata.setName("test-namespace"); 39 | namespace.setMetadata(metadata); 40 | namespaceList.setItems(Collections.singletonList(namespace)); 41 | 42 | // When 43 | when(coreV1Api.listNamespace( 44 | null, null, null, null, null, null, null, null, null, null)) 45 | .thenReturn(namespaceList); 46 | 47 | // Then 48 | var result = namespaceService.listNameSpaces(); 49 | 50 | assertEquals(1, result.size()); 51 | assertEquals("test-namespace", result.get(0).getNamespace()); 52 | 53 | // Verify 54 | verify(coreV1Api, times(1)).listNamespace( 55 | null, null, null, null, null, null, null, null, null, null); 56 | 57 | } 58 | 59 | @Test 60 | void testCreateNamespace() throws ApiException { 61 | 62 | // Given 63 | CreateNamespaceRequest request = CreateNamespaceRequest.builder() 64 | .name("test-namespace") 65 | .build(); 66 | 67 | 68 | V1Namespace createdNamespace = new V1Namespace(); 69 | V1ObjectMeta metadata = new V1ObjectMeta(); 70 | metadata.setName(request.getName()); 71 | createdNamespace.setMetadata(metadata); 72 | 73 | // When 74 | when(coreV1Api.createNamespace(any(), any(), any(), any(), any())) 75 | .thenReturn(createdNamespace); 76 | 77 | // Then 78 | var result = namespaceService.createNamespace(request); 79 | 80 | assertEquals(request.getName(), result.getMetadata().getName()); 81 | 82 | // Verify 83 | verify(coreV1Api, times(1)).createNamespace( 84 | any(), any(), any(), any(), any()); 85 | 86 | } 87 | 88 | @Test 89 | void testEditNamespace() throws ApiException { 90 | 91 | // Given 92 | EditNamespaceRequest request = EditNamespaceRequest.builder() 93 | .existingName("old-namespace") 94 | .updatedName("new-namespace") 95 | .build(); 96 | 97 | V1Namespace existingNamespace = new V1Namespace(); 98 | V1ObjectMeta existingMetadata = new V1ObjectMeta(); 99 | existingMetadata.setName(request.getExistingName()); 100 | existingNamespace.setMetadata(existingMetadata); 101 | 102 | V1Namespace updatedNamespace = new V1Namespace(); 103 | V1ObjectMeta updatedMetadata = new V1ObjectMeta(); 104 | updatedMetadata.setName(request.getUpdatedName()); 105 | updatedNamespace.setMetadata(updatedMetadata); 106 | 107 | V1DeploymentList deploymentList = new V1DeploymentList(); 108 | V1Deployment deployment = new V1Deployment(); 109 | deployment.setMetadata(new V1ObjectMeta()); 110 | deployment.getMetadata().setName("test-deployment"); 111 | deploymentList.setItems(Collections.singletonList(deployment)); 112 | 113 | when(coreV1Api.readNamespace(any(), isNull())) 114 | .thenReturn(existingNamespace); 115 | when(coreV1Api.createNamespace(any(), isNull(), isNull(), isNull(), isNull())) 116 | .thenReturn(updatedNamespace); 117 | when(appsV1Api.listNamespacedDeployment(any(), 118 | isNull(), 119 | isNull(), 120 | isNull(), 121 | isNull(), 122 | isNull(), 123 | isNull(), 124 | isNull(), 125 | isNull(), 126 | isNull(), 127 | isNull())) 128 | .thenReturn(deploymentList); 129 | 130 | // When 131 | var result = namespaceService.editNamespace(request); 132 | 133 | assertEquals(request.getUpdatedName(), result.getMetadata().getName()); 134 | 135 | // Then 136 | verify(coreV1Api, times(1)).readNamespace(any(), isNull()); 137 | verify(coreV1Api, times(1)).createNamespace(any(), isNull(), isNull(), isNull(), isNull()); 138 | verify(appsV1Api, times(1)).listNamespacedDeployment(any(), 139 | isNull(), 140 | isNull(), 141 | isNull(), 142 | isNull(), 143 | isNull(), 144 | isNull(), 145 | isNull(), 146 | isNull(), 147 | isNull(), 148 | isNull()); 149 | } 150 | 151 | @Test 152 | void testDeleteNamespace() throws ApiException { 153 | // Given 154 | DeleteNamespaceRequest request = DeleteNamespaceRequest.builder() 155 | .name("test-namespace") 156 | .build(); 157 | 158 | V1Status deletionStatus = new V1Status(); 159 | deletionStatus.setStatus("Success"); 160 | deletionStatus.setMessage("Namespace deleted successfully"); 161 | 162 | when(coreV1Api.deleteNamespace(any(), isNull(), isNull(), isNull(), isNull(), isNull(), any())) 163 | .thenReturn(deletionStatus); 164 | 165 | // When 166 | var result = namespaceService.deleteNamespace(request); 167 | 168 | assertEquals(deletionStatus.getStatus(), result.getStatus()); 169 | assertEquals(deletionStatus.getMessage(), result.getMessage()); 170 | 171 | // Then 172 | verify(coreV1Api, times(1)).deleteNamespace(any(), isNull(), isNull(), isNull(), isNull(), isNull(), any()); 173 | } 174 | 175 | 176 | 177 | } -------------------------------------------------------------------------------- /src/test/java/com/example/kubernetesjavaclientapi/service/PodServiceTest.java: -------------------------------------------------------------------------------- 1 | package com.example.kubernetesjavaclientapi.service; 2 | 3 | import com.example.kubernetesjavaclientapi.base.BaseServiceTest; 4 | import com.example.kubernetesjavaclientapi.dto.pod.PodDto; 5 | import com.example.kubernetesjavaclientapi.dto.pod.V1ManagedFieldsEntryDto; 6 | import com.example.kubernetesjavaclientapi.dto.pod.V1OwnerReferenceDto; 7 | import com.example.kubernetesjavaclientapi.mapper.V1ManagedFieldsEntryToV1ManagedFieldsEntryDtoMapper; 8 | import com.example.kubernetesjavaclientapi.mapper.V1OwnerReferenceToV1OwnerReferenceDtoMapper; 9 | import com.example.kubernetesjavaclientapi.payload.request.pods.CreatePodRequest; 10 | import com.example.kubernetesjavaclientapi.payload.request.pods.DeletePodRequest; 11 | import com.example.kubernetesjavaclientapi.payload.request.pods.EditPodRequest; 12 | import io.kubernetes.client.openapi.ApiException; 13 | import io.kubernetes.client.openapi.apis.CoreV1Api; 14 | import io.kubernetes.client.openapi.models.*; 15 | import org.junit.jupiter.api.Test; 16 | import org.mockito.InjectMocks; 17 | import org.mockito.Mock; 18 | 19 | import java.time.OffsetDateTime; 20 | import java.util.Collections; 21 | import java.util.HashMap; 22 | import java.util.List; 23 | import java.util.Map; 24 | import java.util.stream.Collectors; 25 | 26 | import static org.junit.jupiter.api.Assertions.*; 27 | import static org.mockito.ArgumentMatchers.any; 28 | import static org.mockito.Mockito.*; 29 | 30 | class PodServiceTest extends BaseServiceTest { 31 | 32 | @InjectMocks 33 | private PodService podService; 34 | 35 | @Mock 36 | private CoreV1Api coreV1Api; 37 | 38 | private final V1ManagedFieldsEntryToV1ManagedFieldsEntryDtoMapper v1ManagedFieldsEntryToV1ManagedFieldsEntryDtoMapper = V1ManagedFieldsEntryToV1ManagedFieldsEntryDtoMapper.initialize(); 39 | 40 | private final V1OwnerReferenceToV1OwnerReferenceDtoMapper v1OwnerReferenceToV1OwnerReferenceDtoMapper = V1OwnerReferenceToV1OwnerReferenceDtoMapper.initialize(); 41 | 42 | @Test 43 | public void testListPods() throws Exception { 44 | 45 | // Given 46 | V1PodList podList = new V1PodList(); 47 | V1Pod pod = new V1Pod(); 48 | 49 | 50 | V1ObjectMeta metadata = new V1ObjectMeta(); 51 | metadata.setName("TestPod"); 52 | pod.setMetadata(metadata); 53 | 54 | // Mock the mapping methods 55 | V1ManagedFieldsEntry v1ManagedFieldsEntry = new V1ManagedFieldsEntry() 56 | .apiVersion("v1") 57 | .fieldsType("FieldsV1") 58 | .fieldsV1("example") 59 | .manager("manager") 60 | .operation("operation") 61 | .subresource("subresource") 62 | .time(OffsetDateTime.now()); 63 | 64 | metadata.setManagedFields(Collections.singletonList(v1ManagedFieldsEntry)); 65 | 66 | V1OwnerReference v1OwnerReference = new V1OwnerReference() 67 | .apiVersion("v1") 68 | .blockOwnerDeletion(true) 69 | .controller(false) 70 | .kind("Kind") 71 | .name("OwnerName") 72 | .uid("OwnerUid"); 73 | 74 | metadata.setOwnerReferences(Collections.singletonList(v1OwnerReference)); 75 | 76 | podList.setItems(Collections.singletonList(pod)); 77 | 78 | List expected = podList.getItems().stream() 79 | .map(item -> { 80 | V1ObjectMeta data = item.getMetadata(); 81 | 82 | List v1ManagedFieldsEntryDtos = v1ManagedFieldsEntryToV1ManagedFieldsEntryDtoMapper.map(data.getManagedFields()); 83 | List v1OwnerReferenceDtos = v1OwnerReferenceToV1OwnerReferenceDtoMapper.map(data.getOwnerReferences()); 84 | 85 | return PodDto.builder() 86 | .uid(data.getUid()) 87 | .name(data.getName()) 88 | .annotations(data.getAnnotations()) 89 | .clusterName(data.getClusterName()) 90 | .creationTimestamp(data.getCreationTimestamp()) 91 | .deletionGracePeriodSeconds(data.getDeletionGracePeriodSeconds()) 92 | .deletionTimestamp(data.getDeletionTimestamp()) 93 | .finalizers(data.getFinalizers()) 94 | .generateName(data.getGenerateName()) 95 | .generation(data.getGeneration()) 96 | .labels(data.getLabels()) 97 | .managedFields(v1ManagedFieldsEntryDtos) 98 | .namespace(data.getNamespace()) 99 | .ownerReferences(v1OwnerReferenceDtos) 100 | .selfLink(data.getSelfLink()) 101 | .build(); 102 | }) 103 | .collect(Collectors.toList()); 104 | 105 | // When 106 | when(coreV1Api.listPodForAllNamespaces( 107 | any(), 108 | any(), 109 | any(), 110 | any(), 111 | any(), 112 | any(), 113 | any(), 114 | any(), 115 | any(), 116 | any())) 117 | .thenReturn(podList); 118 | 119 | 120 | // Then 121 | List actual = podService.listPods(); 122 | 123 | assertEquals(1, actual.size()); 124 | assertEquals(expected.get(0).getName(), actual.get(0).getName()); 125 | assertEquals(expected.get(0).getUid(), actual.get(0).getUid()); 126 | assertEquals(expected.get(0).getManagedFields().size(), actual.get(0).getManagedFields().size()); 127 | assertEquals(expected.get(0).getManagedFields().get(0).getApiVersion(), actual.get(0).getManagedFields().get(0).getApiVersion()); 128 | 129 | // Verify 130 | verify(coreV1Api, times(1)).listPodForAllNamespaces( 131 | any(), 132 | any(), 133 | any(), 134 | any(), 135 | any(), 136 | any(), 137 | any(), 138 | any(), 139 | any(), 140 | any()); 141 | 142 | 143 | } 144 | 145 | @Test 146 | public void testCreatePod() throws ApiException { 147 | 148 | // Given 149 | CreatePodRequest createPodRequest = CreatePodRequest.builder() 150 | .namespace("default") 151 | .podName("test-pod") 152 | .build(); 153 | 154 | // Mock the Kubernetes API response 155 | V1Pod expected = new V1Pod(); 156 | V1ObjectMeta metadata = new V1ObjectMeta(); 157 | metadata.setName(createPodRequest.getPodName()); 158 | expected.setMetadata(metadata); 159 | 160 | // When 161 | when(coreV1Api.createNamespacedPod( 162 | any(), 163 | any(), 164 | any(), 165 | any(), 166 | any(), 167 | any())) 168 | .thenReturn(expected); 169 | 170 | // Then 171 | V1Pod actual = podService.createPod(createPodRequest); 172 | 173 | assertNotNull(actual); 174 | assertNotNull(actual.getMetadata()); 175 | assertEquals(createPodRequest.getPodName(), actual.getMetadata().getName()); 176 | 177 | // Verify 178 | verify(coreV1Api, times(1)).createNamespacedPod( 179 | any(), 180 | any(), 181 | any(), 182 | any(), 183 | any(), 184 | any()); 185 | } 186 | 187 | @Test 188 | public void testEditPod() throws ApiException { 189 | 190 | // Given 191 | EditPodRequest editPodRequest = EditPodRequest.builder() 192 | .namespace("default") 193 | .podName("test-pod") 194 | .updatedLabels(Map.of("key1", "value1", "key2", "value2")) 195 | .build(); 196 | 197 | V1Pod existingPod = new V1Pod(); 198 | V1ObjectMeta metadata = new V1ObjectMeta(); 199 | metadata.setName(editPodRequest.getPodName()); 200 | existingPod.setMetadata(metadata); 201 | 202 | 203 | // Initialize labels if null 204 | if (metadata.getLabels() == null) { 205 | metadata.setLabels(new HashMap<>()); 206 | } 207 | 208 | metadata.getLabels().putAll(editPodRequest.getUpdatedLabels()); 209 | 210 | // When 211 | when(coreV1Api.readNamespacedPod( 212 | any(), 213 | any(), 214 | any())) 215 | .thenReturn(existingPod); 216 | 217 | when(coreV1Api.replaceNamespacedPod( 218 | any(), 219 | any(), 220 | eq(existingPod), 221 | isNull(), 222 | isNull(), 223 | isNull(), 224 | isNull())) 225 | .thenReturn(existingPod); 226 | 227 | 228 | // Then 229 | V1Pod editedPod = podService.editPod(editPodRequest); 230 | 231 | assertNotNull(editedPod); 232 | assertEquals(editPodRequest.getPodName(), editedPod.getMetadata().getName()); 233 | assertEquals(editPodRequest.getUpdatedLabels(), editedPod.getMetadata().getLabels()); 234 | 235 | // Verify 236 | verify(coreV1Api, times(1)).readNamespacedPod( 237 | any(), 238 | any(), 239 | any()); 240 | 241 | verify(coreV1Api, times(1)).replaceNamespacedPod( 242 | any(), 243 | any(), 244 | eq(existingPod), 245 | isNull(), 246 | isNull(), 247 | isNull(), 248 | isNull()); 249 | } 250 | 251 | @Test 252 | public void testDeletePod() throws ApiException { 253 | 254 | // Given 255 | DeletePodRequest deletePodRequest = DeletePodRequest.builder() 256 | .namespace("default") 257 | .podName("test-pod") 258 | .build(); 259 | 260 | V1Pod deletedPod = new V1Pod(); 261 | V1ObjectMeta metadata = new V1ObjectMeta(); 262 | metadata.setName(deletePodRequest.getPodName()); 263 | deletedPod.setMetadata(metadata); 264 | 265 | // When 266 | when(coreV1Api.deleteNamespacedPod( 267 | eq(deletePodRequest.getPodName()), 268 | eq(deletePodRequest.getNamespace()), 269 | isNull(), 270 | isNull(), 271 | isNull(), 272 | isNull(), 273 | isNull(), 274 | isNull())) 275 | .thenReturn(deletedPod); 276 | 277 | // Then 278 | V1Pod v1Pod = podService.deletePod(deletePodRequest); 279 | 280 | // Verify 281 | assertEquals(null, v1Pod.getKind()); 282 | assertNotNull(deletedPod); 283 | assertEquals(deletePodRequest.getPodName(), deletedPod.getMetadata().getName()); 284 | 285 | // Verify 286 | verify(coreV1Api, times(1)).deleteNamespacedPod( 287 | eq(deletePodRequest.getPodName()), 288 | eq(deletePodRequest.getNamespace()), 289 | isNull(), 290 | isNull(), 291 | isNull(), 292 | isNull(), 293 | isNull(), 294 | isNull()); 295 | } 296 | 297 | } --------------------------------------------------------------------------------