2010-02-14 13 views
7

I appologise z góry za długość tego postu ....Przechowywanie poświadczeń Amazon S3 w .bashrc zmiennych environemental powoduje Rails app niepowodzenie

Zajmuję się tworzeniem aplikacji Rais, który używa spinacz do przechowywania rzeczy na Amazon S3. Aplikacja jest hostowana na Heroku. Pracuję nad Ubuntu Karmic.

Problem, który zamierzam opisać, pojawia się w fazie rozwoju (w moim lokalnym hostelu) i produkcji (na Heroku).


Standardowy sposób przekazywania creds S3 spinacza jest przez umieszczenie ich w config/s3.yml tak:

access_key_id: 12345678 
secret_access_key: 903490409fdf09fshsfdoif/43432 

Kiedy to zrobić, wszystko działa dobrze. Ale to utrudnia dzielenie się moim kodem z innymi, więc Heroku sugeruje alternatywną metodę - http://docs.heroku.com/config-vars.

Radzą, które należy umieścić S3_KEY i S3_SECRET do swojego .bashrc tak:

S3_KEY=12345678 
export S3_KEY 
S3_SECRET=903490409fdf09fshsfdoif/43432 
export S3_SECRET 

Następnie sugerują, że tworzenie config/inicjalizatory/s3.yml (zwróć uwagę na nieco inną drogą) i umieścić następujące w tym pliku:

AWS::S3::Base.establish_connection!(
    :access_key_id  => ENV['S3_KEY'], 
    :secret_access_key => ENV['S3_SECRET'] 
) 

ale kiedy to zrobić, spinacz rzuca woblera i wypluwa następujący komunikat o błędzie:

undefined method `stringify_keys' for #<String:0xb6d6c3f4> 

/vendor/plugins/paperclip/lib/paperclip/storage.rb:176:in `parse_credentials' 
/vendor/plugins/paperclip/lib/paperclip/storage.rb:138:in `extended' 
/vendor/plugins/paperclip/lib/paperclip/storage.rb:137:in `instance_eval' 
/vendor/plugins/paperclip/lib/paperclip/storage.rb:137:in `extended' 

.... other stuff 

Wyraźnie wszystko zaczyna się w module storage.rb. Krocząc przez śladu stosu:

Sposób parse_credentials na linii 176 jest oznaczony - oto wezwanie, gdyż pojawia się w kodzie:

def parse_credentials creds 
    creds = find_credentials(creds).stringify_keys 
    (creds[RAILS_ENV] || creds).symbolize_keys 
end 

Sposób parse_credentials próbuje wywołać inną metodą find_credentials, a to gdzie wierzę, że problem leży. Herezje kod find_credentials:

def find_credentials creds 
    case creds 
    when File 
     YAML::load(ERB.new(File.read(creds.path)).result) 
    when String 
     YAML::load(ERB.new(File.read(creds)).result) 
    when Hash 
     creds 
    else 
     raise ArgumentError, "Credentials are not a path, file, or hash." 
    end 
end 

nie widzę, w jaki sposób metoda find_credentials jest przystosowany do odczytu wartości z mojego pliku .bashrc. Ma dwa przypadki, w których może czytać z YAML i jeden, gdzie szuka hasha.

Mój model odwołuje poświadczenia tak:

has_attached_file :photo, 
       (some code removed) 
       :s3_credentials => "#{RAILS_ROOT}/config/initializers/s3.yml", 

Jeśli usunąć: s3_credentials skrót od modelu, błąd stringify_keys odchodzi i konsola szyny wyrzuca komunikat o błędzie, który pojawia się na końcu metoda find_credentials: tzn. "Poświadczenia nie są ścieżką, plikiem ani hash".

Więc jestem zakłopotany. Zdaję sobie sprawę, że jest to prawdopodobnie pytanie dla chłopaków z Heroku (do kogo mam zamiar wysłać ten link w nadziei, że mogą na nie odpowiedzieć) i jest to prawdopodobnie również pytanie do doodów w thinkbot, ale pomyślałem, że StackOverflow może być najlepszym miejscem, aby o to zapytać, ponieważ okazało się, że w przeszłości było to dość wiarygodne forum.

Jak już powiedziałem na początku, moja aplikacja działa poprawnie, gdy przyjmuję standardowe podejście do wtrącania klucza i sekretu do config/s3.yml, ale wolałbym użyć metody, którą sugeruje Heroku, ponieważ sprawia ona, że ​​WAY łatwiejsze dla mnie i oznacza to, że mogę przechowywać moje repo na mojej publicznej stronie github, aby inni mogli z niego korzystać bez konieczności pisania jakichkolwiek sterowników scalających klientów w Git, aby zachować moje klucze APi z domeny publicznej.

Jeszcze raz przepraszam za długotrwały post, a jeśli dotarłeś tak daleko, pochwalam cię. Czy ktoś ma jakieś pomysły?

Próbowałem trzymać zmienne ENV w etc/bash.bashrc, a także ~/.bashrc i po ponownym uruchomieniu komputera nadal mam ten sam problem. Problemy pojawiają się na maszynie programistycznej, a także na Heroku. Upewniłem się również, aby wyposażyć moje config-vars również w Heroku.

Byłem w tym przez 8 godzin prosto! Pójdę teraz obejrzeć piłkę nożną.

Odpowiedz

13

Po długich poszukiwaniach znalazłem odpowiedź tutaj - http://tammersaleh.com/posts/managing-heroku-environment-variables-for-local-development

Sztuką jest usunięcie S3.rb złożyć całkowicie i po prostu odwołać się do zmiennych ENV w modelu tak:

has_attached_file :photo, 
        #... 
        :storage  => :s3, 
        :bucket   => ENV['S3_BUCKET'], 
        :s3_credentials => { :access_key_id  => ENV['S3_KEY'], 
             :secret_access_key => ENV['S3_SECRET'] } 

Zresztą , David, dzięki za twoją sugestię. Nie wiem, czy chcesz zaktualizować dokumenty Heroku, aby powiedzieć, że niektórzy użytkownicy musieli to zrobić w ten sposób. Jeszcze raz dziękuję.

2

Zmień nazwę pliku config/initializers/s3.yml na i spróbuj.

+0

Myślę, że to jest powód! – klew

+0

Przepraszam, ludzie, to nie działa. ten sam problem, ten sam komunikat o błędzie. Wiem, że plik jest czytany, gdy otrzymam błąd nie znaleziono pliku, jeśli zmienię jego nazwę. Wiem również, że zmienne ENV są ​​odczytywane, ponieważ otrzymuję wyjątek, jeśli zmienię nazwę klucza w S3.rb. W każdym razie, to nie koniec świata hte i myślę, że po prostu przejdę dalej i zostawię to w spokoju. Oznacza to po prostu, że będę musiał być bardzo ostrożny przy wkładaniu githuba, ale mogę z tym żyć. Dzięki za pomoc. Jeśli zadzwonię, dam ci znać. – stephenmurdoch

+0

również - umieszcza ENV ['S3_KEY'] z konsoli szyn działa dobrze - więc myślę, że to może być tylko kwestia spinacza - i tak dziękuję – stephenmurdoch

1

Oto problem:

:bucket   => ENV['S3_BUCKET'], 

musi być

:bucket   => <%= ENV['S3_BUCKET'] %>, 

czyli przypisania nie są interpretowane.