Skip to content

Commit b4ddaae

Browse files
csvirimetacosm
authored andcommitted
refactor: mysql sample refactor
1 parent 629c12f commit b4ddaae

File tree

3 files changed

+206
-102
lines changed

3 files changed

+206
-102
lines changed

sample-operators/mysql-schema/src/main/java/io/javaoperatorsdk/operator/sample/MySQLSchemaReconciler.java

Lines changed: 60 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -2,30 +2,28 @@
22

33
import java.sql.Connection;
44
import java.sql.DriverManager;
5-
import java.sql.PreparedStatement;
6-
import java.sql.ResultSet;
75
import java.sql.SQLException;
8-
import java.sql.Statement;
96
import java.util.Base64;
107
import java.util.Optional;
118

129
import org.apache.commons.lang3.RandomStringUtils;
1310
import org.slf4j.Logger;
1411
import org.slf4j.LoggerFactory;
1512

13+
import io.fabric8.kubernetes.api.model.OwnerReference;
1614
import io.fabric8.kubernetes.api.model.Secret;
1715
import io.fabric8.kubernetes.api.model.SecretBuilder;
1816
import io.fabric8.kubernetes.client.KubernetesClient;
1917
import io.javaoperatorsdk.operator.api.reconciler.*;
18+
import io.javaoperatorsdk.operator.sample.schema.SchemaService;
2019

2120
import static java.lang.String.format;
2221

