「✨」 feat: Finished wordpress/php container
This commit is contained in:
13
Makefile
13
Makefile
@ -18,13 +18,13 @@ build-cms:
|
|||||||
docker build -f $(DOCKERFILE_CMS) -t $(CMS_NAME) $(DOCKER_CONTEXT)
|
docker build -f $(DOCKERFILE_CMS) -t $(CMS_NAME) $(DOCKER_CONTEXT)
|
||||||
|
|
||||||
start-db:
|
start-db:
|
||||||
docker compose -f $(DOCKER_CONTEXT)/docker-compose.yml up db --build
|
docker compose -f $(DOCKER_CONTEXT)docker-compose.yml up db --build
|
||||||
|
|
||||||
start-nginx:
|
start-nginx:
|
||||||
docker compose -f $(DOCKER_CONTEXT)/docker-compose.yml up nginx --build
|
docker compose -f $(DOCKER_CONTEXT)docker-compose.yml up nginx --build
|
||||||
|
|
||||||
start-wordp:
|
start-wordp:
|
||||||
docker compose -f $(DOCKER_CONTEXT)/docker-compose.yml up wordpress-php --build
|
docker compose -f $(DOCKER_CONTEXT)docker-compose.yml up wordpress-php --build
|
||||||
|
|
||||||
clean-db:
|
clean-db:
|
||||||
docker stop inception-db
|
docker stop inception-db
|
||||||
@ -32,8 +32,15 @@ clean-db:
|
|||||||
docker volume rm inception_wp-db
|
docker volume rm inception_wp-db
|
||||||
docker image rm inception-db
|
docker image rm inception-db
|
||||||
|
|
||||||
|
clean-wordp:
|
||||||
|
docker stop inception-wordp-php
|
||||||
|
docker container rm inception-wordp-php
|
||||||
|
docker volume rm inception_wp-site
|
||||||
|
docker image rm inception-wordpress-php
|
||||||
|
|
||||||
clean-nginx:
|
clean-nginx:
|
||||||
docker stop inception-nginx
|
docker stop inception-nginx
|
||||||
docker container rm inception-nginx
|
docker container rm inception-nginx
|
||||||
|
docker image rm inception-nginx
|
||||||
|
|
||||||
.PHONY: cms-build db-build websrv-build clean-db clean-nginx
|
.PHONY: cms-build db-build websrv-build clean-db clean-nginx
|
||||||
|
@ -149,7 +149,6 @@ func configureMariaDB(rootPassword, user, password, database string) {
|
|||||||
func main() {
|
func main() {
|
||||||
args := os.Args
|
args := os.Args
|
||||||
|
|
||||||
|
|
||||||
if args[1] == "mariadbd" || args[1] == "mysqld" {
|
if args[1] == "mariadbd" || args[1] == "mysqld" {
|
||||||
_log.Log("note", "Entrypoint script for MariaDB Server started")
|
_log.Log("note", "Entrypoint script for MariaDB Server started")
|
||||||
|
|
||||||
|
82
srcs/cmd/wordpress/entrypoint/entrypoint.go
Normal file
82
srcs/cmd/wordpress/entrypoint/entrypoint.go
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
|
||||||
|
"git.keyzox.me/42_adjoly/inception/internal/env"
|
||||||
|
"git.keyzox.me/42_adjoly/inception/internal/log"
|
||||||
|
"git.keyzox.me/42_adjoly/inception/internal/pass"
|
||||||
|
)
|
||||||
|
|
||||||
|
func makeFpmConf() {
|
||||||
|
val, is := os.LookupEnv("PHP_NOT_CONFIGURE")
|
||||||
|
_, err := os.ReadFile("/www-docker.conf")
|
||||||
|
|
||||||
|
if (is == true && val == "true") {
|
||||||
|
_log.Log("note", "PHP-FPM - Not configuring (PHP-CONFIGURE set to true)")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if errors.Is(err, os.ErrNotExist) {
|
||||||
|
_log.Log("note", "PHP-FPM - already configured, skipping")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
_log.Log("note", "PHP-FPM - Configuring...")
|
||||||
|
v, is := os.LookupEnv("PHP_PORT")
|
||||||
|
content, err := os.ReadFile("/www-docker.conf")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
if !is {
|
||||||
|
v = "9000"
|
||||||
|
}
|
||||||
|
res := bytes.Replace([]byte(content), []byte("$PHP_PORT"), []byte(v), -1)
|
||||||
|
|
||||||
|
if err := os.WriteFile("/etc/php84/php-fpm.d/www.conf", res, 0660); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
os.Remove("/www-docker.conf")
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
args := os.Args
|
||||||
|
|
||||||
|
if args[1] == "php-fpm84" {
|
||||||
|
_log.Log("note", "Entrypoint script for Wordpress-PHP-FPM Server started")
|
||||||
|
|
||||||
|
makeFpmConf()
|
||||||
|
|
||||||
|
_, err := os.ReadFile("/usr/src/wordpress/wp-config.php")
|
||||||
|
|
||||||
|
if err != nil && env.IsEnvSet("WORDPRESS_") {
|
||||||
|
content, err := os.ReadFile("/usr/src/wordpress/wp-config-docker.php")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
res := bytes.Replace([]byte(content), []byte("put your unique phrase here"), []byte(pass.GenStrPass(32)), -1)
|
||||||
|
if err := os.WriteFile("/usr/src/wordpress/wp-config.php", res, 0660); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
cmd := exec.Command("chown", "www-data:www-data", "/usr/src/wordpress/wp-config.php")
|
||||||
|
cmd.Stdout = os.Stdout
|
||||||
|
cmd.Stderr = os.Stderr
|
||||||
|
if err := cmd.Run(); err == nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_log.Log("note", "Starting container")
|
||||||
|
cmd := exec.Command(args[1], args[2:]...)
|
||||||
|
cmd.Stdout = os.Stdout
|
||||||
|
cmd.Stderr = os.Stderr
|
||||||
|
cmd.Stdin = os.Stdin
|
||||||
|
if err := cmd.Run(); err != nil {
|
||||||
|
fmt.Printf("Error running MariaDB: %v\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
@ -1,9 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
|
|
||||||
}
|
|
19
srcs/configs/nginx/ff.conf
Normal file
19
srcs/configs/nginx/ff.conf
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
|
||||||
|
server_name adjoly.42.fr;
|
||||||
|
root /var/www/html;
|
||||||
|
|
||||||
|
index index.php index.html index.htm;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
try_files $uri $uri/ /index.php?$args;
|
||||||
|
}
|
||||||
|
|
||||||
|
location ~ \.php$ {
|
||||||
|
include fastcgi_params;
|
||||||
|
fastcgi_pass php-fpm:9000;
|
||||||
|
fastcgi_index index.php;
|
||||||
|
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||||
|
}
|
||||||
|
}
|
@ -31,17 +31,16 @@ services:
|
|||||||
container_name: inception-wordp-php
|
container_name: inception-wordp-php
|
||||||
build:
|
build:
|
||||||
context: .
|
context: .
|
||||||
dockerfile: docker/wordpress/dockerfile
|
dockerfile: docker/wordpress/Dockerfile
|
||||||
networks:
|
networks:
|
||||||
- inception
|
- inception
|
||||||
environment:
|
environment:
|
||||||
- PHP_MEMORY_LIMIT="512M"
|
- PHP_MEMORY_LIMIT="512M"
|
||||||
- PHP_MAX_UPLOAD="50M"
|
- PHP_MAX_UPLOAD="50M"
|
||||||
|
- PHP_PORT=9000
|
||||||
- TZ=Europe/Paris
|
- TZ=Europe/Paris
|
||||||
volumes:
|
volumes:
|
||||||
- wp-site:/var/www/html
|
- wp-site:/var/www/html
|
||||||
depends_on:
|
|
||||||
- db
|
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
|
||||||
db:
|
db:
|
||||||
|
3
srcs/docker/alpine/Dockerfile
Normal file
3
srcs/docker/alpine/Dockerfile
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
FROM scratch
|
||||||
|
ADD alpine-minirootfs-3.21.2-x86_64.tar.gz /
|
||||||
|
CMD ["/bin/sh"]
|
@ -1,4 +1,5 @@
|
|||||||
FROM alpine:3.21
|
FROM scratch
|
||||||
|
ADD docker/alpine/alpine-minirootfs-3.21.2-x86_64.tar.gz /
|
||||||
|
|
||||||
LABEL version="0.1"
|
LABEL version="0.1"
|
||||||
LABEL maintainer="KeyZox"
|
LABEL maintainer="KeyZox"
|
||||||
|
@ -1,25 +1,49 @@
|
|||||||
FROM alpine:3.21
|
FROM scratch
|
||||||
|
ADD docker/alpine/alpine-minirootfs-3.21.2-x86_64.tar.gz /
|
||||||
|
|
||||||
LABEL version="0.1"
|
LABEL version="0.1"
|
||||||
LABEL maintainer="KeyZox"
|
LABEL maintainer="KeyZox"
|
||||||
|
|
||||||
RUN set -x \
|
RUN set -x \
|
||||||
&& adduser -u 82 -D -S -G www-data www-data \
|
&& adduser -u 82 -D -S -G www-data www-data
|
||||||
&& apk add --no-cache php84-fpm wget
|
|
||||||
|
|
||||||
VOLUME /var/www/html
|
COPY go.mod /build/go.mod
|
||||||
|
COPY cmd /build/cmd
|
||||||
|
COPY internal /build/internal
|
||||||
|
COPY docker/wordpress/www-docker.conf /www-docker.conf
|
||||||
|
|
||||||
WORKDIR /var/www/html
|
RUN apk add --no-cache go curl php84-fpm tzdata fcgi \
|
||||||
RUN wget https://wordpress.org/wordpress-6.7.1.tar.gz \
|
&& cd /build \
|
||||||
&& tar -xzvf wordpress-6.7.1.tar.gz \
|
&& go build git.keyzox.me/42_adjoly/inception/cmd/wordpress/entrypoint \
|
||||||
&& rm workpress-6.7.1.tar.gz
|
&& cp /build/entrypoint /docker-entrypoint \
|
||||||
|
&& chmod +x /docker-entrypoint \
|
||||||
|
&& apk del go \
|
||||||
|
&& rm -Rf /build \
|
||||||
|
&& mkdir -p /usr/src/wordpress
|
||||||
|
|
||||||
#COPY docker-entrypoint.sh /
|
VOLUME /usr/src/wordpress
|
||||||
#RUN [ "chmod", "+x", "/docker-entrypoint.sh" ]
|
|
||||||
|
|
||||||
#ENTRYPOINT [ "/docker-entrypoint.sh" ]
|
WORKDIR /usr/src
|
||||||
WORKDIR /var/www/html
|
|
||||||
|
RUN version='6.7.1' \
|
||||||
|
&& curl -o wordpress.tar.gz -fL "https://wordpress.org/wordpress-$version.tar.gz" \
|
||||||
|
&& apk del curl \
|
||||||
|
&& rm -rf /var/cache/apk/* \
|
||||||
|
&& tar -xzvf wordpress.tar.gz \
|
||||||
|
&& rm wordpress.tar.gz \
|
||||||
|
&& chown -R www-data:www-data /usr/src/wordpress \
|
||||||
|
&& mkdir wp-content \
|
||||||
|
&& for dir in /usr/src/wordpress/wp-content/*/ cache; do \
|
||||||
|
dir="$(basename "${dir%/}")"; \
|
||||||
|
mkdir "wp-content/$dir"; \
|
||||||
|
done \
|
||||||
|
&& chown -R www-data:www-data wp-content \
|
||||||
|
&& chmod -R 1777 wp-content
|
||||||
|
|
||||||
|
ENTRYPOINT [ "/docker-entrypoint" ]
|
||||||
|
WORKDIR /usr/src/wordpress
|
||||||
STOPSIGNAL SIGQUIT
|
STOPSIGNAL SIGQUIT
|
||||||
|
|
||||||
EXPOSE 9000
|
EXPOSE 9000
|
||||||
CMD [ "php-fpm84", "-F" ]
|
CMD [ "php-fpm84", "-F" ]
|
||||||
|
HEALTHCHECK --interval=30s --timeout=10s --retries=3 CMD cgi-fcgi -bind -connect 127.0.0.1:9000 || exit 1
|
||||||
|
139
srcs/docker/wordpress/wp-config-docker.php
Normal file
139
srcs/docker/wordpress/wp-config-docker.php
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* The base configuration for WordPress
|
||||||
|
*
|
||||||
|
* The wp-config.php creation script uses this file during the installation.
|
||||||
|
* You don't have to use the website, you can copy this file to "wp-config.php"
|
||||||
|
* and fill in the values.
|
||||||
|
*
|
||||||
|
* This file contains the following configurations:
|
||||||
|
*
|
||||||
|
* * Database settings
|
||||||
|
* * Secret keys
|
||||||
|
* * Database table prefix
|
||||||
|
* * ABSPATH
|
||||||
|
*
|
||||||
|
* This has been slightly modified (to read environment variables) for use in Docker.
|
||||||
|
*
|
||||||
|
* @link https://developer.wordpress.org/advanced-administration/wordpress/wp-config/
|
||||||
|
*
|
||||||
|
* @package WordPress
|
||||||
|
*/
|
||||||
|
|
||||||
|
// IMPORTANT: this file needs to stay in-sync with https://github.com/WordPress/WordPress/blob/master/wp-config-sample.php
|
||||||
|
// (it gets parsed by the upstream wizard in https://github.com/WordPress/WordPress/blob/f27cb65e1ef25d11b535695a660e7282b98eb742/wp-admin/setup-config.php#L356-L392)
|
||||||
|
|
||||||
|
// a helper function to lookup "env_FILE", "env", then fallback
|
||||||
|
if (!function_exists('getenv_docker')) {
|
||||||
|
// https://github.com/docker-library/wordpress/issues/588 (WP-CLI will load this file 2x)
|
||||||
|
function getenv_docker($env, $default) {
|
||||||
|
if ($fileEnv = getenv($env . '_FILE')) {
|
||||||
|
return rtrim(file_get_contents($fileEnv), "\r\n");
|
||||||
|
}
|
||||||
|
else if (($val = getenv($env)) !== false) {
|
||||||
|
return $val;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return $default;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ** Database settings - You can get this info from your web host ** //
|
||||||
|
/** The name of the database for WordPress */
|
||||||
|
define( 'DB_NAME', getenv_docker('WORDPRESS_DB_NAME', 'wordpress') );
|
||||||
|
|
||||||
|
/** Database username */
|
||||||
|
define( 'DB_USER', getenv_docker('WORDPRESS_DB_USER', 'example username') );
|
||||||
|
|
||||||
|
/** Database password */
|
||||||
|
define( 'DB_PASSWORD', getenv_docker('WORDPRESS_DB_PASSWORD', 'example password') );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Docker image fallback values above are sourced from the official WordPress installation wizard:
|
||||||
|
* https://github.com/WordPress/WordPress/blob/1356f6537220ffdc32b9dad2a6cdbe2d010b7a88/wp-admin/setup-config.php#L224-L238
|
||||||
|
* (However, using "example username" and "example password" in your database is strongly discouraged. Please use strong, random credentials!)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** Database hostname */
|
||||||
|
define( 'DB_HOST', getenv_docker('WORDPRESS_DB_HOST', 'mysql') );
|
||||||
|
|
||||||
|
/** Database charset to use in creating database tables. */
|
||||||
|
define( 'DB_CHARSET', getenv_docker('WORDPRESS_DB_CHARSET', 'utf8') );
|
||||||
|
|
||||||
|
/** The database collate type. Don't change this if in doubt. */
|
||||||
|
define( 'DB_COLLATE', getenv_docker('WORDPRESS_DB_COLLATE', '') );
|
||||||
|
|
||||||
|
/**#@+
|
||||||
|
* Authentication unique keys and salts.
|
||||||
|
*
|
||||||
|
* Change these to different unique phrases! You can generate these using
|
||||||
|
* the {@link https://api.wordpress.org/secret-key/1.1/salt/ WordPress.org secret-key service}.
|
||||||
|
*
|
||||||
|
* You can change these at any point in time to invalidate all existing cookies.
|
||||||
|
* This will force all users to have to log in again.
|
||||||
|
*
|
||||||
|
* @since 2.6.0
|
||||||
|
*/
|
||||||
|
define( 'AUTH_KEY', getenv_docker('WORDPRESS_AUTH_KEY', 'put your unique phrase here') );
|
||||||
|
define( 'SECURE_AUTH_KEY', getenv_docker('WORDPRESS_SECURE_AUTH_KEY', 'put your unique phrase here') );
|
||||||
|
define( 'LOGGED_IN_KEY', getenv_docker('WORDPRESS_LOGGED_IN_KEY', 'put your unique phrase here') );
|
||||||
|
define( 'NONCE_KEY', getenv_docker('WORDPRESS_NONCE_KEY', 'put your unique phrase here') );
|
||||||
|
define( 'AUTH_SALT', getenv_docker('WORDPRESS_AUTH_SALT', 'put your unique phrase here') );
|
||||||
|
define( 'SECURE_AUTH_SALT', getenv_docker('WORDPRESS_SECURE_AUTH_SALT', 'put your unique phrase here') );
|
||||||
|
define( 'LOGGED_IN_SALT', getenv_docker('WORDPRESS_LOGGED_IN_SALT', 'put your unique phrase here') );
|
||||||
|
define( 'NONCE_SALT', getenv_docker('WORDPRESS_NONCE_SALT', 'put your unique phrase here') );
|
||||||
|
// (See also https://wordpress.stackexchange.com/a/152905/199287)
|
||||||
|
|
||||||
|
/**#@-*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* WordPress database table prefix.
|
||||||
|
*
|
||||||
|
* You can have multiple installations in one database if you give each
|
||||||
|
* a unique prefix. Only numbers, letters, and underscores please!
|
||||||
|
*
|
||||||
|
* At the installation time, database tables are created with the specified prefix.
|
||||||
|
* Changing this value after WordPress is installed will make your site think
|
||||||
|
* it has not been installed.
|
||||||
|
*
|
||||||
|
* @link https://developer.wordpress.org/advanced-administration/wordpress/wp-config/#table-prefix
|
||||||
|
*/
|
||||||
|
$table_prefix = getenv_docker('WORDPRESS_TABLE_PREFIX', 'wp_');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For developers: WordPress debugging mode.
|
||||||
|
*
|
||||||
|
* Change this to true to enable the display of notices during development.
|
||||||
|
* It is strongly recommended that plugin and theme developers use WP_DEBUG
|
||||||
|
* in their development environments.
|
||||||
|
*
|
||||||
|
* For information on other constants that can be used for debugging,
|
||||||
|
* visit the documentation.
|
||||||
|
*
|
||||||
|
* @link https://developer.wordpress.org/advanced-administration/debug/debug-wordpress/
|
||||||
|
*/
|
||||||
|
define( 'WP_DEBUG', !!getenv_docker('WORDPRESS_DEBUG', '') );
|
||||||
|
|
||||||
|
/* Add any custom values between this line and the "stop editing" line. */
|
||||||
|
|
||||||
|
// If we're behind a proxy server and using HTTPS, we need to alert WordPress of that fact
|
||||||
|
// see also https://wordpress.org/support/article/administration-over-ssl/#using-a-reverse-proxy
|
||||||
|
if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && strpos($_SERVER['HTTP_X_FORWARDED_PROTO'], 'https') !== false) {
|
||||||
|
$_SERVER['HTTPS'] = 'on';
|
||||||
|
}
|
||||||
|
// (we include this by default because reverse proxying is extremely common in container environments)
|
||||||
|
|
||||||
|
if ($configExtra = getenv_docker('WORDPRESS_CONFIG_EXTRA', '')) {
|
||||||
|
eval($configExtra);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* That's all, stop editing! Happy publishing. */
|
||||||
|
|
||||||
|
/** Absolute path to the WordPress directory. */
|
||||||
|
if ( ! defined( 'ABSPATH' ) ) {
|
||||||
|
define( 'ABSPATH', __DIR__ . '/' );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Sets up WordPress vars and included files. */
|
||||||
|
require_once ABSPATH . 'wp-settings.php';
|
13
srcs/docker/wordpress/www-docker.conf
Normal file
13
srcs/docker/wordpress/www-docker.conf
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
[www]
|
||||||
|
|
||||||
|
user = www-data
|
||||||
|
group = www-data
|
||||||
|
listen = 0.0.0.0:$PHP_PORT
|
||||||
|
listen.owner = www-data
|
||||||
|
listen.group = www-data
|
||||||
|
pm = dynamic
|
||||||
|
pm.max_children = 10
|
||||||
|
pm.start_servers = 2
|
||||||
|
pm.min_spare_servers = 1
|
||||||
|
pm.max_spare_servers = 3
|
||||||
|
clear_env = no
|
23
srcs/internal/env/env_set.go
vendored
Normal file
23
srcs/internal/env/env_set.go
vendored
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
package env
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"regexp"
|
||||||
|
)
|
||||||
|
|
||||||
|
func IsEnvSet(what string) bool {
|
||||||
|
env := os.Environ()
|
||||||
|
|
||||||
|
reg, err := regexp.Compile("^" + what)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, v := range env {
|
||||||
|
if reg.MatchString(v) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
19
srcs/internal/pass/genStr.go
Normal file
19
srcs/internal/pass/genStr.go
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
package pass
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math/rand"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GenStrPass(n int) string {
|
||||||
|
var characters = []rune("abcdef0123456789")
|
||||||
|
var sb strings.Builder
|
||||||
|
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
randomIndex := rand.Intn(len(characters))
|
||||||
|
randomChar := characters[randomIndex]
|
||||||
|
sb.WriteRune(randomChar)
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.String()
|
||||||
|
}
|
Reference in New Issue
Block a user