github.com/pelicanplatform/pelican@v1.0.5/client/sharing_url.go (about)

     1  /***************************************************************
     2   *
     3   * Copyright (C) 2023, University of Nebraska-Lincoln
     4   *
     5   * Licensed under the Apache License, Version 2.0 (the "License"); you
     6   * may not use this file except in compliance with the License.  You may
     7   * obtain a copy of the License at
     8   *
     9   *    http://www.apache.org/licenses/LICENSE-2.0
    10   *
    11   * Unless required by applicable law or agreed to in writing, software
    12   * distributed under the License is distributed on an "AS IS" BASIS,
    13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14   * See the License for the specific language governing permissions and
    15   * limitations under the License.
    16   *
    17   ***************************************************************/
    18  
    19  package client
    20  
    21  import (
    22  	"net/url"
    23  	"strings"
    24  
    25  	"github.com/pelicanplatform/pelican/config"
    26  	"github.com/pelicanplatform/pelican/param"
    27  	"github.com/pkg/errors"
    28  	log "github.com/sirupsen/logrus"
    29  	"github.com/spf13/viper"
    30  )
    31  
    32  func getDirectorFromUrl(objectUrl *url.URL) (string, error) {
    33  	configDirectorUrl := param.Federation_DirectorUrl.GetString()
    34  	var directorUrl string
    35  	if objectUrl.Scheme == "pelican" {
    36  		if objectUrl.Host == "" {
    37  			if configDirectorUrl == "" {
    38  				return "", errors.New("Must specify (or configure) the federation hostname with the pelican://-style URLs")
    39  			}
    40  			directorUrl = configDirectorUrl
    41  		} else {
    42  			discoveryUrl := url.URL{
    43  				Scheme: "https",
    44  				Host:   objectUrl.Host,
    45  			}
    46  			viper.Set("Federation.DirectorUrl", "")
    47  			viper.Set("Federation.DiscoveryUrl", discoveryUrl.String())
    48  			if err := config.DiscoverFederation(); err != nil {
    49  				return "", errors.Wrapf(err, "Failed to discover location of the director for the federation %s", objectUrl.Host)
    50  			}
    51  			if directorUrl = param.Federation_DirectorUrl.GetString(); directorUrl == "" {
    52  				return "", errors.Errorf("Director for the federation %s not discovered", objectUrl.Host)
    53  			}
    54  		}
    55  	} else if objectUrl.Scheme == "osdf" && configDirectorUrl == "" {
    56  		if objectUrl.Host != "" {
    57  			objectUrl.Path = "/" + objectUrl.Host + objectUrl.Path
    58  			objectUrl.Host = ""
    59  		}
    60  		viper.Set("Federation.DiscoveryUrl", "https://osg-htc.org")
    61  		if err := config.DiscoverFederation(); err != nil {
    62  			return "", errors.Wrap(err, "Failed to discover director for the OSDF")
    63  		}
    64  		if directorUrl = param.Federation_DirectorUrl.GetString(); directorUrl == "" {
    65  			return "", errors.Errorf("Director for the OSDF not discovered")
    66  		}
    67  	} else if objectUrl.Scheme == "" {
    68  		if configDirectorUrl == "" {
    69  			return "", errors.Errorf("Must provide a federation name for path %s (e.g., pelican://osg-htc.org/%s)", objectUrl.Path, objectUrl.Path)
    70  		} else {
    71  			directorUrl = configDirectorUrl
    72  		}
    73  	} else if objectUrl.Scheme != "osdf" {
    74  		return "", errors.Errorf("Unsupported scheme for pelican: %s://", objectUrl.Scheme)
    75  	}
    76  	return directorUrl, nil
    77  }
    78  
    79  func CreateSharingUrl(objectUrl *url.URL, isWrite bool) (string, error) {
    80  	directorUrl, err := getDirectorFromUrl(objectUrl)
    81  	if err != nil {
    82  		return "", err
    83  	}
    84  	objectUrl.Path = "/" + strings.TrimPrefix(objectUrl.Path, "/")
    85  
    86  	log.Debugln("Will query director for path", objectUrl.Path)
    87  	dirResp, err := QueryDirector(objectUrl.Path, directorUrl)
    88  	if err != nil {
    89  		log.Errorln("Error while querying the Director:", err)
    90  		return "", errors.Wrapf(err, "Error while querying the director at %s", directorUrl)
    91  	}
    92  	namespace, err := CreateNsFromDirectorResp(dirResp)
    93  	if err != nil {
    94  		return "", errors.Wrapf(err, "Unable to parse response from director at %s", directorUrl)
    95  	}
    96  
    97  	opts := config.TokenGenerationOpts{Operation: config.TokenSharedRead}
    98  	if isWrite {
    99  		opts.Operation = config.TokenSharedWrite
   100  	}
   101  	token, err := AcquireToken(objectUrl, namespace, opts)
   102  	if err != nil {
   103  		err = errors.Wrap(err, "Failed to acquire token")
   104  	}
   105  	return token, err
   106  }