mirror of
https://github.com/gmemstr/sliproad.git
synced 2024-09-20 00:21:15 +01:00
Delete files and create directories.
Added DELETE handler to files endpoint for deleting files and directories, along with new handling for creating directories, as specified with the `X-NAS-Type` header - if this is set to "directory", a new directory is created with the path of the request. Otherwise, an attempt to parse the file from form data is done as before. Also added buttons to interact with the new functionality in the default frontend.
This commit is contained in:
parent
1ba1a14807
commit
e1b8c50d55
|
@ -52,7 +52,9 @@ body, h1 a {
|
||||||
word-wrap: anywhere;
|
word-wrap: anywhere;
|
||||||
margin: 5px 0;
|
margin: 5px 0;
|
||||||
position: relative;
|
position: relative;
|
||||||
border-radius: 5px;
|
border-radius: 5px 0 0 5px;
|
||||||
|
display: inline-block;
|
||||||
|
width: 93%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.list a img {
|
.list a img {
|
||||||
|
@ -100,11 +102,16 @@ body, h1 a {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
form {
|
.forms {
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
width: 40%;
|
width: 40%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
form {
|
||||||
|
display: inline-block;
|
||||||
|
width: 30%;
|
||||||
|
}
|
||||||
|
|
||||||
@media only screen and (max-width: 1170px) {
|
@media only screen and (max-width: 1170px) {
|
||||||
.grid-lg {
|
.grid-lg {
|
||||||
display: block;
|
display: block;
|
||||||
|
@ -129,7 +136,8 @@ input[type="file"] {
|
||||||
z-index: -1;
|
z-index: -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="file"] + label {
|
input[type="file"] + label, input[type="submit"], button {
|
||||||
|
color: var(--orange);
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
font-size: 1.25em;
|
font-size: 1.25em;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
|
@ -139,8 +147,21 @@ input[type="file"] + label {
|
||||||
transition: background-color 0.5s, color 0.5s;
|
transition: background-color 0.5s, color 0.5s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input[type="text"] {
|
||||||
|
padding: 10px;
|
||||||
|
font-size: 1.25em;
|
||||||
|
font-weight: 500;
|
||||||
|
display: inline-block;
|
||||||
|
border: 2px solid var(--orange);
|
||||||
|
border-radius: 5px;
|
||||||
|
transition: background-color 0.5s, color 0.5s;
|
||||||
|
width: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
input[type="file"]:focus + label,
|
input[type="file"]:focus + label,
|
||||||
input[type="file"] + label:hover {
|
input[type="file"] + label:hover,
|
||||||
|
input[type="submit"]:hover,
|
||||||
|
button:hover {
|
||||||
background-color: var(--orange);
|
background-color: var(--orange);
|
||||||
color: var(--white);
|
color: var(--white);
|
||||||
transition: background-color 0.5s, color 0.5s;
|
transition: background-color 0.5s, color 0.5s;
|
||||||
|
@ -159,3 +180,27 @@ progress::-webkit-progress-value {
|
||||||
progress::-moz-progress-bar {
|
progress::-moz-progress-bar {
|
||||||
background: var(--orange);
|
background: var(--orange);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
padding: 1vh;
|
||||||
|
font-size: 24px;
|
||||||
|
font-weight: bold;
|
||||||
|
text-decoration: none;
|
||||||
|
text-align: center;
|
||||||
|
transition: background-color 0.5s;
|
||||||
|
margin: 5px 0;
|
||||||
|
position: relative;
|
||||||
|
border-radius: 0 5px 5px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.directory ~ button {
|
||||||
|
border-color: var(--blue);
|
||||||
|
}
|
||||||
|
.directory ~ button:hover {
|
||||||
|
background-color: var(--blue);
|
||||||
|
}
|
||||||
|
|
||||||
|
.item {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
8
assets/web/icons/trash.svg
Normal file
8
assets/web/icons/trash.svg
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-trash" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<path stroke="none" d="M0 0h24v24H0z"/>
|
||||||
|
<line x1="4" y1="7" x2="20" y2="7" />
|
||||||
|
<line x1="10" y1="11" x2="10" y2="17" />
|
||||||
|
<line x1="14" y1="11" x2="14" y2="17" />
|
||||||
|
<path d="M5 7l1 12a2 2 0 0 0 2 2h8a2 2 0 0 0 2 -2l1 -12" />
|
||||||
|
<path d="M9 7v-3a1 1 0 0 1 1 -1h4a1 1 0 0 1 1 1v3" />
|
||||||
|
</svg>
|
After Width: | Height: | Size: 529 B |
|
@ -1,7 +1,7 @@
|
||||||
// Register our router, and fire it off initially in case user is being linked a dir.
|
// Register our router, and fire it off initially in case user is being linked a dir.
|
||||||
window.addEventListener("hashchange", router, false);
|
window.addEventListener("hashchange", router, false);
|
||||||
router()
|
router()
|
||||||
let input = ""
|
let fileinput = ""
|
||||||
|
|
||||||
// Fetch file listing for a provider and optional path.
|
// Fetch file listing for a provider and optional path.
|
||||||
function getFileListing(provider, path = "") {
|
function getFileListing(provider, path = "") {
|
||||||
|
@ -20,25 +20,43 @@ function getFileListing(provider, path = "") {
|
||||||
files = []
|
files = []
|
||||||
}
|
}
|
||||||
html`
|
html`
|
||||||
<form action="#" method="post">
|
<div class="forms">
|
||||||
|
<form id="uploadfile" action="#" method="post">
|
||||||
<input type="file" id="file" data-dir="${provider}${path}"><label for="file">Upload</label>
|
<input type="file" id="file" data-dir="${provider}${path}"><label for="file">Upload</label>
|
||||||
<progress id="progress" value="0" max="100" hidden=""></progress>
|
<progress id="progress" value="0" max="100" hidden=""></progress>
|
||||||
</form>
|
</form>
|
||||||
|
<form id="createdir" action="#" method="post">
|
||||||
|
<input type="text" id="newdir" data-dir="${provider}${path}">
|
||||||
|
<input type="submit" value="mkdir" id="newdir_submit">
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
<div class="list">
|
<div class="list">
|
||||||
${files.map(file =>
|
${files.map(file =>
|
||||||
`<a class="${file.IsDirectory ? "directory" : "file"}" href="${!file.IsDirectory ? `/api/files/${provider}${path}/${file.Name}` : `#${provider}${path === "" ? "" : path}/${file.Name}`}">
|
`<div class="item"><a class="${file.IsDirectory ? "directory" : "file"}" href="${!file.IsDirectory ? `/api/files/${provider}${path}/${file.Name}` : `#${provider}${path === "" ? "" : path}/${file.Name}`}">
|
||||||
<span>${file.IsDirectory ? '<img src="/icons/folder.svg"/>' : '<img src="/icons/file.svg"/>'}${file.Name}</span>
|
<span>${file.IsDirectory ? '<img src="/icons/folder.svg"/>' : '<img src="/icons/file.svg"/>'}${file.Name}</span>
|
||||||
</a>
|
</a><button onclick="deleteFile('${provider}', '${path === "" ? '' : path}', '${file.Name}')"><img src="/icons/trash.svg"/></button></div>
|
||||||
`
|
`
|
||||||
).join('')}
|
).join('')}
|
||||||
</div>
|
</div>
|
||||||
`
|
`
|
||||||
// Register our new listeners for uploading files.
|
// Register our new listeners for uploading files.
|
||||||
input = document.getElementById("file")
|
fileinput = document.getElementById("file")
|
||||||
input.addEventListener("change", onSelectFile, false)
|
fileinput.addEventListener("change", onSelectFile, false)
|
||||||
|
createdir = document.getElementById("createdir")
|
||||||
|
createdir.addEventListener("submit", mkdir)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function deleteFile(provider, path, filename) {
|
||||||
|
let xhrObj = new XMLHttpRequest()
|
||||||
|
let rp = `${provider}${path === "" ? "" : path}/${filename}`
|
||||||
|
|
||||||
|
xhrObj.addEventListener("loadend", uploadFinish, false)
|
||||||
|
xhrObj.open("DELETE", `/api/files/${rp}`, true)
|
||||||
|
|
||||||
|
xhrObj.send()
|
||||||
|
}
|
||||||
|
|
||||||
// Fetch list of providers and render.
|
// Fetch list of providers and render.
|
||||||
function getProviders() {
|
function getProviders() {
|
||||||
fetch(`/api/providers`)
|
fetch(`/api/providers`)
|
||||||
|
@ -63,6 +81,7 @@ function getProviders() {
|
||||||
// Dumb router function for passing around values from the hash.
|
// Dumb router function for passing around values from the hash.
|
||||||
function router(event = null) {
|
function router(event = null) {
|
||||||
let hash = location.hash.replace("#", "")
|
let hash = location.hash.replace("#", "")
|
||||||
|
console.log(hash)
|
||||||
// If hash is empty, "redirect" to index.
|
// If hash is empty, "redirect" to index.
|
||||||
if (hash === "") {
|
if (hash === "") {
|
||||||
getProviders()
|
getProviders()
|
||||||
|
@ -75,9 +94,23 @@ function router(event = null) {
|
||||||
getFileListing(provider, path)
|
getFileListing(provider, path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function mkdir(event) {
|
||||||
|
event.preventDefault()
|
||||||
|
let xhrObj = new XMLHttpRequest()
|
||||||
|
mkdir = document.getElementById("newdir")
|
||||||
|
let path = mkdir.getAttribute("data-dir")
|
||||||
|
let mkdirvalue = mkdir.value
|
||||||
|
|
||||||
|
xhrObj.addEventListener("loadend", uploadFinish, false)
|
||||||
|
xhrObj.open("POST", `/api/files/${path}/${mkdirvalue}`, true)
|
||||||
|
xhrObj.setRequestHeader("X-NAS-Type", "directory")
|
||||||
|
|
||||||
|
xhrObj.send()
|
||||||
|
}
|
||||||
|
|
||||||
// File upload functions. Uses XMLHttpRequest so we can display file upload progress.
|
// File upload functions. Uses XMLHttpRequest so we can display file upload progress.
|
||||||
function onSelectFile() {
|
function onSelectFile() {
|
||||||
upload(input.getAttribute("data-dir"), input.files[0])
|
upload(fileinput.getAttribute("data-dir"), fileinput.files[0])
|
||||||
}
|
}
|
||||||
function upload(path, file) {
|
function upload(path, file) {
|
||||||
let xhrObj = new XMLHttpRequest()
|
let xhrObj = new XMLHttpRequest()
|
||||||
|
@ -86,10 +119,10 @@ function upload(path, file) {
|
||||||
|
|
||||||
xhrObj.upload.addEventListener("loadstart", uploadStarted, false)
|
xhrObj.upload.addEventListener("loadstart", uploadStarted, false)
|
||||||
xhrObj.upload.addEventListener("progress", uploadProgress, false)
|
xhrObj.upload.addEventListener("progress", uploadProgress, false)
|
||||||
xhrObj.upload.addEventListener("load", uploadFinish, false)
|
xhrObj.upload.addEventListener("loadend", uploadFinish, false)
|
||||||
xhrObj.open("POST", `/api/files/${path}`, true)
|
xhrObj.open("POST", `/api/files/${path}`, true)
|
||||||
|
|
||||||
xhrObj.send(formData);
|
xhrObj.send(formData)
|
||||||
}
|
}
|
||||||
|
|
||||||
function uploadStarted(e) {
|
function uploadStarted(e) {
|
||||||
|
|
|
@ -255,6 +255,17 @@ func (bp *BackblazeProvider) SaveFile(file io.Reader, filename string, path stri
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bp *BackblazeProvider) DetermineType(path string) string {
|
func (bp *BackblazeProvider) DetermineType(path string) string {
|
||||||
// TODO: Implement directory support for B2.
|
// B2 is really a "flat" filesystem, with directories being virtual.
|
||||||
|
// Therefore, we can assume everything is a file ;)
|
||||||
return "file"
|
return "file"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (bp *BackblazeProvider) CreateDirectory(path string) bool {
|
||||||
|
// See above comment about virtual directories.
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bp *BackblazeProvider) Delete(path string) bool {
|
||||||
|
// TODO
|
||||||
|
return false
|
||||||
|
}
|
|
@ -55,17 +55,17 @@ func (dp *DiskProvider) ViewFile(path string, w io.Writer) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dp *DiskProvider) SaveFile(file io.Reader, filename string, path string) bool {
|
func (dp *DiskProvider) SaveFile(file io.Reader, filename string, path string) bool {
|
||||||
fullPath := strings.Join([]string{dp.Location,path,filename}, "/")
|
rp := strings.Join([]string{dp.Location,path,filename}, "/")
|
||||||
f, err := os.OpenFile(fullPath, os.O_WRONLY|os.O_CREATE, 0666)
|
f, err := os.OpenFile(rp, os.O_WRONLY|os.O_CREATE, 0644)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err.Error())
|
fmt.Printf("error creating %v: %v\n", rp, err.Error())
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
|
|
||||||
_, err = io.Copy(f, file)
|
_, err = io.Copy(f, file)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err.Error())
|
fmt.Printf("error writing %v: %v\n", rp, err.Error())
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
|
@ -83,3 +83,23 @@ func (dp *DiskProvider) DetermineType(path string) string {
|
||||||
|
|
||||||
return "file"
|
return "file"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (dp *DiskProvider) CreateDirectory(path string) bool {
|
||||||
|
rp := strings.Join([]string{dp.Location,path}, "/")
|
||||||
|
err := os.Mkdir(rp, 0755)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Error creating directory %v: %v\n", rp, err.Error())
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dp *DiskProvider) Delete(path string) bool {
|
||||||
|
rp := strings.Join([]string{dp.Location,path}, "/")
|
||||||
|
err := os.RemoveAll(rp)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Error removing %v: %v\n", path, err.Error())
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
|
@ -34,6 +34,8 @@ type FileProviderInterface interface {
|
||||||
ViewFile(path string, w io.Writer)
|
ViewFile(path string, w io.Writer)
|
||||||
SaveFile(file io.Reader, filename string, path string) bool
|
SaveFile(file io.Reader, filename string, path string) bool
|
||||||
DetermineType(path string) string
|
DetermineType(path string) string
|
||||||
|
CreateDirectory(path string) bool
|
||||||
|
Delete(path string) bool
|
||||||
}
|
}
|
||||||
|
|
||||||
/** DO NOT USE THESE DEFAULTS **/
|
/** DO NOT USE THESE DEFAULTS **/
|
||||||
|
@ -57,3 +59,11 @@ func (f FileProvider) DetermineType(path string) string {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (f FileProvider) CreateDirectory(path string) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f FileProvider) Delete(path string) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,14 @@ func TestFileProvider(t *testing.T) {
|
||||||
determinetype := fp.DetermineType(""); if determinetype != "" {
|
determinetype := fp.DetermineType(""); if determinetype != "" {
|
||||||
t.Errorf("Default FileProvider DetermineType() did not return an empty string.")
|
t.Errorf("Default FileProvider DetermineType() did not return an empty string.")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
createdirectory := fp.CreateDirectory(""); if createdirectory {
|
||||||
|
t.Errorf("Default FileProvider CreateDirectory() returned %v, expected false.", createdirectory)
|
||||||
|
}
|
||||||
|
|
||||||
|
delete := fp.Delete(""); if delete {
|
||||||
|
t.Errorf("Default FileProvider Delete() returned %v, expected false.", createdirectory)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test functions provided by fileutils, which do not return anything.
|
// Test functions provided by fileutils, which do not return anything.
|
||||||
|
@ -94,6 +102,14 @@ func TestDiskProvider(t *testing.T) {
|
||||||
determinetype := dp.DetermineType("second_test.txt"); if determinetype != "file" {
|
determinetype := dp.DetermineType("second_test.txt"); if determinetype != "file" {
|
||||||
t.Errorf("DiskProvider DetermineType() returned %v, expected \"file\".", determinetype)
|
t.Errorf("DiskProvider DetermineType() returned %v, expected \"file\".", determinetype)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
createdirectory := dp.CreateDirectory("test_dir"); if !createdirectory {
|
||||||
|
t.Errorf("DiskProvider CreateDirectory() returned %v, expected true.", createdirectory)
|
||||||
|
}
|
||||||
|
|
||||||
|
delete := dp.Delete("test_dir"); if !delete {
|
||||||
|
t.Errorf("DiskProvider Delete() returned %v, expected true.", createdirectory)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func DiskProviderTestCleanup() {
|
func DiskProviderTestCleanup() {
|
||||||
|
|
|
@ -18,6 +18,7 @@ func HandleProvider() Handler {
|
||||||
providerCodename = strings.Replace(providerCodename, "/", "", -1)
|
providerCodename = strings.Replace(providerCodename, "/", "", -1)
|
||||||
provider := *files.Providers[providerCodename]
|
provider := *files.Providers[providerCodename]
|
||||||
|
|
||||||
|
// Directory listing or serve file.
|
||||||
if r.Method == "GET" {
|
if r.Method == "GET" {
|
||||||
fileList := provider.GetDirectory("")
|
fileList := provider.GetDirectory("")
|
||||||
if vars["file"] != "" {
|
if vars["file"] != "" {
|
||||||
|
@ -51,28 +52,57 @@ func HandleProvider() Handler {
|
||||||
w.Write(data)
|
w.Write(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// File upload or directory creation.
|
||||||
if r.Method == "POST" {
|
if r.Method == "POST" {
|
||||||
err := r.ParseMultipartForm(32 << 20)
|
xType := r.Header.Get("X-NAS-Type")
|
||||||
if err != nil {
|
|
||||||
return &HTTPError{
|
|
||||||
Message: fmt.Sprintf("error parsing form for %s\n", vars["file"]),
|
|
||||||
StatusCode: http.StatusInternalServerError,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
file, handler, err := r.FormFile("file")
|
|
||||||
defer file.Close()
|
|
||||||
|
|
||||||
success := provider.SaveFile(file, handler.Filename, vars["file"])
|
if xType == "file" || xType == ""{
|
||||||
if !success {
|
err := r.ParseMultipartForm(32 << 20)
|
||||||
return &HTTPError{
|
if err != nil {
|
||||||
Message: fmt.Sprintf("error saving file %s\n", vars["file"]),
|
return &HTTPError{
|
||||||
StatusCode: http.StatusInternalServerError,
|
Message: fmt.Sprintf("error parsing form for %s\n", vars["file"]),
|
||||||
|
StatusCode: http.StatusInternalServerError,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
file, handler, err := r.FormFile("file")
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
success := provider.SaveFile(file, handler.Filename, vars["file"])
|
||||||
|
if !success {
|
||||||
|
return &HTTPError{
|
||||||
|
Message: fmt.Sprintf("error saving file %s\n", vars["file"]),
|
||||||
|
StatusCode: http.StatusInternalServerError,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
w.Write([]byte("saved file"))
|
||||||
|
}
|
||||||
|
if xType == "directory" {
|
||||||
|
dirname := vars["file"]
|
||||||
|
success := provider.CreateDirectory(dirname)
|
||||||
|
if !success {
|
||||||
|
return &HTTPError{
|
||||||
|
Message: fmt.Sprintf("error creating directory %s\n", dirname),
|
||||||
|
StatusCode: http.StatusInternalServerError,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_, _ = w.Write([]byte("created directory"))
|
||||||
}
|
}
|
||||||
w.Write([]byte("saved file"))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
// Delete file.
|
||||||
|
if r.Method == "DELETE" {
|
||||||
|
path := vars["file"]
|
||||||
|
success := provider.Delete(path)
|
||||||
|
if !success {
|
||||||
|
return &HTTPError{
|
||||||
|
Message: fmt.Sprintf("error deleting %s\n", path),
|
||||||
|
StatusCode: http.StatusInternalServerError,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_, _ = w.Write([]byte("deleted"))
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -60,7 +60,7 @@ func Init() *mux.Router {
|
||||||
|
|
||||||
r.Handle(`/api/files/{provider:[a-zA-Z0-9]+}/{file:.+}`, Handle(
|
r.Handle(`/api/files/{provider:[a-zA-Z0-9]+}/{file:.+}`, Handle(
|
||||||
HandleProvider(),
|
HandleProvider(),
|
||||||
)).Methods("GET", "POST")
|
)).Methods("GET", "POST", "DELETE")
|
||||||
|
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,11 +15,11 @@ func main() {
|
||||||
// Initialize file providers.
|
// Initialize file providers.
|
||||||
file, err := ioutil.ReadFile("providers.yml")
|
file, err := ioutil.ReadFile("providers.yml")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
fmt.Println("Unable to read providers.yml file, does it exist?")
|
||||||
}
|
}
|
||||||
err = yaml.Unmarshal(file, &files.ProviderConfig)
|
err = yaml.Unmarshal(file, &files.ProviderConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
fmt.Println("Unable to parse providers.yml file, is it correct?")
|
||||||
}
|
}
|
||||||
files.SetupProviders()
|
files.SetupProviders()
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue