Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for director/federation contact info as a configuration #1012

Merged
merged 4 commits into from
Apr 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions director/director_ui.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"strings"

"github.com/gin-gonic/gin"
"github.com/pelicanplatform/pelican/param"
"github.com/pelicanplatform/pelican/server_structs"
"github.com/pelicanplatform/pelican/web_ui"
log "github.com/sirupsen/logrus"
Expand Down Expand Up @@ -60,6 +61,11 @@ type (
MinResponses int `form:"min_responses"`
MaxResponses int `form:"max_responses"`
}

supportContactRes struct {
Email string `json:"email"`
Url string `json:"url"`
}
)

func (req listServerRequest) ToInternalServerType() server_structs.ServerType {
Expand Down Expand Up @@ -213,6 +219,14 @@ func handleAllowServer(ctx *gin.Context) {
ctx.JSON(http.StatusOK, gin.H{"message": "success"})
}

// Endpoint for director support contact information
func handleDirectorContact(ctx *gin.Context) {
email := param.Director_SupportContactEmail.GetString()
url := param.Director_SupportContactUrl.GetString()

ctx.JSON(http.StatusOK, supportContactRes{Email: email, Url: url})
}

func RegisterDirectorWebAPI(router *gin.RouterGroup) {
directorWebAPI := router.Group("/api/v1.0/director_ui")
// Follow RESTful schema
Expand All @@ -222,5 +236,6 @@ func RegisterDirectorWebAPI(router *gin.RouterGroup) {
directorWebAPI.PATCH("/servers/allow/*name", web_ui.AuthHandler, web_ui.AdminAuthHandler, handleAllowServer)
directorWebAPI.GET("/servers/origins/stat/*path", web_ui.AuthHandler, queryOrigins)
directorWebAPI.HEAD("/servers/origins/stat/*path", web_ui.AuthHandler, queryOrigins)
directorWebAPI.GET("/contact", handleDirectorContact)
}
}
27 changes: 20 additions & 7 deletions docs/pages/serving_a_federation.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ If you haven't installed Pelican, follow the instructions to [install pelican](/

### Prepare TLS Credentials

Pelican servers use `https` for serving its web UI, handling file transfer requests and internal http requests. `https` requires a set of credential files in place to work. For details on how to set up the TLS credentials, refer to the [documentation in Serve an Origin](./serving_an_origin.mdx#prepare-tls-credentials).
Pelican servers use `https` for serving its web UI, handling objects transfer requests and internal http requests. `https` requires a set of credential files in place to work. For details on how to set up the TLS credentials, refer to the [documentation in Serve an Origin](./serving_an_origin.mdx#prepare-tls-credentials).

## Serve a Registry

Expand Down Expand Up @@ -140,14 +140,27 @@ Then pass the file location to `Director.MaxMindKeyFile`.
A Pelican director needs to talk to the registry to get the public keys for namespaces. You will need to set `Federation.RegistryUrl` to the public endpoint of your registry
for your Pelican director to work. An example value looks like `https://your-registry.org:9999`

### Director as a Federation (optional)
### Director as a Federation

For Pelican origins and caches, they need to know where the *federation* is so that they can
attempt to join it. This can be done by either manually passing configuration values or by requesting the
`Federation.DiscoveryUrl` endpoint, which contains various URLs to a federation's registry and director.
You may supply your own endpoint to provide such information or the Pelican director can do it for you.
For Pelican origin, cache, and client, they need to know where the *federation* they belong to so that they can make themselves known to other services or a access objects. This can be done by either manually passing configuration values (e.g. `Federation.DirectorUrl`, `Federation.RegistryUrl`, etc) or by setting the
`Federation.DiscoveryUrl` and Pelican will fetch the metadata from the endpoint automatically. Pelican uses `Federation.DiscoveryUrl` to discover where a federation's central services live, including the registry and director.

This can be done by setting `Federation.DiscoveryUrl` of your *origins* and *caches* to the public url of your director, i.e. `https://<your-director-hostname>:<director-web-port>`. Make sure your director is up and running before starting your origins and caches.
By default, Pelican director hosts the federation discovery endpoint. Therefore, for origins and caches in your federation, as well as Pelican clients that want to access objects in your federation, their `Federation.DiscoveryUrl` value can be set to the director's public URL, i.e. `https://<your-director-hostname>:<director-web-port>` or `https://<your-director-hostname>` if the port number is simply `443`.

Make sure your director is up and running before starting your origins and caches.

### Set Support Contact Information (Recommended)
> `Director.SupportContact` is only available for Pelican >=7.7.0

The Pelican director is your federation's entrypoint, and it is where other services in the federation can learn about each other. Because of this, it is also used to host the contact information for federation administrators. Setting values for the configuration options `Director.SupportContactEmail` and `Director.SupportContactUrl` causes the director to display the information through its website so that users know who and how to contact you for support. See [Configuration](./parameters.mdx#Director-SupportContact) page for details.

```yaml filename="pelican.yaml"
Director:
SupportContactEmail: <your support email>
SupportContactUrl: <url to other support resources>
```

Note that either `SupportContactEmail` or `SupportContactUrl` are optional. You may leave any of them empty is not needed.

### Launch the Director

Expand Down
17 changes: 17 additions & 0 deletions docs/parameters.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1012,6 +1012,23 @@ type: stringSlice
default: none
components: ["director"]
---
name: Director.SupportContactEmail
description: >-
An Email address to receive issues and help requests for the federation the director is hosting. The values will
be displayed on the director web interface if provided. We highly recommend director admin to fill out this field.
type: string
default: none
components: ["director"]
---
name: Director.SupportContactUrl
description: >-
A URL where user can find support information. Can be your website, GitHub discussion, or third-party support portal
for the federation the director is hosting. The values will be displayed on the director web interface if provided.
We highly recommend director admin to fill out this field.
type: string
default: none
components: ["director"]
---
############################
# Registry-level configs #
############################
Expand Down
8 changes: 8 additions & 0 deletions launchers/director_serve.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,10 @@ package launchers
import (
"context"
"fmt"
"net/url"

"github.com/gin-gonic/gin"
"github.com/pkg/errors"
log "github.com/sirupsen/logrus"
"golang.org/x/sync/errgroup"

Expand Down Expand Up @@ -61,6 +63,12 @@ func DirectorServe(ctx context.Context, engine *gin.Engine, egrp *errgroup.Group
" but you provided %q. Was there a typo?", defaultResponse)
}
log.Debugf("The director will redirect to %ss by default", defaultResponse)
if param.Director_SupportContactUrl.IsSet() {
_, err := url.Parse(param.Director_SupportContactUrl.GetString())
if err != nil {
return errors.Wrap(err, "invalid URL for Director.SupportContactUrl")
}
}
rootGroup := engine.Group("/")
director.RegisterDirectorOIDCAPI(rootGroup)
director.RegisterDirectorWebAPI(rootGroup)
Expand Down
2 changes: 2 additions & 0 deletions param/parameters.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions param/parameters_struct.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

27 changes: 27 additions & 0 deletions web_ui/frontend/app/api/docs/pelican-swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,15 @@ definitions:
type: string
description: The status of director file transfer test against the server. Can be Initializing|Unknown|OK|Error
default: Unknown
DirectorContact:
type: object
properties:
email:
type: string
default: ""
url:
type: string
default: ""

tags:
- name: auth
Expand Down Expand Up @@ -1460,6 +1469,24 @@ paths:
schema:
type: object
$ref: "#/definitions/ErrorModel"
/director_ui/contact:
get:
summary: Get the support contact information of the federation the director hostnames
description: "Note that the response value (if successful) `email` and `url` can be either or both empty strings"
tags:
- "director_ui"
responses:
"200":
description: "OK"
schema:
type: object
$ref: "#/definitions/DirectorContact"
"500":
description: "Bad server configuration. Failed to get the director contact information from the server configuration"
schema:
type: object
$ref: "#/definitions/ErrorModel"

/director/namespaces/prefix/{path}:
get:
summary: "Get the longest matched namespace prefix of a path"
Expand Down
Loading