pub struct Gitea { /* private fields */ }
gitea
only.Expand description
Module to work with Gitea container.
Starts an instance of Gitea
, fully functional git server, with reasonable defaults
and possibility to tune some configuration options.
From the Gitea
documentation:
Gitea is a painless, self-hosted, all-in-one software development service.
It includes Git hosting, code review, team collaboration, package registry,
and CI/CD. It is similar to GitHub, Bitbucket and GitLab.
By default, Gitea
server container starts with the following config:
- accepts SSH (Git) protocol requests on port GITEA_SSH_PORT;
- accepts HTTP requests on port GITEA_HTTP_PORT;
- has a single configured user with admin privileges, with pre-defined username and password;
- configured git server hostname is
localhost
; this is a name whichGitea
uses in the links to repositories; - no repositories are created.
Additionally to defaults, it’s possible to:
- use HTTPS instead of HTTP with auto-generated self-signed certificate or provide your own certificate;
- redirect HTTP calls to HTTPS listener, if HTTPS is enabled;
- change git server hostname, which is used in various links to repos or web-server;
- provide your own admin user credentials as well as its SSH public key to authorize git calls;
- create any number of public or private repositories with provided names during server startup;
- execute set of
gitea admin ...
commands during server startup to customize configuration; - add environment variables
§Examples
- Minimalistic server
use testcontainers::{runners::AsyncRunner, ImageExt};
use testcontainers_modules::gitea::{self, Gitea, GiteaRepo};
#[tokio::test]
async fn default_gitea_server() {
// Run default container
let gitea = Gitea::default().start().await.unwrap();
let port = gitea
.get_host_port_ipv4(gitea::GITEA_HTTP_PORT)
.await
.unwrap();
let url = format!(
"http://localhost:{port}/api/v1/users/{}",
gitea::GITEA_DEFAULT_ADMIN_USERNAME
);
// Anonymous query Gitea API for user info
let response = reqwest::Client::new().get(url).send().await.unwrap();
assert_eq!(response.status(), 200);
}
- Customized server
use testcontainers::{runners::AsyncRunner, ImageExt};
use testcontainers_modules::gitea::{self, Gitea, GiteaRepo};
#[tokio::test]
async fn gitea_server_with_custom_config() {
// Start server container with:
// - custom admin credentials
// - two repos: public and private
// - TLS enabled
// - port mapping for HTTP and SSH
// - custom git hostname
let gitea = Gitea::default()
.with_git_hostname("gitea.example.com")
.with_admin_account("custom-admin", "password", None)
.with_repo(GiteaRepo::Public("public-test-repo".to_string()))
.with_repo(GiteaRepo::Private("private-test-repo".to_string()))
.with_tls(true)
.with_mapped_port(443, gitea::GITEA_HTTP_PORT)
.with_mapped_port(22, gitea::GITEA_SSH_PORT)
.start()
.await
.unwrap();
// Obtain auto-created root CA certificate
let ca = gitea.image().tls_ca().unwrap();
let ca = reqwest::Certificate::from_pem(ca.as_bytes()).unwrap();
// Attach custom CA to the client
let client = reqwest::ClientBuilder::new()
.add_root_certificate(ca)
.build()
.unwrap();
// Get list of repos of particular user.
// This query should be authorized.
let response = client
.get("https://localhost/api/v1/user/repos")
.basic_auth("custom-admin", Some("password"))
.header("Host", "gitea.example.com")
.send()
.await
.unwrap();
assert_eq!(response.status(), 200);
let repos = response.json::<serde_json::Value>().await.unwrap();
assert_eq!(repos.as_array().unwrap().len(), 2);
}
Implementations§
Source§impl Gitea
impl Gitea
Sourcepub fn with_admin_account(
self,
username: impl Into<String>,
password: impl Into<String>,
public_key: Option<String>,
) -> Self
pub fn with_admin_account( self, username: impl Into<String>, password: impl Into<String>, public_key: Option<String>, ) -> Self
Change admin user credential to the custom provided username
and password
instead of using defaults.
If public_key
value is provided, it will be added to the admin account.
§Example
#[tokio::test]
async fn test() {
const PUB_KEY: &str = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJRE5a67/cTbR6DpWqzBl6BTY0LE0Hg715ZI/FMK7iCH";
let gitea = Gitea::default()
.with_admin_account("git-admin", "nKz4SC7bkz4KSXbQ", Some(PUB_KEY))
.start()
.await
.unwrap();
// ...
}
Sourcepub fn with_git_hostname(self, hostname: impl Into<String>) -> Self
pub fn with_git_hostname(self, hostname: impl Into<String>) -> Self
Set git server hostname instead of the default localhost
.
This is not a containers’ hostname, but the name which git server uses in various links like repo URLs.
Sourcepub fn with_repo(self, repo: GiteaRepo) -> Self
pub fn with_repo(self, repo: GiteaRepo) -> Self
Create a repository during startup.
It’s possible to call this method more than once to create several repositories.
§Example
#[tokio::test]
async fn test() {
let gitea = Gitea::default()
.with_repo(GiteaRepo::Public("example-public-repo"))
.with_repo(GiteaRepo::Private("example-private-repo"))
.start()
.await
.unwrap();
// ...
}
Sourcepub fn with_admin_command(
self,
command: impl IntoIterator<Item = impl Into<String>>,
) -> Self
pub fn with_admin_command( self, command: impl IntoIterator<Item = impl Into<String>>, ) -> Self
Add gitea admin ...
command with parameters to execute after server startup.
This method is useful, for example, to create additional users or to do other admin stuff.
It’s possible to call this method more than once to add several consecutive commands.
§Example
#[tokio::test]
async fn test() {
let cmd = vec![
"user",
"create",
"--username",
"test-user",
"--password",
"test-password",
"--email",
"test@localhost",
"--must-change-password=true",
]
.into_iter()
.map(String::from)
.collect::<Vec<String>>();
let gitea = Gitea::default()
.with_admin_command(command)
.start()
.await
.unwrap();
// ...
}
Sourcepub fn with_tls(self, enabled: bool) -> Self
pub fn with_tls(self, enabled: bool) -> Self
Gitea
web server will start with HTTPS listener (with auto-generated certificate),
instead of the default HTTP.
If enabled
is true,
web server will be started with TLS listener with auto-generated self-signed certificate.
If Root CA certificate is needed to ensure fully protected communications,
it can be obtained by Gitea::tls_ca() method call.
Note: If TLS is enabled, additional HTTP listener will be started on port GITEA_HTTP_REDIRECT_PORT to redirect all HTTP calls to the HTTPS listener.
Sourcepub fn with_tls_certs(
self,
cert: impl Into<String>,
key: impl Into<String>,
) -> Self
pub fn with_tls_certs( self, cert: impl Into<String>, key: impl Into<String>, ) -> Self
Gitea
web server will start with HTTPS listener (with provided certificate), instead of the default HTTP.
cert
and key
are strings with PEM encoded certificate and its key.
This method is similar to Gitea::with_tls() but use provided certificate instead of generating self-signed one.
Note: If TLS is enabled, additional HTTP listener will be started on port GITEA_HTTP_REDIRECT_PORT to redirect all HTTP calls to the HTTPS listener.
Sourcepub fn tls_ca(&self) -> Option<&str>
pub fn tls_ca(&self) -> Option<&str>
Return PEM encoded Root CA certificate of the Gitea servers’ certificate issuer.
If TLS has been enabled using Gitea::with_tls_certs() method (with auto-generated self-signed certificate),
then this method returns Some
option with issuer root CA certificate to verify servers’ certificate
and ensure fully protected communications.
If TLS isn’t enabled or TLS is enabled with external certificate,
provided using Gitea::with_tls_certs method,
this method returns None
since there is no known CA certificate.
Trait Implementations§
Source§impl Default for Gitea
impl Default for Gitea
Source§fn default() -> Self
fn default() -> Self
Returns default Gitea server setup with the following defaults:
- hostname is
localhost
; - admin account username from GITEA_DEFAULT_ADMIN_USERNAME;
- admin account password from GITEA_DEFAULT_ADMIN_PASSWORD;
- without admins’ account SSH public key;
- without additional startup admin commands;
- without TLS (SSH and HTTP protocols only);
- without repositories.
Source§impl Image for Gitea
impl Image for Gitea
Source§fn tag(&self) -> &str
fn tag(&self) -> &str
Source§fn ready_conditions(&self) -> Vec<WaitFor>
fn ready_conditions(&self) -> Vec<WaitFor>
Source§fn copy_to_sources(&self) -> impl IntoIterator<Item = &CopyToContainer>
fn copy_to_sources(&self) -> impl IntoIterator<Item = &CopyToContainer>
Source§fn expose_ports(&self) -> &[ContainerPort]
fn expose_ports(&self) -> &[ContainerPort]
Source§fn exec_after_start(
&self,
_cs: ContainerState,
) -> Result<Vec<ExecCommand>, TestcontainersError>
fn exec_after_start( &self, _cs: ContainerState, ) -> Result<Vec<ExecCommand>, TestcontainersError>
Source§fn env_vars(
&self,
) -> impl IntoIterator<Item = (impl Into<Cow<'_, str>>, impl Into<Cow<'_, str>>)>
fn env_vars( &self, ) -> impl IntoIterator<Item = (impl Into<Cow<'_, str>>, impl Into<Cow<'_, str>>)>
Source§fn mounts(&self) -> impl IntoIterator<Item = &Mount>
fn mounts(&self) -> impl IntoIterator<Item = &Mount>
Source§fn entrypoint(&self) -> Option<&str>
fn entrypoint(&self) -> Option<&str>
Source§fn cmd(&self) -> impl IntoIterator<Item = impl Into<Cow<'_, str>>>
fn cmd(&self) -> impl IntoIterator<Item = impl Into<Cow<'_, str>>>
CMD
this image needs to be created with.Source§fn exec_before_ready(
&self,
cs: ContainerState,
) -> Result<Vec<ExecCommand>, TestcontainersError>
fn exec_before_ready( &self, cs: ContainerState, ) -> Result<Vec<ExecCommand>, TestcontainersError>
Auto Trait Implementations§
impl Freeze for Gitea
impl RefUnwindSafe for Gitea
impl Send for Gitea
impl Sync for Gitea
impl Unpin for Gitea
impl UnwindSafe for Gitea
Blanket Implementations§
Source§impl<T, I> AsyncRunner<I> for T
impl<T, I> AsyncRunner<I> for T
Source§fn start<'async_trait>(
self,
) -> Pin<Box<dyn Future<Output = Result<ContainerAsync<I>, TestcontainersError>> + Send + 'async_trait>>where
T: 'async_trait,
fn start<'async_trait>(
self,
) -> Pin<Box<dyn Future<Output = Result<ContainerAsync<I>, TestcontainersError>> + Send + 'async_trait>>where
T: 'async_trait,
ContainerAsync
.Source§fn pull_image<'async_trait>(
self,
) -> Pin<Box<dyn Future<Output = Result<ContainerRequest<I>, TestcontainersError>> + Send + 'async_trait>>where
T: 'async_trait,
fn pull_image<'async_trait>(
self,
) -> Pin<Box<dyn Future<Output = Result<ContainerRequest<I>, TestcontainersError>> + Send + 'async_trait>>where
T: 'async_trait,
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<RI, I> ImageExt<I> for RI
impl<RI, I> ImageExt<I> for RI
Source§fn with_cmd(
self,
cmd: impl IntoIterator<Item = impl Into<String>>,
) -> ContainerRequest<I>
fn with_cmd( self, cmd: impl IntoIterator<Item = impl Into<String>>, ) -> ContainerRequest<I>
Source§fn with_name(self, name: impl Into<String>) -> ContainerRequest<I>
fn with_name(self, name: impl Into<String>) -> ContainerRequest<I>
{domain}/{owner}/{image}
).
Can be used to specify a custom registry or owner.Source§fn with_tag(self, tag: impl Into<String>) -> ContainerRequest<I>
fn with_tag(self, tag: impl Into<String>) -> ContainerRequest<I>
Source§fn with_container_name(self, name: impl Into<String>) -> ContainerRequest<I>
fn with_container_name(self, name: impl Into<String>) -> ContainerRequest<I>
Source§fn with_network(self, network: impl Into<String>) -> ContainerRequest<I>
fn with_network(self, network: impl Into<String>) -> ContainerRequest<I>
Source§fn with_label(
self,
key: impl Into<String>,
value: impl Into<String>,
) -> ContainerRequest<I>
fn with_label( self, key: impl Into<String>, value: impl Into<String>, ) -> ContainerRequest<I>
Source§fn with_labels(
self,
labels: impl IntoIterator<Item = (impl Into<String>, impl Into<String>)>,
) -> ContainerRequest<I>
fn with_labels( self, labels: impl IntoIterator<Item = (impl Into<String>, impl Into<String>)>, ) -> ContainerRequest<I>
Source§fn with_env_var(
self,
name: impl Into<String>,
value: impl Into<String>,
) -> ContainerRequest<I>
fn with_env_var( self, name: impl Into<String>, value: impl Into<String>, ) -> ContainerRequest<I>
Source§fn with_host(
self,
key: impl Into<String>,
value: impl Into<Host>,
) -> ContainerRequest<I>
fn with_host( self, key: impl Into<String>, value: impl Into<Host>, ) -> ContainerRequest<I>
Source§fn with_mount(self, mount: impl Into<Mount>) -> ContainerRequest<I>
fn with_mount(self, mount: impl Into<Mount>) -> ContainerRequest<I>
Source§fn with_copy_to(
self,
target: impl Into<String>,
source: impl Into<CopyDataSource>,
) -> ContainerRequest<I>
fn with_copy_to( self, target: impl Into<String>, source: impl Into<CopyDataSource>, ) -> ContainerRequest<I>
Source§fn with_mapped_port(
self,
host_port: u16,
container_port: ContainerPort,
) -> ContainerRequest<I>
fn with_mapped_port( self, host_port: u16, container_port: ContainerPort, ) -> ContainerRequest<I>
Source§fn with_ulimit(
self,
name: &str,
soft: i64,
hard: Option<i64>,
) -> ContainerRequest<I>
fn with_ulimit( self, name: &str, soft: i64, hard: Option<i64>, ) -> ContainerRequest<I>
Source§fn with_privileged(self, privileged: bool) -> ContainerRequest<I>
fn with_privileged(self, privileged: bool) -> ContainerRequest<I>
Source§fn with_cap_add(self, capability: impl Into<String>) -> ContainerRequest<I>
fn with_cap_add(self, capability: impl Into<String>) -> ContainerRequest<I>
Source§fn with_cap_drop(self, capability: impl Into<String>) -> ContainerRequest<I>
fn with_cap_drop(self, capability: impl Into<String>) -> ContainerRequest<I>
Source§fn with_cgroupns_mode(self, cgroupns_mode: CgroupnsMode) -> ContainerRequest<I>
fn with_cgroupns_mode(self, cgroupns_mode: CgroupnsMode) -> ContainerRequest<I>
Source§fn with_userns_mode(self, userns_mode: &str) -> ContainerRequest<I>
fn with_userns_mode(self, userns_mode: &str) -> ContainerRequest<I>
Source§fn with_shm_size(self, bytes: u64) -> ContainerRequest<I>
fn with_shm_size(self, bytes: u64) -> ContainerRequest<I>
Source§fn with_startup_timeout(self, timeout: Duration) -> ContainerRequest<I>
fn with_startup_timeout(self, timeout: Duration) -> ContainerRequest<I>
Source§fn with_working_dir(self, working_dir: impl Into<String>) -> ContainerRequest<I>
fn with_working_dir(self, working_dir: impl Into<String>) -> ContainerRequest<I>
/
.Source§fn with_log_consumer(
self,
log_consumer: impl LogConsumer + 'static,
) -> ContainerRequest<I>
fn with_log_consumer( self, log_consumer: impl LogConsumer + 'static, ) -> ContainerRequest<I>
Source§fn with_user(self, user: impl Into<String>) -> ContainerRequest<I>
fn with_user(self, user: impl Into<String>) -> ContainerRequest<I>
Source§fn with_readonly_rootfs(self, readonly_rootfs: bool) -> ContainerRequest<I>
fn with_readonly_rootfs(self, readonly_rootfs: bool) -> ContainerRequest<I>
Source§fn with_security_opt(
self,
security_opt: impl Into<String>,
) -> ContainerRequest<I>
fn with_security_opt( self, security_opt: impl Into<String>, ) -> ContainerRequest<I>
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left
is true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left(&self)
returns true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read moreSource§impl<T> IntoResult<T> for T
impl<T> IntoResult<T> for T
type Err = Infallible
fn into_result(self) -> Result<T, <T as IntoResult<T>>::Err>
Source§impl<T> IntoResult<T> for T
impl<T> IntoResult<T> for T
type Err = Infallible
fn into_result(self) -> Result<T, <T as IntoResult<T>>::Err>
Source§impl<T> PolicyExt for Twhere
T: ?Sized,
impl<T> PolicyExt for Twhere
T: ?Sized,
Source§impl<T, I> SyncRunner<I> for T
impl<T, I> SyncRunner<I> for T
Source§fn start(self) -> Result<Container<I>, TestcontainersError>
fn start(self) -> Result<Container<I>, TestcontainersError>
Container
.