Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
Orhun Parmaksız
gluebuddy
Commits
7ab61c71
Verified
Commit
7ab61c71
authored
Feb 19, 2021
by
Levente Polyak
🚀
Browse files
wip: shared state
parent
62f9e811
Changes
4
Hide whitespace changes
Inline
Side-by-side
src/main.rs
View file @
7ab61c71
...
...
@@ -21,6 +21,7 @@ use structopt::StructOpt;
use
anyhow
::
Result
;
use
env_logger
::
Env
;
use
log
::
error
;
use
std
::
sync
::{
Arc
,
Mutex
};
async
fn
run
(
args
:
Args
)
->
Result
<
()
>
{
/* Early exit for completions */
...
...
@@ -32,26 +33,29 @@ async fn run(args: Args) -> Result<()> {
_
=>
{}
}
let
mut
state
=
State
::
new
();
//let keycloak_glue = Keycloak::new().await?;
let
gitlab_glue
=
GitLabGlue
::
new
()
.await
?
;
let
state
=
Arc
::
new
(
Mutex
::
new
(
State
::
new
()));
//keycloak_glue.gather(&mut state).await?;
gitlab_glue
.gather
(
&
mut
state
)
.await
?
;
let
keycloak_glue
=
Keycloak
::
new
(
state
.clone
())
.await
?
;
let
gitlab_glue
=
GitLabGlue
::
new
(
state
.clone
())
.await
?
;
keycloak_glue
.gather
()
.await
?
;
gitlab_glue
.gather
()
.await
?
;
match
args
.command
{
Command
::
Completions
(
_
)
=>
{}
Command
::
Keycloak
(
action
)
=>
{
//
keycloak_glue.run(
&state,
action).await?;
keycloak_glue
.run
(
action
)
.await
?
;
}
Command
::
Gitlab
(
action
)
=>
gitlab_glue
.run
(
&
state
,
action
)
.await
?
,
Command
::
Gitlab
(
action
)
=>
{
gitlab_glue
.run
(
action
)
.await
?
},
Command
::
Plan
=>
{
//
keycloak_glue.run(
&state,
Action::Plan).await?;
gitlab_glue
.run
(
&
state
,
Action
::
Plan
)
.await
?
;
keycloak_glue
.run
(
Action
::
Plan
)
.await
?
;
gitlab_glue
.run
(
Action
::
Plan
)
.await
?
;
}
Command
::
Apply
=>
{
//
keycloak_glue.run(
&state,
Action::Apply).await?;
gitlab_glue
.run
(
&
state
,
Action
::
Apply
)
.await
?
;
keycloak_glue
.run
(
Action
::
Apply
)
.await
?
;
gitlab_glue
.run
(
Action
::
Apply
)
.await
?
;
}
}
Ok
(())
...
...
src/mods/gitlab/gitlab.rs
View file @
7ab61c71
...
...
@@ -23,43 +23,38 @@ use gitlab::api::common::{AccessLevel, VisibilityLevel};
use
gitlab
::
api
::
projects
::{
Projects
,
FeatureAccessLevel
};
use
gitlab
::
api
::
groups
::
members
::{
GroupMembers
,
AddGroupMember
,
RemoveGroupMember
};
use
tokio
::
task
;
use
std
::
sync
::{
Arc
,
Mutex
};
const
MAIN_BRANCH
:
&
str
=
"main"
;
const
ALL_TAGS
:
&
str
=
"*"
;
pub
struct
GitLabGlue
{
client
:
Gitlab
,
state
:
Arc
<
Mutex
<
State
>>
,
}
impl
GitLabGlue
{
pub
async
fn
new
()
->
Result
<
GitLabGlue
>
{
task
::
spawn_blocking
(
move
||
create_client
(
))
.await
?
pub
async
fn
new
(
state
:
Arc
<
Mutex
<
State
>>
)
->
Result
<
GitLabGlue
>
{
create_client
(
state
)
}
pub
async
fn
gather
<
'a
>
(
&
'a
self
,
state
:
&
mut
State
<
'a
>
)
->
Result
<
()
>
{
pub
async
fn
gather
(
&
self
)
->
Result
<
()
>
{
Ok
(())
}
pub
async
fn
run
<
'a
>
(
&
self
,
state
:
&
State
<
'a
>
,
action
:
Action
)
->
Result
<
()
>
{
task
::
spawn_blocking
(
move
||
update_gitlab_group_members
(
&
action
))
.await
??
;
pub
async
fn
run
<
'a
>
(
&
self
,
action
:
Action
)
->
Result
<
()
>
{
self
.update_gitlab_group_members
(
&
action
)
.await
?
;
/*
task::spawn_blocking(move || {
update_gitlab_group_members(guard, &action)
}).await??;
*/
//task::spawn_blocking(move || update_package_repositories(&action)).await??;
Ok
(())
}
}
pub
fn
create_client
()
->
Result
<
GitLabGlue
>
{
let
token
=
&
env
::
var
(
"GLUEBUDDY_GITLAB_TOKEN"
)
.context
(
"Missing env var GLUEBUDDY_GITLAB_TOKEN"
)
?
;
let
client
=
Gitlab
::
new
(
"gitlab.archlinux.org"
,
token
)
.unwrap
();
Ok
(
GitLabGlue
{
client
})
}
/*
fn protect_tags(client: &Gitlab, project_id: u64) -> std::result::Result<ProtectedTag, gitlab::api::ApiError<>> {
}
*/
fn
update_gitlab_group_members
(
action
:
&
Action
)
->
Result
<
()
>
{
async
fn
update_gitlab_group_members
(
&
self
,
action
:
&
Action
)
->
Result
<
()
>
{
let
token
=
&
env
::
var
(
"GLUEBUDDY_GITLAB_TOKEN"
)
.context
(
"Missing env var GLUEBUDDY_GITLAB_TOKEN"
)
?
;
let
client
=
Gitlab
::
new
(
"gitlab.archlinux.org"
,
token
)
.unwrap
();
...
...
@@ -71,8 +66,17 @@ fn update_gitlab_group_members(action: &Action) -> Result<()> {
.build
()
.unwrap
();
let
members
:
Vec
<
GroupMember
>
=
members_endpoint
.query
(
&
client
)
.unwrap
();
for
member
in
members
{
println!
(
"{} {} {} {}"
,
member
.id
,
member
.username
,
member
.email
.unwrap_or
(
"-"
.to_string
()),
member
.access_level
);
for
member
in
&
members
{
println!
(
"{} {} {} {}"
,
member
.id
,
member
.username
,
member
.email
.as_ref
()
.unwrap_or
(
&
"-"
.to_string
()),
member
.access_level
);
}
let
state
=
self
.state
.lock
()
.unwrap
();
for
staff
in
&
state
.staff
{
let
member_names
=
members
.iter
()
.map
(|
e
|
e
.username
.clone
())
.collect
::
<
Vec
<
_
>>
();
let
staff_username
=
&
staff
.username
;
if
!
member_names
.contains
(
&
staff_username
)
{
println!
(
"not in group: {}"
,
staff_username
);
}
}
println!
(
"project"
);
...
...
@@ -83,7 +87,7 @@ fn update_gitlab_group_members(action: &Action) -> Result<()> {
.unwrap
();
let
members
:
Vec
<
GroupMember
>
=
members_endpoint
.query
(
&
client
)
.unwrap
();
for
member
in
members
{
println!
(
"{} {} {} {}"
,
member
.id
,
member
.username
,
member
.email
.unwrap_or
(
"-"
.to_string
()),
member
.access_level
);
println!
(
"{} {} {} {}"
,
member
.id
,
member
.username
,
member
.email
.
as_ref
()
.
unwrap_or
(
&
"-"
.to_string
()),
member
.access_level
);
}
println!
(
"search"
);
...
...
@@ -129,7 +133,6 @@ fn update_gitlab_group_members(action: &Action) -> Result<()> {
.build()
.unwrap();
gitlab::api::ignore(endpoint).query(&client).unwrap();
*/
let endpoint = gitlab::api::projects::members::EditProjectMember::builder()
.project("bot-test/sandbox/lib10000")
...
...
@@ -138,10 +141,19 @@ fn update_gitlab_group_members(action: &Action) -> Result<()> {
.build()
.unwrap();
gitlab::api::ignore(endpoint).query(&client).unwrap();
*/
}
Ok
(())
}
}
pub
fn
create_client
(
state
:
Arc
<
Mutex
<
State
>>
)
->
Result
<
GitLabGlue
>
{
let
token
=
&
env
::
var
(
"GLUEBUDDY_GITLAB_TOKEN"
)
.context
(
"Missing env var GLUEBUDDY_GITLAB_TOKEN"
)
?
;
let
client
=
Gitlab
::
new
(
"gitlab.archlinux.org"
,
token
)
.unwrap
();
Ok
(
GitLabGlue
{
client
,
state
})
}
fn
update_package_repositories
(
action
:
&
Action
)
->
Result
<
()
>
{
let
token
=
...
...
@@ -308,7 +320,7 @@ fn update_package_repositories(action: &Action) -> Result<()> {
}
*/
set_project_settings
(
&
client
,
&
project
);
set_project_settings
(
&
client
,
&
project
)
?
;
}
}
...
...
src/mods/keycloak/keycloak.rs
View file @
7ab61c71
...
...
@@ -18,14 +18,17 @@ use log::{debug, info};
use
std
::
env
;
use
crate
::
state
::
State
;
use
crate
::
state
::
User
;
use
std
::
sync
::{
Mutex
,
Arc
};
pub
struct
Keycloak
<
'a
>
{
admin
:
KeycloakAdmin
<
'a
>
,
realm
:
String
,
state
:
Arc
<
Mutex
<
State
>>
,
}
impl
Keycloak
<
'
_
>
{
pub
async
fn
new
<
'a
>
(
)
->
Result
<
Keycloak
<
'a
>>
{
impl
<
'a
>
Keycloak
<
'
a
>
{
pub
async
fn
new
(
state
:
Arc
<
Mutex
<
State
>>
)
->
Result
<
Keycloak
<
'a
>>
{
let
username
=
&
env
::
var
(
"GLUEBUDDY_KEYCLOAK_USERNAME"
)
.context
(
"Missing env var GLUEBUDDY_KEYCLOAK_USERNAME"
)
?
;
let
password
=
&
env
::
var
(
"GLUEBUDDY_KEYCLOAK_PASSWORD"
)
...
...
@@ -47,10 +50,11 @@ impl Keycloak<'_> {
Ok
(
Keycloak
{
admin
,
realm
:
realm
.to_string
(),
state
,
})
}
pub
async
fn
gather
<
'a
>
(
&
'a
self
,
state
:
&
mut
State
<
'a
>
)
->
Result
<
()
>
{
pub
async
fn
gather
(
&
self
)
->
Result
<
()
>
{
let
root_groups
=
vec!
[
"Arch Linux Staff"
,
"External Contributors"
];
let
all_groups
=
self
...
...
@@ -89,6 +93,7 @@ impl Keycloak<'_> {
});
let
group_members
=
try_join_all
(
groups_members
)
.await
?
;
let
mut
state
=
self
.state
.lock
()
.unwrap
();
// TODO: avoid duplicates in staff when multiple groups match
for
(
group
,
users
)
in
group_members
{
...
...
@@ -99,26 +104,26 @@ impl Keycloak<'_> {
group_name
,
user
.username
.as_ref
()
.unwrap
()
);
match
group_name
.as_ref
()
{
match
group_name
{
"DevOps"
=>
{
state
.staff
.push
(
user
.clone
(
));
state
.devops
.push
(
user
.clone
(
));
state
.staff
.push
(
User
::
new
(
user
.username
.as_ref
()
.unwrap
()
.to_string
()
));
state
.devops
.push
(
User
::
new
(
user
.username
.as_ref
()
.unwrap
()
.to_string
()
));
}
"Developers"
=>
{
state
.staff
.push
(
user
.clone
(
));
state
.developers
.push
(
user
.clone
(
));
state
.staff
.push
(
User
::
new
(
user
.username
.as_ref
()
.unwrap
()
.to_string
()
));
state
.developers
.push
(
User
::
new
(
user
.username
.as_ref
()
.unwrap
()
.to_string
()
));
}
"Trusted Users"
=>
{
state
.staff
.push
(
user
.clone
(
));
state
.trusted_users
.push
(
user
.clone
(
));
state
.staff
.push
(
User
::
new
(
user
.username
.as_ref
()
.unwrap
()
.to_string
()
));
state
.trusted_users
.push
(
User
::
new
(
user
.username
.as_ref
()
.unwrap
()
.to_string
()
));
}
"Security Team"
=>
{
// TODO: do not add reporters
state
.staff
.push
(
user
.clone
(
));
state
.security_team
.push
(
user
.clone
(
));
state
.staff
.push
(
User
::
new
(
user
.username
.as_ref
()
.unwrap
()
.to_string
()
));
state
.security_team
.push
(
User
::
new
(
user
.username
.as_ref
()
.unwrap
()
.to_string
()
));
}
"External Contributors"
=>
{
state
.external_contributors
.push
(
user
.clone
(
));
state
.external_contributors
.push
(
User
::
new
(
user
.username
.as_ref
()
.unwrap
()
.to_string
()
));
}
_
=>
{}
}
...
...
@@ -128,7 +133,7 @@ impl Keycloak<'_> {
Ok
(())
}
pub
async
fn
run
<
'a
>
(
&
self
,
state
:
&
State
<
'a
>
,
action
:
Action
)
->
Result
<
()
>
{
pub
async
fn
run
(
&
self
,
action
:
Action
)
->
Result
<
()
>
{
Ok
(())
}
}
...
...
src/state.rs
View file @
7ab61c71
use
keycloak
::
types
::
UserRepresentation
;
pub
struct
State
<
'a
>
{
pub
staff
:
Vec
<
UserRepresentation
<
'a
>>
,
pub
developers
:
Vec
<
UserRepresentation
<
'a
>>
,
pub
trusted_users
:
Vec
<
UserRepresentation
<
'a
>>
,
pub
devops
:
Vec
<
UserRepresentation
<
'a
>>
,
pub
security_team
:
Vec
<
UserRepresentation
<
'a
>>
,
pub
external_contributors
:
Vec
<
UserRepresentation
<
'a
>>
,
pub
struct
User
{
pub
username
:
String
,
}
impl
State
<
'_
>
{
pub
fn
new
<
'a
>
()
->
State
<
'a
>
{
impl
User
{
pub
fn
new
(
username
:
String
)
->
User
{
User
{
username
,
}
}
}
pub
struct
State
{
pub
staff
:
Vec
<
User
>
,
pub
developers
:
Vec
<
User
>
,
pub
trusted_users
:
Vec
<
User
>
,
pub
devops
:
Vec
<
User
>
,
pub
security_team
:
Vec
<
User
>
,
pub
external_contributors
:
Vec
<
User
>
,
}
impl
State
{
pub
fn
new
()
->
State
{
State
{
staff
:
Vec
::
new
(),
developers
:
Vec
::
new
(),
...
...
@@ -24,7 +36,6 @@ impl State<'_> {
pub
fn
user_may_have_gitlab_access
(
&
self
,
username
:
&
str
)
->
bool
{
self
.staff
.iter
()
.chain
(
self
.external_contributors
.iter
())
.map
(|
e
|
e
.username
.as_ref
()
.unwrap
())
.any
(|
e
|
e
.eq
(
username
))
.any
(|
e
|
e
.username
.eq
(
username
))
}
}
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment