Skip to content

Commit a0c733e

Browse files
feat: onboard serverupdate service (#150)
relates to STACKITSDK-253
1 parent 428416a commit a0c733e

36 files changed

+9508
-0
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
## Release (2025-MM-DD)
22
- `objectstorage`: [v0.1.0](services/objectstorage/CHANGELOG.md#v010)
33
- Initial onboarding of STACKIT Java SDK for Object storage service
4+
- `serverupdate`: [v0.1.0](services/serverupdate/CHANGELOG.md#v010)
5+
- Initial onboarding of STACKIT Java SDK for Server Update service
46

57
## Release (2025-10-29)
68
- `core`:

examples/serverupdate/build.gradle

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
dependencies {
2+
implementation project (':services:serverupdate')
3+
implementation 'com.squareup.okhttp3:okhttp:4.12.0'
4+
}
5+
6+
ext.mainClassName = 'cloud.stackit.sdk.serverupdate.examples.ServerUpdateExample'
Lines changed: 242 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,242 @@
1+
package cloud.stackit.sdk.serverupdate.examples;
2+
3+
import cloud.stackit.sdk.core.KeyFlowAuthenticator;
4+
import cloud.stackit.sdk.core.config.CoreConfiguration;
5+
import cloud.stackit.sdk.core.exception.ApiException;
6+
import cloud.stackit.sdk.serverupdate.api.ServerUpdateApi;
7+
import cloud.stackit.sdk.serverupdate.model.*;
8+
import java.io.IOException;
9+
import java.net.HttpURLConnection;
10+
import java.time.Duration;
11+
import java.util.Objects;
12+
import java.util.UUID;
13+
import java.util.concurrent.TimeUnit;
14+
import okhttp3.OkHttpClient;
15+
16+
final class ServerUpdateExample {
17+
18+
private ServerUpdateExample() {}
19+
20+
@SuppressWarnings({
21+
"PMD.CyclomaticComplexity",
22+
"PMD.CognitiveComplexity",
23+
"PMD.NPathComplexity",
24+
"PMD.NcssCount",
25+
"PMD.SystemPrintln",
26+
"PMD.AvoidThrowingRawExceptionTypes",
27+
"PMD.AvoidDuplicateLiterals"
28+
})
29+
public static void main(String[] args) throws IOException {
30+
// Credentials are read from the credentialsFile in `~/.stackit/credentials.json` or the env
31+
// STACKIT_SERVICE_ACCOUNT_KEY_PATH / STACKIT_SERVICE_ACCOUNT_KEY
32+
CoreConfiguration configuration = new CoreConfiguration();
33+
34+
OkHttpClient httpClient = new OkHttpClient();
35+
KeyFlowAuthenticator authenticator = new KeyFlowAuthenticator(httpClient, configuration);
36+
httpClient =
37+
httpClient
38+
.newBuilder()
39+
.authenticator(authenticator)
40+
// Some create / update requests may take a few seconds.
41+
// To prevent a timeout, we increase the read timeout to 30 seconds
42+
.readTimeout(Duration.ofSeconds(30))
43+
.build();
44+
45+
ServerUpdateApi serverUpdateApi = new ServerUpdateApi(httpClient, configuration);
46+
47+
// the id of your STACKIT project, read from env var for this example
48+
String projectId = System.getenv("STACKIT_PROJECT_ID");
49+
if (projectId == null || projectId.isEmpty()) {
50+
System.err.println("Environment variable 'STACKIT_PROJECT_ID' not found.");
51+
return;
52+
}
53+
54+
// the region which should be used to interact with serverupdate
55+
String region = "eu01"; // NOPMD
56+
57+
// the id of your STACKIT server, read from env var for this example
58+
String serverId = System.getenv("STACKIT_SERVER_ID");
59+
if (serverId == null || serverId.isEmpty()) {
60+
System.err.println("Environment variable 'STACKIT_SERVER_ID' not found.");
61+
return;
62+
}
63+
64+
try {
65+
/*
66+
* ///////////////////////////////////////////////////////
67+
* // U P D A T E P O L I C I E S //
68+
* ///////////////////////////////////////////////////////
69+
*/
70+
/* fetching all available update policies */
71+
System.out.println("List all available update policies:");
72+
GetUpdatePoliciesResponse listUpdatePolicies =
73+
serverUpdateApi.listUpdatePolicies(projectId);
74+
Objects.requireNonNull(listUpdatePolicies.getItems());
75+
for (UpdatePolicy policy : listUpdatePolicies.getItems()) {
76+
System.out.println("*************************");
77+
System.out.println("* Policy name: " + policy.getName());
78+
System.out.println("* Description: " + policy.getDescription());
79+
System.out.println("* Policy ID: " + policy.getId());
80+
System.out.println("* RRULE: " + policy.getRrule());
81+
System.out.println("* Enabled: " + policy.getEnabled());
82+
System.out.println("* Default: " + policy.getDefault());
83+
}
84+
85+
/*
86+
* ///////////////////////////////////////////////////////
87+
* // U P D A T E E N A B L E M E N T //
88+
* ///////////////////////////////////////////////////////
89+
*/
90+
/* checking if update service is enabled for the server */
91+
System.out.println("\nChecking update service status for the server:");
92+
try {
93+
GetUpdateServiceResponse updateServiceStatus =
94+
serverUpdateApi.getServiceResource(projectId, serverId, region);
95+
Objects.requireNonNull(updateServiceStatus.getEnabled());
96+
System.out.println("* Update service enabled: " + updateServiceStatus.getEnabled());
97+
} catch (ApiException e) {
98+
// If response status is not found, update service is not enabled for the server
99+
if (e.getCode() == HttpURLConnection.HTTP_NOT_FOUND) {
100+
System.out.println("* Update service is not enabled for the server");
101+
System.out.println("* Enabling update service...");
102+
String policyIdString = listUpdatePolicies.getItems().get(0).getId();
103+
Objects.requireNonNull(policyIdString);
104+
UUID policyId = UUID.fromString(policyIdString);
105+
serverUpdateApi.enableServiceResource(
106+
projectId,
107+
serverId,
108+
region,
109+
new EnableServiceResourcePayload().updatePolicyId(policyId));
110+
System.out.println("* Update service successful enabled for the server");
111+
}
112+
}
113+
114+
/*
115+
* ///////////////////////////////////////////////////////
116+
* // U P D A T E S C H E D U L E //
117+
* ///////////////////////////////////////////////////////
118+
*/
119+
/* creating a new nightly update schedule for the server*/
120+
System.out.println("\nCreating a new update schedule:");
121+
UpdateSchedule newSchedule =
122+
serverUpdateApi.createUpdateSchedule(
123+
projectId,
124+
serverId,
125+
region,
126+
new CreateUpdateSchedulePayload()
127+
.name("Nightly 3 AM")
128+
.enabled(true)
129+
.maintenanceWindow(5)
130+
.rrule(
131+
"DTSTART;TZID=Europe/Berlin:20251210T030000 RRULE:FREQ=DAILY;INTERVAL=1"));
132+
System.out.println("* Schedule ID: " + newSchedule.getId());
133+
System.out.println("* Name: " + newSchedule.getName());
134+
System.out.println("* Enabled: " + newSchedule.getEnabled());
135+
System.out.println("* RRULE: " + newSchedule.getRrule());
136+
System.out.println("* Maintenance Window: " + newSchedule.getMaintenanceWindow());
137+
138+
/* updating the created update schedule */
139+
System.out.println("\nUpdating the update schedule:");
140+
UpdateSchedule updatedSchedule =
141+
serverUpdateApi.updateUpdateSchedule(
142+
projectId,
143+
serverId,
144+
newSchedule.getId().toString(),
145+
region,
146+
new UpdateUpdateSchedulePayload()
147+
.name("Nightly 10 PM")
148+
.enabled(false)
149+
.maintenanceWindow(2)
150+
.rrule(
151+
"DTSTART;TZID=Europe/Berlin:20251210T220000 RRULE:FREQ=DAILY;INTERVAL=1"));
152+
System.out.println("* Schedule ID: " + updatedSchedule.getId());
153+
System.out.println("* Name: " + updatedSchedule.getName());
154+
System.out.println("* Enabled: " + updatedSchedule.getEnabled());
155+
System.out.println("* RRULE: " + updatedSchedule.getRrule());
156+
System.out.println("* Maintenance Window: " + updatedSchedule.getMaintenanceWindow());
157+
158+
/* list all available update schedules of the server */
159+
System.out.println("\nList all update schedules");
160+
GetUpdateSchedulesResponse listUpdateSchedules =
161+
serverUpdateApi.listUpdateSchedules(projectId, serverId, region);
162+
Objects.requireNonNull(listUpdateSchedules.getItems());
163+
for (UpdateSchedule schedule : listUpdateSchedules.getItems()) {
164+
System.out.println("*************************");
165+
System.out.println("* Schedule ID: " + schedule.getId());
166+
System.out.println("* Name: " + schedule.getName());
167+
System.out.println("* Enabled: " + schedule.getEnabled());
168+
System.out.println("* RRULE: " + schedule.getRrule());
169+
System.out.println("* Maintenance Window: " + schedule.getMaintenanceWindow());
170+
}
171+
172+
/* deleting the update schedule we created */
173+
System.out.println("\nDeleting update schedule:");
174+
serverUpdateApi.deleteUpdateSchedule(
175+
projectId, serverId, newSchedule.getId().toString(), region);
176+
System.out.println("* Deleted update schedule successful");
177+
178+
/*
179+
* ///////////////////////////////////////////////////////
180+
* // U P D A T E S //
181+
* ///////////////////////////////////////////////////////
182+
*/
183+
/* trigger manually an update of the server */
184+
System.out.println("\nTrigger a server update:");
185+
Update newUpdate =
186+
serverUpdateApi.createUpdate(
187+
projectId,
188+
serverId,
189+
region,
190+
new CreateUpdatePayload()
191+
.backupBeforeUpdate(false)
192+
.maintenanceWindow(11));
193+
System.out.println("* Update status: " + newUpdate.getStatus());
194+
195+
/* wait for the update to complete */
196+
while (Objects.equals(
197+
serverUpdateApi
198+
.getUpdate(projectId, serverId, newUpdate.getId().toString(), region)
199+
.getStatus(),
200+
"running")) {
201+
System.out.println("Waiting for update to complete ...");
202+
TimeUnit.SECONDS.sleep(5);
203+
}
204+
System.out.println("* Update finished");
205+
206+
/* fetch details of the update */
207+
System.out.println("\nUpdate details:");
208+
Update getUpdate =
209+
serverUpdateApi.getUpdate(
210+
projectId, serverId, newUpdate.getId().toString(), region);
211+
System.out.println("* ID: " + getUpdate.getId());
212+
System.out.println("* Status: " + getUpdate.getStatus());
213+
System.out.println("* Installed updates: " + getUpdate.getInstalledUpdates());
214+
System.out.println("* Failed updates: " + getUpdate.getFailedUpdates());
215+
if (getUpdate.getFailReason() != null && !getUpdate.getFailReason().isEmpty()) {
216+
System.out.println("* Fail reason: " + getUpdate.getFailReason());
217+
}
218+
System.out.println("* Start date: " + getUpdate.getStartDate());
219+
System.out.println("* End date: " + getUpdate.getEndDate());
220+
221+
/* list all executed updated */
222+
System.out.println("\nList updates:");
223+
GetUpdatesListResponse listUpdates =
224+
serverUpdateApi.listUpdates(projectId, serverId, region);
225+
Objects.requireNonNull(listUpdates.getItems());
226+
for (Update update : listUpdates.getItems()) {
227+
System.out.println("*************************");
228+
System.out.println("* ID: " + update.getId());
229+
System.out.println("* Status: " + update.getStatus());
230+
System.out.println("* Installed updates: " + update.getInstalledUpdates());
231+
System.out.println("* Failed updates: " + update.getFailedUpdates());
232+
if (update.getFailReason() != null && !update.getFailReason().isEmpty()) {
233+
System.out.println("* Fail reason: " + update.getFailReason());
234+
}
235+
System.out.println("* Start date: " + update.getStartDate());
236+
System.out.println("* End date: " + update.getEndDate());
237+
}
238+
} catch (ApiException | InterruptedException e) {
239+
throw new RuntimeException(e);
240+
}
241+
}
242+
}

services/serverupdate/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
## v0.1.0
2+
- Initial onboarding of STACKIT Java SDK for Server Update service

services/serverupdate/README.md

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
# STACKIT Java SDK for STACKIT Server Update Management API
2+
3+
- API version: 2.0
4+
5+
API endpoints for Server Update Operations on STACKIT Servers.
6+
7+
8+
This package is part of the STACKIT Java SDK. For additional information, please visit the [GitHub repository](https://github.com/stackitcloud/stackit-sdk-java) of the SDK.
9+
10+
## Installation from Maven Central (recommended)
11+
12+
The release artifacts for this SDK submodule are available on [Maven Central](https://central.sonatype.com/artifact/cloud.stackit.sdk/serverupdate).
13+
14+
### Maven users
15+
16+
Add this dependency to your project's POM:
17+
18+
```xml
19+
<dependency>
20+
<groupId>cloud.stackit.sdk</groupId>
21+
<artifactId>serverupdate</artifactId>
22+
<version><SDK_VERSION></version>
23+
<scope>compile</scope>
24+
</dependency>
25+
```
26+
27+
### Gradle users
28+
29+
Add this dependency to your project's build file:
30+
31+
```groovy
32+
repositories {
33+
mavenCentral()
34+
}
35+
36+
dependencies {
37+
implementation "cloud.stackit.sdk:serverupdate:<SDK_VERSION>"
38+
}
39+
```
40+
41+
## Installation from local build
42+
43+
Building the API client library requires:
44+
1. Java SDK (version 11 to 21 should be supported) installed on your system
45+
46+
To install the API client library to your local Maven repository, simply execute:
47+
48+
```shell
49+
./gradlew services:serverupdate:publishToMavenLocal
50+
```
51+
52+
### Maven users
53+
54+
Add this dependency to your project's POM:
55+
56+
```xml
57+
<dependency>
58+
<groupId>cloud.stackit.sdk</groupId>
59+
<artifactId>serverupdate</artifactId>
60+
<version><SDK_VERSION></version>
61+
<scope>compile</scope>
62+
</dependency>
63+
```
64+
65+
### Gradle users
66+
67+
Add this dependency to your project's build file:
68+
69+
```groovy
70+
repositories {
71+
mavenLocal()
72+
}
73+
74+
dependencies {
75+
implementation "cloud.stackit.sdk:serverupdate:<SDK_VERSION>"
76+
}
77+
```
78+
79+
## Getting Started
80+
81+
See the [serverupdate examples](https://github.com/stackitcloud/stackit-sdk-java/tree/main/examples/serverupdate/src/main/java/cloud/stackit/sdk/serverupdate/examples).
82+
83+
## Recommendation
84+
85+
It's recommended to create an instance of `ApiClient` per thread in a multithreaded environment to avoid any potential issues.

services/serverupdate/VERSION

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
0.1.0

services/serverupdate/build.gradle

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
2+
ext {
3+
jakarta_annotation_version = "1.3.5"
4+
}
5+
6+
dependencies {
7+
implementation "com.google.code.findbugs:jsr305:3.0.2"
8+
implementation 'com.squareup.okhttp3:okhttp:4.12.0'
9+
implementation 'com.squareup.okhttp3:logging-interceptor:4.12.0'
10+
implementation 'com.google.code.gson:gson:2.9.1'
11+
implementation 'io.gsonfire:gson-fire:1.9.0'
12+
implementation 'jakarta.ws.rs:jakarta.ws.rs-api:2.1.6'
13+
implementation 'org.openapitools:jackson-databind-nullable:0.2.6'
14+
implementation group: 'org.apache.commons', name: 'commons-lang3', version: '3.17.0'
15+
implementation "jakarta.annotation:jakarta.annotation-api:$jakarta_annotation_version"
16+
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.10.3'
17+
testImplementation 'org.mockito:mockito-core:3.12.4'
18+
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.10.3'
19+
}

0 commit comments

Comments
 (0)