2322
@ControllerConfiguration
2423
public class MySQLSchemaReconciler
2524
implements Reconciler<MySQLSchema>, ErrorStatusHandler<MySQLSchema> {
26-
static final String USERNAME_FORMAT = "%s-user";
27-
static final String SECRET_FORMAT = "%s-secret";
28-
25+
public static final String SECRET_FORMAT = "%s-secret";
26+
public static final String USERNAME_FORMAT = "%s-user";
2927
private final Logger log = LoggerFactory.getLogger(getClass());
3028

3129
private final KubernetesClient kubernetesClient;
@@ -40,98 +38,36 @@ public MySQLSchemaReconciler(KubernetesClient kubernetesClient, MySQLDbConfig my
4038
public UpdateControl<MySQLSchema> reconcile(MySQLSchema schema,
4139
Context context) {
4240
try (Connection connection = getConnection()) {
43-
if (!schemaExists(connection, schema.getMetadata().getName())) {
44-
try (Statement statement = connection.createStatement()) {
45-
statement.execute(
46-
format(
47-
"CREATE SCHEMA `%1$s` DEFAULT CHARACTER SET %2$s",
48-
schema.getMetadata().getName(), schema.getSpec().getEncoding()));
49-
}
50-
41+
var dbSchema = SchemaService.getSchema(connection, schema.getMetadata().getName());
42+
if (!dbSchema.isPresent()) {
43+
var schemaName = schema.getMetadata().getName();
5144
String password = RandomStringUtils.randomAlphanumeric(16);
52-
String userName = String.format(USERNAME_FORMAT, schema.getMetadata().getName());
53-
String secretName = String.format(SECRET_FORMAT, schema.getMetadata().getName());
54-
try (Statement statement = connection.createStatement()) {
55-
statement.execute(format("CREATE USER '%1$s' IDENTIFIED BY '%2$s'", userName, password));
56-
}
57-
try (Statement statement = connection.createStatement()) {
58-
statement.execute(
59-
format("GRANT ALL ON `%1$s`.* TO '%2$s'", schema.getMetadata().getName(), userName));
60-
}
61-
Secret credentialsSecret =
62-
new SecretBuilder()
63-
.withNewMetadata()
64-
.withName(secretName)
65-
.endMetadata()
66-
.addToData(
67-
"MYSQL_USERNAME", Base64.getEncoder().encodeToString(userName.getBytes()))
68-
.addToData(
69-
"MYSQL_PASSWORD", Base64.getEncoder().encodeToString(password.getBytes()))
70-
.build();
71-
this.kubernetesClient
72-
.secrets()
73-
.inNamespace(schema.getMetadata().getNamespace())
74-
.create(credentialsSecret);
45+
String secretName = String.format(SECRET_FORMAT, schemaName);
46+
String userName = String.format(USERNAME_FORMAT, schemaName);
7547

76-
SchemaStatus status = new SchemaStatus();
77-
status.setUrl(
78-
format(
79-
"jdbc:mysql://%1$s/%2$s",
80-
System.getenv("MYSQL_HOST"), schema.getMetadata().getName()));
81-
status.setUserName(userName);
82-
status.setSecretName(secretName);
83-
status.setStatus("CREATED");
84-
schema.setStatus(status);
48+
SchemaService.createSchemaAndRelatedUser(connection, schemaName,
49+
schema.getSpec().getEncoding(), userName, password);
50+
createSecret(schema, password, secretName, userName);
51+
updateStatusPojo(schema, secretName, userName);
8552
log.info("Schema {} created - updating CR status", schema.getMetadata().getName());
86-
8753
return UpdateControl.updateStatus(schema);
8854
}
8955
return UpdateControl.noUpdate();
9056
} catch (SQLException e) {
9157
log.error("Error while creating Schema", e);
92-
SchemaStatus status = new SchemaStatus();
93-
status.setUrl(null);
94-
status.setUserName(null);
95-
status.setSecretName(null);
96-
status.setStatus("ERROR: " + e.getMessage());
97-
schema.setStatus(status);
98-
99-
return UpdateControl.updateStatus(schema);
58+
throw new IllegalStateException(e);
10059
}
10160
}
10261

103-
@Override
104-
public Optional<MySQLSchema> updateErrorStatus(MySQLSchema resource, RetryInfo retryInfo,
105-
RuntimeException e) {
106-
107-
return Optional.empty();
108-
}
109-
11062
@Override
11163
public DeleteControl cleanup(MySQLSchema schema, Context context) {
11264
log.info("Execution deleteResource for: {}", schema.getMetadata().getName());
113-
11465
try (Connection connection = getConnection()) {
115-
if (schemaExists(connection, schema.getMetadata().getName())) {
116-
try (Statement statement = connection.createStatement()) {
117-
statement.execute(format("DROP DATABASE `%1$s`", schema.getMetadata().getName()));
118-
}
119-
log.info("Deleted Schema '{}'", schema.getMetadata().getName());
120-
121-
if (schema.getStatus() != null) {
122-
if (userExists(connection, schema.getStatus().getUserName())) {
123-
try (Statement statement = connection.createStatement()) {
124-
statement.execute(format("DROP USER '%1$s'", schema.getStatus().getUserName()));
125-
}
126-
log.info("Deleted User '{}'", schema.getStatus().getUserName());
127-
}
128-
}
129-
130-
this.kubernetesClient
131-
.secrets()
132-
.inNamespace(schema.getMetadata().getNamespace())
133-
.withName(schema.getStatus().getSecretName())
134-
.delete();
66+
var dbSchema = SchemaService.getSchema(connection, schema.getMetadata().getName());
67+
if (dbSchema.isPresent()) {
68+
var userName = schema.getStatus() != null ? schema.getStatus().getUserName() : null;
69+
SchemaService.deleteSchemaAndRelatedUser(connection, schema.getMetadata().getName(),
70+
userName);
13571
} else {
13672
log.info(
13773
"Delete event ignored for schema '{}', real schema doesn't exist",
@@ -144,6 +80,18 @@ public DeleteControl cleanup(MySQLSchema schema, Context context) {
14480
}
14581
}
14682

83+
@Override
84+
public Optional<MySQLSchema> updateErrorStatus(MySQLSchema schema, RetryInfo retryInfo,
85+
RuntimeException e) {
86+
SchemaStatus status = new SchemaStatus();
87+
status.setUrl(null);
88+
status.setUserName(null);
89+
status.setSecretName(null);
90+
status.setStatus("ERROR: " + e.getMessage());
91+
schema.setStatus(status);
92+
return Optional.empty();
93+
}
94+
14795
private Connection getConnection() throws SQLException {
14896
String connectionString =
14997
format("jdbc:mysql://%1$s:%2$s", mysqlDbConfig.getHost(), mysqlDbConfig.getPort());
@@ -153,26 +101,36 @@ private Connection getConnection() throws SQLException {
153101
mysqlDbConfig.getPassword());
154102
}
155103

156-
private boolean schemaExists(Connection connection, String schemaName) throws SQLException {
157-
try (PreparedStatement ps =
158-
connection.prepareStatement(
159-
"SELECT * FROM information_schema.schemata WHERE schema_name = ?")) {
160-
ps.setString(1, schemaName);
161-
try (ResultSet resultSet = ps.executeQuery()) {
162-
// CATALOG_NAME, SCHEMA_NAME, DEFAULT_CHARACTER_SET_NAME, DEFAULT_COLLATION_NAME, SQL_PATH
163-
var exists = resultSet.next();
164-
return exists;
165-
}
166-
}
104+
private void updateStatusPojo(MySQLSchema schema, String secretName, String userName) {
105+
SchemaStatus status = new SchemaStatus();
106+
status.setUrl(
107+
format(
108+
"jdbc:mysql://%1$s/%2$s",
109+
System.getenv("MYSQL_HOST"), schema.getMetadata().getName()));
110+
status.setUserName(userName);
111+
status.setSecretName(secretName);
112+
status.setStatus("CREATED");
113+
schema.setStatus(status);
167114
}
168115

169-
private boolean userExists(Connection connection, String userName) throws SQLException {
170-
try (PreparedStatement ps =
171-
connection.prepareStatement("SELECT User FROM mysql.user WHERE User = ?")) {
172-
ps.setString(1, userName);
173-
try (ResultSet resultSet = ps.executeQuery()) {
174-
return resultSet.first();
175-
}
176-
}
116+
private void createSecret(MySQLSchema schema, String password, String secretName,
117+
String userName) {
118+
Secret credentialsSecret =
119+
new SecretBuilder()
120+
.withNewMetadata()
121+
.withName(secretName)
122+
.withOwnerReferences(new OwnerReference("mysql.sample.javaoperatorsdk/v1",
123+
false, false, "MySQLSchema",
124+
schema.getMetadata().getName(), schema.getMetadata().getUid()))
125+
.endMetadata()
126+
.addToData(
127+
"MYSQL_USERNAME", Base64.getEncoder().encodeToString(userName.getBytes()))
128+
.addToData(
129+
"MYSQL_PASSWORD", Base64.getEncoder().encodeToString(password.getBytes()))
130+
.build();
131+
this.kubernetesClient
132+
.secrets()
133+
.inNamespace(schema.getMetadata().getNamespace())
134+
.create(credentialsSecret);
177135
}
178136
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package io.javaoperatorsdk.operator.sample.schema;
2+
3+
import java.util.Objects;
4+
5+
public class Schema {
6+
7+
private String name;
8+
private String characterSet;
9+
10+
public Schema(String name, String characterSet) {
11+
this.name = name;
12+
this.characterSet = characterSet;
13+
}
14+
15+
public String getName() {
16+
return name;
17+
}
18+
19+
public String getCharacterSet() {
20+
return characterSet;
21+
}
22+
23+
@Override
24+
public boolean equals(Object o) {
25+
if (this == o)
26+
return true;
27+
if (o == null || getClass() != o.getClass())
28+
return false;
29+
Schema schema = (Schema) o;
30+
return Objects.equals(name, schema.name) && Objects.equals(characterSet, schema.characterSet);
31+
}
32+
33+
@Override
34+
public int hashCode() {
35+
return Objects.hash(name, characterSet);
36+
}
37+
}
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
package io.javaoperatorsdk.operator.sample.schema;
2+
3+
import java.sql.*;
4+
import java.util.Optional;
5+
6+
import org.slf4j.Logger;
7+
import org.slf4j.LoggerFactory;
8+
9+
import io.javaoperatorsdk.operator.sample.MySQLDbConfig;
10+
11+
import static java.lang.String.format;
12+
13+
public class SchemaService {
14+
15+
16+
private static final Logger log = LoggerFactory.getLogger(SchemaService.class);
17+
18+
private final MySQLDbConfig mySQLDbConfig;
19+
20+
public SchemaService(MySQLDbConfig mySQLDbConfig) {
21+
this.mySQLDbConfig = mySQLDbConfig;
22+
}
23+
24+
public Optional<Schema> getSchema(String name) {
25+
try (Connection connection = getConnection()) {
26+
return getSchema(connection, name);
27+
} catch (SQLException e) {
28+
throw new IllegalStateException(e);
29+
}
30+
}
31+
32+
public static void createSchemaAndRelatedUser(Connection connection, String schemaName,
33+
String encoding,
34+
String userName,
35+
String password) {
36+
try {
37+
try (Statement statement = connection.createStatement()) {
38+
statement.execute(
39+
format(
40+
"CREATE SCHEMA `%1$s` DEFAULT CHARACTER SET %2$s",
41+
schemaName, encoding));
42+
}
43+
44+
try (Statement statement = connection.createStatement()) {
45+
statement.execute(format("CREATE USER '%1$s' IDENTIFIED BY '%2$s'", userName, password));
46+
}
47+
48+
try (Statement statement = connection.createStatement()) {
49+
statement.execute(
50+
format("GRANT ALL ON `%1$s`.* TO '%2$s'", schemaName, userName));
51+
}
52+
} catch (SQLException e) {
53+
throw new IllegalStateException(e);
54+
}
55+
}
56+
57+
public static void deleteSchemaAndRelatedUser(Connection connection, String schemaName,
58+
String userName) {
59+
try {
60+
try (Statement statement = connection.createStatement()) {
61+
statement.execute(format("DROP DATABASE `%1$s`", schemaName));
62+
}
63+
log.info("Deleted Schema '{}'", schemaName);
64+
if (userName != null) {
65+
try (Statement statement = connection.createStatement()) {
66+
statement.execute(format("DROP USER '%1$s'", userName));
67+
}
68+
log.info("Deleted User '{}'", userName);
69+
}
70+
71+
} catch (SQLException e) {
72+
throw new IllegalStateException(e);
73+
}
74+
}
75+
76+
public static Optional<Schema> getSchema(Connection connection, String schemaName) {
77+
try (PreparedStatement ps =
78+
connection.prepareStatement(
79+
"SELECT * FROM information_schema.schemata WHERE schema_name = ?")) {
80+
ps.setString(1, schemaName);
81+
try (ResultSet resultSet = ps.executeQuery()) {
82+
// CATALOG_NAME, SCHEMA_NAME, DEFAULT_CHARACTER_SET_NAME, DEFAULT_COLLATION_NAME, SQL_PATH
83+
var exists = resultSet.next();
84+
if (!exists) {
85+
return Optional.empty();
86+
} else {
87+
return Optional.of(new Schema(resultSet.getString("SCHEMA_NAME"),
88+
resultSet.getString("DEFAULT_CHARACTER_SET_NAME")));
89+
}
90+
}
91+
} catch (SQLException e) {
92+
throw new IllegalStateException(e);
93+
}
94+
}
95+
96+
private Connection getConnection() {
97+
try {
98+
String connectionString =
99+
format("jdbc:mysql://%1$s:%2$s", mySQLDbConfig.getHost(), mySQLDbConfig.getPort());
100+
101+
log.debug("Connecting to '{}' with user '{}'", connectionString, mySQLDbConfig.getUser());
102+
return DriverManager.getConnection(connectionString, mySQLDbConfig.getUser(),
103+
mySQLDbConfig.getPassword());
104+
} catch (SQLException e) {
105+
throw new IllegalStateException(e);
106+
}
107+
}
108+
109+
}

0 commit comments

Comments
 (0)